This week was largely about planning for the Node Action System. The nuts and bolts of it. Planning actually tends to be the most agitating parts of this project. The simple reality is that just stopping and making sure everything makes sense together can feel like a waste of time in a project that isn’t moving fast enough. In addition to that, having no other programmers around to bounce ideas off of makes the process take significantly longer. If there’s a single department where I feel the limitations of working solo hurt the most, it’s the planning. You just don’t get the wider perspective, or a second check for blind spots. Let’s take a look at how the planning thought process went.
We already know what Node Actions are: a list of actions the player chooses from when ending their turn on a node. We already know that they can come from the node itself, sub-nodes, and quest objectives. The question remained, what systems actually handle executing them. It just so happened that we have a system built entirely around executing an arbitrary number of actions with the capacity to freely branch as needed in the quest system. So sure enough, just run the relevant quest when a player selects an action. If it’s created by a quest objective, then it needs to merely mark that objective as a success.
While the quest system can do many things, counting the number of times it has been ran wasn’t really one of them. So elements like having an action only usable a finite number of times, or only usable every so many turns was best pushed into the NodeAction system itself. Through this process of considering “what can a NodeAction do?”, a new idea was born for passive NodeActions. Essentially sub-nodes that have a chance of occurring instead of the action the player selected. This allows for the idea of potential “traps” that can trigger when selecting actions on certain tiles to create a sense of risk in using certain nodes, as well as potential rewards for investing actions heavily on a given node.
With the NodeAction system fairly fleshed out, it came time to consider the consequences. Nodes, sub-nodes needed to be defined with what actions they bring to the table. When defining nodes a question arose: how does the generator know where to put these things? A pretty simple system came out of that: GenerationConstraints. Essentially each node would have a list of GenerationConstraints that specify where they could and could not be placed. GenerationConstraints come in a variety of flavors: stock constraints specify that only so many of a node type can be generated in each section (only one healing fountain per rank), distance constraints specify that nodes can only be generated when so far or so close from another node type (don’t put the healing fountain too close to town), etc. This system doesn’t quite solve everything since Warp, Blockade, Dungeon nodes and so on require very specific positioning in the world, but they’re easily enough hard coded into the terrain generation where they belong since they’re primarily part of the layout.
The last bit of consequences stem from the fact that the quest system now needs to be able to interact with the new node systems. You might want a quest to spawn a new subnode as a reward, decimate some forest nodes for the villain to make a point, and so forth. Nothing particularly interesting about the process though, just outlining the required new actions and how they work.
Most of the planning is complete, so we’ll see how the actual execution goes next week.
———————————————-
A nice little problem fell out of this planning: turn order. It’s a hot topic in board games, with authors adding all sorts of systems to try to mitigate first or last player advantages: shuffling turn order, letting players purchase a sooner order with various mechanics, giving certain advantages on last turns to mitigate first turn advantages, and so on. The problem arises here with node actions that have a timer before they can be used again. The natural inclination is to set such a timer to however many rounds- rounds being a full cycle of player turns. But doing so makes it so that the timer always refreshes on the turn of the player who last used it- making it trivial for them to “camp” an action. There’s a few possible solutions to this: Make it so that the timer ends exactly one turn after the player who used it last (but that’s kind of abusive), make the timer specific to each player (but that removes player interaction), don’t care and inherently give an advantage to “the first player who uses it”, and probably many others. I haven’t really decided yet. Will probably just experiment with them in action as the game progresses.