Flag (dynamic conditions + logic gates)!

Flag


By @avodey (my main account)!

:package: Module

This uses an Assert module, and Event module, both of which I made not specifically for this. It would help if you found bugs in those!

Summary (v1.0.0)


There have been many times where I’ve run into long conditions. How would you tackle this problem?

The frame is visible if any is true:

  • I’m a developer
  • I’m in studio
  • I’m playing the test game
  • I’m an admin
  • I’m the owner of the private server

And if this is true:

  • This is the start place

This can be simplified, but it still would still look long. And what if one of these conditions was a private variable from another script? Forget about it.

When I came across a similar problem, I ended up setting a frame invisible in multiple different fashions just to avoid making a module like this. I would set the frame invisible, set it’s size to zero, position it out of screen… all to make it disappear if one condition was true!

What’s it for?


This module allows you to set parts of the condition from anywhere using logic gates.
It also allows you set multiple values dynamically, and get back the one with the highest priority. This has use cases that will be explained later!

I’m releasing this module because, around 4 years ago when I was relatively new to scripting, I was pondering the idea of this type of module. It would have helped! It is no longer an idea.

Logic Gates


In the module, there are 3 logic gates available.

AND: All values must be truthy
OR: At least one value must be truthy
XOR: At least one value, but not all, must be truthy

View Examples
local Flag = require(game.ReplicatedStorage:WaitForChild("Flag"))
local PanelVisible = Flag.new()

PanelVisible:Set("Developer", false)
PanelVisible:Set("Studio", true)
PanelVisible:Set("PrivateServer", false)

print(PanelVisible:Get(Flag.Enum.Gate.OR)) --> true

The code prints true because one of the set values was true. The Flag.Enum.Gate dictionary provides the names of the logic gates. You do not have to use this, you could also just put "XOR", "AND", and "OR". The dictionary is used for auto completing your code!

These are not the only real logic gates, though. There is also XNOR, NAND, and NOT. But, you can just put a not before the flag. If this is wrong, tell me!

Prioritized Variables


You can set values associated with priorities. When you get the result value, it will return the one with the highest priority, and of which is active!

View Examples
local CursorMode = Flag.new()

CursorMode:Set("Tool", nil, 1)
CursorMode:Set("Tweaker", nil, 2)
CursorMode:Set("Error", nil, 99)
CursorMode:Set("Disabled", nil, 100)

-- later:

CursorMode:Set("Tool", "Brush")

print(CursorMode:Get()) --> Brush

CursorMode:Set("Disabled", "Disabled")

print(CursorMode:Get()) --> Disabled

CursorMode:Set("Disabled", nil)

print(CursorMode:Get()) --> Brush

This is a real use case of which I used when making a project. That’s the project I made this module for! Let me explain each line.

1: Make a new flag called CursorMode
3: Set the deactivated Tool stripe with the priority 1
4: Set the deactivated Tweaker stripe with the priority 2
5: Set the deactivated Error stripe with the priority 99
6: Set the deactivated Disabled stripe with the priority 100

They are disabled because their value is nil! They will be ignored when getting the value.

10: Set the Tool stripe to "Brush"

The result value is "Brush" because it has the highest priority at the moment.

14: Set the Disabled stripe to "Disabled"

Since the "Disabled" stripe has a higher priority, it will be the result value.

18: Deactivate the "Disabled" stripe.

The result value is back to Brush because the Disabled stripe was deactivated.


This makes getting the cursor mode value much more manageable. No more lengthy conditions checker what that value would be!

Too restricting? Get the stripe itself! It provides more information and could help sort your data. For example, I may not want to set the stripe’s value to it’s name. It could be hard to read.

CursorMode:Set("Tool", "Brush")

print(CursorMode:GetStripe().Name .. ":", CursorMode:GetStripe().Value) --> Tool: Brush

CursorMode:Set("Disabled", true)

print(CursorMode:GetStripe().Name .. ":", CursorMode:GetStripe().Value) --> Disabled: true

CursorMode:Set("Disabled", nil)

print(CursorMode:GetStripe().Name .. ":", CursorMode:GetStripe().Value) --> Tool: Brush

The name of the stripe may be important for you, so that’s why you can get it with the GetStripe method.

:warning: Heads Up

Setting the "Disabled" flag to false will keep it activated. Set it to nil to prevent this stripe from being the prioritized one.

API


Super.new()

Returns a new Flag object.

Flag:Set(name: string, x: any, priority: number?): Flag

Set a stripe’s value and priority.
name: The stripe’s name
x: The stripe’s value
priority: (number) The stripe’s priority
priority: (nil) Keep priority the same, or zero if none

Flag:SetPriority(name: string, priority: number?): Flag

Set a stripe’s priority.
name: The stripe’s name
priority: (number) The stripe’s priority
priority: (nil) Keep the priority the same, or zero if none

Flag:Get(gate: string?)

Get the flag’s result value.
gate: (string) Use a logic gate to get a boolean based on the active and unactive stripes
gate: (nil) Get the highest prioritized and activated stripe value

Flag:GetStripe(): Stripe?

Get the highest prioritized activated stripe.

Flag.Changed: Event

Fired once the topmost stripe has changed.

Conclusion


If you find any bugs, I will try and fix them! Just be sure to provide a reproduction script that causes the bug, and some context as well.

Any typos on this topic or in the code? That’s bad! DM about those so I can fix them.

No, I’m not uploading this to GitHub or ‘Wally’. I don’t understand them!

I hope you can find this useful!

:+1:

5 Likes