Building a flexible attribute system can be a challenging task, but the first step is always understanding what it is that you want the system to accomplish. I had already cobbled together a system for health, hunger, energy and mood, but it lacked ability for colonist attribute effects.
I wanted to be able to tack on effects like sickness that might temporarily effect health and mood temporarily until the effect goes away. I wanted a flexible system that would allow me to quickly tack on new effects without having to tie it in to the underlying values each time. I often confuse design problems for programming problems, but I think I have a good infrastructure for colonist attributes.
This really depends on the project, but I originally thought things like health, hunger and energy were attributes. This was true in a general sense, but lacked the detail I needed for adding attribute effects. Hunger, for instance, is actually three different attributes relating to its current value, max value and rate of change over time. Dealing with these values separately allows for them to be effected separately as well. An attribute is simply just a means of storing and manipulating a value via attached effects.
Health, hunger and energy become containers for attributes and each attribute has a list of effects that manipulate the underlying value. The colonist, via the component system, has Attribute Controller components attached. Each controller has a list of attributes that it monitors and each attribute has a list of attribute effectors that effect the final output value of the given attribute.
The attribute controller monitors its attributes and can make decisions about what to do under different circumstances. For instance health is simply current and maximum attributes and the health controller can let the colonist know that when the current value is 0 then the colonist should be dead. The attribute controller is both the container and what gives the attributes meaning.
Each attribute has a unique identifier and a list of attribute effects. We can get the final value of the attribute by adding/multiplying the effect values to the base value of the attribute. The attribute controller can then get this final value and never needs to know about what effects are currently being applied to it.
Attribute effects have a single attribute that it effects and can be permanent or temporary.
The above image illustrates the HungerController and its attributes. The HungerController uses the attributes to clamp the hunger_current to the hunger_max and allow hunger_rate to effect the hunger_current value. The hunger_rate, by default, is a negative value which decreases hunger at a fixed rate over time.
In this example I’ve attached an attribute effect which temporarily turns hunger_rate in to a positive number which will refill hunger_current. This attribute effect would get applied when the colonist eats some food.
I’m pretty happy, so far, with the result of the attribute system as it allows the easy creation of new attributes and effects. As with most everything else attributes and attribute effects are created in external XML files so that I can add new content without touching the code base. The only thing I can see adding at this point would be some sort of attribute effect group that would allow multiple attribute effects to be applied all at once.