I am trying to figure out how to set up a damage calculation system.
I have a couple of character classes, each who have individual abilities.
What I am trying to accomplish is to detect when a player selects an ability from a character, targets an enemy, and then calculates the abilitiy’s stats + the using character’s stats (fx. applying Strengthto the damage) and then apply the damage to the enemy target.
What I have right now:
A test ability which is an object named as the ability (I will have one for each ability) and this object will have a script with ability perameters.
Script example:
AS_Backstab
dmgType (string = physical)
+dmg% (float = 150f)
and a damage calculating script (which is on a GameController object) which will add all parameters from both the ability script, target stat script, caster stat script, and caster weapon stat script.
Now.
I want to make a script for each individual ability. Is this a good way to go? (instead of having a generic damage script).
And what would seem the best way to detect which ability is being used and how to calculate the outcome?
I apologize if it seem confusing, but it is kinda hard to explain.
Think of it kinda like how Diablo 2/3 manages ability use/damage calculation
If you have a tutorial which explains I would be happy to watch that.
Each ability need it’s own script to tell what they do. Some will do damage.
// Every ability should have this method. Each will have a different implementation on it.
void OnUseAbility ()
{
// This is a damaging ability example.
Character target = GetMouseTarget (); // Your method to adquire the target
float damageAmmount = 1.5f * strength; // Your damage formula for this ability
Damage (this, damageAmmount, DamageType.Magic, target); // This ability calls damage instantly. Some other ability could make a projectile that calls the damage when it collides.
}
It calls a method that damages the target. Any damage reduction effect calculation goes in the Damage method. OnUseAbility method calculates outgoing damage. Damage method calculates incoming damage.
Alright that makes sense.
Now if I want to be able to click an ability and then choose a target.
My first thought was to store the ability object in a PlayerController object. Then when clicking on a target it would cross reference the allowed targets of the ability with the clicked target.
I would achieve this by having a ray cast in the PlayerController. If no ability is set as selected then set the clicked ability as “Selected Ability”.
If an ability is already selected (and a target is clicked) then run the ability’s setup (damage and what not and then run the Damage calculation script).
But is it better to have a ray cast on each ability object and that way set what ability is currently selected?
I think i`d keep the same layout, but add a simple SelectTarget coroutine
void OnUseAbility ()
{
if (target == null)
{
StartCoroutine (SelectTarget (this));
}
else
{
BeginCast (target);
}
}
void BeginCast (Character target)
{
// This is a damaging ability example.
Character target = GetMouseTarget (); // Your method to adquire the target float damageAmmount = 1.5f * strength; // Your damage formula for this ability
Damage (this, damageAmmount, DamageType.Magic, target); // This ability calls damage instantly. Some other ability could make a projectile that calls the damage when it collides.
}
IEnumerator SelectTarget(IAbility ability)
{
while (true)
{
// You can also display some target selection sprite here.
Character target = GetMouseTarget (); // Your method to select the target.
if (target != null)
{
ability.BeginCast (target);
break;
}
yield return new WaitForEndOfFrame;
}
}
My syntax could be wrong, but you’ll get the idea. You still need some sort of control over the coroutine to properly stop it if you select another ability or cancel the current one. But this should get you started.
Another problem has arisen though. This is going to be a bit long winded.
Hopefully you have played Warcraft 3, WoW, Dota or any game the like where you have a control panel UI with your character’s abilities.
The problem is I am trying to create something the like.
As I stated I have a couple of different characters with different abilities. The players can control 3 characters and I need the ability panel/UI to change when another character is selected.
I have tried, instead of having the abilities on separate GameObjects, to store the ability scripts directly on the character GameObject. Then having GameObjects as “AbilitySlot_01”, “AbilitySlot_02”, “AbilitySlot_03”, and so forth.
Because the player will end up having to decide which abilities will be shown in the ability panel of each of his characters.
That’s why I slaughtered the idea of each ability having its own GameObject.
Instead I need to be able to have those AbilitySlot GameObjects store an ability. And more problematic. Have that GameObject refer to the stored ability once clicked. With targets allowed and all that jazz.
You can use GameObjects or ScriptableObjects for that. Consider this:
There’s a Fireball ability, which is a ScriptableObject.
There’s a Character A and a Character B. Both have the Fireball ability, but A has level 2 fireball and B has level 1 fireball.
So each character needs a list of which abilities they have along with some other info such as ability level and cooldown. All characters that have the same Fireball ability share the same object on their list, but each has a different level / cooldown and other variables for it.
This way you can use the editor to assign the abilities to the characters, and edit some abilities properties such as icons and other info.
You can use the character abilities list to display them on the UI.
Edit:
You know what. Scratch that last post. It didn’t make much sense.
I think I am getting the hang of this but I have a few more questions.
Take this line: Character target= GetMouseTarget ();
From what I can deduct the “Character” is the GameObject that is going to deal damage. Therefore I have replaced “Character” with GameObject. Is that correct?
IEnumerator confuses me a bit. Take this line: IEnumerator SelectTarget(IAbility ability)
What do I have to replace “IAbility” with and what do I replace “ability” with?
The whole damage method. I was thinking of having a GameObject which calculates all damage in a script (let’s call it DamageCalculation) instead of calculating the damage in each ability script. What do you think of that?
The target method. Originally I wanted to set the target in a general PlayerController GameObject script.
But is that the best way to get around it?
Like. Each player has a PlayerController which defines the player. Each of his characters will have a CharacterStat script with all of the stat types he has. Strength, Movement Speed, etc etc. This CharacterScript also has a GameObject list with the abilities that type of character can use.
You must have a script containing data such as health, attack damage and such. This should be your Character script.
Target is the target of the ability, the character receiving damage.
It’s a coroutine to select the target for an ability. “ability” is the ability whose target is being selected. IAbility is the interface for your abilities. All abilities should inherit from this.
Why would you do that? Each ability has it’s own damage output. And then there’s a method to calculate the incoming damage for the target, which is the Damage() method. You don’t need a gameobject for that.
That could work.
You can think of the target as a target for an action, so whenever an action is requested, a target is required.
For an attack action, the player clicks an attack button, and a SelectTarget coroutine starts,and when the target is selected, the attack action starts with that target. Same goes for skills.
You can have hotkeys for some actions, such as right clicking a character, issues attack action on that target.