Conflicting Status Effects

I have a system that I fear might not work so well.

Basically, let’s say I inflict a player with Slowness that lowers the affected player’s walkspeed by 25%, but then they get inflicted with Stunned Ⅰ, which lowers the affected player’s walkspeed by 75%.

When the status effect completes its lifetime, it’ll revert the changes back to the original walkspeed that it saves before the effect happens. This means Stunned Ⅰ conflicts with Slowness, and I’m guessing once Stunned Ⅰ ends, it’ll save the affected walkspeed that was caused by Slowness.

Slowness Code

local Target = script.Parent.Target
local Activated = script.Parent.Activated

local SavedWP = 0
local SavedSS = 0

function Effect()
	local char = Target.Value
	local Humanoid = char:FindFirstChildWhichIsA("Humanoid")
	
	local WalkSpeed = char:GetAttribute("WalkSpeed")
	local SprintSpeed = char:GetAttribute("SprintSpeed")
	
	SavedWP = WalkSpeed
	SavedSS = SprintSpeed
	
	local AffectedSS = (SprintSpeed - (SprintSpeed * .25))
	local AffectedWS = (WalkSpeed - (WalkSpeed * .25))
	
	char:SetAttribute("WalkSpeed",AffectedWS)
	char:SetAttribute("SprintSpeed",AffectedSS)
end

function RevertChanges()
	local char = Target.Value
	local WalkSpeed = char:GetAttribute("WalkSpeed")
	local SprintSpeed = char:GetAttribute("SprintSpeed")
	local Humanoid = char:FindFirstChildWhichIsA("Humanoid")
	
	char:SetAttribute("WalkSpeed",SavedWP)
	char:SetAttribute("SprintSpeed",SavedSS)
end

function ActivatedCheck()
	if Activated.Value == true then
		Effect()
	elseif Activated.Value == false then
		RevertChanges()
	end
end

Activated:GetPropertyChangedSignal("Value"):Connect(ActivatedCheck)

Stunned Ⅰ Code

local Target = script.Parent.Target
local Activated = script.Parent.Activated

local SavedWP = 0
local SavedSS = 0

function Effect()
	local char = Target.Value
	local Humanoid = char:FindFirstChildWhichIsA("Humanoid")
	
	local WalkSpeed = char:GetAttribute("WalkSpeed")
	local SprintSpeed = char:GetAttribute("SprintSpeed")
	
	SavedWP = WalkSpeed
	SavedSS = SprintSpeed
	
	local AffectedSS = (SprintSpeed - (SprintSpeed * .75))
	local AffectedWS = (WalkSpeed - (WalkSpeed * .75))
	
	char:SetAttribute("WalkSpeed",AffectedWS)
	char:SetAttribute("SprintSpeed",AffectedSS)
end

function RevertChanges()
	local char = Target.Value
	local WalkSpeed = char:GetAttribute("WalkSpeed")
	local SprintSpeed = char:GetAttribute("SprintSpeed")
	local Humanoid = char:FindFirstChildWhichIsA("Humanoid")
	
	char:SetAttribute("WalkSpeed",SavedWP)
	char:SetAttribute("SprintSpeed",SavedSS)
end

function ActivatedCheck()
	if Activated.Value == true then
		Effect()
	elseif Activated.Value == false then
		RevertChanges()
	end
end

Activated:GetPropertyChangedSignal("Value"):Connect(ActivatedCheck)

If you guys got any ideas or suggestions to help prevent that issue from happening.

Have your effects apply themselves in reverse when they finish.
Like if their walkspeed is 16 by defualt then when slowness is applied it’s
16 * .75 = 12
Then when stunned is applied while they’re slowed it would be
12 * .25 = 3

And then whenever one of the statuses goes away apply it in reverse and no matter of the order you would end up with 16.
3 / .25 / .75 = 16
3 / .75 / .25 = 16

2 Likes

What’s a good way to format this idea for my game? Because there are different levels of Slowness that can affect the player, the affected value won’t be consistent.

There’s lots of different ways, I would store your definitions with the information on how to apply the status effects and how to remove them.
Because sometimes this may be affecting stats, sometimes it may just be adding/removing a tag that other things look for.
For one of min it looks like:

{
			Count = 2,
			Description = "10% Increase",
			Forward = function(Unit) 
				Unit.UnitStats.Damage.Value *= 1.1
			end,
			Reverse = function(Unit)
				Unit.UnitStats.Damage.Value *=  (1/1.1)
			end,
		},
		{
			Count = 4,
			Description = "20% Increase",
			Forward = function(Unit) 
				Unit.UnitStats.Damage.Value *= 1.2
			end,
			Reverse = function(Unit)
				Unit.UnitStats.Damage.Value *=  (1/1.2)
			end,
		},

You should save it as a variable better to not save the walk speed before the effect

Conflict resolution is the answer here. Each effect you apply should be stored somewhere and read from in a heartbeat loop or one some custom EffectsChanged event, and the values should be unified to create a valid walkspeed that considers both effects