Let's talk Statistics

Let's talk Statistics
Custom Stat System for my currently Untitled RPG Game

Well it took some time and head scratching, but I think I have the Stat System down. I've broken it down into 3 classes:

  • ActorStats - A resource object that houses all base stat values. Like most use cases for Resource objects, class is simply a re-usable data container. It make adding base stats to all Actors (Player, NPCs, Monsters etc) easy. Its usability will also be quite a benefit when introducing a class system.
  • StatModifer - Another resource object. This one contains a few exported enums that will match up with the enums in StatsComponent which I'll talk about next. This lets you state what Stat is being modified, the modification type (FLAT_TO_BASE, PERCENT_TO_TOTAL, etc.) as well as the value. I've also included an _init() function so that you can also generate modifiers via code, and not just in the editor. This is useful for things like the Dash State for the player, allowing you to add a speed modifier while dashing all through code.
  • StatsComponent - The final part of the puzzle, this is the Component object you'll add to the player, NPCs, Monsters etc. It has an exported ActorStats variable and that's all the setup needed when adding stats to a Actor. The component does the rest. It is responsible for keeping a reference to the ActorStats to know the base values, a Dictionary that keeps record of all the modifiers for all the stats, and some handy helper functions for calculating current stat values, while also factoring Core stat benefits. ie: Strength adds Physical Attack.

This all sounds great, but how does it work in practice? Well it's quite simple. The ActorStats never gets modified at runtime, meaning you always have these values stored for base values and your starting point. Then at runtime anytime a modifier is added or removed to the StatComponent's Dictionary a Signal gets emitted, letting any listeners know "Hey! It's time to update your values!" those listeners then request the most recent stats values from the StatComponent and everything is smooth sailing. It some Stat systems people like to let the modifiers container also keep track of things like timers etc for Buff systems, however, I like to keep the responsibility on that of the source of the modifier. When storing a modifier, StatsComponent also keeps track of the source of that modifier, the Node that added it. This way, when I implement the Boons or Buffs Component, it will be responsible for maintaining all its own timers, then when timers run out, it can tell the StatsComponent, "Hey, times up, remove this modifier." or alternatively it could also say "Hey, you know what? Remove all modifiers I'm responsible for." as I have functions implemented for both, and is easy to handle since it keeps track of the sources.

Subscribe to IndieGameDad

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe