06 Dec, 2010, andril wrote in the 1st comment:
Votes: 0
Anyone at all familiar with the affects code in SMAUG knows what a mess it is and since SWR is a derivative my head hurts. So I decided to attempt a rewrite of, more or less, the whole thing.

The way I envision this turning out is a complete replacement for both the affect_data and smaug_affect structures and systems with one unified effect_data class and systems.

Here's what I have so far, sort of coding by the seat of my pants right now(bad idea, I know), and would like some opinions on what little I've done. Get some ideas for other things to add and whatnot.


enum _effect_layer_types
{
ELAYER_OVERWRITE, // overwrites first effect of same type applied. Can cancel out eq effects if strong enough
ELAYER_RESET, // resets first effect of same type applied. Equipment effects absorb the reset
ELAYER_CUMULATIVE, // just shoves another effect onto the target to allow multiples of the same type
ELAYER_COMBINE, // adds duration, mod, layer and resist values of new effect to old one
MAX_ELAYER // add new effect layer types above here
};

class effect_data
{
void * target; // what this effect is currently attached to.
short resistVal; // resist/save strength. -val = susceptible, 0 = N/A, +val = resistance. Range -100…100
// for effects that modify resistance or saving throws

short maxDuration; // how long the effect will exist. -1 is permanent(only for effects added by worn eq)
short timeTillExpire; // time left till the effect expires
short effectType; // what effect, if any, it adds to the target(effects in _aff_flags enum above)
short targetType; // what the effect can be placed on, characters, eq, rooms, some combination
short statModType; // what stat, if any, gets modified. See enum _apply_types above.
short statModVal; // mod value for the specified stat
short layerMode; // what happens when the same effect is applied to target multiple times

short layerStrength; // how strong the effect is. helps determine layer behavior
short numTargetType; // how many targets it can encompass.
// 0 = caster, 1 = group(of caster), 2 = target, 3 = group(of target), 4 = room

std::string casterMsg; // message caster sees when spell is finished. not used for eq effects that target wearer
std::string targetMsg; // message target sees when hit by effect, if any
std::string othersMsg; // message others in the room see when the effect hits the target
std::string offTarMsg; // message for visible/tangible wearoff effects to affected target
std::string offOthMsg; // message for visible/tangible wearoff effects to others in the room

public:
// TODO: add get/set functions for the private stuff up above

effect_data(effect_data*);
effect_data();
~effect_data();

void apply(/*?????*/); // use function overloading? void pointers? strings(<O/R/M><vnum/name>)? Not sure.
void remove(); // handle removal of this effect
void countdown(); // decrement timeTillExpire at one second intervals. When it reaches 0 remove the effect and destroy.
// Change return type to short? Can an object call it's own destructor without problems? Hmmm…
};

If I can get this up and working the way I want it will allow for ready made effects to be slapped onto targets at will, make any desired changes and forget about it from that point on.

So, any suggestions for other things to add in? Ideas on how I can handle telling the setting of the target applied to simply? Too many comments in the code? Anything? :)

Let the ridicule begin!

Thanks.
06 Dec, 2010, Tonitrus wrote in the 2nd comment:
Votes: 0
andril said:
The way I envision this turning out is a complete replacement for both the affect_data and smaug_affect structures and systems with one unified effect_data class and systems.


andril said:
short maxDuration; // how long the effect will exist. -1 is permanent(only for effects added by worn eq)


Not to insult your intelligence, but do you know the difference between smaug_affects and affect_data? If you really intend to make them one data type, I'd recommend using a string for durations.
06 Dec, 2010, andril wrote in the 3rd comment:
Votes: 0
smaug_affects are, if memory serves, a way for imms to create custom affects for skills with no dedicated code. spell_smaug right? I could be, and probably am, wrong though. Why make duration a string?
06 Dec, 2010, Tonitrus wrote in the 4th comment:
Votes: 0
andril said:
smaug_affects are, if memory serves, a way for imms to create custom affects for skills with no dedicated code. spell_smaug right? I could be, and probably am, wrong though. Why make duration a string?


Smaug spells, yes. Smaug spells are immensely useful, and, in my opinion, one of the best things about smaug. smaug_affect uses a string as a duration. affect_data uses an int or a short or some such.

I'll give you an example:

affect_data for fly would have a duration like 1200.
smaug_affect data for fly would have a duration like 'l*24' (level times 24).

The string allows you to embed formulas into numerical fields. I believe smaug_affects actually use strings for most of the fields that end up being numerical. If you were to make these fields a string in your unified type, you could have one data type for both smaug_affects and affect_data while still maintaining the flexibility of smaug spells. The easiest way I can think to do this is to store the duration as a string and increment a value indicating how much time has passed, then compare it against the string/formula for comparison. I'm not sure it's really beneficial to have these as one data type, though. It would probably be more trouble than it's worth.

[edit: Easier still would be to have "template" values for each numerical value that stores the formula, then a derived numerical value for each one that acts sanely, so you don't have to do a lot of extra bookkeeping.]
06 Dec, 2010, andril wrote in the 5th comment:
Votes: 0
Well, there's two fields in smaug_affect that use strings(char*), duration and modifier, but I see what you mean.

I guess I could convert maxDuration to a string and parse that to determine what to stick in timeTillExpire. It would just need a simple if check and do whatever as necessary from there. Thanks for the suggestion!

Tonitrus said:
The easiest way I can think to do this is to store the duration as a string and increment a value indicating how much time has passed, then compare it against the string/formula for comparison.
What I was going to do was have the max duration for the effect be in maxDuration, which I'll still do for now unless someone has a better idea, then when the effect gets slapped onto a target, stick that into timeTillExpire which would get decremented by one automatically every second by a call to effect->countdown() from within update_handler. Once that timer reaches zero the effect is automatically removed from the target. This way I won't need to parse the desired max duration more then once.

Thanks again.

Edit:
Just in case anyone is curious, as of right now I'm planning on sticking all active effects into a single std::list which gets iterated through once every second. This is how the call to effect->countdown() will be dealt with. Seems much simpler then adding a list of effects to each individual obj/mob/room and having to iterate through all of them looking for ones that have active effects. I'll probably also stick a list into room_index_data, char_data, object_data and the index structs for objects and mobs as well so that when an effect is added to the target I'll just go through the list on the target to determine if, based on the layering system(should probably rename that), the new effect modifies one of the old ones. If so, make the changes, which should, I hope, also be reflected in the global list at the same time. Saves time having to slog through a ton of effect instances looking for ones on my target.
06 Dec, 2010, Exodus wrote in the 6th comment:
Votes: 0
Smaug affects are a tricky creature. You have two data structures that are used for numerous things - stats on equipment, spell effects and effects on characters. When we rewrote the affect system it was actually a long ordeal. We redid what and effect could affect as far as target types go (object, character, room, area, plane, world, ect) and categorized them into types (natural, magical, psionic, supernatural, divine, ect). The reasoning behind this is while SMAUG affects is a great system, it is in some ways extremely limited and has a lot of half-implemented features.

My only real suggestion to you is to think about taking a more design-centric approach. Think about how you want affects to work in your world. What are the physics of your magic system going to be? How limited or flexible do you want the system to be? We decided that we wanted spells that could be very selective in what or whom they affect. For example, you could have a spell that has multiple effects and each effect affects a specific type of creature, even in a different way. It could have a healing effect for you and those you are grouped with while damaging everyone else. Hell, you could even have one that only affects creatures of a specific class or race, however specific we wanted it to be.

We also wanted to have different types of effects. Say you created an effect called 'claw'. It is a natural effect of which the result is slashing damage. We categorized these in this manner so things like protection against magical things would have no bearing on something scratching or biting you. More importantly, this adds new complexities to combat and spellcasting when you have to determine what types of attacks and defenses to use against different opponents. Your 'circle of magical protection' granting you +spell resistance will be no help when psionic attacks tear through your head. Other functions are things like how your magical effects function when dispel attempts are made against you or when you walk into an anti-magic field, they can be suppressed until you leave the area or whatever effect created it wears off.

The point is to plan out how you want things to function and how they will relate to each other. Otherwise, you may end up with a completely rewritten system that still has half-implemented features and shortcomings just like the original system.

As for what you have so far, it seems like you are starting out on the right track. I agree that durations should be strings because dice formulas are an extremely flexible way of adding both a bit of randomization into number crunching as well as making things scalable with character power. I am curious about the affect layers you mentioned. I understand the purpose of them, but I was confused what the difference between cumulative and combine would be? Multiple instances of the same effect on something would be the same effect as combining the same number of instances as far as durations and stat modification goes. Maybe it would take longer to dispel multiple castings of the spell if it were cumulative?

You're also probably already thinking about this but I wouldn't limit the things effects can modify to just stats. There are many properties of characters, objects and even rooms that can be modified. Maybe even have effects that modify other effects, who knows?
06 Dec, 2010, andril wrote in the 7th comment:
Votes: 0
Well, that layer deal which, like I already mentioned, needs to be renamed IMO is the beginnings of a way to handle things when an effect is added to a target that already has an effect of the same type. For instance say your character has an armor spell on you that improves your ac. What happens if you have another armor spell, or something that uses the same flag or whatever, cast on you while the first one is still active? My thought was that, using this system, the person that designs the spell/effect could say that the new effect replaces(ELAYER_OVERWRITE) the old one if it's stronger. If not it could just fizzle into nothing(probably need to add an entry for this), strengthen and extend the first one(ELAYER_COMBINE), or just get tacked on as another instance(ELAYER_CUMULATIVE, probably a bad name for it) in which case you'd have two armor spells on you at once with separate durations and strength.

Here's what I wrote up real quick in the source as a note to myself while I was thinking about it on possible happenings using this as a reference:

Quote
For direct damage effects: duration of 0, instant, using effectType to determine what kind of magical damage is done;
fireshield does fire damage to the victim, shock does electrical, ice cold etc.

For effect adding stuff e.g. each time you hit the target there's a chance the weapon could hit them with a weaken effect or something,
it'll have a pretty short duration and low strength, but will probably have a layer effect of either ELAYER_OVERWRITE/ELAYER_RESET(might be extra weak for the duration of the fight) or ELAYER_COMBINE(every time you get hit with the effect you get a little weaker for a little longer).


That's kind of where I was going with this idea, the second example being more applicable and to the point.

Part of the problem I have is that the mud is an SWR, not really that big an issue though - it'll never be open for play, so "magic" doesn't really exist in great variety. The force could only do so much apparently. Like I said though, it's not really that big of an issue because I'm using it more like a sandbox where I can play around and tinker with stuff so I'll probably just go crazy and make any changes as expansive and flexible as I can.

One thing I'm giving some thought to is "chaining" effects together. To take an example from D&D, the Contingency spell. Assume you can choose two spells due to your level. When it's initially set up it contains a pointer/reference to a second effect, which points to the the third one. Or a list/array/vector/whatever of its own with the two other spells in it. When the conditions of the Contingency spell are met it goes off, automatically causing the two stored spells to get applied. Can we say double fireball?

Exodus said:
You're also probably already thinking about this but I wouldn't limit the things effects can modify to just stats. There are many properties of characters, objects and even rooms that can be modified.

Right now I'm simply trying to get something basic, and basicaly working, down. But yes, I had planned on having it do more then just modify stuff like strength and hit points.

Exodus said:
Maybe even have effects that modify other effects, who knows?
The layer system kinda already would do this, in a very limited fashion, but yes. Definitely something to keep in mind.
06 Dec, 2010, Exodus wrote in the 8th comment:
Votes: 0
For anyone that's interested, I dug up some of the original notes from like 2007. It's changed a lot over the years but this was the basic idea for a stock SMAUG.

Affects notes

I do like the idea of chaining affects. Would that be for a single person chaining them together or a combination of two or more sources on the same target?
06 Dec, 2010, andril wrote in the 9th comment:
Votes: 0
At the moment it would essentially be one person, but depending on the numTargetType and what it's set to it could affect multiple targets very easily. Depending on what the target of the effect is you could theoretically have a character in combat with another and when this effect expires automatically place the chained effect on the opponent. Something like, on wear off of one effect, effect->chainedeffect->apply(target->fighting); or whatever. It would just depend on how the effects are set up initially. You could very easily have effects that get triggered by the actions taken by others too.

You know what, I think this could be a great way for the players to set up their own custom spells. For example lets say a group is fighting a strong mob and they've got a bunch of effects set on each member of the group specifically designed to combat this enemy. The mage, or whatever, could cast a triggering spell, like a laser to paint the target for a guided bomb/missile, that causes all these active effects on the other group members to go off and hit the mob with their payload all at once. Think I'll have to work this in somehow. Could be pretty awesome.

Back to work for me now though.
06 Dec, 2010, Exodus wrote in the 10th comment:
Votes: 0
andril said:
The mage, or whatever, could cast a triggering spell, like a laser to paint the target for a guided bomb/missile, that causes all these active effects on the other group members to go off and hit the mob with their payload all at once.


That's exactly what I was thinking. It would be a real team effort and the combination of their efforts could lead to a more devastating force. We did something similar to this. Chain bonuses are merely an amplifier for damage. If an effect is chainable and is applied more than once in a single round before its timer expires, chain bonuses apply. You can only chain an affect with itself or something it has specific synergy with. For example:

Synergy
Mage A casts fireball, and immediately after, Mage B casts air blast. Mage B's air blast is not created, but instead it changes to fire blast, dealing more damage than air blast would normally (and changing it's damtype to fire, among other things).


Chaining I
Mage A casts fireball. Mage B casts fireball immediately after. Both fireballs hit, except Mage B's fireball damage is augmented slightly because of a chain bonus (Target got hit with the same affect more than once in a round)
Mage A's fireball singes An Armed Guard. (97 dmg)
Your fireball chars An Armed Guard! (142 dmg) Chain x2!


Chaining II
Mage A casts a spell which damages an opponent multiple times, 3 or 4 hits in this case. The first hit deals normal damage and the subsequent three hits deal additional damage due to chain bonuses, each hit increasing a chain bonus.
Your meteor storm smashes An Armed Guard! (202 dmg)
Your meteor storm smashes An Armed Guard! (212 dmg) Chain x 2
Your meteor storm | CRUSHES | An Armed Guard! (222 dmg) Chain x 3
Your meteor storm PULVERIZES An Armed Guard! (233 dmg) Chain x 4



It's all great fun. We actually capped the chain bonus at 25 hits. There were players that strategically chained low damage, multi-hit skills all at once and dispatched things very efficiently.
Incidentally, spells that hit every creature in the room once for every other creature in the room isn't as good of an idea as it sounds.
07 Dec, 2010, andril wrote in the 11th comment:
Votes: 0
Exodus said:
Incidentally, spells that hit every creature in the room once for every other creature in the room isn't as good of an
idea as it sounds.


I can just see what might have happened here. No check to make sure it didn't keep hitting stuff after the first time or something?

I've been wanting to see something very similar to, if not exactly like it, what you described with that synergy system for a long while now. Spells interacting with each other in interesting ways.

Example: A mage(with hover/fly effect on) and a warrior(stuck on the ground) are fighting in a room with an outdoor sector, forest or something else without a solid(stone) floor. The mage could cast a water based spell at the ground around the fighter(room target) which would cause the ground to turn into deep mud thereby slowing the movement of the fighter(apply some effect automatically to simulate restricted movement*). Then the mage would cast a heat based spell at the ground around the fighter(room target again) which would cause the muddy ground the fighter is trying to move through to solidify(remove whatever effect from the room is causing the restricted movement) and at the same time traps any creatures, including the fighter, in the freshly hardened baked dirt. Kick ass way to immobilize a target. And the mage would be safe because they weren't on the ground but floating above it when all these effects were happening.

water+fire=steam: water hits target and gets under armor/soaks into clothing. Fire hits and converts the water to steam, causing more heat damage then it would have otherwise because the armor doesn't provide any defense against what's inside of it. Stuff like that. :biggrin:

* would probably be something that caused the fighter character to have fewer attacks and more movement point loss for actions(if move is lost from actions other then moving of course)
09 Dec, 2010, Exodus wrote in the 12th comment:
Votes: 0
Actually just a logical oversight. Players are good at finding those.
0.0/12