Apologies @Chris_v for the snark. I did not understand your tone to be sarcastic in the initial post. Regardless, it was unwarranted and I apologize.
My original comment stands. You have not given enough information for me to provide you with much advice.
- What do you consider a status effect system?
- What performance issues are you most worried about? Execution speed or RAM usage?
- What devices are you targeting? Windows? Mobile Devices? Low-End Mobile Devices?
But here’s some thoughts. RefCounted does not save you much of anything performance-wise. I don’t recommend using it unless you have a very specific need that it solves, or you feel it would help during optimization. In other words, don’t start there.
Resources are good for things you will change a lot during development, or you want the player to change in-game and you want to save those changes to disk.
Godot uses inheritance and composition together. If you can use Nodes, then it’s pretty easy to drop them on and off a character and make things modular.
Ultimately it comes down to your design philosophy. I would not use a SatusEffectManager for example. If I was, I would name it StatusEffects. There was a talk a number of years ago at a C++ conference about how using “Manager” in everything tends to cause us to be lazy in naming things. I have embraced that approach.
However, in this case, that’s not why I wouldn’t use it. It’s because I would create a base StatusEffect node inherited from Node. Then for each status effect I had, I would inherit StatusEffect, so like, StatusEffectBurning would know everything about shaders, damage taken, etc.
Then a Character (Players/NPCs/Enemies) would look through it’s children nodes, find any of type StatusEffect, call their apply() method, passing in a reference to themselves. This would encapsulate areas of responsibility. The Character doesn’t need to know what the individual effects do, and the StatusEffect doesn’t need to care who it is affecting.
If you want to add a new StatusEffect, you just make a new inherited Node.
What I don’t know is if this is where I would end up leaving it. I’ve not yet made a game where I would want to save status effects. I.E. Allow someone to save a game in the middle of a battle or what have you. In that case, I might later refactor my code for saving. Maybe. That would involve changing StatusEffect from inheriting Node to inheriting Resource Then the application of status effects would have to change from a node-based approach, to storing the effects in an array on the Character.
The benefit of this system is that from a RAM perspective, no code will ever get run that doesn’t need to. There will be a lot less conditionals and therefore slightly faster code execution and a smaller memory footprint. The drawback to this system would be that in a bullet hell game, memory would be bloated by these nodes. In which case I’d probably store all statuses in a single int and use bitmasks to pull them out and apply them. Then a StatusEffects autoload might be more performant. The tradeoff being that in my opinion, it’s harder to maintain and less flexible.