Spell buffs, temporal skill boost, temporal character states, etc. How to?

I just finished my database system to hold all the items and spells of my game, but now Im having problems conceiving how to make items that give the player temporal boost or spells, or even how to give the player or enemies temporal states (such as poison, on flames etc…)

My item setup is really basic, there is a basic “Item” class with an abstract void and the different classes for the different types of items that override that abstract void with their own void. Same with spells.

My question is more from a conceptual stand point, I mean I don’t need help with the code it self but more on which approach would be more optimal to this kind of features.

For example, lets say I have a spell that increases the attack stat by 10 for 10 seconds and lets say the attack calculation is:

Attack4-E.Defense2

Do you rise the attack stat like this:

Attack= Attack+10;

Attack4-E.Defense2

Or you would rather add a new variable so the attack calculation is now:

Boost = 10;

attack4+Boost-E.Defense2

or how would you do this kind of stuff?

My point of view on this topic is that in the end it really depends what your needs are.

I would probably keep references to all effects in dictionnaries of lists for fast access to all effect of a type and calculate when appropriate, but then again if you don’t ever cumulate any effect that isn’t of any use and if you have 1 million mobs with active effects on each, calculating each frame could even turn out to be painfull whereas having the sum ready would be effective.

Also, if you plan on having effects affecting other effects, this conception might be of some help as well…

I would recommend you calculate all boosts separately from the base attack. When you go to serialize, or save, the data do you really want to worry about if the current stats are boosted? I would say keep real values separate from temporary values for this reason, and others, however you’ll end up with the same result either way.

I would take the hit of the increased memory allocation and computation, which should be negligible, for the decoupling of boosts and real values. This however seems like a subjective design decision that doesn’t have a TRUE black and white answer.

I would put those values (AttackBonus, DefenseBonus, FireDamage) into properties and let them query any effects/influences when needed. The effects itself are in a list on the player/enemy and checked every update if they still apply or need to be removed (time over). When a boosted value is required (the property is called) the list is iterated and all effects of that specific type are summed up and returned by the property.
So in general you put an effect in the list, the player class checks itself if it still applies and the calculation queries the summed value when needed. simple and extendable. Your items/spells just need to modify the list (fe when an item is unequiped the bonus is removed, antidot removes poison etc). All you need is a class for handling all the functionality (timed, unlimited, enum for the effect, value for the effect, possibly a list of those itself) and a method which queries all objects in the list and asks them if they have an effect on attack, defense, damage to player over time etc. .

Edit:
this way you can also handle permanent class bonuses.

Thanks all, I got a few ideas!.

If anyone more want to add anything more please do, Im always open for more points of view on this matter.

Kind regards!

In doing this you also want to keep an order of events.

Attack = base * percentage + 5 + 3 - 2;

!=

Attack = (base + 5 + 3 - 2) * percentage;

Yes I understand.

The idea I had following the example I said in the opening post goes something like this:

There is a TempVariable for the Attack, at the start the TempVariable is equal to the Attack stat

TempVariable = Attack;

Then when the Boost is applied +10 is added to the TempVariable

TempVariable += 10;

Then it counts 10 seconds and subtracts the extra 10 points and the boost is over.

TempVariable -= 10;

I don’t know exactly how I’m going to add the boots to the characters, I like the idea @exiguous said about the lists but I don’t know if is possible to Auto-eliminate stuff from the lists (boots eliminating themselves from the list when the boost is over) so I don’t know…

A cool way to do this, is to add “modifiers” or component scripts to your character. You do this by using Polymorphism and a base class.

Here is an example:

using UnityEngine;
using System.Collections;

public class Modifier : MonoBehaviour {
	public float timeRemaining = 10;
	public string modifierText = "Generic Modifier";
	public int order = 0;
	
	// Update is called once per frame
	void Update () {
		DoTimer ();
	}

	public Character GetCharacter(){
		return transform.root.gameObject.GetComponent<Character>();
	}

	public Character GetTarget(){
		Character chr = transform.root.gameObject.GetComponent<Character>();
		if(!chr) return null;
		return chr.target;
	}

	public virtual void DoTimer(){
		if (timeRemaining != Mathf.Infinity) {
			timeRemaining -= Time.deltaTime;
		}
		
		if (timeRemaining <= 0) Destroy (this);
	}

	public virtual float ModifyDamage(float value){ return value; }
	public virtual float ModifyAccuracy(float value){ return value; }
	public virtual float ModifyAvoidance(float value){ return value; }
	public virtual float ModifyHealing(float value){ return value; }
	public virtual float ModifyDamageResistance(float value){ return value; }


	// these are here for after effects, like heal on damage.
	public virtual void FinalDamage(float value){}
	public virtual void FinalHeal(float value){}
}

using this as a base class, you crate things like this:

using UnityEngine;
using System.Collections;

public class Blessed : Modifier {
	public float timeRemaining = Mathf.Infinity;
	public string modifierText = "Blessed, damage +1, healing + 1";
	
	public override float ModifyDamage(float value) {
		return value + 1;
	}
	
	public override void FinalDamage(float value){
		Character chr = GetCharacter ();
		if (!chr) return;
		chr.ApplyHealing (ModifyHealing (1));
	}
}

Now, all you have to do is to run a loop on all the modifiers and call specific things. like

value = mod.ModifyDamage(value);

This changes the value. Using the order, you simply count to the max order number and modify them in order.

I did probably about 20 scripts just to make sure things worked out ok. I did things like food buffs, debuffs, cursed items debuff throwing modifiers (like acidic, gives an acid debuff) I did protectors, like AidProtection which stops damage. (the acid debuff looks for the AcidProtection and stops it from being attached or stops the damage if it is attached. The timer part works just fine because I am subclassing it,all I have to do is to rewrite the time remaining part. I use Mathf.Infinity to make permenant modifiers, like a Acidic sword is permenant, but a SpellBlessed sword would not be permenant.

I can check the character for all modifiers and apply them to the damage, healing and other things. it is very expandable IMO.

I created the Character base class, which is what the Blessed item does. and apply healing every hit. I also created a Weapon base class, with default attack and hit stuff.

Since this is an entire system and involves way too many scripts, I am not going to share it all here.

I see, I get the concept its a great system, I may copy the idea of using components instead of lists, thanks!.

The problem I have is when I first started working on this game I wanted to do an action adventure but soon I changed my mind (because Im an idiot :lol: ) I started adding RPG elements to it but by then I realized the player character class and enemy character class where very different, so now to do something like this I will have to rewrite both classes to inherit from the same character base class (like any normal RPG) so both player and enemies can use the same states and boosts. I guess I will have to anyways or it wont be a proper RPG :roll_eyes:

You may also want to review the Decorator Pattern.

Take a look at the Java code coffee example, after reading the base text.
I know some guys who were using this for RPG effects.

Lots of other examples out there.

After checking over that… it is exactly the same as I had discussed.

Its not exactly the same.

In your version

With a decorator, each decoration wraps all the previous decorations and the original object.
In the coffee example the last value of “c” is the Sprinkles.

Then you get a value.

public double getCost() {
    return super.getCost() + 0.7;
}

It reaches down into the previous decoration to get that cost, then all the decorations before that, etc… and then adds the last cost. It doesnt use a loop to get the value.

I’m not saying either one is better. But they are different.

1 Like