Advertisement

How to Handle Complex Side Effects and Event Sequencing in a Turn-Based Game Like XCOM?

Started by February 05, 2025 04:30 PM
4 comments, last by MagForceSeven 1 week, 3 days ago

I'm trying to make a turn-based game like XCOM, and I've run into an architectural problem that I haven't been able to solve for quite a long time.

In my game, logic is completely separated from animations - when something happens in the game world, for example, a unit is given a command to move, then all the effects of this action are calculated, and the corresponding animations are just queued for playback.

But I don't understand how to build logic architecture taking into account various side effects properly. The usual depth-first approach, when one effect simply causes another, and so on in a cascade, is not quite suitable.

For example, there is the following scenario:

  • a unit makes a shot (action points are deducted, ammo is subtracted, trajectory is calculated)

  • the shot hits an explosive barrel. its health drops to zero and it "dies"

  • the barrel triggers the "death rattle" effect, and it explodes

  • all units and objects around the barrel take damage

  • all tiles around the barrel are engulfed in flames

  • each affected unit loses morale

  • some units and objects die from the damage they take

  • one of the destroyed objects is another barrel, and it also triggers the "death rattle", which leads to a chain reaction

  • panicked units start to play out their panic actions in turn - escape, shoot, which can also lead to chain reactions

in this scenario, dealing damage does not immediately lead directly to the death of a unit, and its death does not directly lead to the "death rattle", they have some kind of delayed effect. and it seems to me that the system must work in a layered style - first all damage is dealt, then all deaths, then all death rattles, etc.

However, there is another scenario in which this logic should work differently:

  • a unit makes a series of shots (a machine gun burst)

  • each of the shots hits some target, this target is immediately damaged, its morale drops, and some of the victims go into the "dead" status.

  • when all the shots are finished, the remaining effects are played - death rattle, unit panic, chain reactions

It is important here that some of the effects should happen immediately after the bullet "hits", and some after all of the "hits" - this is necessary for the correct animation order:

  • projectile animation 1

  • damage animation

  • death animation

  • projectile animation 2

  • damage animation

  • death animation

  • death rattle 1

  • death rattle 2

  • panic 1

  • panic 2

  • etc.

this is fundamentally different from the example with the explosion earlier, because the explosion from the point of view of time happens at one moment, while the line of shots is already stretched out in time.

the rest of the effects should be played as usual - after all the hits. because it would be strange if during the line some unit panicked and ran away.

I understand how to hardcode such a system, but it will result in a very large amount of work, and it seems to me that there is a more elegant approach here, which I can’t get to.

Just from your description, it seams your problem is that ALL actions/animations are pre calculated in its entirety.

Would it not be more reliable to break the chain into discrete action points and review the current/next action according to what happened on the last loop?

You can still pre load everything as you are doing, if anything the result to what is working as you like will still be the same, but you get the chance to intervene mid way if necessary and add dynamism to chain of actions not easily predictable.

"No, you're never too old to rock and roll
If you're too young to die"

Advertisement

this is fundamentally different from the example with the explosion earlier, because the explosion from the point of view of time happens at one moment, while the line of shots is already stretched out in time.

I am not sure there is a fundamental difference. To me it seems all scenarios are chronologically ordered. The amount of time between cause and reaction may vary, but that's more about animation lengths than the decision what to show perhaps.

Maybe a tree of causes and reactions could work? A cause can have several reactions, which each can have several reactions which ….

If you want to take time into account, then all the connections in the tree between a cause and its effects may have varying length.

/Edit; Misread, please disregard that.

I will say it was a very hard problem. For XCom2 there was even an extensive refactor/rewrite of the ability visualizations for War of the Chosen. At the most basic level, each ability had a fixed tree of small, reusable, visualization building blocks (move camera, do flyover, etc) that defined how it would play out. So in your first example, TakeShot (which deals damage to the target), DeathRattle (which does all the damage and fire around the barrel), MoraleModifier, Panic, etc would all have their own visualization. Each one of these visualization trees would have places where other trees could be hooked up to it, so TakeShot would have a spot in the tree where “the damage is dealt” which would kick off another tree, be that DeathRattle, or a Muton's Rage, or what have you. XCom was built in such a way as all of the gameplay changes for an action were resolved entirely without the need to visualize. Then we'd use the gameplay changes to build the visualization, so by the time we were showing it we actually knew 100% what would happen. All the randomness had already played out. It was very complicated and you may notice that even in WOTC, complicated ability visualizations still sometimes don't play out very well.

Sometimes those spots could trigger multiple visualization trees, like when you want to show the damage to all the units in an AoE simultaneously. But sometimes you're doing something (like with cameras) and you just have to sort of pick an order to use the resource in a linear order even if it's not technically how it would play out in “reality”.

We made a lot of improvements for Marvel's Midnight Suns which took advantage of blueprints to nearly all the vis tree logic and then there was an overarching visualization manager that played them back to back. Again we had the advantage of the full gamestate had already been created and we were just replaying what was already determined to have happened.

--Russell Aasland
--Principal Engineer
--Midsummer Studios

Advertisement