• 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.

Death Coil v1.1c

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Requires

Leakless - Hopefully
Lagless - Yes
MUI - Yes
MPI - yes

Description
The Death Knight tethers a target unit to a demonic obelisk. If the target unit exceeds a set distance from the obelisk, the link will snap dealing damage and instantly moveing the target unit back to the obelisk.

Level 1 - Deals 75 damage. 500 max distance. Last for 15 seconds.
Level 2 - Deals 125 damage. 600 max distance. Last for 20 seconds.
Level 3 - Deals 175 damage. 700 max distance. Last for 25 seconds.
Level 4 - Deals 225 damage. 800 max distance. Last for 30 seconds.

Mana Cost: 100
Cooldown: 26 / 24 / 22 / 20

JASS:
                                   // Death Coil \\
                                  // by: Carnerox \\
                                 //   credits to:  \\
                //Jesus4Lyf for SpellStruct, Damage, AIDS, and Event\\

                // How to use import this spell:
                // 1) Copy this trigger
                // 2) Open your map, create a new trigger with the name "Death Coil".
                // 3) Click Edit, and convert the trigger to custom text.
                // 4) Copy the trigger, and paste it into the trigger.
                // 5) Add all the systems that the spell uses.
                // 6) Change the ABIL_ID, and DUMMY_ID to the correct rawcodes, and customize the spell to what you want.

scope DeathCoil  
    ////////////////////////////////CONFIGURATION DATA!\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    globals
        private constant integer    ABIL_ID         = 'A000' // Rawcode of the ability.
        private constant integer    DUMMY_ID        = 'h000' // Rawcode of the obelisk.
        private constant real       PERIODIC        = 0.01   // How often the timer will run the function.
        private constant real       COLOR_R         = 100.00 // Lightning red
        private constant real       COLOR_G         = 0.00   // Lightning green
        private constant real       COLOR_B         = 0.00   // Lightning blue
        private constant real       COLOR_A         = 10.00  // Lightning alpha
        private constant real       FLOAT           = 45.00  // Lightning height
        private constant string     LIGHTNING_ID    = "MFPB" // Lightning type - Mana Flare
        private constant string     EFFECT          = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl" //Effect when link snaps
        private constant attacktype ATTACK_TYPE     = ATTACK_TYPE_NORMAL //Attack type dealt
        private constant damagetype DAMAGE_TYPE     = DAMAGE_TYPE_MAGIC //Damage type dealt
        private constant boolean    DAMAGE_MELEE    = true //Is the damage melee?
        private constant boolean    DAMAGE_RANGED   = false //Is the damage ranged?
        private constant boolean    SHARED_VISION   = true //Is there shared vision of the Target?
    endglobals
    ///////////////////// Do not change anything in this struct!\\\\\\\\\\\\\\\\\
    private struct DeathCoil extends SpellStruct
        unit Dummy
        lightning Lightning
        real x
        real y
        real x1
        real x2
        real y1
        real y2
        real z1
        real z2
        implement SpellStruct
        
        //How much damage is dealt to the Target
        method operator Damage takes nothing returns real
            return 50.00*.level+25.00
        endmethod
        
        //Distance of how far the unit can move away from the Obelisk
        method operator Distance takes nothing returns real
            return 100*.level+400.00
        endmethod
        
        //Duration of the Obelisk
        method operator Duration takes nothing returns real
            return 5.00*.level+10.00
        endmethod
        
        //The z of the Obelisk, and Target
        method GetUnitZ takes unit u returns real
            local location Point=Location(GetUnitX(u),GetUnitY(u))
            local real Real=GetLocationZ(Point)+GetUnitFlyHeight(u)
            call RemoveLocation(Point)
            set Point=null
            return Real
        endmethod
        
        ///////////////////////////END OF CONFIGURATION DATA!\\\\\\\\\\\\\\\\\\\\\\\
        method periodic takes nothing returns nothing
            set .x2=GetUnitX(.targetUnit)
            set .y2=GetUnitY(.targetUnit)
            set .z2=GetUnitZ(.targetUnit)+FLOAT
            set .x=.x2-.x1
            set .y=.y2-.y1
            call MoveLightningEx(.Lightning,true,.x1,.y1,.z1,.x2,.y2,.z2)
            if (SquareRoot(.x*.x+.y*.y)>=this.Distance) then
                call .stopTimer(.periodic)
                call DestroyLightning(.Lightning)
                call DestroyEffect(AddSpecialEffect(EFFECT,.x1,.y1))
                call DestroyEffect(AddSpecialEffect(EFFECT,.x2,.y2))
                call RemoveUnit(.Dummy)
                call SetUnitX(.targetUnit,.x1)
                call SetUnitY(.targetUnit,.y1)
                static if (LIBRARY_Damage) then
                    call Damage_Spell(.caster,.targetUnit,this.Damage)
                else
                    call UnitDamageTarget(.caster,.targetUnit,this.Damage,DAMAGE_MELEE,DAMAGE_RANGED,ATTACK_TYPE,DAMAGE_TYPE,null)
                endif
                if (SHARED_VISION==true) then
                    call UnitShareVision(.targetUnit,.owner,false)
                endif
                set .Dummy=null
                set .Lightning=null
            elseif (IsUnitType(.Dummy,UNIT_TYPE_DEAD)==true) or (IsUnitType(.targetUnit,UNIT_TYPE_DEAD)==true) then
                call .stopTimer(.periodic)
                call DestroyLightning(.Lightning)
                call DestroyEffect(AddSpecialEffect(EFFECT,.x1,.y1))
                call RemoveUnit(.Dummy)
                if (SHARED_VISION==true) then
                    call UnitShareVision(.targetUnit,.owner,false)
                endif
                set .Dummy=null
                set .Lightning=null
            endif
        endmethod

        method onEffect takes nothing returns nothing
            set .x2=GetUnitX(.targetUnit)
            set .y2=GetUnitY(.targetUnit)
            set .z2=GetUnitZ(.targetUnit)+FLOAT
            set .Dummy=CreateUnit(.owner,DUMMY_ID,.x2,.y2,0.00)
            set x1=GetUnitX(.Dummy)
            set y1=GetUnitY(.Dummy)
            set .z1=GetUnitZ(.Dummy)+FLOAT
            set .Lightning=AddLightningEx(LIGHTNING_ID,true,.x1,.y1,.z1,.x2,.y2,.z2)
            call UnitApplyTimedLife(.Dummy,'BTLF',this.Duration)
            call SetLightningColor(.Lightning,COLOR_R,COLOR_G,COLOR_B,COLOR_A)
            if (SHARED_VISION==true) then
                call UnitShareVision(.targetUnit,.owner,true)
            endif
            call .startTimer(.periodic,PERIODIC)
        endmethod
       
        private static method onInit takes nothing returns nothing
            set thistype.abil=ABIL_ID
        endmethod
    endstruct
endscope
JASS:
                                   // Death Coil \\
                                  // by: Carnerox \\
                                 //   credits to:  \\
                //Jesus4Lyf for SpellStruct, Damage, AIDS, and Event\\

                // How to use import this spell:
                // 1) Copy this trigger
                // 2) Open your map, create a new trigger with the name "Death Coil".
                // 3) Click Edit, and convert the trigger to custom text.
                // 4) Copy the trigger, and paste it into the trigger.
                // 5) Add all the systems that the spell uses.
                // 6) Change the ABIL_ID, and DUMMY_ID to the correct rawcodes, and customize the spell to what you want.
scope DeathCoil  
    ////////////////////////////////CONFIGURATION DATA!\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    globals
        private constant integer    ABIL_ID         = 'A000' // Rawcode of the ability.
        private constant integer    DUMMY_ID        = 'h000' // Rawcode of the obelisk.
        private constant real       PERIODIC        = 0.01   // How often the timer will run the function.
        private constant real       COLOR_R         = 100.00 // Lightning red
        private constant real       COLOR_G         = 0.00   // Lightning green
        private constant real       COLOR_B         = 0.00   // Lightning blue
        private constant real       COLOR_A         = 10.00  // Lightning alpha
        private constant real       FLOAT           = 45.00  // Lightning height
        private constant string     LIGHTNING_ID    = "MFPB" // Lightning type - Mana Flare
        private constant string     EFFECT          = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl" //Effect when link snaps
        private constant attacktype ATTACK_TYPE     = ATTACK_TYPE_NORMAL //Attack type dealt
        private constant damagetype DAMAGE_TYPE     = DAMAGE_TYPE_MAGIC //Damage type dealt
        private constant boolean    DAMAGE_MELEE    = true //Is the damage melee?
        private constant boolean    DAMAGE_RANGED   = false //Is the damage ranged?
        private constant boolean    SHARED_VISION   = true //Is there shared vision of the Target?
    endglobals
    
    ///////////////////// Do not change anything in this struct!\\\\\\\\\\\\\\\\\
    private struct DeathCoil
        static unit Caster
        static unit Target
        static unit Dummy
        static player Owner
        static lightning Lightning
        static timer Timer=CreateTimer()
        static integer Level
        static real x
        static real y
        static real x1
        static real x2
        static real y1
        static real y2
        static real z1
        static real z2
    
        //How much damage is dealt to the Target
        private static method Damage takes integer level returns real
            return 50.00*level+25.00
        endmethod
        
        //Distance of how far the unit can move away from the Obelisk
        private static method Distance takes integer level returns real
            return 100*level+400.00
        endmethod
        
        //Duration of the Obelisk
        private static method Duration takes integer level returns real
            return 5.00*level+10.00
        endmethod
        
        //The z of the Obelisk, and Target
        private static method GetUnitZ takes unit u returns real
            local location Point=Location(GetUnitX(u),GetUnitY(u))
            local real Real=GetLocationZ(Point)+GetUnitFlyHeight(u)
            call RemoveLocation(Point)
            set Point=null
            return Real
        endmethod
        
        ///////////////////////////END OF CONFIGURATION DATA!\\\\\\\\\\\\\\\\\\\\\\\
        private static method periodic takes nothing returns nothing
            set DeathCoil.x2=GetUnitX(DeathCoil.Target)
            set DeathCoil.y2=GetUnitY(DeathCoil.Target)
            set DeathCoil.z2=DeathCoil.GetUnitZ(DeathCoil.Target)+FLOAT
            set DeathCoil.x=DeathCoil.x2-DeathCoil.x1
            set DeathCoil.y=DeathCoil.y2-DeathCoil.y1
            call MoveLightningEx(DeathCoil.Lightning,true,DeathCoil.x1,DeathCoil.y1,DeathCoil.z1,DeathCoil.x2,DeathCoil.y2,DeathCoil.z2)
            if (SquareRoot(DeathCoil.x*DeathCoil.x+DeathCoil.y*DeathCoil.y)>=DeathCoil.Distance(DeathCoil.Level)) then
                call PauseTimer(DeathCoil.Timer)
                call DestroyTimer(DeathCoil.Timer)
                call DestroyLightning(DeathCoil.Lightning)
                call DestroyEffect(AddSpecialEffect(EFFECT,DeathCoil.x1,DeathCoil.y1))
                call DestroyEffect(AddSpecialEffect(EFFECT,DeathCoil.x2,DeathCoil.y2))
                call RemoveUnit(DeathCoil.Dummy)
                call SetUnitX(DeathCoil.Target,DeathCoil.x1)
                call SetUnitY(DeathCoil.Target,DeathCoil.y1)
                static if (LIBRARY_Damage) then
                    call Damage_Spell(DeathCoil.Caster,DeathCoil.Target,DeathCoil.Damage(DeathCoil.Level))
                else
                    call UnitDamageTarget(DeathCoil.Caster,DeathCoil.Target,DeathCoil.Damage(DeathCoil.Level),DAMAGE_MELEE,DAMAGE_RANGED,ATTACK_TYPE,DAMAGE_TYPE,null)
                endif
                if (SHARED_VISION==true) then
                    call UnitShareVision(DeathCoil.Target,DeathCoil.Owner,false)
                endif
                set DeathCoil.Caster=null
                set DeathCoil.Target=null
                set DeathCoil.Dummy=null
                set DeathCoil.Lightning=null
                set DeathCoil.Timer=null
            elseif (IsUnitType(DeathCoil.Dummy,UNIT_TYPE_DEAD)==true) or (IsUnitType(DeathCoil.Target,UNIT_TYPE_DEAD)==true) then
                call PauseTimer(DeathCoil.Timer)
                call DestroyTimer(DeathCoil.Timer)
                call DestroyLightning(DeathCoil.Lightning)
                call DestroyEffect(AddSpecialEffect(EFFECT,DeathCoil.x1,DeathCoil.y1))
                call RemoveUnit(DeathCoil.Dummy)
                if (SHARED_VISION==true) then
                    call UnitShareVision(DeathCoil.Target,DeathCoil.Owner,false)
                endif
                set DeathCoil.Caster=null
                set DeathCoil.Target=null
                set DeathCoil.Dummy=null
                set DeathCoil.Lightning=null
                set DeathCoil.Timer=null
            endif
        endmethod

        static method onCreate takes nothing returns nothing
            local thistype dc=thistype.allocate()
            set dc.Caster=GetTriggerUnit()
            set dc.Target=GetSpellTargetUnit()
            set dc.Owner=GetTriggerPlayer()
            set dc.Level=GetUnitAbilityLevel(dc.Caster,ABIL_ID)
            set dc.x2=GetUnitX(dc.Target)
            set dc.y2=GetUnitY(dc.Target)
            set dc.z2=GetUnitZ(dc.Target)+FLOAT
            set dc.Dummy=CreateUnit(dc.Owner,DUMMY_ID,dc.x2,dc.y2,0.00)
            set dc.x1=GetUnitX(dc.Dummy)
            set dc.y1=GetUnitY(dc.Dummy)
            set dc.z1=GetUnitZ(dc.Dummy)+FLOAT
            set dc.Lightning=AddLightningEx(LIGHTNING_ID,true,dc.x1,dc.y1,dc.z1,dc.x2,dc.y2,dc.z2)
            call UnitApplyTimedLife(dc.Dummy,'BTLF',DeathCoil.Duration(dc.Level))
            call SetLightningColor(dc.Lightning,COLOR_R,COLOR_G,COLOR_B,COLOR_A)
            if (SHARED_VISION==true) then
                call UnitShareVision(dc.Target,dc.Owner,true)
            endif
            call TimerStart(dc.Timer,PERIODIC,true,function DeathCoil.periodic)
        endmethod
    endstruct
       
    private function onCast takes nothing returns boolean
        if (GetSpellAbilityId()==ABIL_ID) then
            call DeathCoil.onCreate()
        endif
        return false
    endfunction
        
    private function init takes nothing returns nothing
        local trigger trig=CreateTrigger()
        local integer index=0
        loop
            exitwhen index == bj_MAX_PLAYER_SLOTS
            call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            set index=index+1
        endloop
        call TriggerAddCondition(trig,Condition(function onCast))
        set trig=null
    endfunction
endscope

Change log

v1.0a
- Released Spell.
v1.0b
- Added documentation.
- Renamed the trigger to the correct name.
v1.0c
- Made the spell more customizable.
- Changed the model of the Link.
- Removed Jesus4Lyf Damage, AIDS, and Event system till I figure how I'll add the optional Damage system.
- Fixed the description, to prevent confusion.
v1.0d
- Allowed an option to use the Damage system.
- Improved some parts of the code.
v1.0e
- Made it so Damage/Distance/Duration can be set with a function, instead of being constant.
- An effect is created at the target's x/y before it is moved to the obelisk.
- Improved the documentation.
v1.1a
- Raised the height of the link so it doesn't look like it's on the ground.
- The link now works correctly with flying units so it's on attached to their x/y on the ground.
- Created a constant for the floating height for the link.
- Improved the documentation again.
v1.1b
- Created a version that doesn't use the SpellStruct.
- Slightly improved the documentation.
v1.1b
- Fixed the z location with help of Laiev.
- Improved the documentation.
- Added a constant boolean to check if target shares vision.
- Changed the DUMMY/LIGHTNING/etc.. to Dummy/Lightning/etc..
- Changed the trigger from a Library to a Scope.
Keywords:
The Obelisk,Tether,Red Rope,Red,Death,Coil
Contents

Death Knight (Map)

Reviews
12th Dec 2015 IcemanBo: Too long time as NeedsFix. Rejected. 14:10, 4th Mar 2011 Bribe: Really original name; 0.01 is way too fast for a timer like this, SpellStruct is too inefficient for such a simple usage as you give this, you don't need...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long time as NeedsFix. Rejected.

14:10, 4th Mar 2011
Bribe:

Really original name; 0.01 is way too fast for a timer like this, SpellStruct is too inefficient for such a simple usage as you give this, you don't need == true, capitalization on struct member variables? Really bad for readability. GetUnitZ needs to use a static location.

Status: Rejected until updated
 
Level 15
Joined
Jul 6, 2009
Messages
889
I ripped this from my post at TheHelper :)

The ability reminds me of a dog leash, the target is held on by the obelisk then pulled back if he tries to escape, also reminds me of my other spell Restrain :)

Coding

I like how you use Jesus4Lyf's resources, I haven't seen a spell submitted with them in use :O However, there are numerous things you can improve in this ability:

  1. Configuration: The ability has all the number figures hardcoded into the ability, this is bad. It is bad because you force users to go through your code themselves if they want to change any figures. The solution is to create a list of globals / functions that allow the user to easily modify spell values.

    Your ability should have these figures configurable:
    • Snap distance (if (SquareRoot(.x*.x+.y*.y)>=800.00) then
    • Teleport effect (call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl",.x1,.y1))
    • Damage dealt (call Damage_Spell(.caster,.targetUnit,50*.level+25))
    • Dummy rawcode (set .d=CreateUnit(.owner,'h000',.x2,.y2,0.00))
    • Lightning type (set .l=AddLightning("MFPB",true,.x1,.y1,.x2,.y2))
    • Spell duration (call UnitApplyTimedLife(.d,'BTLF',15.00))
    • Lightning colour (call SetLightningColor(.l,100.00,0.00,0.00,10))
    • Timer period (call .startTimer(.periodic,0.01))
    • Ability rawcode (set thistype.abil='A000')

    The globals, being constant, will inline into the ability code so it'll be the same as what you are doing presently.
    .
  2. Encapsulation: Your struct is this: struct DeathCoil extends SpellStruct, someone else could name a struct DeathCoil as well, this leads to the names conflicting. The solution is to place the struct inside a scope or library, and then adding private at the front of the struct.
    .
  3. Variable Naming:

    JASS:
    .
        unit d
        real x
        real y
        real x1
        real x2 
        real y1
        real y2
        lightning l

    It'd be nice to assist other users checking your code by commenting your code. Variable names such as d[/code], and [icode=jass]l don't really tell me much (ignoring the fact they stand for dummy and lightning) either, but in bigger code, you'll definitely want to name things better. I'd suggest something like dummy and lightning.
    .
  4. Damage isn't particularly needed for this ability, it's a commonly used system and is actually quite nice, but I'd just leave it to the user to make the ability run off Damage themselves, besides, you can always make Damage optional.
    .
  5. if (SquareRoot(.x*.x+.y*.y)>=800.00) then
    You can remove the square root of this by squaring both sides of the equation. ( .x * .x + .y * .y ) >= (800.00 * 800.00) --> ( .x * .x + .y * .y ) >= (640000.00). However, the value should be configurable as well.
 
Level 6
Joined
Nov 3, 2008
Messages
117
look good so far, except for the fact that you implement 3 systems, for just 1 function call:
call Damage_Spell(.caster,.targetUnit,50*.level+25) can be replaced with
call UnitDamageTarget(.caster,.targetUnit,50.*.level+25,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_SPELL,null)
 
Level 6
Joined
Nov 3, 2008
Messages
117
not like this!!
JASS:
private struct DeathCoil extends SpellStruct
        unit DUMMY
        static integer ABIL_ID='A000'
        integer DUMMY_ID='h000'
        integer DAMAGE=50*.level+25
        string EFFECT="Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl"
        string LIGHTNING_ID="MFPB"
        attacktype ATTACK_TYPE=ATTACK_TYPE_NORMAL
        damagetype DAMAGE_TYPE=DAMAGE_TYPE_MAGIC
        lightning LIGHTNING
        real DISTANCE=800.00
        real PERIODIC=0.01
        real DURATION=15.00
        real COLOR_R=100.00
        real COLOR_G=0.00
        real COLOR_B=0.00
        real COLOR_A=10.00

use sth like this:
JASS:
globals
    private constant integer ABIL_ID = 'A000'
    private constant real     MAX_OFFSET = 800.
    .....
endglobals
 
Level 6
Joined
Nov 3, 2008
Messages
117
why do your methods take an integer level when you use the level via SpellStruct.

Convert them into method operators:
JASS:
method operator Damage takes nothing returns real
    return 50.00*.level+25.00
endmethod
        
method operator Distance takes nothing returns real
    return 100*.level+400.00       
endmethod
        
method operator Duration takes nothing returns real            
    return 5.00*.level+10.00
endmethod
 
Short Review:

  • You should only move the lightning if it doesn't get destroyed. Just add an else to your if and move that action there.
    Ex:
    JASS:
                if (SquareRoot(DeathCoil.x*DeathCoil.x+DeathCoil.y*DeathCoil.y)>=DeathCoil.Distance(DeathCoil.LEVEL)) then
                    ...
                elseif (IsUnitType(DeathCoil.DUMMY,UNIT_TYPE_DEAD)==true) or (IsUnitType(DeathCoil.TARGET,UNIT_TYPE_DEAD)==true) then
                    ...
                else
                    call MoveLightningEx(DeathCoil.LIGHTNING,true,DeathCoil.x1,DeathCoil.y1,DeathCoil.z1,DeathCoil.x2,DeathCoil.y2,DeathCoil.z2)
                endif
  • Minor improvement: You can use GetTriggerPlayer instead of GetOwningPlayer(dc.CASTER)
    It's faster and easier to type. ;P
  • It's a bit confusing to have configuration functions inside the struct and then tell the user "Do not change anything in this struct!"
    If I were you, I would just have the configuration functions as separate from the struct, and use constant functions that take in variables.

    Of course, this is just a matter of preference and appearance so it's not all too important. XP
This is only on the code without SpellStruct:

  • It's a bad idea to not destroy the struct when you're done with it.
  • What you're doing with TIMER is not a good idea. This tutorial should give you a better idea of how to do this.
  • The only thing that should be static is TIMER. Everything else being static causes the spell to be not MUI.
  • I'm unsure about the code with SpellStruct, but I think you should have an onDestroy method since there are some things that are repeated when the spell should be done. Specifically, everything under the check for whether the dummy or target is dead can be put in the onDestroy method and anything repeated in the above check can be omitted. This is just to cut down on redundancy.
 
Level 15
Joined
Jul 6, 2009
Messages
889
SpellStruct version:

  • The library should have SpellStruct as a requirement.
  • There is some sort of unset standard in which struct members are camelCase, local variables are lowercase and constant globals are CAPITAL_CASE. I don't see why you name the dummy and lightning members in your struct as DUMMY & LIGHTNING. It looks terrible!

Anyways, this is how I want your configuration section to look like;


JASS:
    globals
        private constant integer    ABIL_ID		    = 'A000'	// Rawcode of the ability.
        private constant integer    DUMMY_ID	    = 'h000'	// Rawcode of the obelisk.

        private constant real 	    PERIODIC	    = 0.01		// How often the timer will run the function.

        private constant real 	    COLOR_R		    = 100.00	// Lightning red
        private constant real 	    COLOR_G		    = 0.00		// Lightning green
        private constant real       COLOR_B		    = 0.00		// Lightning blue
        private constant real 	    COLOR_A		    = 10.00		// Lightning alpha
        private constant real 	    FLOAT		    = 45.00		// Lightning height
        private constant string     LIGHTNING_ID    = "MFPB"	// Lightning type - Mana Flare

        private constant string 	EFFECT		    = "Abilities\\Spells\\Demon\\DarkPortal\\DarkPortalTarget.mdl"

        private constant attacktype ATTACK_TYPE	    = ATTACK_TYPE_NORMAL
        private constant damagetype DAMAGE_TYPE	    = DAMAGE_TYPE_MAGIC
        private constant boolean 	DAMAGE_MELEE    = true
        private constant boolean 	DAMAGE_RANGED   = false
    endglobals
Code.jpg
 
JASS:
        method GetUnitZ takes unit u returns real
            local location Point=Location(GetUnitX(u),GetUnitY(u))
            local real Real=GetLocationZ(Point)+GetUnitFlyHeight(u)
            call RemoveLocation(Point)
            set Point=null
            return Real
        endmethod

Really need a global location. Not only, but why not use GetUnitLoc? This not only wastefully uses dynamic locations but does it inefficiently :p

Why post the code twice?
 
Top