Well, You must have already headed to bed, so I'll attempt to formulate my incohesive thoughts into a cohesive mass of text for you to read while you're at work not working when you're supposed to be working.
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.
Well, this pretty much meshes with my view on the subject as well. And contributes to why I have such an issue with getting this system underway. I just can't find a place to begin, and even when I do, I can't get my thoughts in order, and then lose said starting place from indecisiveness.
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.
Let's look at how I'd started to combine the two separate affects structs into one:
* An effect. (Spelled properly.)
* So limited... so few fields... should we add more?
* Updated and reworked. - Kayle 6/22/09
effectData( const effectData & );
effectData &operator = ( const effectData & );
virtual ~effectData( );
std::bitset< ? > bitvector; //Can't remember what exactly is stored in the EXT_BV bitvector; field of AFFECT_DATA....
const char *durationFormula;
const char *modifierFormula;
Now, Should that be further broken down into something that differentiates between the different types of effects? Or perhaps, is scrapping the existing implementation entirely and starting completely from scratch a better option?
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.
Agreed. I've always hated the fact that characters can get "corrupted" from a mishap where an affect wasn't properly removed.
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.
I like the idea, but wouldn't this require changing a *lot* of code?
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.
I think you lost me on this part. So bear with me. I think I get the gist of it. You think that all modifiers to stats should be stored in a separate variable, instead of the base value. But I thought Smaug already did this? At the very least with Str, Dex, etc. since they have a perm_ and mod_ field for each of them.
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.
I like this, but how (from an in-game perspective) would you go about adding the flags to the effects themselves?