I have made a movement system in my game that works on priority so that things like stun will override things like a movement debuff from using an ability as it is of more importance. I use string values and int values to do this. Here is the folder :
It is a bit complex but here is the script if you want to see how it works :
--This script controls the mobility of each individual player
local char = script.Parent.Parent.Parent
local Humanoid = char:WaitForChild("Humanoid")
local Default = script.Parent.CurrentValues
local NewValues = script.Parent.NewValues
local Tier = script.Parent.ChangeID.Tier
local ID = script.Parent.ChangeID.ID
local Timers = script.Parent.Timers
--Setup of the timers
for _,timer in pairs(Timers:GetChildren()) do
local TierTable = {}
--Detects when the timer changes
timer.Changed:Connect(function(WaitTime)
--Resets the timer so a new one can start
timer.Value = 0
--Ensures the change is not a reset
if WaitTime ~= 0 then
-------------------------------------------------------------------------------------------
local NewValue = NewValues:FindFirstChild(timer.Name).Value
NewValues:FindFirstChild(timer.Name).Value = 0
local ChangeTier = Tier.Value
-------------------------------------------------------------------------------------------
--Checks if the WaitTime is Undefined(Not a set wait time)
if WaitTime ~= -1 then
-------------------------------------------------------------------------------------------
local ContinueRunning = true
local connection
connection = timer.Changed:Connect(function(newTime)
if ChangeTier == Tier.Value then
ContinueRunning = false
for i,v in pairs(TierTable) do
if v == ChangeTier then
table.remove(TierTable,i)
break
end
end
connection:Disconnect()
end
end)
--Spawns a thread with the WaitTime
spawn(function()
task.wait(WaitTime/1000)
ContinueRunning = false
--Removes the Timer from the Table of Timers
for i,v in pairs(TierTable) do
if v == ChangeTier then
table.remove(TierTable,i)
break
end
end
--Resets Movement to default in the event that no other timers are running.
if #TierTable == 0 then
if timer.Name == "WalkSpeed" then
Humanoid.WalkSpeed = Default.CurrentSpeed.Value
else
Humanoid.JumpPower = Default.CurrentJump.Value
end
end
end)
-------------------------------------------------------------------------------------------
--Inserts the timer into the Table of Timers
table.insert(TierTable,1,ChangeTier)
--A loop that continuously changes the Walkspeed/JumpPower for the duration of the timer
while true do
--Breaks the loop at the end of the timer
if not ContinueRunning then
break
end
local pause = false
--Pauses the loop if there is a active timer with a higher priority
if table.maxn(TierTable) > ChangeTier then
pause = true
else
pause = false
end
--Changes the WalkSpeed/JumpPower
if not pause then
if timer.Name == "WalkSpeed" then
Humanoid.WalkSpeed = NewValue
else
Humanoid.JumpPower = NewValue
end
end
wait(0.1)
end
-------------------------------------------------------------------------------------------
else --Runs a never ending timer until stopped
-------------------------------------------------------------------------------------------
table.insert(TierTable,1,ChangeTier)
local Identity = ID.Value
local continueRunning = true
local Connection
-------------------------------------------------------------------------------------------
--Detects when the placeholder is destroyed
Connection = timer.AttributeChanged:Connect(function()
if timer:GetAttribute("Reset") == Identity then
Connection:Disconnect()
timer:SetAttribute("Reset",nil)
continueRunning = false
--Removes the Timer from the Table of Timers
for i,v in pairs(TierTable) do
if v == ChangeTier then
table.remove(TierTable,i)
break
end
end
--Resets the WalkSpeed/JumpPower in the event that there are no running timers
if #TierTable == 0 then
if timer.Name == "WalkSpeed" then
Humanoid.WalkSpeed = Default.CurrentSpeed.Value
else
Humanoid.JumpPower = Default.CurrentJump.Value
end
end
else
timer:SetAttribute("Reset",nil)
end
end)
-------------------------------------------------------------------------------------------
while true do
--Terminates the loop
if not continueRunning then
break
end
local pause = false
--Pauses the loop if there are any running timers of a higher priority
if table.maxn(TierTable) > ChangeTier then
pause = true
else
pause = false
end
--Changes the WalkSpeed/JumpPower
if not pause then
if timer.Name == "WalkSpeed" then
Humanoid.WalkSpeed = NewValue
else
Humanoid.JumpPower = NewValue
end
end
wait(0.1)
end
-------------------------------------------------------------------------------------------
end
end
end)
end
I am just worried that using value objects appose to something like a module script might break the code if new timers keep getting added in quick succession. Thing is since I need to detect a change within a change to see if a timer must be stopped which is difficult to do since there is no event that I know of to detect if a function within a module is called, correct me if I am wrong.
Here is an example of how I would use it:
MovementPriority.Value = 1
MovementID.Value = "Age"
NewMovement.WalkSpeed.Value = 5
MovementTimers.WalkSpeed.Value = -1