• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Attribute Scaling Abilities

Level 7
Joined
Feb 23, 2020
Messages
253
Hello, how do you make an ability scale with a hero attribute? For example, i want an ability to gain 5x the agility in bonus damage.

Note: I am not a professional with triggers

Thanks in advance.
 
Level 5
Joined
Jun 12, 2018
Messages
148
Hi Xzere, welcome to the Hive ! You can achieve want you want with a very simple trigger.
This example below will add (x5 agility * level of ability) as base damage when the ability is learnt :goblin_yeah:

  • Your Ability Trigger
    • Events
      • Unit - A unit Learns a skill
    • Conditions
      • (Learned Hero Skill) Equal to Agility Damage
    • Actions
      • Unit - Set Base Damage of (Triggering unit) to ((Unit: (Triggering unit)'s Weapon Integer Field: Attack Damage Base ('ua1b') at Index:0) + ((5 x (Agility of (Triggering unit) (Include bonuses))) x (Level of Agility Damage for (Triggering unit)))) for weapon index: 0
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
First we create an Integer (Array). This will store the desired abilities base damage per level.
  • Breath of Fire Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet BreathOfFire_Damage[1] = 100.00
      • Set VariableSet BreathOfFire_Damage[2] = 200.00
      • Set VariableSet BreathOfFire_Damage[3] = 300.00
Then when we cast the ability we calculate the amount of damage it should deal referencing the BreathOfFire_Damage variable. We also use some arithmetic to add in the bonus Attribute damage.
  • Breath of Fire Cast
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Breath of Fire
    • Actions
      • Set VariableSet Level = (Level of (Ability being cast) for (Triggering unit))
      • Set VariableSet Amount = (BreathOfFire_Damage[Level] + (5.00 x (Real((Agility of (Triggering unit) (Include bonuses))))))
      • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Breath of Fire)'s Real Level Field: Damage ('Ucs1') of Level: (Level - 1) to Amount
So I'm changing the casting unit's Breath of Fire ability to deal the base damage + (5 * Agility). If the Ability is Level 3 then it will reference BreathOfFire_Damage[3] and deal the appropriate amount of damage.

Notice that I convert the Hero Attribute to a Real, this is required as Attributes are Integers but the Damage field is a Real.

Also, the Level field is actually indexed starting at 0. That's why I subtract 1 from Level. In other words, putting 0 in the "Level:" field is actually going to reference Ability Level 1.
0 = Level 1
1 = Level 2
2 = Level 3
etc

Finally, make sure that you use the correct version of "Damage". See how it has the code next to it's name: 'Ucs1'. You can view these codes in the Object Editor by pressing Control + D (Display Values As Raw Data). In Breath of Fire's case it uses Damage ('Ucs1'). See the picture I attached for an example.

So this trigger references the Object Editor data for the given ability and replaces one of it's fields with a new value. This is useful if you want to customize Blizzard's spells beyond the limitations of the Object Editor.
 

Attachments

  • rawcode dmg.png
    rawcode dmg.png
    1.5 MB · Views: 89
  • Breath Of Fire Example.w3m
    18.5 KB · Views: 57
Last edited:
Level 7
Joined
Jun 9, 2020
Messages
97
First we create an Integer (Array). This will store the desired abilities base damage per level.
  • Breath of Fire Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet BreathOfFire_Damage[1] = 100.00
      • Set VariableSet BreathOfFire_Damage[2] = 200.00
      • Set VariableSet BreathOfFire_Damage[3] = 300.00
Then when we cast the ability we calculate the amount of damage it should deal referencing the BreathOfFire_Damage variable. We also use some arithmetic to add in the bonus Attribute damage.
  • Breath of Fire Cast
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Breath of Fire
    • Actions
      • Set VariableSet Level = (Level of (Ability being cast) for (Triggering unit))
      • Set VariableSet Amount = (BreathOfFire_Damage[Level] + (5.00 x (Real((Agility of (Triggering unit) (Include bonuses))))))
      • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Breath of Fire)'s Real Level Field: Damage ('Ucs1') of Level: (Level - 1) to Amount
So I'm changing the casting unit's Breath of Fire ability to deal the base damage + (5 * Agility). If the Ability is Level 3 then it will reference BreathOfFire_Damage[3] and deal the appropriate amount of damage.

Notice that I convert the Hero Attribute to a Real, this is required as Attributes are Integers but the Damage field is a Real.

Also, the Level field is actually indexed starting at 0. That's why I subtract 1 from Level. In other words, putting 0 in the "Level:" field is actually going to reference Ability Level 1.
0 = Level 1
1 = Level 2
2 = Level 3
etc

Finally, make sure that you use the correct version of "Damage". See how it has the code next to it's name: 'Ucs1'. You can view these codes in the Object Editor by pressing Control + D (Display Values As Raw Data). In Breath of Fire's case it uses Damage ('Ucs1'). See the picture I attached for an example.

So this trigger references the Object Editor data for the given ability and replaces one of it's fields with a new value. This is useful if you want to customize Blizzard's spells beyond the limitations of the Object Editor.
Your trigger is amazing! Finally a simple one xD But I have some questions about it:
Do I have to create those global varibales (Amount & Level) for every other spell? Or can I use them for every hero and spell?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
Your trigger is amazing! Finally a simple one xD But I have some questions about it:
Do I have to create those global varibales (Amount & Level) for every other spell? Or can I use them for every hero and spell?
Those variables are purely optional. If you really wanted to you could do everything inside of the Ability function:
  • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Breath of Fire)'s Real Level Field: Damage ('Ucs1') of Level: ((Level of (Ability being cast) for (Triggering unit)) - 1) to (BreathOfFire_Damage[(Level of (Ability being cast) for (Triggering unit)] + (5.00 x (Real((Agility of (Triggering unit) (Include bonuses))))))
But as you can see that's not very pretty.

And yes, you can use them for every hero and spell.
 
Level 7
Joined
Jun 9, 2020
Messages
97
Those variables are purely optional. If you really wanted to you could do everything inside of the Ability function:
  • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Breath of Fire)'s Real Level Field: Damage ('Ucs1') of Level: ((Level of (Ability being cast) for (Triggering unit)) - 1) to (BreathOfFire_Damage[(Level of (Ability being cast) for (Triggering unit)] + (5.00 x (Real((Agility of (Triggering unit) (Include bonuses))))))
But as you can see that's not very pretty.

And yes, you can use them for every hero and spell.
Okay thanks for your answer. Have a good night mate
 
Level 18
Joined
Mar 16, 2008
Messages
721
First we create an Integer (Array). This will store the desired abilities base damage per level.
  • Breath of Fire Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet BreathOfFire_Damage[1] = 100.00
      • Set VariableSet BreathOfFire_Damage[2] = 200.00
      • Set VariableSet BreathOfFire_Damage[3] = 300.00
Then when we cast the ability we calculate the amount of damage it should deal referencing the BreathOfFire_Damage variable. We also use some arithmetic to add in the bonus Attribute damage.
  • Breath of Fire Cast
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Breath of Fire
    • Actions
      • Set VariableSet Level = (Level of (Ability being cast) for (Triggering unit))
      • Set VariableSet Amount = (BreathOfFire_Damage[Level] + (5.00 x (Real((Agility of (Triggering unit) (Include bonuses))))))
      • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Breath of Fire)'s Real Level Field: Damage ('Ucs1') of Level: (Level - 1) to Amount
So I'm changing the casting unit's Breath of Fire ability to deal the base damage + (5 * Agility). If the Ability is Level 3 then it will reference BreathOfFire_Damage[3] and deal the appropriate amount of damage.

Notice that I convert the Hero Attribute to a Real, this is required as Attributes are Integers but the Damage field is a Real.

Also, the Level field is actually indexed starting at 0. That's why I subtract 1 from Level. In other words, putting 0 in the "Level:" field is actually going to reference Ability Level 1.
0 = Level 1
1 = Level 2
2 = Level 3
etc

Finally, make sure that you use the correct version of "Damage". See how it has the code next to it's name: 'Ucs1'. You can view these codes in the Object Editor by pressing Control + D (Display Values As Raw Data). In Breath of Fire's case it uses Damage ('Ucs1'). See the picture I attached for an example.

So this trigger references the Object Editor data for the given ability and replaces one of it's fields with a new value. This is useful if you want to customize Blizzard's spells beyond the limitations of the Object Editor.
Is this MUI?
 
Level 18
Joined
Mar 16, 2008
Messages
721
Oh true.

Well I was worried if multiple players are spamming it, maybe the "level" variable could get used in the wrong player's trigger. still don't fully understand how that works. if triggers run one-at-a-time or not.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
Oh true.

Well I was worried if multiple players are spamming it, maybe the "level" variable could get used in the wrong player's trigger. still don't fully understand how that works. if triggers run one-at-a-time or not.
That'll never happen here. Here's how triggers execute (basically):

Step 1: An Event occurs. For example "A unit enters a Region".
Step 2: A unique instance of each trigger using that Event is created (if any exist).
Step 3: The game picks one of the trigger instances just created and executes all of it's logic. The one it picks is basically random.
Step 4: The game proceeds to the next trigger instance (if any exist). Note that this Step doesn't care about Waits. This is part of why Waits can cause problems.

So try to think of it like a queue, the triggers are lining up one by one and executing in some kind of order.

Or if you're familiar with Magic the Gathering, it's similar logic to "The Stack" mechanic.

So for example, if two units cast Breath of Fire at the "same time" then two trigger instances of my above trigger will be created. One instance will execute first, then the other after it. They will execute in the same game frame, however, one of them will technically happen first. This is why only one of us would get the kill credit if we both Breath of Fired a 1 hp unit at the same time. Someone has to deal the damage/kill the unit first, even though we both cast the ability at the same time. That someone would be whoever's trigger instance was chosen to execute first (so basically at random).

HOWEVER, there's a special case where the Actions of one trigger will insert themselves into the Actions of another trigger, breaking the Steps I described above. It's really rare and is related to specific Events/Actions. For instance, a trigger with the "A unit dies" event and a trigger that kills a unit (directly or with damage) can cause this issue to happen. When that happens there's a chance that things can break depending on the contents of the two triggers. For example, if both triggers were sharing a global variable then that variable's value may get changed to something undesirable and cause problems.
 
Last edited:
Top