Creating state-based combat frameworks

I know this topic has probably been talked about to death, but how would you handle a basic combat system that fluctuates between an actioning, stunned, and blocking state?

A big question that comes to mind when asking this is the handling durations of each state. Would I create a new ‘timer thread’ each time I need to cast a timed state on to a player (like stunning a player for 5 seconds) or is there a better approach that comes to mind that isn’t so reliant on these threads?

attributes. task.spawn. case closed. goodnight

I always saw attributes as slow to get and set, and for using new threads to handle the durations; wouldn’t the server have issues performance wise with handling around 30 of them concurrently? Assuming that they’re constantly checking the state attribute of the player and the rate at which the while loop waits for.

Attributes are much faster. I don’t know where you are getting this info from.

And plus instead of looping through them all, just use humanoid.attributechanged.

Attributes (and even worse, NumberValues and others) are slower than pure lua (either module script or a table). The performance of Attributes is far from problematic, you really have to abuse them for it to be an issue, but it still quite a bit slower than keeping the information in a module script

I’m saying for easy global values.

Im more of comparing it to number values, in which attributes are far superior.

This is true, if you wanted to make a module that handled these values, it would be very efficient.

1 Like

Isn’t getting and setting a value in a table a lot faster than setting an attribute on an object? Also, I don’t know what you mean by “looping through them all”. I was referring to a loop the ‘timer thread’ would check the player’s state after a wait interval has been passed in order to update the player with the state’s conditions (i.e. if the player was stunned, every interval of this loop would probably change the characters walkspeed and jumppower to a slower value). If the player’s state is changed, this loop would break, and the function responsible for changing the state would cancel the past ‘timer thread’.

Edit: The update would also be responsible for incrementally lowering the “stun time” or “action time” in that given thread, and the thread would check to see if this time is zero or the action has been changed which would then break this timer thread.

If you know, Then why did you make this post? Cause we are giving you options, just for you to object.

I made this post because I want to refine my approach and help anyone who is going through a similar issue. If someone has their own two cents on the topic, I’d like to consider it.

Quick benchmark as throwing statements around without supporting them isn’t very satisfactory:

image
image
This is 10k iterations, so the performance of Attributes is still far from being an issue if you don’t fall into insanity. The difference in performance is quite staggering though

I tend to prefer ModuleScripts rather than attributes as I also get autocomplete and more customization of how I want my system to work

2 Likes

That is pretty interesting stuff. I’ll definitely stick to the modulated approach because I do intend on adding attacking NPCs and stuff of that nature

You could try playing with threads like this,

local thread = task.delay(5, function()
	-- Update stats after 5 seconds
end)

-- Stuff happens, and the state changes again

if coroutine.status(thread) ~= "dead" then 
	task.cancel(thread)
end

-- Overwrite with a new function
local thread = task.delay(3, function()
	-- Update stats after 3 seconds
end)

This is just an example, and a flawed one at that, if you use threads like this, I’d suggest making a update state function that cancels the previous thread if it’s still suspended, and replaces the old thread variable with the new one, so the cycle can start over again with more thread cancelling and stuff

2 Likes

Yea by far I think this is the best conceptual implementation I’ve seen for making something like this. I’ve thought about benchmarking the states and activating enlisting an ‘update’ function that would check to see if its time was up but at the end of the day its just doing the same thing. Thank you for your perspective.

1 Like