How to implement a flexible calculation system?

I want to implement a flexible calculation system that can calculate the damage of an ability based on it’s level.
I’m not sure how to go about doing that. The best I’ve thought of so far is to create a “Calculation” class where you can select the type of calculation you want: substraction, addition, multiplication, exponentional, etc. but that doesn’t seem very flexible.

I want to be able to do complex operations like this:
Ability damage = (((ability level * 10) - 40) + (ability level / 2)) *10

Does anyone have any experience or ideas on designing such a system?

I’d try making it a curve that represents the modifier and use “time” as the level in order to evaluate the curve at a specific point.

2 Likes

Yeah, if there’s only one input variable, then an animation curve is clearly the way to go for that.

If you do want to create a “formula editor”, you could do that by doing what you’d originally suggested, but allow nesting - each component of the formula has left and right references (which may be a constant, an input variable, or another formula), and an “operator” enum.

1 Like

AnimationCurve seems interesting. I’ll have to look more into it. What if there’s 2 or more input? I actually wanted it to be based on level + character stats.

Depends on how you want to allow them to combine. You can use multiple AnimationCurves (and add or multiply them together), or you can use a formula system as I described.

You might also go for something like the $10 Python interpreter, and treat typed-in equations as a part of a Python code.

1 Like

The information about the ability should probably be available internally in the ability - you shouldn’t need to calculate this stuff from the outside.

So instead of storing the damage anywhere, when you use the ability, you have a GetDamage() method that gives the ability the character that uses it, and returns the damage:

public abstract class Ability {
    public int level;

    public abstract int GetDamage(Character user);
}

public class Fireball : Ability {
    public override int GetDamage(Character user) {
        return (((level * 10) - 40) + (user.level / 2)) *10
    }
}
2 Likes

Do you know if it works in Unity 5?

I don’t want to hard-code it. If I have say a “Projectile” ability then they’ll all have to use the same damage formula because it’s hard-coded.

It’s possible to go too far to the “non-hard-coding” extreme, and this case is sort of right on the borderline. At a certain point avoiding hard-coding gets to be more trouble than it’s worth.

Don’t know anything about that plugin and 5.0. I just found it on the AS.

1 Like

I like to live on the edge :stuck_out_tongue:

I don’t get this. How/why would you create a formula in a non-hardcoded way?

I agree with @Baste . The formula should be encapsulated by the class doing the damage. However, this is only part of an interesting combat system. You should look into how the D&D damage system works. Some of the big MMO’s still use a “D20” engine under the hood to keep things interesting.

If you want simplistic formulas, you could just put them in a string field and write a parser that turns that into an equation. Writing a program that can parse something like:

(((ability level * 10) - 40) + (character level / 2)) *10

isn’t very hard at all.

2 Likes

I still don’t get it. then your formula is hardcoded into a string.
If you really want to make your formulas dynamically, then use an Expression Tree. But I can’t imagine why you would need to make such a complicated system.

Well when I say hard-coded I mean non-customizable. With @Baste 's latest idea, I could have a string field and then customize the damage formula for every individual ability.

You could achieve the same thing via a virtual method like @Baste suggested previously

1 Like

Who is doing the customizing?

If it’s you, then you already have a perfectly good parser. It’s called the Mono compiler.

Creating a string parser is overkill. The only reason you would need such a thing would be to interpret from another system which can’t provide better than a string - like a user entering custom damage formulas (which sounds like a terrible idea to me). And, any parser capable of arbitrary complexity formulas (and I don’t mean complicated, just arbitrary number of brackets and variables) would need to build an expression tree anyways.

I’m sure you’re over complicating this.

Ok well let’s say I have a base Ability with a GetDamage function and other Abilities override and implement their own formula.

Let’s say I have this code here:

public class Fireball : Ability {
    public override int GetDamage(Character user) {
        return (((level * 10) - 40) + (user.level / 2)) *10
    }
}

Then that means every time I want to create a new ability, I have to create a new class even if that ability works in almost exactly the same way. In the case of Fireball, what if I have an Icebolt skill that functions the same way as Fireball? But It should do (user.lvl / 1.2) instead then I have to make a new ability just for that? OK in that example you might say "just make that a variable* so you can reuse the class but what if I wanted Fireball to do base + (ability level ^ i) * y and I wanted Icebolt to do base + ability level * i? Seems like a waste to create a new ability just for that if they’re going to function similarly.
Those are just my thoughts. Not sure if I’m wrong or not making sense. What do you guys think?

I think that having your Icebolt skill use the Fireball class would be overly confusing :stuck_out_tongue:

At this point, you’ve spent far more time discussing this on the forum than it would have taken you to implement ANY of the 3 solutions…

Yes so I only have 1 Projectile class I re-use for all projectile-based abilities.

Well other people thought there was no need for such a system so I wanted to clarify why I was looking to implement such a system and see if my logic made sense or if I was still wrong.
Isn’t the whole point of the forum to discuss stuff :stuck_out_tongue:
I’m at work and can’t program anything anyway.

1 Like