(In the below, read "is" as "should be IMO".

)
An effect is any kind of modification on a character's state (where "state" is the collection of "game-play values", such as stats, resistances, etc.). This can include setting an "active skill" flag on a character, such as "this character is currently affected by sanctuary" This modification can be transient (i.e., will expire after an event or timed delay) or permanent (i.e., doesn't go away normally). In other words, an effect is anything that modifies (affects) a character's normal state.
There are several ways of representing this in code. The straightforward "object oriented" way is to have some kind of generic effect that doesn't actually do anything, but that notes when it times out, perhaps where it comes from (e.g., which character or object is responsible for this effect?), etc., basically all things common to all effects. Then you specialize this effect into categories:
- effects that add to stats (str, con, ...), resistances, HP, mana, ...
- effects that add skill numbers
- effects that enable skills (...?)
and so on.
It must be decided if effect, err, effects are 'cached'. SMAUG takes the approach that when you apply an effect to a character, it goes and modifies actual values, such that if the effect is not removed completely properly, you can end up with a "lingering" effect whose state changes persist even though the effect itself is gone. This is Very Bad.
Another approach is to separate base values from modifier values, and to perhaps cache the modifier values so that you don't need to recompute them every time you ask for the character's strength, but to recompute them occasionally e.g. on character load, save, etc. In this way, you get the efficiency gains, but you ensure that your character's base values are stable. This is Much Better, because a bug in your effects code will not permanently mess up characters.
If you cache things, you need to have methods that are called when an effect is added to and removed from a character. (If we wanted to get fancy, these could also act on objects -- and maybe even entire rooms! -- but that would require more object orientation in the general codebase.)
If you don't cache things, you need to figure out how to get the values one way or another, which would mean tagging effects with enough data that the CHAR_DATA methods would know how to extract the appropriate data.
FWIW, I think that a good approach is to cache things on separate variables, such that the base variables stay "safe". Then, when you ask for a character's current value for X, you return
base_X + modifiers_X.
--
Using an architecture where an effect is basically just a modification of state, a whole lot of things can be represented very generically. For example, racial effects can be stored as any old effects, with no expiration and perhaps a "permanent" flag set (so that they can't be canceled by dispels, for instance). Any thing that modifies game-play values can be represented the same way.
.........................
David Haley
Head Coder, Legends of the Darkstone
BabbleMUD Project
http://david.the-haleys.org