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

[GUI] Custom Life & Mana Drain 0.05

Custom Life & Mana Drain
by rulerofiron99

Description
Life/mana drain, except that you don't need to channel.

Features:
  • Configure life, mana drain and bonus drain for level up
  • Configure sfx for caster/target, lightning art, range (+level up), duration (+level up)
  • Fully MUI
  • To improve efficiency; distance check frequency can be changed.
  • Configure which buffs and states (e.g. invis) break the drain
  • Configure ethereal bonus

Requires Bribe's GUI Unit Indexer

Limited to one life drain flavour, that is, you can't use this system for two life drain spells in one map. To be added.

Triggers
  • NCLD Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set ncld_Ability = Life Drain
      • Set ncld_DrainHP = 25.00
      • Set ncld_DrainHPUp = 15.00
      • Set ncld_DrainMP = 0.00
      • Set ncld_DrainMPUp = 0.00
      • Set ncld_Duration = 5.00
      • Set ncld_Duration_Up = 2.00
      • Set ncld_Range = 500.00
      • Set ncld_RangeUp = 100.00
      • Set ncld_LightningArt = Drain
      • Set ncld_TargetSFXArt = Abilities\Spells\Other\Drain\DrainTarget.mdl
      • Set ncld_CasterSFXArt = Abilities\Spells\Other\Drain\DrainCaster.mdl
      • -------- Performance settings - how many loops between the actual drains and the distance checks, respectively --------
      • Set ncld_FreqDrain = 10
      • Set ncld_FreqDistance = 20
      • -------- Ethereal Bonus --------
      • Set ncld_EtherealBonus = 1.50
      • -------- Setup all buffs that will break life drain --------
      • Set ncld_buffId = (ncld_buffId + 1)
      • Set ncld_BuffList[ncld_buffId] = Wind Walk
      • -------- Checks - any of these well cancel the spell --------
      • Set ncld_CheckImmune = False
      • Set ncld_CheckResistant = False
      • Set ncld_CheckVisibile = True
      • -------- Don't edit below, the values are being adjusted to be used more than once a second --------
      • Set tempReal = ((Real(ncld_FreqDrain)) x 0.03)
      • Set ncld_DrainHP = (ncld_DrainHP x tempReal)
      • Set ncld_DrainHPUp = (ncld_DrainHPUp x tempReal)
      • Set ncld_DrainMP = (ncld_DrainMP x tempReal)
      • Set ncld_DrainMPUp = (ncld_DrainMPUp x tempReal)
  • NCLD Add
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to ncld_Ability
    • Actions
      • -------- gather data --------
      • Set tempUnit = (Triggering unit)
      • Set Key = (Custom value of tempUnit)
      • Set ncld_Target[Key] = (Target unit of ability being cast)
      • Unit Group - Add tempUnit to ncld_Group
      • Set ncld_Tick[Key] = 0
      • -------- set instance's values --------
      • Set ncld_TicksRemaining[Key] = (Integer(((ncld_Duration + (ncld_Duration_Up x (Real(((Level of ncld_Ability for tempUnit) - 1))))) x 33.00)))
      • Set ncld_Hp[Key] = (ncld_DrainHP + (ncld_DrainHPUp x (Real(((Level of ncld_Ability for tempUnit) - 1)))))
      • Set ncld_Mp[Key] = (ncld_DrainMP + (ncld_DrainMPUp x (Real(((Level of ncld_Ability for tempUnit) - 1)))))
      • Set ncld_Rng[Key] = (ncld_Range + (ncld_RangeUp x (Real(((Level of ncld_Ability for tempUnit) - 1)))))
      • -------- coords of source unit --------
      • Set tempLoc1 = (Position of tempUnit)
      • Custom script: set udg_tempX1 = GetLocationX(udg_tempLoc1)
      • Custom script: set udg_tempY1 = GetLocationY(udg_tempLoc1)
      • Custom script: set udg_tempZ1 = GetLocationZ(udg_tempLoc1)
      • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit))
      • Set tempZ1 = (tempZ1 + 60.00)
      • Custom script: call RemoveLocation(udg_tempLoc1)
      • -------- coords of target --------
      • Set tempLoc1 = (Position of ncld_Target[Key])
      • Custom script: set udg_tempX2 = GetLocationX(udg_tempLoc1)
      • Custom script: set udg_tempY2 = GetLocationY(udg_tempLoc1)
      • Custom script: set udg_tempZ2 = GetLocationZ(udg_tempLoc1)
      • Set tempZ2 = (tempZ2 + (Current flying height of ncld_Target[Key]))
      • Set tempZ2 = (tempZ2 + 60.00)
      • Custom script: call RemoveLocation(udg_tempLoc1)
      • -------- create lightning, sfx --------
      • Custom script: set udg_ncld_Lightning[udg_Key] = AddLightningEx(udg_ncld_LightningArt, true, udg_tempX1, udg_tempY1, udg_tempZ1, udg_tempX2, udg_tempY2, udg_tempZ2)
      • Special Effect - Create a special effect attached to the chest of tempUnit using ncld_CasterSFXArt
      • Set ncld_CasterSFX[Key] = (Last created special effect)
      • Special Effect - Create a special effect attached to the chest of ncld_Target[Key] using ncld_TargetSFXArt
      • Set ncld_TargetSFX[Key] = (Last created special effect)
      • -------- enable trigger --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (NCLD Loop <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on NCLD Loop <gen>
        • Else - Actions
  • NCLD Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in ncld_Group and do (Actions)
        • Loop - Actions
          • Set tempUnit = (Picked unit)
          • Set Key = (Custom value of tempUnit)
          • -------- check spell duration --------
          • Set ncld_TicksRemaining[Key] = (ncld_TicksRemaining[Key] - 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ncld_TicksRemaining[Key] Greater than or equal to 0
            • Then - Actions
              • -------- increment tick --------
              • Set ncld_Tick[Key] = (ncld_Tick[Key] + 1)
              • -------- every tick: move lightning --------
              • Set tempLoc1 = (Position of tempUnit)
              • Set tempLoc2 = (Position of ncld_Target[Key])
              • -------- coords of source unit --------
              • Custom script: set udg_tempX1 = GetLocationX(udg_tempLoc1)
              • Custom script: set udg_tempY1 = GetLocationY(udg_tempLoc1)
              • Custom script: set udg_tempZ1 = GetLocationZ(udg_tempLoc1) + GetUnitFlyHeight(udg_tempUnit) + 60
              • -------- coords of target --------
              • Custom script: set udg_tempX2 = GetLocationX(udg_tempLoc2)
              • Custom script: set udg_tempY2 = GetLocationY(udg_tempLoc2)
              • Custom script: set udg_tempZ2 = GetLocationZ(udg_tempLoc2) + GetUnitFlyHeight(udg_ncld_Target[udg_Key]) + 60
              • Custom script: call MoveLightningEx(udg_ncld_Lightning[udg_Key], true, udg_tempX1, udg_tempY1, udg_tempZ1, udg_tempX2, udg_tempY2, udg_tempZ2)
              • -------- transfer hp/mana --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (ncld_Tick[Key] mod ncld_FreqDrain) Equal to 0
                • Then - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (ncld_Target[Key] is Magic Immune) Equal to False
                    • Then - Actions
                      • Unit - Cause tempUnit to damage ncld_Target[Key], dealing 0.00 damage of attack type Spells and damage type Normal
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (ncld_Target[Key] is Ethereal) Equal to True
                        • Then - Actions
                          • Unit - Set life of ncld_Target[Key] to ((Life of ncld_Target[Key]) - (ncld_Hp[Key] x ncld_EtherealBonus))
                          • Unit - Set mana of ncld_Target[Key] to ((Mana of ncld_Target[Key]) - (ncld_Mp[Key] x ncld_EtherealBonus))
                          • Unit - Set life of tempUnit to ((Life of tempUnit) + (ncld_Hp[Key] x ncld_EtherealBonus))
                          • Unit - Set mana of tempUnit to ((Mana of tempUnit) + (ncld_Mp[Key] x ncld_EtherealBonus))
                        • Else - Actions
                          • Unit - Set life of ncld_Target[Key] to ((Life of ncld_Target[Key]) - ncld_Hp[Key])
                          • Unit - Set mana of ncld_Target[Key] to ((Mana of ncld_Target[Key]) - ncld_Mp[Key])
                          • Unit - Set life of tempUnit to ((Life of tempUnit) + ncld_Hp[Key])
                          • Unit - Set mana of tempUnit to ((Mana of tempUnit) + ncld_Mp[Key])
                    • Else - Actions
                • Else - Actions
              • -------- check distance --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (ncld_Tick[Key] mod ncld_FreqDistance) Equal to 0
                • Then - Actions
                  • Set tempDistance = (Distance between tempLoc1 and tempLoc2)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • tempDistance Greater than ncld_Rng[Key]
                    • Then - Actions
                      • -------- end spell --------
                      • Set ncld_Tick[Key] = 0
                      • Set ncld_TicksRemaining[Key] = 0
                      • Unit Group - Remove tempUnit from ncld_Group
                      • Set ncld_Target[Key] = No unit
                      • Lightning - Destroy ncld_Lightning[Key]
                      • Special Effect - Destroy ncld_CasterSFX[Key]
                      • Special Effect - Destroy ncld_TargetSFX[Key]
                    • Else - Actions
                • Else - Actions
                  • Set CheckBool = True
                  • For each (Integer LoopBuffs) from 1 to ncld_buffId, do (Actions)
                    • Loop - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (ncld_Target[Key] has buff ncld_BuffList[LoopBuffs]) Equal to True
                        • Then - Actions
                          • Set CheckBool = False
                        • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ncld_CheckImmune Equal to True
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (ncld_Target[Key] is Magic Immune) Equal to True
                        • Then - Actions
                          • Set CheckBool = False
                        • Else - Actions
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ncld_CheckResistant Equal to True
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (ncld_Target[Key] is Resistant) Equal to True
                        • Then - Actions
                          • Set CheckBool = False
                        • Else - Actions
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ncld_CheckVisibile Equal to True
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (ncld_Target[Key] is visible to (Owner of tempUnit)) Equal to False
                        • Then - Actions
                          • Set CheckBool = False
                        • Else - Actions
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Or - Any (Conditions) are true
                        • Conditions
                          • CheckBool Equal to False
                          • (ncld_Target[Key] is dead) Equal to True
                          • (ncld_Target[Key] is hidden) Equal to True
                    • Then - Actions
                      • -------- end spell --------
                      • Set ncld_Tick[Key] = 0
                      • Set ncld_TicksRemaining[Key] = 0
                      • Unit Group - Remove tempUnit from ncld_Group
                      • Set ncld_Target[Key] = No unit
                      • Lightning - Destroy ncld_Lightning[Key]
                      • Special Effect - Destroy ncld_CasterSFX[Key]
                      • Special Effect - Destroy ncld_TargetSFX[Key]
                    • Else - Actions
              • Custom script: call RemoveLocation(udg_tempLoc1)
              • Custom script: call RemoveLocation(udg_tempLoc1)
            • Else - Actions
              • -------- end spell --------
              • Set ncld_Tick[Key] = 0
              • Unit Group - Remove tempUnit from ncld_Group
              • Set ncld_Target[Key] = No unit
              • Lightning - Destroy ncld_Lightning[Key]
              • Special Effect - Destroy ncld_CasterSFX[Key]
              • Special Effect - Destroy ncld_TargetSFX[Key]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (ncld_Group is empty) Equal to True
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
To do list:
  • Allow multiple data sets
  • AoE option

Changelog

0.05
  • Added vision check
  • Frequency of drain and distance check configurable
  • Immunity, etc configurable
  • Added ethereal bonus (configurable)
0.04
  • Fixed a leak
  • Added check for spell immunity
0.03
  • Added check for hidden and specific buffs; e.g. invis/invulnerability (customisable)
  • Merged the addition for udg_tempZ1/2.


Credits
Bribe for his Unit Indexer, as always
http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/beginners-guide-lightning-effects-220370/ by -Derp-

Keywords:
life drain, mana drain, drain, non channel, non channel life drain, non channel mana drain, leech, life leech, mana leech
Contents

Customl Life/Mana Drain 0.05 (Map)

Reviews
01:24, 8th Sep 2012 Magtheridon96: Approved. If only GUI had some form of preprocessor directives. If it did, most of that crap if/then/else code could be a one-liner without needing any work done by the user. :/ Good job with this. That...

Moderator

M

Moderator

01:24, 8th Sep 2012
Magtheridon96: Approved.

If only GUI had some form of preprocessor directives.
If it did, most of that crap if/then/else code could be a one-liner without needing any work done by the user. :/

Good job with this.
That Buff-list is not something that people would often include in their resources, but I guess it could be useful in this case.
 
this

  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit))
    • Set tempZ1 = (tempZ1 + 60.00)
should be

  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit) + 60.0)
or better yet, merge them into the Custom script where you set the initial tempZ1
  • Custom script: set udg_tempZ1 = GetLocationZ(udg_tempLoc1) + GetUnitFlyHeight(udg_tempUnit) + 60.0
To improve efficiency; distance (for range check) only calculated every second, although the lightning effect updates at 0.03. Lightning effect also raises for flying units.

I think it is more efficient if it checks distance for every drain interval [in this case 0.3 seconds]... XD... and you might want to make the drain interval easily customizable by the user (e.g. put it into a variable at set-up)...

Suggestion:
instead of checking if tick is = 10 or 20 or 30, you might want to utilize the modulo function which returns the remainder of a division... so instead of tick = 10 or 20 or 30, you can just use if modulo of tick divided by 10 is equal to zero... that way you can just let the tick value go on and on instead of reseting it to 0 after it reaches 30... that way, you can also use the tick variable to determine if the drain is supposed to end already [effectively eliminating the need for the TicksRemaining variable]...
 
Level 8
Joined
Oct 26, 2008
Messages
387
It doesn't check if the target is hidden or invisible.

this

  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit))
    • Set tempZ1 = (tempZ1 + 60.00)
should be

  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit) + 60.0)
or better yet, merge them into the Custom script where you set the initial tempZ1
  • Custom script: set udg_tempZ1 = GetLocationZ(udg_tempLoc1) + GetUnitFlyHeight(udg_tempUnit) + 60.0


I think it is more efficient if it checks distance for every drain interval [in this case 0.3 seconds]... XD... and you might want to make the drain interval easily customizable by the user (e.g. put it into a variable at set-up)...

Suggestion:
instead of checking if tick is = 10 or 20 or 30, you might want to utilize the modulo function which returns the remainder of a division... so instead of tick = 10 or 20 or 30, you can just use if modulo of tick divided by 10 is equal to zero... that way you can just let the tick value go on and on instead of reseting it to 0 after it reaches 30... that way, you can also use the tick variable to determine if the drain is supposed to end already [effectively eliminating the need for the TicksRemaining variable]...

Some people say that reputation means nothing... but then i see people like you guys, spoting out problems right away, and giving constructive answers, this is the way things go one step forward. Just nice :)
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
this

  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit))
    • Set tempZ1 = (tempZ1 + 60.00)
should be

  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit) + 60.0)
or better yet, merge them into the Custom script where you set the initial tempZ1
  • Custom script: set udg_tempZ1 = GetLocationZ(udg_tempLoc1) + GetUnitFlyHeight(udg_tempUnit) + 60.0
Will do!

I think it is more efficient if it checks distance for every drain interval [in this case 0.3 seconds]... XD... and you might want to make the drain interval easily customizable by the user (e.g. put it into a variable at set-up)...

I'll add the option to customise, I know how intense distance checks can be, but then again how powerful many pcs these days are.

Suggestion:
instead of checking if tick is = 10 or 20 or 30, you might want to utilize the modulo function which returns the remainder of a division... so instead of tick = 10 or 20 or 30, you can just use if modulo of tick divided by 10 is equal to zero... that way you can just let the tick value go on and on instead of reseting it to 0 after it reaches 30... that way, you can also use the tick variable to determine if the drain is supposed to end already [effectively eliminating the need for the TicksRemaining variable]...

Isn't modulo a calculation (costly division calculation, and then some). I'd like to keep it like this, for efficiency's sake.


Make the same thing for mana too maybe ?

It already works for mana! You can customised it to drain life or mana or both, and change the lightning art and sfx.

EDIT:
Fixed:
- merged addition for tempZ
- checks for hidden
- checks a predetermined buff list for break
 
Last edited:
Level 22
Joined
Nov 14, 2008
Messages
3,256
There is actually more you can do.

-The buff checks are pure crap. Use boolean check if unit is visible. And Invulnerable.
-Use one static location for Z, the X/Y coordinates can be recieved from doing GetUnitX/Y(udg_tempUnit)
-Leaks
  • Set tempDistance = (Distance between (Point(tempX1, tempY1)) and (Point(tempX2, tempY2)))
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
There is actually more you can do.
-The buff checks are pure crap. Use boolean check if unit is visible. And Invulnerable.

I had a look, the only applicable boolean was visibility by triggers.

-Use one static location for Z, the X/Y coordinates can be recieved from doing GetUnitX/Y(udg_tempUnit)

Z has to be changing; units might change height during the course of the spell.

-Leaks
  • Set tempDistance = (Distance between (Point(tempX1, tempY1)) and (Point(tempX2, tempY2)))

Oh wow how did I miss that.
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
Oh, in JASS there is IsUnitVisible or something ^^

Anyway you can use one location for Z, just call "MoveLocation(loc, x, y)" and it should be fine.

Hmm, I suppose I can do a Player - Visibility check, although I've never worked with them before.

Don't quite understand what you mean about the Z - I still have to use 2 locations to check the distance anyway, right? Well technically I could just use distance formula, but what advantage does that give? Just a little neater?
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Alright let's break it down. And btw you forgot to merge a few variables, I'll fix it for ya here!

In the add trigger, instead of doing this:

  • Set tempLoc1 = (Position of tempUnit)
  • Custom script: set udg_tempX1 = GetLocationX(udg_tempLoc1)
  • Custom script: set udg_tempY1 = GetLocationY(udg_tempLoc1)
  • Custom script: set udg_tempZ1 = GetLocationZ(udg_tempLoc1)
  • Set tempZ1 = (tempZ1 + (Current flying height of tempUnit))
  • Set tempZ1 = (tempZ1 + 60.00)
  • Custom script: call RemoveLocation(udg_tempLoc1)
  • -------- coords of target --------
  • Set tempLoc1 = (Position of ncld_Target[Key])
  • Custom script: set udg_tempX2 = GetLocationX(udg_tempLoc1)
  • Custom script: set udg_tempY2 = GetLocationY(udg_tempLoc1)
  • Custom script: set udg_tempZ2 = GetLocationZ(udg_tempLoc1)
  • Set tempZ2 = (tempZ2 + (Current flying height of ncld_Target[Key]))
  • Set tempZ2 = (tempZ2 + 60.00)
  • Custom script: call RemoveLocation(udg_tempLoc1)
You can do like this:
  • Custom script: local real x
  • Custom script: local real y
  • Location StaticZ
  • Custom script: set x = GetUnitX(udg_tempUnit)
  • Custom script: set y = GetUnitY(udg_tempUnit)
  • Custom script: call Movelocation(udg_StaticZ, x, y)
  • Custom script: set udg_tempX1 = x
  • Custom script: set udg_tempY1 = y
  • Custom script: set udg_tempZ1 = GetLocationZ(udg_StaticZ) + GetUnitFlyHeight(udg_tempUnit) + 60.
  • Custom script: set x = GetUnitX(udg_ncld_Target[udg_key])
  • Custom script: set y = GetUnitY(udg_ncld_Target[udg_key])
  • -------- coords of target --------
  • Custom script: call Movelocation(udg_StaticZ, x, y)
  • Custom script: set udg_tempX2 = x
  • Custom script: set udg_tempY2 = y
  • Custom script: set udg_tempZ2 = GetLocationZ(udg_StaticZ) + GetUnitFlyHeight(udg_ncld_Target[udg_Key]) + 60.
You see the brilliance here? Now you re-use the location every single time AND it doesn't leak!
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
Ah, I see! Thanks again.

So this StaticZ point, I just keep moving it around, never using RemoveLocation on it? Or can I remove it at the end of each loop?

I still prefer the modulo version since its easier to modify... and it will be more friendly at the time that you make the interval to be easily changeable by the user... because right now, if the user changes the interval, then he needs to change the IF-Conditions too...

Fair enough, I'll change it.
 
Level 19
Joined
Feb 25, 2009
Messages
2,004
You could keep the effect on if the target is magic immune, since most people will not give a unit permanent immunity. Thus, if the immunity wears off, it can start draining it again. Otherwise it is just a waste of casting.

Also, please come up with some other name. This "Non-channeling" thing is just not fitting in here. Other things look good I guess.
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
You could keep the effect on if the target is magic immune, since most people will not give a unit permanent immunity. Thus, if the immunity wears off, it can start draining it again. Otherwise it is just a waste of casting.

Also, please come up with some other name. This "Non-channeling" thing is just not fitting in here. Other things look good I guess.

Alrighty. What name would you suggest? Custom Life Drain?
 
Top