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

Consume Mana V1.2

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
My first spell, or rather first spell worth uploading here :-D.
Creates an orb, that consumes mana from nearby enemy ground units and sends it to the caster. Units are damaged for the amount of mana consumed. If the caster dies befor receiving mana, an orb explodes, damaging all nearby units.
Level 1 - consumes 100 mana points
Level 2 - consumes 200 mana points
Level 3 - consumes 300 mana points

  • WConfiguration
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Ability Variable --------
      • Set W_Ability = Consume Mana
      • -------- Damage multiplier (variable index = level-1). Set it to 0 to negate damage --------
      • Set W_DamageMultiplier[0] = 1.00
      • Set W_DamageMultiplier[1] = 1.00
      • Set W_DamageMultiplier[2] = 1.00
      • -------- Amount of mana absorbed per level. If you want to add new levels, just increase variable size and add new amount, you don't have to change anything in other triggers. Just remember - index=level-1 --------
      • Set W_ManaAmount[0] = 100.00
      • Set W_ManaAmount[1] = 200.00
      • Set W_ManaAmount[2] = 300.00
      • -------- Damage Radius --------
      • Set W_Range[0] = 300.00
      • Set W_Range[1] = 300.00
      • Set W_Range[2] = 300.00
      • -------- Lightning effect between caster and central effect --------
      • Set W_MainLightningVisual = Seryjne bĹ‚yskawice - GĹ‚Ăłwne
      • -------- Lightning effect between targeted units and central effect --------
      • Set W_SecondaryLightningVisual = Seryjne bĹ‚yskawice - Dodatkowe
      • -------- Model path for central special effect. Just CnP it from object editor --------
      • Set W_CentralEffectVisual = Abilities\Weapons\SpiritOfVengeanceMissile\SpiritOfVengeanceMissile.mdl
      • -------- Radius of explosion (if caster is dead) --------
      • Set W_UltimateRange = 200.00
      • -------- Effect of the explosion --------
      • Set W_UltimateDamageEffect = Units\NightElf\Wisp\WispExplode.mdl
  • WCast
    • Events
      • Unit - A unit starts the effect of an ability
    • Warunki
      • (Ability being cast) Equals to W_Ability
    • Actions
      • Set W_Index = (W_Index + 1)
      • Set W_StolenMana[W_Index] = 0.00
      • Set W_LightningIndex[W_Index] = 0
      • Set W_Caster[W_Index] = (Triggering unit)
      • Set W_Point[W_Index] = (Target point of ability being cast)
      • Set W_Level[W_Index] = (Level of W_Ability for W_Caster[W_Index])
      • Special Effect - Create a special effect at W_Point[W_Index] using W_CentralEffectVisual
      • Set W_Effect[W_Index] = (Last created special effect)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • W_Index Equals to 1
        • Then - Actions
          • Trigger - Turn on WLoop <gen>
        • Else - Actions
  • WLoop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer W_Loop) from 1 to W_Index, do (Actions)
        • Loop - Actions
          • Set W_Counter[W_Loop] = (W_Counter[W_Loop] + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • W_Counter[W_Loop] Equals to 2
            • Then - Actions
              • Unit Group - Add all units of (Units within W_Range[(W_Level[W_Loop] - 1)] of W_Point[W_Loop] matching ((((Matching unit) is Ground Unit) Equals to YES) and (((Matching unit) belongs to an enemy of (Owner of W_Caster[W_Loop])) Equals to YES))) to W_Group[W_Loop]
              • Unit Group - Pick every unit in W_Group[W_Loop] and do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • And - All (Conditions) are true
                        • Conditions
                          • (Mana of (Picked unit)) Greater than 0.00
                          • ((Picked unit) is alive) Equals to YES
                    • Then - Actions
                      • Set W_PickedLocation = position of (picked unit)
                      • Lightning - Create a W_SecondaryLightningVisual lightning effect from source (Position of (Picked unit)) to target W_Point[W_Loop]
                      • Set W_Lightning[W_LightningIndex[W_Loop]] = (Last created lightning effect)
                      • Custom script: call RemoveLocation(udg_W_PickedLocation)
                      • Set W_LightningIndex[W_Loop] = (W_LightningIndex[W_Loop] + 1)
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Mana of (Picked unit)) Greater or Equal to W_ManaAmount[(W_Level[W_Loop] - 1)]
                        • Then - Actions
                          • Set W_StolenMana[W_Loop] = (W_StolenMana[W_Loop] + W_ManaAmount[W_Level[W_Loop]])
                          • Unit - Cause W_Caster[W_Loop] to damage (Picked unit), dealing (W_DamageMultiplier[(W_Level[W_Loop] - 1)] x W_ManaAmount[(W_Level[W_Loop] - 1)]) damage of attack type Spells and damage type Magic
                          • Unit - Set mana of (Picked unit) to ((Mana of (Picked unit)) - W_ManaAmount[(W_Level[W_Loop] - 1)])
                        • Else - Actions
                          • Set W_StolenMana[W_Loop] = (W_StolenMana[W_Loop] + (Mana of (Picked unit)))
                          • Unit - Cause W_Caster[W_Loop] to damage (Picked unit), dealing ((Mana of (Picked unit)) x W_DamageMultiplier[(W_Level[W_Loop] - 1)]) damage of attack type Spells and damage type Magic
                          • Unit - Set mana of (Picked unit) to 0.00
                    • Else - Actions
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • W_Counter[W_Loop] Equals to 6
                • Then - Actions
                  • Set W_Integer[W_Loop] = 0
                  • For each (Integer W_Integer[W_Loop]) from 0 to W_LightningIndex[W_Loop], do (Actions)
                    • Loop - Actions
                      • Lightning - Destroy W_Lightning[W_LightningIndex[W_Loop]]
                      • Set W_LightningIndex[W_Loop] = (W_LightningIndex[W_Loop] - 1)
                      • Set W_Integer[W_Loop] = (W_Integer[W_Loop] - 1)
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • W_Counter[W_Loop] Equals to 8
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (W_Caster[W_Loop] is alive) Equals to YES
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • W_StolenMana[W_Loop] Greater than 0.00
                            • Then - Actions
                              • Set W_CasterLocation = Position of W_Caster[W_Loop]
                              • Lightning - Create a W_MainLightningVisual lightning effect from source W_Point[W_Loop] to target W_CasterLocation
                              • Set W_MainLightning[W_Loop] = (Last created lightning effect)
                              • Custom script: call RemoveLocation(udg_CasterLocation)
                            • Else - Actions
                        • Else - Actions
                          • Unit Group - Add all units of (Units within W_UltimateRange of W_Point[W_Loop]) to W_UltimateDamageGroup[W_Loop]
                          • Set W_UltimateDamage[W_Loop] = (W_StolenMana[W_Loop] / (Real((Number of units in W_UltimateDamageGroup[W_Loop]))))
                          • Special Effect - Create a special effect at W_Point[W_Loop] using W_UltimateDamageEffect
                          • Special Effect - Destroy (Last created special effect)
                          • Unit Group - Pick every unit in W_UltimateDamageGroup[W_Loop] and do (Actions)
                            • Loop - Actions
                              • Unit - Cause W_Caster[W_Loop] to damage (Picked unit), dealing W_UltimateDamage[W_Loop] damage of attack type Spells and damage type Normal
                              • Unit Group - Remove (Picked unit) from W_UltimateDamageGroup[W_Loop]
                          • Special Effect - Destroy W_Effect[W_Loop]
                          • Custom script: call RemoveLocation(udg_W_Point[udg_W_Loop])
                          • Set W_Counter[W_Loop] = 0
                          • Set W_Index = (W_Index - 1)
                          • Set W_Loop = (W_Loop - 1)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • W_Index Equals to 0
                            • Then - Actions
                              • Trigger - Turn off WLoop <gen>
                            • Else - Actions
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • W_Counter[W_Loop] Equals to 9
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • W_StolenMana[W_Loop] Greater than 0.00
                            • Then - Actions
                              • Lightning - Destroy W_MainLightning[W_Loop]
                            • Else - Actions
                          • Unit - Set mana of W_Caster[W_Loop] to ((Mana of W_Caster[W_Loop]) + W_StolenMana[W_Loop])
                          • Special Effect - Destroy W_Effect[W_Loop]
                          • Custom script: call RemoveLocation(udg_W_Point[udg_W_Loop])
                          • Unit Group - Remove all units from W_Group[W_Loop]
                          • Set W_Counter[W_Loop] = 0
                          • Set W_Index = (W_Index - 1)
                          • Set W_Loop = (W_Loop - 1)
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • W_Index Equals to 0
                            • Then - Actions
                              • Trigger - Turn off WLoop <gen>
                            • Else - Actions
                        • Else - Actions

If you want to add more levels to the ability, simply add new level in object editor, and new data in configuration trigger - you don't have to change anything in loop and cast triggers.
  • 1.0 - uploaded
  • 1.1 - loop is now turned off when index is equal to 0, lightning no longer displays when spell doesn't steal any mana, changed integer A to custom variable, deleted 'skip remaining actions
  • 1.2 - removed location leaks


Keywords:
Mana, orb, drain, explode, ball, lightning, mage, arcane,
Contents

Consume 1.00 Test (Map)

Reviews
20:31, 1st Sep 2015 IcemanBo: http://www.hiveworkshop.com/forums/spells-569/consume-mana-v1-2-a-269240/#post2725315
Level 37
Joined
Jul 22, 2015
Messages
3,485
Pretty impressive for your first spell :) however, there are still a lot things you're going to need to work on.


  • Why are you doing variable index = level - 1 to find out the level of an ability? You can just save time and do variable index = level.
  • All your unit groups leak.
  • I wouldn't recommend using (Integer A). Create your own variable for it.
  • What's the purpose of using Skip remaining actions?
  • You're going to want to recycle any variable that's in the Cast trigger that is being used in the loop.
  • You're not turning the loop off. Use a condition that checks if index = 0, if so turn loop off.

  • What is the purpose of this? You can just make the unit group only pick enemy units.
    • Unit Group - Add all units of (Units within W_Range[(W_Level[W_Loop] - 1)] of W_Point[W_Loop] matching (((Matching unit) is A ground unit) Equal to True)) to W_Group[W_Loop]
    • Player Group - Pick every player in (All allies of (Owner of W_Caster[W_Loop])) and do (Actions)
      • Loop - Actions
        • Unit Group - Remove all units of (Units owned by (Picked player)) from W_Group[W_Loop]
  • You don't need to put And - All (Conditions are true)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • And - All (Conditions) are true
          • Conditions
            • (Mana of (Picked unit)) Greater than 0.00
            • ((Picked unit) is alive) Equal to True
 
Level 20
Joined
Feb 23, 2015
Messages
243
[*]Why are you doing variable index = level - 1 to find out the level of an ability? You can just save time and do variable index = level.
I used to think that array size matters, and after I found out it doesn't, I just didn't have enough patience to change this fragment of code :-D.
[*]All your unit groups leak.
When I used custom script to remove them, the instance stopped workin' at all. I thought that when I remove all units from group, I'll be able to recycle this group next time the instance runs, so I will only have as many groups as maximum number of instances at one time. I'll look into it again.
[*]I wouldn't recommend using (Integer A). Create your own variable for it.
I'll do it, although I don't think I really need new variable in this place, as I don't use it in loop :).
[*]What's the purpose of using Skip remaining actions?
I thought it works like break function from C++, so it stops current istance of the loop. I'll delete it if it doesn't.
[*]You're going to want to recycle any variable that's in the Cast trigger that is being used in the loop.
What do you mean?
[*]You're not turning the loop off. Use a condition that checks if index = 0, if so turn loop off.
I forgot :-D.

[*]What is the purpose of this? You can just make the unit group only pick enemy units.
  • Unit Group - Add all units of (Units within W_Range[(W_Level[W_Loop] - 1)] of W_Point[W_Loop] matching (((Matching unit) is A ground unit) Equal to True)) to W_Group[W_Loop]
  • Player Group - Pick every player in (All allies of (Owner of W_Caster[W_Loop])) and do (Actions)
    • Loop - Actions
      • Unit Group - Remove all units of (Units owned by (Picked player)) from W_Group[W_Loop]
So I can put 'AND' condition in adding units to group. I didn't know, thanks.
[*]You don't need to put And - All (Conditions are true)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • And - All (Conditions) are true
        • Conditions
          • (Mana of (Picked unit)) Greater than 0.00
          • ((Picked unit) is alive) Equal to True
Ok, thank you. I'm gonna work on this things :-D.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
When I used custom script to remove them, the instance stopped workin' at all. I thought that when I remove all units from group, I'll be able to recycle this group next time the instance runs, so I will only have as many groups as maximum number of instances at one time. I'll look into it again.

You're probably destroying it to early. Place them where you're removing all the units from the group.

I'll do it, although I don't think I really need new variable in this place, as I don't use it in loop :).

Using Integer A is slower because its another function call. Someone else could also decide to use your spell in their map, and what's going to happen if they are using Integer A in another trigger? Baaad things.

I thought it works like break function from C++, so it stops current istance of the loop. I'll delete it if it doesn't.

You use break in a ranged-based loop to reach a specific array in C++, which is not at all what you're doing here in a spell xP You would want to stop the current instance of the loop when the spell instance is done. That's where recycling + counter timers come into play.

What do you mean?

You basically re-adjust all current instances of the spell. It's what helps a spell become MUI. Think of it like this:

You have 3 instances of your spell that happen almost simultaneously. Data would be anything like Caster, CasterLoc, Target, TargetLoc, etc.
  • Instance 1 (data x)
  • Instance 2 (data y)
  • Instance 3 (data z)
Instance 1 will finish first because it was casted first. Once Instance 1 is done casting, you need to re-adjust Instance 2 to be Instance 1, and Instance 3 to be Instance 2. We want a result like this:
  • Instance 1 (data y)
  • Instance 2 (data z)
This is currently what your trigger is doing.
  • Instance 1 (data x + y)
  • Instance 2 (data y + z)
So I can put 'AND' condition in adding units to group. I didn't know, thanks.

Yes :) I would recommend a method like this. It looks cleaner and its a lot easier to read.
 
Level 20
Joined
Feb 23, 2015
Messages
243
I fixed loop, deleted 'skip remaining actions', added custom integer, but after I try to remove group with:
  • Custom script: call DestroyGroup (udg_W_Group[udg_W_Loop])
I can't recycle this instance again. Group is permanently deleted, and I cannot use instance 1.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I fixed loop, deleted 'skip remaining actions', added custom integer, but after I try to remove group with:
  • Custom script: call DestroyGroup (udg_W_Group[udg_W_Loop])
I can't recycle this instance again. Group is permanently deleted, and I cannot use instance 1.

You aren't recycling that xP its not used in the Init trigger. Can you also update your triggers in the description?
 
Leaks must been fixed. Create a thread in Triggers & Scripts forum if you have problems with your code. http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/memory-leaks-263410/#post2661133

Where do you deindex? http://www.hiveworkshop.com/forums/...orials-279/visualize-dynamic-indexing-241896/

Make as much configurable as possible. For example attack- damage type should be.

Responses like (Picked Unit) should be stored into a variable when used more often.

'And All Conditions are True' only can be useful with combination with 'Or Any Condtions" block. In your case it's not needed.

"W" is not enough for a prefix, it should have at least 2-3 letters.

The (Level -1) could be done once onCast.
 
Top