System: My game uses an "ECS + event queue" architecture where every tick, various events change the state of JSON-able data. Plain JS objects.
Problem: I want to be able to save the game-state as JSON, and there is one place where I run into an issue: multi-turn actions. For example, the player has an "intent" array that stores the next few stages:
// pseudocode:
let player = {
health: 5,
damage: 2,
actor: true,
intent: [ () => wait(), () => wait(), () => uniqueContextualStatefulAction()],
}
(...)
every tick
for every actor with intent:
execute and remove entity.intent[0]()
If all actions took a single "turn" or tick, there would be no problem, as intent would be cleared. But every tick, the function (callback?) of every actor is called (with some more complexity on the side). These callbacks are often unique and contextual, for example waiting for 5 turns, then crafting a custom item out of two others, then deleting the ingredients, all modified by status effects at the time of execution (rather than creation).
My question is as such. What is an "ECS-friendly", save-game-friendly, and sanity-friendly way to handle this system? At the extreme, storing every instance of every function and its arguments as strings, but I really don't... want to?
There's gotta be a better way. This is also deterring me from advancing the game systems, and I tend to go into over-engineering to avoid this problem.
Side-note: I am open to suggestions about changing some of the architecture altogether, since I can't imagine how to do this in other architectures either. Thank you!
An example of actual in-game code:
function createWait(ticks) {
return {
effect: () => {},
duration: ticks,
pause: timing.msPerTick,
}
}
player.addPattern({
durations: [
{ baseName: "1 tick", dur: 1 },
{ baseName: "3 ticks", dur: 3 },
{ baseName: "6 ticks", dur: 6 },
{ baseName: "12 ticks", dur: 12 },
{ baseName: "60 ticks", dur: 60 },
],
intents: function() {
let intents = [];
for (let duration of this.durations) {
function effect() {
newLine(`You wait ${duration.baseName}`)
}
intents.push({
representation: [game.word("wait"), game.word(duration.baseName)],
sequence: [{ effect }, createWait(duration.dur)]
});
}
return intents;
}
});
```