How to handle Status/Effects on a Turn-Base Game

Hello , Recently I have been struggling for 3 days to find a way on how to handle the status/efffects for my game :sweat_smile: ( i know it seems silly )

I have managed to create a state machine for my game core , like on turn start , on turn end , and another one. Now lets talk about effect/status
For Generic effects susch boosting stats for certain number of turns are eazy to handle and i dont have any problem with, but for effects/status (such as stun that should not allow you to play turn , or thorns that should reflect 20% of the damage to the opponet , BattleCry effect that increase your damage for 20%during attack, and cloack effecti that makes you untargetable) How do you handle it? i want to hardcode as mininmum as i can, i was planning to use state machine but i don’t think they are enough here.

So in short , if you’d please:
Give me some ideas on state machines that could help me such as onattack and so on
how to hoandle special effect/status

ScriptableObject usage in RPGs:

Usage as a shared common data container:

Here’s more goodies about coding up a combat system:

before i dive into this i actually have a confession, im not using this language but anotherone called lua if you knoww it, just want to confirm, is this what turn base gamme devs mostly use?

I mean C# is the scripting language of Unity. So unless you’re using something to integrate Lua into Unity, then you can only use C#.

Unless you’re not using Unity?

This may not be as straightforward as it seems. Imagine a character with an attack value of 10. You apply a RaiseAttack effect that increases this value by 2 for a few turns, and a BattleCry effect that increases it by 20%.

You need to decide the order in which modifiers are calculated, because this not only affects the final value but also determines what happens when an effect ends and its modifier is removed.

For example:

  • If you apply RaiseAttack first and then BattleCry, the result is:
    (10+2)×1.2=14.4 attack.
  • If you reverse the order, the result is:
    (10×1.2)+2=14 attack.

Having different values for the same effects depending on the order they’re applied can be very confusing. This becomes even more problematic if the effects come from equipping items. In that case, players might feel forced to unequip everything, then re-equip items one by one, just to find the order that gives the best result.

The same issue arises when effects are removed. In the first example, if RaiseAttack ends and you subtract 2, the calculation would give:
14.4 – 2 = 12.4 attack.
But the correct result should be 12, because the only remaining modifier is BattleCry, which gives a 20% boost to the base 10.

There are also nuances around how percentage modifiers are defined. Should they be applied to the current modified value or the original base value? For instance, a character with a speed of 10 slowed by 50% would have a speed of 5. If another effect applies an additional 50% slow, does the final speed become 0 or 2.5?

To avoid confusion, check tutorials on flat, additive, and multiplicative modifiers, and consider applying modifiers in a predefined order that has been determined by the game design.

Also, for some links to tutorials and extra info, check the topic here:
https://discussions.unity.com/t/stats-modifier-system/1556874

im using another game engine
but dont worry i can translate it from c# into lua since i havee heard lua camee from c#
why asked here,well because the engine im useing its developper discussion website is not thag helpful

Right, but depending on the architecture of the engine you’re using, a lot of our suggestions might be entirely useless, such as Kurt’s suggestion of scriptable objects.

about ordering i think the player can choose it depending on what buffs he chose,when a buff is applied i was planing on storing the added/subtracted amount whether raw or percentage then when the effect ends , it will remove that stored effect with its amount being callculated laater

would u give me a quick example please about this approach with an example of effects please,jusst to get the idea

Why would I give an example using scriptable objects when it might be not applicable in the engine you’re using?

trust me give itin ur programming langiage and i can translare it , i have just tested it wih gpt and it worked

It’s not just about the programming language. Scriptable Objects are a feature specific to the Unity game engine. Effectively custom assets you can write, make instances of, and author said data of.

Then plenty of other aspects we might write in a hypothetical example that will also depend on Unity’s component system.

You’ve not said what engine you’re using. All our examples would be based in how the Unity engine works and might be completely useless in whatever engine you’re using.

I kind of like using behavior trees. Unity has Behavior graphs but there are other alternatives if you’re using lua.

So as an example, every time I apply an effect I might create a new Effect instance that contains a blackboard and list of behavior trees (grouped effects like poison and burn for 3 turns). Then add this to a list of effects for that character. I’d give each effect it’s own blackboard since the data can be specific for the effect e.g. apply poison damage for 3 turns and allow offset poison stacking. This way the graph can handle:

  • Trigger/End conditions: apply poison for 3 turns, next attack does double damage, next time attacked reflect damage once, on cure remove poison.
  • Effects: on turn apply poison damage, add green effect to character if any poison effect is active.
  • Conditions: there is a 50% chance of reflecting damage.
  • Flow / time control: thorns effect active, on attacked: play thorn particles, make attacker play hit by thorns animation, time delay, apply damage, play sound, play particles etc.
  • For any buffs I’d normally apply them to multiplier and addition totals.

I think ultimately it comes down to providing the right hooks so different kinds of status effects all have what they need to work.

If you have a state machine to proceed the flow of a turn based game, then I might have a separate system that hook into procession of the turn and handles status effects; meaning all status effects are all handled by the one system rather than each character/entity separately.

Then you provide an interface:

public interface IStatusEffect
{
    void OnStatusApplied();
    
    void OnStatusRemoved();
    
    void OnStartTurn();
    
    void OnEndTurn();
}

And then have a system that these can be registered to, and calls the right methods at the right time.

Needless to say what the status effects do is a separate matter altogether, and you will likely need multiple other systems to make various types of effects and such work.

It depends on the game and status effects, I would argue that 95% of the “classic” status effects (like buffs, de-buffs, heal per turn, damage per turn, shields, etc) can be implemented as simple stat values which are changed by the status effect and implemented in some general “stat system” instead of adding a implementation for the status effects.

If you have more complex status effects like “deal 30% damage but only during full moon and if you are fighting against 3+ rats” then it’s a different story, but a “deal 10% more physical damage” or “deal 3 dmg per turn” is a simple stat value.

well for now i only have 3 states that control the flow of the battle , but im struggling on what states should i create for the game action , for example i was thinking on using onattack,ondefense , but then i realised that this feels more like hardcoding, because imagine if the player doesnt attack but heal insteas

from what i have understood, what u suggested to me is a way to handle the functions of an effect thaat are under the player, i aam not actually struggling here, but on how to do that function, like i said do i use hooks/states or what

I think for status effects you care less about the actual stages of the turn, but instead the procession of stages throughout the turn. You care about when the turn starts or ends. You care about when a character attacks, or is attacked. And so on and so forth.

That’s what I mean about creating the necessary hooks, so that other systems can hook into the turn sequence and simply do their thing when the time comes around. To be literal, I’m referring to using delegates/events that you subscribe to, or interfaces in C#'s case, that objects can implement and register themselves under.

these processions of the stage , what are they called? for this reply i will use states because i truly don’t know what i should call thel

like i said i was thinking of useing the onattack, attackedplayer satetes untill i realised that i will end up hardcoing some states , for example when a player heals himself/his teamates , do i make a state out of it like the onheal, what about recieving a buff/fdebuff , thats where im stuck , if you could only please help me with this using an example of unity’s language i’d truly apperciate it , :smiley:

What I’m saying is you care more about when the stages of a turn change, often not what the stages actually are. In some cases you will care about particular stages, but that’s also a simple hook to create.

I don’t think a state machine is a very good idea for a turn-based game to be honest. Unless you’re designing something whacky, turn-based-games have a loop of predictable stages, all of which can be abstracted as such that you don’t need to design a “state” for every action in the game. Or for something like Baulder’s Gate 3 (aka DnD), it’s more of a queue.

There was discussion about this a little while ago, so there’s code examples here: Best Practices to organize multiple processes in game flow (Actions, Inputs and Dialogue) - #2 by spiney199

Later on I posted an example of how you might do a state machine for a turn based game: Best Practices to organize multiple processes in game flow (Actions, Inputs and Dialogue) - #6 by spiney199

Even then you still want the stages to be abstracted in such a way that you aren’t coding every stage down to the minutia.

Your confusion about how to travel down this path should make it clear to you that this isn’t the best approach to take.

You don’t need to make states for each action. They are simply that actions. When the player heals themselves or an ally, you just need to do said action, and then provide the means for other things to be listening for that kind of event.