• 🏆 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!

[Trigger] Abillity like Necromastery

Level 2
Joined
Apr 19, 2023
Messages
11
Hey! I was creating an ability that increases the intelligence of my hero by 1 everytime he kills a unit, the trigger works fine but is not MUI at all, meaning if i kill more than 1 unit at a time the other effects will freeze. Any help with how i transform this into MUI? Thanks in advance.
  • Sacrifice
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Level of Sacrifice for (Killing unit)) Equal to 1
    • Actions
      • Set VariableSet Sacrifice_TU = (Killing unit)
      • Set VariableSet Sacrifice_LocTu = (Position of Sacrifice_TU)
      • Set VariableSet Sacrifice_LocDead = (Position of (Dying unit))
      • Unit - Create 1 Dummy Sacrifice for (Owner of Sacrifice_TU) at Sacrifice_LocTu facing (Angle from Sacrifice_LocDead to Sacrifice_LocTu) degrees
      • Set VariableSet Sacrifice_Soul = (Last created unit)
      • Trigger - Turn on Sacrifice Loop <gen>
  • Sacrifice Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Sacrifice_LocTu and Sacrifice_LocDead) Greater than or equal to 10.00
        • Then - Actions
          • Unit - Move Sacrifice_Soul instantly to (Sacrifice_LocDead offset by 12.00 towards (Angle from Sacrifice_LocDead to Sacrifice_LocTu) degrees.), facing (Angle from Sacrifice_LocDead to Sacrifice_LocTu) degrees
          • Set VariableSet Sacrifice_LocDead = (Position of Sacrifice_Soul)
          • Set VariableSet Sacrifice_LocTu = (Position of Sacrifice_TU)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Sacrifice_LocTu and Sacrifice_LocDead) Less than or equal to 25.00
        • Then - Actions
          • Unit - Kill Sacrifice_Soul
          • Unit - Remove Sacrifice_Soul from the game
          • Special Effect - Create a special effect at Sacrifice_LocDead using Abilities\Weapons\ZigguratMissile\ZigguratMissile.mdl
          • Special Effect - Set Scale of (Last created special effect) to 2.00
          • Special Effect - Destroy (Last created special effect)
          • Hero - Modify Intelligence of Sacrifice_TU: Add 1.
          • Set VariableSet Sacrifice_IntGain = (Sacrifice_IntGain + 1)
          • Ability - Set Extended Tooltip of Sacrifice to (Collects the souls of the enemies slain by the Cursed Noble, each soul gives |cff0080C01 intelligence|r. Because of the pact, all souls are lost on death. |n|n|cff0080C0Souls Collected: + ((String(Sacrifice_IntGain)) + .|r)) for level 0
          • Custom script: call RemoveLocation(udg_Sacrifice_LocTu)
          • Custom script: call RemoveLocation(udg_Sacrifice_LocDead)
          • Trigger - Turn off (This trigger)
        • Else - Actions

  • Sacrifice Dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Dying unit) Equal to Sacrifice_TU
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Sacrifice_Soul is alive) Equal to True
        • Then - Actions
          • Trigger - Turn off Sacrifice Loop <gen>
          • Unit - Kill Sacrifice_Soul
          • Unit - Remove Sacrifice_Soul from the game
          • Hero - Modify Intelligence of Sacrifice_TU: Subtract Sacrifice_IntGain.
          • Set VariableSet Sacrifice_IntGain = 0
        • Else - Actions
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
How about using a Missile System to do the leg work for you:
This allows you to easily send a Missile towards your Killing unit which will grant +1 Intelligence on impact.

You can then use Indexing or a Hashtable to convert the Sacrifice_IntGain variable into one that works for every unit or one unit per player depending on your method of choice.
 
Last edited:
Level 2
Joined
Apr 19, 2023
Messages
11
Thanks, ill look into it, but i dont even know custom scripts that much, imagine using a jass or lua script hahaha
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
Here's a working example, you don't really need to do much besides copy the triggers over to your map. Just remember that I'm referencing MY Sacrifice ability in my triggers, which will most likely have a different ID in your map thus "breaking" the triggers during the import process. The fix is simple, adjust anywhere my ability is being referenced to use your own ability instead.

It's MPI, meaning only one unit can have this ability per player. If you wanted it to be MUI (works for any number of units) it's a very easy change. All you need to do is import Bribe's Unit Indexer into your map and change the SacPN variable to use the Custom Value of the Sacrifice unit rather than it's Owner's Player Number.

A Unit Indexer is a system which automatically assigns a unique number to the units in your map. So if you had 100 units in your map then they'd all be numbered from 1 to 100. This number is stored to the unit using something called Custom Value, which is basically a bonus stat Blizzard provides to us in the Trigger Editor.

This isn't really all that useful until you begin combining it with Array variables. What this does is make your Array variables very powerful as they can now store data directly to individual units. This is done by plugging a unit's Custom value into the [index] of any Array, for example:
  • Unit - Create 1 Archmage for Player 1...
  • Set Variable AbilityPower[Custom value of (Last created unit)] = 100
AbilityPower is an Integer array variable. The number in the brackets is called it's [index]. An Array variable can have an index ranging from 0 to 32,768. Each [index] acts like a unique instance of the variable so you can store up to 32,768 unique Integer values inside of AbilityPower. Thinking back to the Unit Indexer we remember that it uses Custom Value which is an Integer. This is important since it means we can use it as the [index] in our Arrays, and since each unit has a unique Custom Value we know that the Array won't have any issues with conflicting data.
 

Attachments

  • Sacrifice Example 1.w3x
    1 MB · Views: 2
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
This helps a lot, thanks. Ill see if i learn some basic indexing while im at it
No problem. I find it helps to learn how to use Arrays first, then jump into Bribe's Unit Indexer demo map and test the map. There should be text messages that help explain what's happening. It's really super simple, try not to overthink it.
 
Level 2
Joined
Apr 19, 2023
Messages
11
yeah i actually tried fiddling with arrays before reading your answer, got nowhere tho haha,
  • Sacrifice
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Level of Sacrifice for (Killing unit)) Equal to 1
    • Actions
      • Set VariableSet Sacrifice_LocMui = (Sacrifice_LocMui + 1)
      • Set VariableSet Sacrifice_SoulsMui = (Sacrifice_SoulsMui + 1)
      • Set VariableSet Sacrifice_TU = (Killing unit)
      • Set VariableSet Sacrifice_LocTu = (Position of Sacrifice_TU)
      • Set VariableSet Sacrifice_LocDead[Sacrifice_LocMui] = (Position of (Dying unit))
      • Unit - Create 1 Dummy Sacrifice for (Owner of Sacrifice_TU) at Sacrifice_LocDead[Sacrifice_LocMui] facing (Angle from Sacrifice_LocDead[Sacrifice_LocMui] to Sacrifice_LocTu) degrees
      • Set VariableSet Sacrifice_Soul[Sacrifice_SoulsMui] = (Last created unit)
      • Trigger - Turn on Sacrifice Loop <gen>
  • Sacrifice Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Sacrifice_LocTu and Sacrifice_LocDead[Sacrifice_LocMui]) Greater than or equal to 25.00
        • Then - Actions
          • Unit - Move Sacrifice_Soul[Sacrifice_SoulsMui] instantly to (Sacrifice_LocDead[Sacrifice_LocMui] offset by 15.00 towards (Angle from Sacrifice_LocDead[Sacrifice_LocMui] to Sacrifice_LocTu) degrees.), facing (Angle from Sacrifice_LocDead[Sacrifice_LocMui] to Sacrifice_LocTu) degrees
          • Set VariableSet Sacrifice_LocDead[Sacrifice_LocMui] = (Position of Sacrifice_Soul[Sacrifice_SoulsMui])
          • Set VariableSet Sacrifice_LocTu = (Position of Sacrifice_TU)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Sacrifice_LocTu and Sacrifice_LocDead[Sacrifice_LocMui]) Less than or equal to 25.00
        • Then - Actions
          • Unit - Kill Sacrifice_Soul[Sacrifice_SoulsMui]
          • Unit - Remove Sacrifice_Soul[Sacrifice_SoulsMui] from the game
          • Special Effect - Create a special effect at Sacrifice_LocDead[Sacrifice_LocMui] using Abilities\Weapons\ZigguratMissile\ZigguratMissile.mdl
          • Special Effect - Set Scale of (Last created special effect) to 2.00
          • Special Effect - Destroy (Last created special effect)
          • Hero - Modify Intelligence of Sacrifice_TU: Add 1.
          • Set VariableSet Sacrifice_IntGain = (Sacrifice_IntGain + 1)
          • Ability - Set Extended Tooltip of Sacrifice to (Collects the souls of the enemies slain by the Cursed Noble, each soul gives |cff0080C01 intelligence|r. Because of the pact, all souls are lost on death. |n|n|cff0080C0Souls Collected: + ((String(Sacrifice_IntGain)) + .|r)) for level 0
          • Custom script: call RemoveLocation(udg_Sacrifice_LocTu)
          • Set VariableSet Sacrifice_LocMui = 0
          • Set VariableSet Sacrifice_SoulsMui = 0
          • Trigger - Turn off (This trigger)
        • Else - Actions
  • Sacrifice Dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Dying unit) Equal to Sacrifice_TU
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Sacrifice_Soul[Sacrifice_SoulsMui] is alive) Equal to True
        • Then - Actions
          • Trigger - Turn off Sacrifice Loop <gen>
          • Unit - Kill Sacrifice_Soul[Sacrifice_SoulsMui]
          • Unit - Remove Sacrifice_Soul[Sacrifice_SoulsMui] from the game
          • Special Effect - Create a special effect at Sacrifice_LocDead[Sacrifice_LocMui] using Abilities\Weapons\ZigguratMissile\ZigguratMissile.mdl
          • Special Effect - Set Scale of (Last created special effect) to 2.00
          • Special Effect - Destroy (Last created special effect)
          • Hero - Modify Intelligence of Sacrifice_TU: Subtract Sacrifice_IntGain.
          • Set VariableSet Sacrifice_IntGain = 0
          • Set VariableSet Sacrifice_LocMui = 0
          • Set VariableSet Sacrifice_SoulsMui = 0
          • Custom script: call RemoveLocation(udg_Sacrifice_LocTu)
        • Else - Actions
Leaking a location, i know, was trying to get it to work first. Ill try the system tho, seems fun to mess with
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,539
Some issues:
The idea of tracking when Sacrifice_TU dies doesn't make sense anymore since you want this to work for multiple units. Sacrifice_TU can only be equal to one unit at a time. With that it in mind, you can't reset Sacrifice variables back to 0 for the same reason. You need to be 100% sure that all instances of Sacrifice have resolved before resetting anything. Same goes for Turning off the trigger, you don't want to turn it off while others are still using it. Your Point array variable doesn't make much sense either assuming the units can move. You want to create brand new Points every 0.03 seconds to get updated information on the positions of your units. Remember, a variable doesn't magically update itself. It will contain a reference to whatever you Set it to at that EXACT moment.

I highly recommend using a Unit Indexer over what you're doing now. It's far more convenient and powerful.

You should track the (Killing units) using an Array Unit variable and use a Unit Group variable (non-array) to track the Soul Dummys.
  • Unit - Create 1 Dummy Sacrifice...
  • Set Variable Sacrifice_SoulTarget[(Custom value of (Last created unit)) = (Killing unit)
Then in your Loop trigger you can use the Pick Every Unit action to get a reference to your Dummy units and then using their Custom Value you can get a reference to their Sacrifice_SoulTarget[] which will be the (Killing unit) that spawned them. You could also track how many of these Souls are currently active using an Integer array variable that is linked to the (Killing unit), +1 on soul creation and -1 on soul completion. This way whenever a Soul reaches it's target you can subtract 1 from this Integer and if the Integer is equal to 0 then you know that all of that unit's Souls are finished and you can remove your (Killing unit) from the Unit Group. Then check if the Unit Group is empty as a result, and if it is you know that ALL instances of the ability are finished and you can finally Turn off your Loop trigger.

With this design you can also easily reset things when your unit with the Sacrifice ability dies. For instance, you can kill all of the active Souls that belong to it since you don't want them to affect the now dead unit. These Souls are in the Unit Group and are linked to their target with Sacrifice_SoulTarget[] so this information is readily available at any time. Do NOT destroy the Unit Group as it's intended to exist permanently (some people make this mistake when trying to fix memory leaks).
 
Last edited:
Level 2
Joined
Apr 19, 2023
Messages
11
Nice, i thinks its almost working (im still planning to use the system btw, just trying to see if i can learn how to do it myself), other than leaking locations, what am i missing?
  • Sacrifice
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Level of Sacrifice for (Killing unit)) Equal to 1
    • Actions
      • Set VariableSet MUI = (MUI + 1)
      • Set VariableSet Sacrifice_TU[MUI] = (Killing unit)
      • Set VariableSet Sacrifice_LocTu = (Position of Sacrifice_TU[(Custom value of (Killing unit))])
      • Set VariableSet Sacrifice_LocDead[MUI] = (Position of (Dying unit))
      • Unit - Create 1 Dummy Sacrifice for (Owner of Sacrifice_TU[MUI]) at Sacrifice_LocDead[MUI] facing (Angle from Sacrifice_LocDead[MUI] to Sacrifice_LocTu) degrees
      • Set VariableSet Sacrifice_Soul[(Custom value of (Last created unit))] = (Last created unit)
      • Unit Group - Add Sacrifice_Soul[(Custom value of (Last created unit))] to Sacrifice_DummyGroup
      • Trigger - Turn on Sacrifice Loop <gen>
  • Sacrifice Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Sacrifice_LocDead[MUI] and Sacrifice_LocTu) Greater than or equal to 25.00
        • Then - Actions
          • Unit Group - Pick every unit in Sacrifice_DummyGroup and do (Actions)
            • Loop - Actions
              • Unit - Move (Picked unit) instantly to (Sacrifice_LocDead[MUI] offset by 15.00 towards (Angle from Sacrifice_LocDead[MUI] to Sacrifice_LocTu) degrees.), facing (Angle from Sacrifice_LocDead[MUI] to Sacrifice_LocTu) degrees
              • Set VariableSet Sacrifice_LocDead[MUI] = (Position of (Picked unit))
              • Set VariableSet Sacrifice_LocTu = (Position of Sacrifice_TU[MUI])
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Sacrifice_LocDead[MUI] and Sacrifice_LocTu) Less than 25.00
        • Then - Actions
          • Special Effect - Create a special effect at (Position of Sacrifice_Soul[MUI]) using Abilities\Weapons\ZigguratMissile\ZigguratMissile.mdl
          • Special Effect - Set Scale of (Last created special effect) to 2.00
          • Special Effect - Destroy (Last created special effect)
          • Unit Group - Remove Sacrifice_Soul[(Custom value of (Last created unit))] from Sacrifice_DummyGroup.
          • Unit - Kill Sacrifice_Soul[(Custom value of (Last created unit))]
          • Unit - Remove Sacrifice_Soul[(Custom value of (Last created unit))] from the game
          • Hero - Modify Intelligence of Sacrifice_TU[MUI]: Add 1.
          • Set VariableSet Sacrifice_IntGain = (Sacrifice_IntGain + 1)
          • Ability - Set Extended Tooltip of Sacrifice to (Collects the souls of the enemies slain by the Cursed Noble, each soul gives |cff0080C01 intelligence|r. Because of the pact, all souls are lost on death. |n|n|cff0080C0Souls Collected: + ((String(Sacrifice_IntGain)) + .|r)) for level 0
          • For each (Integer MUI) from 1 to MUI, do (Actions)
            • Loop - Actions
              • Custom script: call RemoveLocation(udg_Sacrifice_LocTu)
              • Custom script: call RemoveLocation(udg_Sacrifice_LocDead)
          • Set VariableSet MUI = (MUI - 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • MUI Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
Also the custom value thingy, i got what it does but im still a bit lost on how to use it, i tried using like you said and setting it as killing unit, but it just removes my hero from the game when i remove it , unless i got it wrong and was not supposed to use it on the last created unit and use it on my killing unit instead, oh also, i meant gui but only in the sense of the dying unit, only one hero will have the Sacrifice ability.
 
Last edited:
Top