[Game] Buffs increasing damage?

Started by
2 comments, last by All8Up 12 years, 2 months ago
[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

well, I started to make a game, but I have a little "problem" here, how can I make a spell/buff that will increase damage of next spell?

[/font]

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

so let's say I have spell "Flaming Hands" that will increase fire damage by 100% for the next 10 sec, now, I wanna cast Fireball that will deal intellect*2 damage, sooo, I discovered only 1 way how to do this:

[/font]

http://pastebin.com/1iJq6pMx

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

so, I don't know if this is a good way, cuz I have to write all the buffs there etc, so, can someone who already have created some RPG help me? or give me better idea or something?

[/font]

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

Thanks!

[/font]

Advertisement
Could change it to GetBuffMultiplier() and just multiply damage by that... I don't know any other way to improve though.
Follow and support my game engine (still in very basic development)? Link
In my game I have it something like this:


class Power {
public:

// Iterates through modifiers_.value() and returns the sum total value. calls check_timestamp()
// for each modifier
int TotalOfModifiers();

private:
List<Modifier*> modifiers_;
// compares modifier.time_length() to modifier.timestamp() and pops the node if the modifier has expired
void CheckTimestamp_();
}

class Modifier {
public:

//accessors
int value();
// returns number of turns the effect lasts for
int time_length();
// returns the timestamp from when modifier was added
int timestamp();

private:
int value_;
int time_length_;
int timestamp_;


Basically, my characters, spells, equipment etc all have modifier lists in them. I also extended the modifier class to store the name of the modifier, icon, source, visual effect etc....

I'm sure there's a more elegant way to accomplish this, but this one at least works for me. And it works for bonuses from equipment, terrain, buffing spells etc.
I use an attribute modifier system myself. A character has a set of base attributes which match all the buffs/debuffs in the system. So, for instance, the starting set of attributes for a player is: fire damage=1, cold damage=1, etc. When a spell is cast it says: "damage = caster_attrib[ fire_damage ] * spell[ fire_damage ]". Instead of listing "all" such attributes though, they are all assumed to be "1" if they don't exist in modified form. What this does is solves a LOT of different problems:

1. For your problem, the assumption is that under most circumstances the player/npc/whomever won't have a corresponding attribute so you just use 1 * the normal damage.
2. When you apply your buff you add 1 to the current attribute on the player. So, if the player does not have a "fire damage", assign one with 2*current value (which will be 200% total).

That takes care of the "buff", it just says while I'm active, multiply fire damage by 2, when I go away, go back to normal. What else this does for you though is include debuff's, equipment modifiers, etc. (NOTE: you generally want to recompute everything when there is a change, don't rely on *2 and /2 as things come and go, floating point error sucks and such a simple system leaves less flexibility.) So, in general, each attribute becomes a list of effects and you can use this to take care of all sorts of things:

3. Debuffed fire damage: same as the buff, just with /2 as the effect on the entities fire damage as an example.
4. Allows all equations to reflect receivers values also. I.e. instead of just "damage = me[ fire_damage ] * spell[ fire_damage ]" it can be "damage = me[ fire_damage ] * spell[ fire_damage ] * target[ fire_resist ]". All using the same system without constantly customizing code.
5. Completely expandable, add "cartoon_damage" type to a spell and everyone starts with a 1 by default. When you get around to adding proper buffs/debuffs etc, they all work the same way.
6. Boss fights with non-avoidable damage types work the same as all the above, just assign all boss abilities to a non-existing attribute. (I.e. always 1.)


Code wise this basically means the following is your damage effect:


struct FireDamageEffect
{
void operator ()( Entity& src, Entity& dst ) const
{
dst.TakeDamage( src[ kFireDamageModifier ] * mSpellDamage * dst[ kFireDamageResist ] );
}

float mSpellDamage;
};


Most of the time I'm using FastDelegates for this or boost::bind/tr1::bind so I don't even bother with the above structure. I just queue a function call such as:


CombatManager::TriggerEffect(
boost::bind(
&Spell::operator (), spell, source, dest
)
);


Which then calls into the spell functor which as follows:


class Spell
{
public:
void operator ()( Entity_t& src, Entity_t& dst ) const
{
dst.TakeDamage(
src[ kModifierFireDamage ] * mDamage * dst[ kModifierFireResist ] );
}

float mDamage;
};


The supplied code cuts out a lot of trivial details but the key item is that you leave all the effect properties and how to deal with them decentralized and the description of the spell itself is just a mixin to make it all work as appropriate. The spell itself only supplies the basic information of how much of a given type of damage will be done. The equation applied can be very complicated if you want, this is just a very simple example. I've used the pattern though such that for instance it can easily cover "immune to next spell, no matter what it is", "200% debuff to fire", etc. It is almost purely data driven so the goofy things designers may want to do doesn't effect the code in any notable way unless they want a new damage equation. The attributes are not part of the object definitions, they only exist in response to external input (i.e. attribute on armor item, natural attribute of race, buff, debuff, whatever).

This topic is closed to new replies.

Advertisement