





🌟 Special thanks to our amazing supporters:
✨ $10 Tier: [Geeks Love Detail]
🌈 $5 Tier: [Arch Toasty][Benedikt][David Martínez Martí]
Hi all! Im back with a story about how we improved the undo functionality. To give a bit of background, the skirmish portion of our game is implemented so it can be simulated in advance of actually using an ability. Every time the hit tile changes, we make a copy of the relevant game state, and run the whole game logic through it, with some flags set to make the end result usable for other things. The output of that process is a list of actions that change the original state to essentially match the simulated one. The original reason why we did it this way was that we wanted to have a spell like revert time which would play the last sequence of actions in reverse. This obviously never went in because of lack of time and some additional tech issues, but the general infrastructure is still proving to be useful. Since we have a copy of the game state with all the changes an action would do, we can query differences between the original and the cloned state. This is how we implemented exact previews of how much health a unit would lose and whether it would die from the hit, where a unit would get pushed or pulled to, which covers would get destroyed, etc. The only way this can work consistently is if all relevant objects are referenced with an equivalent ID. Since the codebase is in C++, the option of pointers is there, but is not useful because theres no easy way to translate/map pointers to between two copies of an object that are considered equivalent or the same. Thus, we use handles. Pretty much every important thing is mostly referenced to with its handle, which is in practical terms just an index into an array. Each thing would be an element in an array, and if we ever needed to destroy the thing, we would just mark the slot as no longer in use. This means we could reuse slots when, say, status effects expired and a new one got created, it would just be placed into the same slot as an expired one. This was the main issue with the system to prevent full undo functionality. Undoing a sequence of actions where one status effect expired and another one got created in the previous ones slot means information loss. There is no easy way to restore the information about the previous status effect in that slot because the new one overwrote that information. This is why creating and destroying things in those arrays wasnt able to be undone. The change we did was to no longer reuse slots. Each thing that gets created has its own slot which is forever owned by that thing and nothing else. When a status effect expires, its slot is marked as retired, but the information it had is still there, untouched. If we wanted to revert/undo the expiration of that effect, wed just undo the retire operation on that slot and thats it, the thing is back just as it was before. Ofcourse, each action has a set of micro operations that need to happen to fully restore the state back to where it was. A status effect tracks the units its affecting, the units which are considered the affector of that effect, both types of units also track which status effect is affecting them and which effects they caused, the creation and removal of status effects can cause unit attributes to change, etc. Each change to any of these things is a micro operation that has to be fully revertable for the system to work properly. To prevent everything to actually be undoable, abilities will define whether their use can be undone or not. All position changing abilities are currently undoable (Run, Sprint and upgrades, Translocation, and a relic or two). And the whole point of this was to fix Tariq from being unable to undo his Run ability use, because his passive effect is implemented as an aura that has a feedback loop with the status effects created on enemies to increase Tariqs power. And there you have it. A sneak peek of how we do stuff with code! If you want to ask questions or comment on something you read, you can find us on our Discord server. Cheers! MarkoP
[ 6075 ]
[ 1294 ]
[ 4061 ]