• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Scaling skills

Level 4
Joined
Oct 9, 2024
Messages
63
I'm making a healing skill for a hero and I want the higher his intelligence attribute, the greater his healing, how do I make a spell like the paladin's holy light start to be affected by the hero's amount of intelligence.
 

Remixer

Map Reviewer
Level 33
Joined
Feb 19, 2011
Messages
2,112
The implementation requires triggering - the amount depending on how refined you want the system to be.
The essential steps are as follows:
1) Detect when a unit starts to cast the spell of interest (Holy Light)
2) Get the casting unit's hero stat Intelligence and use it in the predefined formula to calculate the amount of desired healing.
3) Change the value that the ability heals through the native Ability - Set Ability Real Level Field.

If you want to make the system more user-friendly you might wish to update the ability's tooltip whenever the healing value changes. This can be done by detecting situations when the units' intelligence amount (or the spell level) changes. Alternatively, you can update the tooltip periodically, which might be an easier solution to implement, depending on the complexity of your map. The tooltip can be updated with the Ability - Tooltip natives.

Edit:
This is essentially the trigger you might want to recreate.
(Note: Depending on the complexity of the map the variable names and system accuracy might be insufficient).
  • Melee Initialization
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Holy Light
    • Actions
      • Set VariableSet AbilityLevel = (Level of Holy Light for (Triggering unit))
      • Set VariableSet HeroIntelligence = (Intelligence of (Triggering unit) (Include bonuses))
      • Set VariableSet HealAmount = ((200.00 x (Real(AbilityLevel))) + (Real(HeroIntelligence)))
      • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Holy Light)'s Real Level Field: Amount Healed/Damaged ('Hhb1') of Level: (AbilityLevel - 1) to HealAmount
 
Last edited:
Level 4
Joined
Oct 9, 2024
Messages
63
Could you please send me a map file with this trigger, I learn better by seeing them in the editor.
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
What Remixer quoted is exactly how it looks in the editor. Are you using a non-english language editor making it difficult to find the functions in your language? There is the trigger action search box BTW, which is relevant because many of the new actions are not sorted/grouped with other similar older functions so it may be easier to search than to scroll the list.
 
Level 4
Joined
Oct 9, 2024
Messages
63
I understand your answer, what if I want different levels of the same magic to have different scales? the higher the level, the higher the scale.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,876
I understand your answer, what if I want different levels of the same magic to have different scales? the higher the level, the higher the scale.
Do you understand what these Variables are doing?
  • Set VariableSet HeroIntelligence = (Intelligence of (Triggering unit) (Include bonuses))
  • Set VariableSet HealAmount = ((200.00 x (Real(AbilityLevel))) + (Real(HeroIntelligence)))
HeroIntelligence = How much Intelligence your hero has.
HealAmount = The final result, how much you will heal.

I recommend playing around with these variables and using the Arithmetic function to see what you can come up with. Just remember that AbilityLevel is an Integer and your "Scale" will likely use a Real which means you have to do Conversion -> Convert Integer To Real or Convert Real To Integer. You can see an example of this with AbilityLevel being multiplied by 200.00.

Hint: HeroIntelligence is a good place to start. Try multiplying that variable by your scale.
 
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
you have to do Conversion -> Convert Integer To Real or Convert Real To Integer
@Teldrin, Uncle sort of glossed over this here and I'm certain he would say the same if he had thought to say it:
  • Converting to reals and working only with real variables is generally the way you want to go for 99% of all things you might ever do with numbers in wc3. Arithmetic using real numbers works as you expect: (3.5)(2)(0.85) = 5.95

  • Converting to integers and working only with integer variables can behave in ways you might not anticipate because integer operations do not ever round up, they only ever round down (otherwise known as "truncating"). These often seem like bugs, though they follow their own consistent logic. Usually you would not convert everything in a computation into ant int because it is simply annoying to do that, but lest you forget and do something like "(Level of Ability) / 4" where they are all integers you may get something odd:
    _
    • (3.5) as an integer becomes 3
    • (2) as an integer becomes 2
    • (0.85) as an integer becomes 0
    • Therefore int(3.5)*int(2)*int(0.85) = 0. Yes actually 0!
      _
  • GUI can't do this, but in a mixed-case operation the end result will be a real. As long as the computation doesn't have any two consecutive integers there is nothing to worry about (because any int operating with a real will always give a real, so no opportunity for fuckery).

TL;DR - Always convert to reals, never convert to integers unless you know it won't produce an issue.
 
Level 4
Joined
Oct 9, 2024
Messages
63
Where is my error?
  • Untitled Trigger 001
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Holy Light
    • Actions
      • Set VariableSet AbilityLevel = (Level of Holy Light for (Triggering unit))
      • Set VariableSet HeroIntelligence = (Intelligence of (Triggering unit) (Include bonuses))
      • Set VariableSet HealAmount = (Max((Real(AbilityLevel)), (Real(HeroIntelligence))))
      • If ((Ability being cast) Equal to Holy Light) then do (Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Holy Light)'s Real Level Field: Amount Healed/Damaged ('Udc1') of Level: (Min(AbilityLevel, -1)) to HealAmount) else do (Do nothing)
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,876
This line doesn't make any sense:
  • Set VariableSet HealAmount = (Max((Real(AbilityLevel)), (Real(HeroIntelligence))))
Do you know what Max does? It picks whichever of the two variables has the largest value and uses that value, which would likely always be HeroIntelligence. So you're setting HealAmount = Intelligence.

Also, you don't need to use an If Then Else. Just change the Ability directly:
  • Actions
    • Set VariableSet AbilityLevel = (Level of Holy Light for (Triggering unit))
    • Set VariableSet HeroIntelligence = (Intelligence of (Triggering unit) (Include bonuses))
    • Set VariableSet HealAmount = (Max((Real(AbilityLevel)), (Real(HeroIntelligence))))
    • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Holy Light)'s Real Level Field: Amount Healed/Damaged ('Udc1') of Level: (AbilityLevel - 1) to HealAmount)
Another problem, you used the Min function for the Level. This does the opposite of Max, it picks whichever of the two variables has the smallest value and uses that value. In this case you're always setting the Level to -1 which doesn't make any sense and won't work.

Like I said before, you want to use the Arithmetic function to add/subtract/multiply/divide your different variables.
 
Last edited:
Level 4
Joined
Oct 9, 2024
Messages
63
Where did I go wrong now?
  • Untitled Trigger 001
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Holy Light
    • Actions
      • Set VariableSet AbilityLevel = (Level of Holy Light for (Triggering unit))
      • Set VariableSet HeroIntelligence = (Intelligence of (Triggering unit) (Include bonuses))
      • Set VariableSet HealAmount = ((Real(AbilityLevel)) + (Real(HeroIntelligence)))
      • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Holy Light)'s Real Level Field: Amount Healed/Damaged ('Hhb1') of Level: (AbilityLevel - 1) to HealAmount
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,876
Where did I go wrong now?
  • Untitled Trigger 001
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Holy Light
    • Actions
      • Set VariableSet AbilityLevel = (Level of Holy Light for (Triggering unit))
      • Set VariableSet HeroIntelligence = (Intelligence of (Triggering unit) (Include bonuses))
      • Set VariableSet HealAmount = ((Real(AbilityLevel)) + (Real(HeroIntelligence)))
      • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Holy Light)'s Real Level Field: Amount Healed/Damaged ('Hhb1') of Level: (AbilityLevel - 1) to HealAmount
That should work fine. Your only issue is the math for HealAmount, you're adding AbilityLevel + HeroIntelligence.

So if the Ability is Level 2 and the Hero has 25 Intelligence, your HealAmount will be 2 + 25 = 27.


Here's an example of increasing the Heal's intelligence scaling per level:
  • Events
    • Unit - A unit Begins casting an ability
  • Conditions
    • (Ability being cast) Equal to Holy Light
  • Actions
    • Set VariableSet AbilityLevel = (Level of Holy Light for (Triggering unit))
    • Set VariableSet AbilityScale = (0.8 + (0.2 x (Real(AbilityLevel)))
    • Set VariableSet HeroIntelligence = (Real(Intelligence of (Triggering unit) (Include bonuses)))
    • Set VariableSet HeroIntelligence = (HeroIntelligence x AbilityScale)
    • Set VariableSet HealAmount = (200.00 x (Real(AbilityLevel)))
    • Set VariableSet HealAmount = (HealAmount + HeroIntelligence)
    • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Holy Light)'s Real Level Field: Amount Healed/Damaged ('Udc1') of Level: (AbilityLevel - 1) to HealAmount)
I changed HeroIntelligence to be a Real variable since that made everything easier. I added a new variable, AbilityScale, which is a Real variable that increases based on AbilityLevel. It's set to (0.80 + 0.20 per level) which means it'll use 100% of your Intelligence at Level 1, 120% at Level 2, and 140% at Level 3.

So if Holy Light was Level 2 and your Hero had 30 Intelligence then the final result would be:
HealAmount = (200 * 2)
HealAmount = 400 + 36
HealAmount = 436
 
Last edited:
Level 4
Joined
Oct 9, 2024
Messages
63
I understand the formula, but I would like to ask why -1 in this part of the trigger
1729710308149.png
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,876
Good question, that's because it's indexed starting at 0. It was a rather stupid decision by the Reforged developers to handle it that way when working in the Trigger Editor.

In other words, the developers decided that:
0 = Level 1
1 = Level 2
2 = Level 3

So you need to subtract 1 from the Ability Level to make it work.

The original Warcraft 3 developers had decided that when you're working in the Trigger Editor (GUI) it was more logical for the average user to start at 1 for most things. A Level 0 ability cannot exist after all. Although, there are some rare cases where they were inconsistent as well (Teams come to mind).
 
Last edited:
Level 4
Joined
Oct 9, 2024
Messages
63
So putting this -1 at the end of the trigger wouldn't make the entire trigger only affect the spell at its level 1?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,876
So putting this -1 at the end of the trigger wouldn't make the entire trigger only affect the spell at its level 1?
Not sure I understand but it's a pretty simple rule:

Put the current level of the Ability here:
  • Level Field: Amount Healed/Damaged ('Udc1') of Level: X
But subtract 1 from X.

Level: 0 = Level 1
Level: 1 = Level 2
Level: 2 = Level 3
 
Top