System Impale System

Discussion in 'Graveyard' started by Angel_Island, Feb 9, 2010.

  1. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    Impale System (IMPS)
    By Angel_Island

    Code:
    JASS:
    library IMPS initializer InitTrig
    //=====================================================================================\\
    //                                                                                     \\
    //                                Impale System (IMPS)                                 \\
    //                                  By Angel_Island                                    \\
    //                                                                                     \\
    //      This system makes easy configurable impale spells.                             \\
    //      It allows impaling targets multiple times even when the target is in mid-air   \\
    //                                                                                     \\
    //      Requires:                                                                      \\
    //          - A vJASS preprocessor like NewGen.                                        \\
    //          - A dummy unit.                                                            \\
    //                                                                                     \\
    //=====================================================================================\\
    
    //=====================================================================================\\
    //                                                                                     \\
    //      How to implement:                                                              \\
    //                                                                                     \\
    //      1. Create a new trigger in your map. Convert it to custom text. Copy this      \\
    //         entire script and paste it in the new trigger overwriting what was inside.  \\
    //         Or if you want to do it the easy way, just copy this trigger to your map.   \\
    //                                                                                     \\
    //      2. Create a dummy unit or copy the dummy in this map. Should have Id 'h000'.   \\
    //         Else change it below in configurables.                                      \\
    //                                                                                     \\
    //      3. Done! Try it out by making a spell using this system.                       \\
    //                                                                                     \\
    //=====================================================================================\\
    
    //==============================================================================================================================================================\\
    //                                                                                                                                                              \\
    //      How to use:                                                                                                                                             \\
    //                                                                                                                                                              \\
    //                     call IMPS_Start(Caster,X,Y,Range,Damage,StunDuration,Angle)                                                                              \\
    //                             - Gives you a normal impale that uses x,y                                                                                        \\
    //                                                                                                                                                              \\
    //                                                 or                                                                                                           \\
    //                                                                                                                                                              \\
    //                   call IMPS_StartLoc(Caster,Point,Range,Damage,StunDuration,Angle)                                                                           \\
    //                             - Gives you a normal impale that uses locations                                                                                  \\
    //                                                                                                                                                              \\
    //                                                 or                                                                                                           \\
    //                                                                                                                                                              \\
    //call IMPS_StartLocEx(Caster,Point,CastPoint,Range,Damage,StunDuration,Angle,Area,Height,AirTime,SpikeSfx,HitSfx,StunSfx,AttPoint,RangeBased,MoveUnit,HideUnit)\\
    //                             - Gives you a more customizable impale that uses locations                                                                       \\
    //                                                                                                                                                              \\
    //                                                 or                                                                                                           \\
    //                                                                                                                                                              \\
    //call IMPS_StartEx(Caster,X,Y,CastX,CastY,Range,Damage,StunDuration,Angle,Area,Height,AirTime,SpikeSfx,HitSfx,StunSfx,AttPoint,RangeBased,MoveUnit,HideUnit)   \\
    //                             - Gives you a more customizable impale that uses x,y                                                                             \\
    //                                                                                                                                                              \\
    //      Caster:         The unit who casted the spell or whatever it did.                                                                                       \\
    //      Point:          The point where the impale begins.                                                                                                      \\
    //      X,Y:            x,y coordinates of the Caster.                                                                                                          \\
    //      CastPoint:      The point where the spell is cast. Not needed if RangeBased = false                                                                     \\
    //      CastX,CastY:    x,y coordinates of target point. Not needed if RangeBased = false                                                                       \\
    //      Range:          How long the impale will go. Not needed if RangeBased = true.                                                                           \\
    //      Damage:         How much damage that will be dealt to the targets.                                                                                      \\
    //      StunDuration:   How long the impale will stun the targets. Can be set to 0.00 without stunning forever.                                                 \\
    //      Angle:          The angle the impale will go. Must be in degrees.                                                                                       \\
    //      Area:           How big area the impale will have when picking targets.                                                                                 \\
    //      Height:         How high up in the air the targets will fly.                                                                                            \\
    //      AirTime:        How long time in the air the targets will be.                                                                                           \\
    //      SpikeSfx:       Model for the spikes.                                                                                                                   \\
    //      HitSfx:         Effect when targets are hit.                                                                                                            \\
    //      StunSfx:        Effect when targets are stunned.                                                                                                        \\
    //      AttPoint:       Where StunSfx is attached on the target                                                                                                 \\
    //      RangeBased:     This will decide if the impale will be based on how far away you cast your impale. Won't work if                                        \\
    //                      there is no target location.                                                                                                            \\
    //      MoveUnit:       Decides if the Caster will be moved to the end of the impale.                                                                           \\
    //      HideUnit:       Decides if you want to hide the Caster while the impale is in effect. Good for spells like                                              \\
    //                      Burrowstrike from DotA where the caster digs underground and pops up at the end of the impale                                           \\
    //                                                                                                                                                              \\
    //==============================================================================================================================================================\\
    
    //=====================================================================================\\
    //                                                                                     \\
    //      Other functions:                                                               \\
    //                                                                                     \\
    //      call IsUnitImpaled(Unit):  Checks if the Unit is in mid-air caused by an impale\\
    //                                 Good for making things happen if the Unit is in     \\
    //                                 mid-air.                                            \\
    //                                                                                     \\
    //=====================================================================================\\
    
    
    //CONFIGURABLES:
    
    globals
        private constant real    HEIGHT         = 500.00
        //How high up the targets will fly. Used in IMPS_Start(Loc).
        
        private constant real    AREA           = 175.00
        //How big area the impale will have when picking targets. Used in IMPS_Start(Loc).
        
        private constant real    AIRTIME        = 1.00
        //How long time in the air the targets will be. Used in IMPS_Start(Loc).
        
        constant         string  SPIKE_SFX      = "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl"
        //Model for the spikes for IMPS_Start(Loc). This is not private so you can use this
        //variable instead of have to type in everything.
        
        constant         string  HIT_SFX        = "Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl"
        //Effect when targets are hit for IMPS_Start(Loc). Same reason as above why it isnt private.
    
        constant         string  STUN_SFX       = "Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl"
        //Effect when targets are stunned for IMPS_Start(Loc).
        
        constant         string  ATT_POINT      = "overhead"
        //Where StunSfx is attached on the targets.
        
        private constant real    SPACE          = 150.00
        //Space between every spike. I recommend you leave this as it is.
        
        private constant real    SPIKE_INTERVAL = 0.10
        //Interval between spawning spikes.
        
        private constant real    INTERVAL       = 0.03
        //Interval between height change. You should leave this as it is.
        
        private constant integer STORM_CROW     = 'Arav'
        //Raw code for Storm crow form.
        
        private constant integer DUMMY          = 'h000'
        //Raw code for Dummy.
        
    endglobals
    
    //=====================================================================//
    //                                                                     //
    //       DON'T TOUCH BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING     //
    //                                                                     //
    //=====================================================================//
    private keyword Data
    
    globals
        private Data      array Dt
        private unit      array caster
        private unit      array ImpaledUnit
        private integer   array in
        private integer   array I
        private integer         I2        = 0
        private integer         Instances = 0
        private integer         CusVal    = 0
        private integer         Loop      = 1
        private integer         Loop2     = 1
        private timer           Timer     = CreateTimer()
        private timer           Timer2    = CreateTimer()
        private timer           Timer3    = CreateTimer()
        private real      array n
        private real      array x
        private real      array y
        private real      array damage
        private real      array airtime
        private real      array stunduration
        private real      array height
        private string    array hitsfx
        private string    array stunsfx
        private string    array attpoint
        private group     array G
        private group     array StunG
        private effect    array stuneffect
        private hashtable       h         = InitHashtable()
    endglobals
    
    //======================================================================
    private struct Data
        unit     caster       = null
        effect   sfx          = null
        real     px           = 0.00
        real     py           = 0.00
        real     castrange    = 0.00
        real     range        = 0.00
        real     stunduration = 0.00
        real     sin          = 0.00
        real     cos          = 0.00
        real     area         = 0.00
        real     airtime      = 0.00
        real     damage       = 0.00
        real     height       = 0.00
        string   spikesfx     = ""
        string   hitsfx       = ""
        string   stunsfx      = ""
        string   attpoint     = ""
        boolean  based        = false
        boolean  moveunit     = false
        boolean  hideunit     = false
        
        static method create takes unit Caster, real X, real Y, real CastX, real CastY, real Range, real Damage, real StunDuration, real Angle, real Area, real Height, real AirTime, string SpikeSfx, string HitSfx, string StunSfx, string AttPoint, boolean RangeBased, boolean MoveUnit, boolean HideUnit returns Data
            local Data d = Data.allocate()
            local real dx = 0.00
            local real dy = 0.00
            
            set dx = CastX - X
            set dy = CastY - Y
            
            set d.caster       = Caster
            set d.px           = X
            set d.py           = Y
            set d.castrange    = SquareRoot(dx * dx + dy * dy)
            set d.range        = Range
            set d.damage       = Damage
            set d.stunduration = StunDuration
            set d.sin          = Sin(Angle)
            set d.cos          = Cos(Angle)
            set d.area         = Area
            set d.height       = Height
            set d.airtime      = AirTime
            set d.spikesfx     = SpikeSfx
            set d.hitsfx       = HitSfx
            set d.stunsfx      = StunSfx
            set d.attpoint     = AttPoint
            set d.based        = RangeBased
            set d.moveunit     = MoveUnit
            set d.hideunit     = HideUnit
            
            return d
        endmethod
        
    endstruct
    
    //=====================================================================
    private function Check_Units takes nothing returns boolean
        local unit u
        local player p
        set u = GetFilterUnit()
        set p = GetOwningPlayer(caster[Loop])
        return IsUnitEnemy(u,p) and GetWidgetLife(u) > 0 and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and u != caster[Loop] and IsUnitInGroup(u,G[Loop]) == false
    endfunction
    
    private function Check_Dummy takes nothing returns boolean
        return GetUnitTypeId(GetTriggerUnit()) == DUMMY
    endfunction
    
    private function CountUnits takes nothing returns nothing
        set bj_groupCountUnits = bj_groupCountUnits + 1
    endfunction
    
    //=====================================================================
    private function Flying takes nothing returns nothing
        local real xx
        local real yy
        local unit u
        local unit un
        
        set I[Loop2] = I[Loop2] + 1
        set u = GetEnumUnit()
        call PauseUnit(u,true)
        call SaveReal(h,I[Loop2],Loop2,LoadReal(h,I[Loop2],Loop2) + (SquareRoot(height[Loop2]) * 2.00) / (airtime[Loop2] / INTERVAL))
        call SetUnitFlyHeight(u,(height[Loop2]) - (SquareRoot(height[Loop2]) - LoadReal(h,I[Loop2],Loop2)) * (SquareRoot(height[Loop2]) - LoadReal(h,I[Loop2],Loop2)),0.00)
        if GetUnitFlyHeight(u) <= (SquareRoot(height[Loop2]) * 2.00) / (airtime[Loop2] / INTERVAL) then
            set I2 = I2 + 1
            call PauseUnit(u,false)
            call SetUnitPathing(u,true)
            call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u),0.00)
            call UnitDamageTarget(caster[Loop2],u,damage[Loop2],true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
            call GroupRemoveUnit(G[Loop2],u)
            if GetUnitState(u,UNIT_STATE_LIFE) > 0 and stunduration[Loop2] > 0.00 then
                set CusVal = CusVal + 1
                set StunG[CusVal] = CreateGroup()
                call GroupAddUnit(StunG[CusVal],u)
                set ImpaledUnit[CusVal] = u
                set stuneffect[CusVal] = AddSpecialEffectTarget(stunsfx[Loop2],u,attpoint[Loop2])
                set xx = GetUnitX(u)
                set yy = GetUnitY(u)
                set un = CreateUnit(GetOwningPlayer(caster[Loop2]),DUMMY,xx,yy,270.00)
                call UnitApplyTimedLife(un,'BTLF',stunduration[Loop2])
                call SetUnitUserData(un,CusVal)
            endif
            set bj_groupCountUnits = 0
            call ForGroup(G[Loop2],function CountUnits)
            if bj_groupCountUnits == 0 and Dt[Loop2] == 0 then
                call DestroyGroup(G[Loop2])
                set I2 = 0
            endif
        endif
        set u = null
    endfunction
    
    private function Flying_Init takes nothing returns nothing
        local real     xx
        local real     yy
        local effect   e
        local unit     u
        
        set u = GetEnumUnit()
        set xx = GetUnitX(u)
        set yy = GetUnitY(u)
        set e = AddSpecialEffect(hitsfx[Loop],xx,yy)
        call DestroyEffect(e)
        call UnitAddAbility(u,STORM_CROW)
        call UnitRemoveAbility(u,STORM_CROW)
        call PauseUnit(u,true)
        call SetUnitPathing(u,false)
        call GroupAddUnit(G[Loop],u)
        set e = null
        set u = null
    endfunction
    
    private function Call_Flying takes nothing returns nothing
        loop
            exitwhen Loop2 > Instances
            call ForGroup(G[Loop2],function Flying)
            set I[Loop2] = I2
            set Loop2 = Loop2 + 1
        endloop
        set Loop2 = 1
    endfunction
    
    //=====================================================================
    private function Stun takes nothing returns nothing
        local real xx
        local real yy
        
        set xx = GetUnitX(GetEnumUnit())
        set yy = GetUnitY(GetEnumUnit())
        call SetUnitPosition(GetEnumUnit(),xx,yy)
    endfunction
    
    private function Call_Stun takes nothing returns nothing
        local integer i = 1
    
        loop
            exitwhen i > CusVal
            call ForGroup(StunG[i],function Stun)
            set i = i + 1
        endloop
    endfunction
    
    private function Remove_Stun takes nothing returns nothing
        call GroupRemoveUnit(StunG[GetUnitUserData(GetTriggerUnit())],ImpaledUnit[GetUnitUserData(GetTriggerUnit())])
        call DestroyEffect(stuneffect[GetUnitUserData(GetTriggerUnit())])
    endfunction
    
    //=====================================================================
    private function SpawnSpikes takes nothing returns nothing
        local Data     d = 0
        local group    g = CreateGroup()
        local real     dx = 0.00
        local real     dy = 0.00
        
        loop
            exitwhen Loop > Instances
            if Dt[Loop] != 0 then
                set d = Dt[Loop]
                set caster[Loop] = d.caster
                set airtime[Loop] = d.airtime
                set damage[Loop] = d.damage
                set stunduration[Loop] = d.stunduration
                set height[Loop] = d.height
                set hitsfx[Loop] = d.hitsfx
                set stunsfx[Loop] = d.stunsfx
                set attpoint[Loop] = d.attpoint
                set in[Loop] = in[Loop] + 1
                set x[Loop] = d.px + (SPACE * in[Loop]) * d.cos
                set y[Loop] = d.py + (SPACE * in[Loop]) * d.sin
                set d.sfx = AddSpecialEffect(d.spikesfx,x[Loop],y[Loop])
                call DestroyEffect(d.sfx)
                call GroupEnumUnitsInRange(g,x[Loop],y[Loop],d.area,Condition(function Check_Units))
                call ForGroup(g,function Flying_Init)
                call DestroyGroup(g)
                set g = CreateGroup()
                set dx = d.px - x[Loop]
                set dy = d.py - y[Loop]
                    
                if d.based then
                    if SquareRoot(dx * dx + dy * dy) >= d.castrange then
                        if d.moveunit then
                            call SetUnitX(d.caster,d.px + (SPACE * in[Loop]) * d.cos)
                            call SetUnitY(d.caster,d.py + (SPACE * in[Loop]) * d.sin)
                        endif
                        if d.hideunit then
                            call ShowUnit(d.caster,true)
                            if GetLocalPlayer() == GetOwningPlayer(d.caster) then
                                call SelectUnit(d.caster, true)
                            endif
                        endif
                        set x[Loop] = 0
                        set y[Loop] = 0
                        set in[Loop] = 0
                        set Dt[Loop] = 0
                        set bj_groupCountUnits = 0
                        call ForGroup(G[Loop],function CountUnits)
                        if bj_groupCountUnits == 0 and Dt[Loop] == 0 then
                            call DestroyGroup(G[Loop])
                            set I2 = 0
                        endif
                    endif
                elseif SquareRoot(dx * dx + dy * dy) >= d.range then
                    if d.moveunit then
                        call SetUnitX(d.caster,d.px + (SPACE * in[Loop]) * d.cos)
                        call SetUnitY(d.caster,d.py + (SPACE * in[Loop]) * d.sin)
                    endif
                    if d.hideunit then
                        call ShowUnit(d.caster,true)
                        if GetLocalPlayer() == GetOwningPlayer(d.caster) then
                            call SelectUnit(d.caster, true)
                        endif
                    endif
                    set x[Loop] = 0
                    set y[Loop] = 0
                    set in[Loop] = 0
                    set Dt[Loop] = 0
                    set bj_groupCountUnits = 0
                    call ForGroup(G[Loop],function CountUnits)
                    if bj_groupCountUnits == 0 and Dt[Loop] == 0 then
                        call DestroyGroup(G[Loop])
                        set I2 = 0
                    endif
                endif
            endif
            set Loop = Loop + 1
        endloop
        set Loop = 1
        set g = null
    endfunction
    
    //=====================================================================
    function IsUnitImpaled takes unit u returns boolean
        local integer i = 1
        
        loop
            exitwhen i > Instances
            if IsUnitInGroup(u,G[i]) then
                return true
            endif
            set i = i + 1
        endloop
        
        return false
    endfunction
    
    //=====================================================================
    public function StartEx takes unit Caster, real X, real Y, real CastX, real CastY, real Range, real Damage, real StunDuration, real Angle, real Area, real Height, real AirTime, string SpikeSfx, string HitSfx, string StunSfx, string AttPoint, boolean RangeBased, boolean MoveUnit, boolean HideUnit returns boolean
        local Data d = 0
        
        if RangeBased == false then
            if Area < 0.00 or StunDuration < 0.00 or Range <= 0.00 then
                debug call BJDebugMsg("Error: Invalid input in IMPS_Start()")
                return false
            endif
        elseif Area < 0.00 or StunDuration < 0.00 then
            debug call BJDebugMsg("Error: Invalid input in IMPS_Start()")
            return false
        endif
        
        set d = Data.create(Caster,X,Y,CastX,CastY,Range,Damage,StunDuration,(Angle * 0.01745328),Area,Height,AirTime,SpikeSfx,HitSfx,StunSfx,AttPoint,RangeBased,MoveUnit,HideUnit)
        
        set Instances = Instances + 1
        set G[Instances] = CreateGroup()
        call TimerStart(Timer,SPIKE_INTERVAL,true,function SpawnSpikes)
        call TimerStart(Timer2,INTERVAL,true,function Call_Flying)
        call TimerStart(Timer3,0.03,true,function Call_Stun)
        set Dt[Instances] = d
        if HideUnit then
            call ShowUnit(Caster,false)
        endif
        
        return true
    endfunction
    
    //====================================================================
    public function StartLocEx takes unit Caster, location Point, location CastPoint, real Range, real Damage, real StunDuration, real Angle, real Area, real Height, real AirTime, string SpikeSfx, string HitSfx, string StunSfx, string AttPoint, boolean RangeBased, boolean MoveUnit, boolean HideUnit returns nothing
        call IMPS_StartEx(Caster,GetLocationX(Point),GetLocationY(Point),GetLocationX(CastPoint),GetLocationY(CastPoint),Range,Damage,StunDuration,Angle,Area,Height,AirTime,SpikeSfx,HitSfx,StunSfx,AttPoint,RangeBased,MoveUnit,HideUnit)
    endfunction
    
    public function StartLoc takes unit Caster, location Point, real Range, real Damage, real StunDuration, real Angle returns nothing
        call IMPS_StartEx(Caster,GetLocationX(Point),GetLocationY(Point),0.00,0.00,Range,Damage,StunDuration,Angle,AREA,HEIGHT,AIRTIME,SPIKE_SFX,HIT_SFX,STUN_SFX,ATT_POINT,false,false,false)
    endfunction
    
    public function Start takes unit Caster, real X, real Y, real Range, real Damage, real StunDuration, real Angle returns nothing
        call IMPS_StartEx(Caster,X,Y,0.00,0.00,Range,Damage,StunDuration,Angle,AREA,HEIGHT,AIRTIME,SPIKE_SFX,HIT_SFX,STUN_SFX,ATT_POINT,false,false,false)
    endfunction
    //====================================================================
    private function InitTrig takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer index = 0
        loop
            call TriggerRegisterPlayerUnitEvent(t,Player(index),EVENT_PLAYER_UNIT_DEATH,null)
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t,Condition(function Check_Dummy))
        call TriggerAddAction(t,function Remove_Stun)
    endfunction
    
    endlibrary
    This is my first time coding in vJass. It was little hard to understand at first, but later it became easy and I made this Impale System and I want to know what you think about my first vJass code.

    Updates:
    Version 1.30: 2 new functions and more configurables

    Version 1.20: Some fixes, removed location usage and removed UnitUserData Usage

    Version 1.10: Some fixes, code improvement and new function

    Version 1.00: Initial Release
     

    Attached Files:

    • Like Like x 1
  2. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    Remove usage of locations(slower), long function parameters(like worms), BJ(slower), UnitUserData(interrupt the unit indexing system).

    JASS:
        call TimerStart(Timer3,0.01,true,function Call_Stun)

    Cause performance issue. 0.03125 is good for it.

    JASS:
    function InitTrig takes nothing returns nothing

    Should be private.

    JASS:
        private constant string  SPIKE_SFX

    You should let users use their custom models.

    JASS:
    Recommended values are 0.01-0.04.

    Recommended values are above 0.03

    JASS:
        private constant integer STORM_CROW     = 'Arav'

    You can use AutoFly for it.

    JASS:
        private integer       Cv        = 0
        private integer       Cv2       = 0

    Needs better naming method.

    JASS:
    private function Check_Units takes nothing returns boolean
        local Data d = 0
        set d = Dt[Loop]
        return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(d.caster)) and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE) > 0 and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) == false and GetFilterUnit() != d.caster and IsUnitInGroup(GetFilterUnit(),G[Loop]) == false
    endfunction

    JASS:
    private function Flying takes nothing returns nothing

    Store the d.caster's owner + GetFilterUnit + GetEnumUnit into variable to reduce function calls.

    JASS:
            call BJDebugMsg("Error: Invalid input in IMPS_Start()")

    Should be debug call BJDebugMsg("...")
     
  3. Executor

    Executor I see you

    Ratings:
    +57 / 0 / -0
    Okay, lets begin:

    - Never (!) use UnitUserData, that way you fuck up the most indexing systems.

    - Syntax of common create method should be:
    JASS:
    static method create takes ..arguments.. returns thistype
       local thistype this = thistype.allocate()
       // ... code ...
       // due to the var "this" you can use ".caster" for ex. to access
       // the vars of this instance. ".caster" equals "this.caster"
       return this
    endmethod


    - Never (!) use locations (except for the known "GetFloorHeight" func). You can nearly always directly access the x,y-coordinates. (SetUnitX+SetUnitY instead of SetUnitPosition!)

    - Why 3 timers? combine all in one.

    - A neat advantage of vJass is, that you can move all struct related functions as methods into the struct. Globals can also join the struct as static variables (or constants).

    Thats a template, how such a system could look like.

    JASS:
    struct Impale
       // configuration
       private static constant string HIT_SFX = "blabla.mdx"
       
       private static method damageLoss takes real distance returns real
           return - distance * 5.
       endmethod
       // endconfiguration
    
       private static timer TheTimer
       private static thistype TempInstance // for enumerations
       private static thistype First // for linked list (looping via linked list is faster than an array loop!)
    
       private unit caster
       private real damage
    
       private thistype next // linked list
       private thistype last  // linked list
    
       private static method onTimer takes nothing returns nothing
           local thistype this = .First
           loop
               exitwhen this.next == 0
               // code
               set this = this.next // the linked list magic :p
           endloop
       endmethod
    
       private static method cast takes unit caster, real sourcex, real sourcey, real targetx, real targety, real damage ... returns nothing
          local thistype this = thistype.allocate ..
          // ...
       endmethod
       private static method onInit takes nothing returns nothing
           set .TheTimer = CreateTimer()
           call TimerStart(.TheTimer,0.03125,true,function thistype.onTimer)
       endmethod
    endstruct
     
  4. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    kingkingyyk3:

    - Remove usage of locations(slower), long function parameters(like worms), BJ(slower), UnitUserData(interrupt the unit indexing system).

    The system works fine, so why should I need remove usage of locations? I have now created another function that is shorter for easier use. BJs removed. I can't find a solution for replacing UnitUserData right now.

    - Cause performance issue. 0.03125 is good for it.

    - Should be private.

    - You should let users use their custom models.

    - Recommended values are above 0.03

    - Needs better naming method.

    - Store the d.caster's owner + GetFilterUnit + GetEnumUnit into variable to reduce function calls.

    - Should be debug call BJDebugMsg("...")

    Fixed all above.

    - You can use AutoFly for it.

    Why do I need that?


    Executor:

    - Never (!) use UnitUserData, that way you fuck up the most indexing systems.

    As I said above I can't find a solution for replacing UnitUserData right now.

    - Never (!) use locations (except for the known "GetFloorHeight" func). You can nearly always directly access the x,y-coordinates. (SetUnitX+SetUnitY instead of SetUnitPosition!)

    Why not? Is it because it is slower? What is the diffrence?

    - Why 3 timers? combine all in one.

    How?
     
  5. Executor

    Executor I see you

    Ratings:
    +57 / 0 / -0
    Locations are slower (!) and can leak when not removed.

    Cause AutoFly uses the crow-form-bug on all units exactly once and that when they enter the map. Your code will use the bug on every unit hit even if it can already "fly".

    Reduce an integer in the onTimer function, do the things you want on a specific "tick" and reset it when it becomes 0.

    I'd like to help you with UnitUserData and the Timer thing, but I your code is really hard to read (for me).
     
  6. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    Great improvement.

    To achieve :
    Use XY instead of location
    Remove usage of UnitUserData, replace it with hashtable/unit indexing system.
     
  7. eclypt

    eclypt New Member

    Ratings:
    +4 / 0 / -0
    JASS:
    globals
        private constant real    HEIGHT         = 500.00
        //How high up the targets will fly. Used in IMPS_Start.


    whats the wrong with this? i still gotting Syntax Error with this


    {My bad english owns xD}
     
  8. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    I think because in my code it is not used. I forgot to use it :eek:. Will be fixed.
     
  9. Laiev

    Laiev Hey Listen!!

    Ratings:
    +187 / 0 / -0
    is just with me or your template don't work?

    I mean, the effect happen and etc, everything work except damage lol

    EDIT: suggestion: if you don't want to remove location, just ok but make a new function which support x/y, most of people like it and is more safe then location, also a little bit faster :p

    EDIT²: well, this version the damage happen but you still using user data and location D: i don't see any thing what you change in changelog in trigger, also you forget to update the code :x
     
  10. BlackRose

    BlackRose Forum User

    Ratings:
    +239 / 0 / -0
    - Can you make it not hit units already in the air? I know it is like that in DotA and that people will want what DotA has, but I think you should make it hit units only within height range.
    - GetWidgetLife() is I hear better than GetUnitState[/jass]. - [ljass]"Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl", Am I seeing right? An effect NOT configurable?
     
  11. Laiev

    Laiev Hey Listen!!

    Ratings:
    +187 / 0 / -0
    Ya, you see it lol

    I really don't understand what he update... in the code he still using location and unit date :confused:

    here is the updated script from the test map:

    JASS:
    library IMPS initializer InitTrig
    //=====================================================================================\\
    //                                                                                     \\
    //                                Impale System (IMPS)                                 \\
    //                                  By Angel_Island                                    \\
    //                                                                                     \\
    //      This system makes easy configurable impale spells.                             \\
    //      It allows impaling targets multiple times even when the target is in mid-air   \\
    //                                                                                     \\
    //      Requires:                                                                      \\
    //          - A vJASS preprocessor like NewGen.                                        \\
    //          - A dummy unit.                                                            \\
    //                                                                                     \\
    //=====================================================================================\\
    
    //=====================================================================================\\
    //                                                                                     \\
    //      How to implement:                                                              \\
    //                                                                                     \\
    //      1. Create a new trigger in your map. Convert it to custom text. Copy this      \\
    //         entire script and paste it in the new trigger overwriting what was inside.  \\
    //         Or if you want to do it the easy way, just copy this trigger to your map.   \\
    //                                                                                     \\
    //      2. Create a dummy unit or copy the dummy in this map.                          \\
    //                                                                                     \\
    //      3. Done! Try it out by making a spell using this system.                                \\
    //                                                                                     \\
    //=====================================================================================\\
    
    //==========================================================================================================================================\\
    //                                                                                                                                          \\
    //      How to use:                                                                                                                         \\
    //                                                                                                                                          \\
    //                     call IMPS_Start(Caster,Point,Range,Damage,StunDuration,Angle)                                                        \\
    //                                      - Gives you a normal impale                                                                         \\
    //                                                                                                                                          \\
    //                                                 or                                                                                       \\
    //                                                                                                                                          \\
    //call IMPS_StartEx(Caster,Point,CastPoint,Range,Damage,StunDuration,Angle,Area,Height,AirTime,SpikeSfx,HitSfx,RangeBased,MoveUnit,HideUnit)\\
    //                                 - Gives you a more customizable impale                                                                   \\
    //                                                                                                                                          \\
    //      Caster:         The unit who casted the spell or whatever it did.                                                                   \\
    //      Point:          The point where the impale begins.                                                                                  \\
    //      CastPoint:      The point where the spell is cast. Not needed if RangeBased = false                                                 \\
    //      Range:          How long the impale will go. Not needed if RangeBased = true.                                                       \\
    //      Damage:         How much damage that will be dealt to the targets.                                                                  \\
    //      StunDuration:   How long the impale will stun the targets. Can be set to 0.00 without stunning forever.                             \\
    //      Angle:          The angle the impale will go. Must be in degrees.                                                                   \\
    //      Area:           How big area the impale will have when picking targets.                                                             \\
    //      Height:         How high up in the air the targets will fly.                                                                        \\
    //      AirTime:        How long time in the air the targets will be.                                                                       \\
    //      RangeBased:     This will decide if the impale will be based on how far away you cast your impale. Won't work if                    \\
    //                      there is no target location.                                                                                        \\
    //      SpikeSfx:       Model for the spikes.                                                                                               \\
    //      HitSfx:         Effect when targets are hit.                                                                                        \\
    //      MoveUnit:       Decides if the Caster will be moved to the end of the impale.                                                       \\
    //      HideUnit:       Decides if you want to hide the Caster while the impale is in effect. Good for spells like                          \\
    //                      Burrowstrike from DotA where the caster digs underground and pops up at the end of the impale                       \\
    //                                                                                                                                          \\
    //==========================================================================================================================================\\
    
    //=====================================================================================\\
    //                                                                                     \\
    //      Other functions:                                                               \\
    //                                                                                     \\
    //      call IsUnitImpaled(Unit):  Checks if the Unit is in mid-air caused by an impale\\
    //                                 Good for making things happen if the Unit is in     \\
    //                                 mid-air.                                            \\
    //                                                                                     \\
    //=====================================================================================\\
    
    
    //CONFIGURABLES:
    
    globals
        private constant real    HEIGHT         = 500.00
        //How high up the targets will fly. Used in IMPS_Start.
        
        private constant real    AREA           = 175.00
        //How big area the impale will have when picking targets. Used in IMPS_Start.
        
        private constant real    AIRTIME        = 1.00
        //How long time in the air the targets will be. Used in IMPS_Start.
        
        constant         string  SPIKE_SFX      = "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl"
        //Model for the spikes for IMPS_Start. This is not private so you can use this
        //variable instead of have to type in everything.
        
        constant         string  HIT_SFX        = "Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl"
        //Effect when targets are hit for IMPS_Start. Same reason as above why it isnt private.
    
        private constant real    SPACE          = 150.00
        //Space between every spike. I recommend you leave this as it is.
        
        private constant real    SPIKE_INTERVAL = 0.10
        //Interval between spawning spikes.
        
        private constant real    INTERVAL       = 0.03
        //Interval between height change. You should leave this as it is.
        
        private constant integer STORM_CROW     = 'Arav'
        //Raw code for Storm crow form.
        
        private constant integer DUMMY          = 'h000'
        //Raw code for Dummy.
        
    endglobals
    
    //=====================================================================//
    //                                                                     //
    //       DON'T TOUCH BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING     //
    //                                                                     //
    //=====================================================================//
    private keyword Data
    
    globals
        private Data      array Dt
        private unit      array caster
        private unit      array ImpaledUnit
        private integer   array in
        private integer   array I
        private integer         I2        = 0
        private integer         Instances = 0
        private integer         CusVal    = 0
        private integer         Loop      = 1
        private integer         Loop2     = 1
        private timer           Timer     = CreateTimer()
        private timer           Timer2    = CreateTimer()
        private timer           Timer3    = CreateTimer()
        private real      array n
        private real      array x
        private real      array y
        private real      array damage
        private real      array airtime
        private real      array stunduration
        private real      array height
        private string    array hitsfx
        private group     array G
        private group     array StunG
        private effect    array stuneffect
        private hashtable       h         = InitHashtable()
    endglobals
    
    //======================================================================
    private struct Data
        unit     caster       = null
        location point        = null
        effect   sfx          = null
        real     castrange    = 0.00
        real     range        = 0.00
        real     stunduration = 0.00
        real     sin          = 0.00
        real     cos          = 0.00
        real     area         = 0.00
        real     airtime      = 0.00
        real     damage       = 0.00
        real     height       = 0.00
        string   spikesfx     = ""
        string   hitsfx       = ""
        boolean  based        = false
        boolean  moveunit     = false
        boolean  hideunit     = false
        
        static method create takes unit Caster, location Point, location CastPoint, real Range, real Damage, real StunDuration, real Angle, real Area, real Height, real AirTime, string SpikeSfx, string HitSfx, boolean RangeBased, boolean MoveUnit, boolean HideUnit returns Data
            local Data d = Data.allocate()
            local real dx = 0.00
            local real dy = 0.00
            
            set dx = GetLocationX(CastPoint) - GetLocationX(Point)
            set dy = GetLocationY(CastPoint) - GetLocationY(Point)
            
            set d.caster       = Caster
            set d.point        = Point
            set d.castrange    = SquareRoot(dx * dx + dy * dy)
            set d.range        = Range
            set d.damage       = Damage
            set d.stunduration = StunDuration
            set d.sin          = Sin(Angle)
            set d.cos          = Cos(Angle)
            set d.area         = Area
            set d.height       = Height
            set d.airtime      = AirTime
            set d.spikesfx     = SpikeSfx
            set d.hitsfx       = HitSfx
            set d.based        = RangeBased
            set d.moveunit     = MoveUnit
            set d.hideunit     = HideUnit
            
            return d
        endmethod
        
    endstruct
    
    //=====================================================================
    private function Check_Units takes nothing returns boolean
        local unit u
        local player p
        set u = GetFilterUnit()
        set p = GetOwningPlayer(caster[Loop])
        return IsUnitEnemy(u,p) and GetUnitState(u,UNIT_STATE_LIFE) > 0 and IsUnitType(u,UNIT_TYPE_STRUCTURE) == false and u != caster[Loop] and IsUnitInGroup(u,G[Loop]) == false
    endfunction
    
    private function Check_Dummy takes nothing returns boolean
        return GetUnitTypeId(GetTriggerUnit()) == DUMMY
    endfunction
    
    private function CountUnits takes nothing returns nothing
        set bj_groupCountUnits = bj_groupCountUnits + 1
    endfunction
    
    //=====================================================================
    private function Flying takes nothing returns nothing
        local real xx
        local real yy
        local unit u
        local unit un
        
        set I[Loop2] = I[Loop2] + 1
        set u = GetEnumUnit()
        call PauseUnit(u,true)
        call SaveReal(h,I[Loop2],Loop2,LoadReal(h,I[Loop2],Loop2) + (SquareRoot(height[Loop2]) * 2.00) / (airtime[Loop2] / INTERVAL))
        call SetUnitFlyHeight(u,(height[Loop2]) - (SquareRoot(height[Loop2]) - LoadReal(h,I[Loop2],Loop2)) * (SquareRoot(height[Loop2]) - LoadReal(h,I[Loop2],Loop2)),0.00)
        if GetUnitFlyHeight(u) <= (SquareRoot(height[Loop2]) * 2.00) / (airtime[Loop2] / INTERVAL) then
            set I2 = I2 + 1
            call PauseUnit(u,false)
            call SetUnitPathing(u,true)
            call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u),0.00)
            call UnitDamageTarget(caster[Loop2],u,damage[Loop2],true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
            call GroupRemoveUnit(G[Loop2],u)
            if GetUnitState(u,UNIT_STATE_LIFE) > 0 and stunduration[Loop2] > 0.00 then
                set CusVal = CusVal + 1
                set StunG[CusVal] = CreateGroup()
                call GroupAddUnit(StunG[CusVal],u)
                set ImpaledUnit[CusVal] = u
                set stuneffect[CusVal] = AddSpecialEffectTarget("Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl",u,"overhead")
                set xx = GetUnitX(u)
                set yy = GetUnitY(u)
                set un = CreateUnit(GetOwningPlayer(caster[Loop2]),DUMMY,xx,yy,270.00)
                call UnitApplyTimedLife(un,'BTLF',stunduration[Loop2])
                call SetUnitUserData(un,CusVal)
            endif
            set bj_groupCountUnits = 0
            call ForGroup(G[Loop2],function CountUnits)
            if bj_groupCountUnits == 0 and Dt[Loop2] == 0 then
                call DestroyGroup(G[Loop2])
                set I2 = 0
            endif
        endif
        set u = null
    endfunction
    
    private function Flying_Init takes nothing returns nothing
        local real     xx
        local real     yy
        local effect   e
        local unit     u
        
        set u = GetEnumUnit()
        set xx = GetUnitX(u)
        set yy = GetUnitY(u)
        set e = AddSpecialEffect(hitsfx[Loop],xx,yy)
        call DestroyEffect(e)
        call UnitAddAbility(u,STORM_CROW)
        call UnitRemoveAbility(u,STORM_CROW)
        call PauseUnit(u,true)
        call SetUnitPathing(u,false)
        call GroupAddUnit(G[Loop],u)
        set e = null
        set u = null
    endfunction
    
    private function Call_Flying takes nothing returns nothing
        loop
            exitwhen Loop2 > Instances
            call ForGroup(G[Loop2],function Flying)
            set I[Loop2] = I2
            set Loop2 = Loop2 + 1
        endloop
        set Loop2 = 1
    endfunction
    
    //=====================================================================
    private function Stun takes nothing returns nothing
        local real xx
        local real yy
        
        set xx = GetUnitX(GetEnumUnit())
        set yy = GetUnitY(GetEnumUnit())
        call SetUnitPosition(GetEnumUnit(),xx,yy)
    endfunction
    
    private function Call_Stun takes nothing returns nothing
        local integer i = 1
    
        loop
            exitwhen i > CusVal
            call ForGroup(StunG[i],function Stun)
            set i = i + 1
        endloop
    endfunction
    
    private function Remove_Stun takes nothing returns nothing
        call GroupRemoveUnit(StunG[GetUnitUserData(GetTriggerUnit())],ImpaledUnit[GetUnitUserData(GetTriggerUnit())])
        call DestroyEffect(stuneffect[GetUnitUserData(GetTriggerUnit())])
    endfunction
    
    //=====================================================================
    private function SpawnSpikes takes nothing returns nothing
        local Data     d = 0
        local group    g = CreateGroup()
        local real     dx = 0.00
        local real     dy = 0.00
        
        loop
            exitwhen Loop > Instances
            if Dt[Loop] != 0 then
                set d = Dt[Loop]
                set caster[Loop] = d.caster
                set airtime[Loop] = d.airtime
                set damage[Loop] = d.damage
                set stunduration[Loop] = d.stunduration
                set height[Loop] = d.height
                set hitsfx[Loop] = d.hitsfx
                set in[Loop] = in[Loop] + 1
                set x[Loop] = GetLocationX(d.point) + (SPACE * in[Loop]) * d.cos
                set y[Loop] = GetLocationY(d.point) + (SPACE * in[Loop]) * d.sin
                set d.sfx = AddSpecialEffect(d.spikesfx,x[Loop],y[Loop])
                call DestroyEffect(d.sfx)
                call GroupEnumUnitsInRange(g,x[Loop],y[Loop],d.area,Condition(function Check_Units))
                call ForGroup(g,function Flying_Init)
                call DestroyGroup(g)
                set g = CreateGroup()
                set dx = GetLocationX(d.point) - x[Loop]
                set dy = GetLocationY(d.point) - y[Loop]
                    
                if d.based then
                    if SquareRoot(dx * dx + dy * dy) >= d.castrange then
                        if d.moveunit then
                            call SetUnitX(d.caster,GetLocationX(d.point) + (SPACE * in[Loop]) * d.cos)
                            call SetUnitY(d.caster,GetLocationY(d.point) + (SPACE * in[Loop]) * d.sin)
                        endif
                        if d.hideunit then
                            call ShowUnit(d.caster,true)
                            if GetLocalPlayer() == GetOwningPlayer(d.caster) then
                                call SelectUnit(d.caster, true)
                            endif
                        endif
                        set x[Loop] = 0
                        set y[Loop] = 0
                        set in[Loop] = 0
                        set Dt[Loop] = 0
                        set bj_groupCountUnits = 0
                        call ForGroup(G[Loop],function CountUnits)
                        if bj_groupCountUnits == 0 and Dt[Loop] == 0 then
                            call DestroyGroup(G[Loop])
                            set I2 = 0
                        endif
                    endif
                elseif SquareRoot(dx * dx + dy * dy) >= d.range then
                    if d.moveunit then
                        call SetUnitX(d.caster,GetLocationX(d.point) + (SPACE * in[Loop]) * d.cos)
                        call SetUnitY(d.caster,GetLocationY(d.point) + (SPACE * in[Loop]) * d.sin)
                    endif
                    if d.hideunit then
                        call ShowUnit(d.caster,true)
                        if GetLocalPlayer() == GetOwningPlayer(d.caster) then
                            call SelectUnit(d.caster, true)
                        endif
                    endif
                    set x[Loop] = 0
                    set y[Loop] = 0
                    set in[Loop] = 0
                    set Dt[Loop] = 0
                    set bj_groupCountUnits = 0
                    call ForGroup(G[Loop],function CountUnits)
                    if bj_groupCountUnits == 0 and Dt[Loop] == 0 then
                        call DestroyGroup(G[Loop])
                        set I2 = 0
                    endif
                endif
            endif
            set Loop = Loop + 1
        endloop
        set Loop = 1
        set g = null
    endfunction
    
    //=====================================================================
    function IsUnitImpaled takes unit u returns boolean
        local integer i = 1
        
        loop
            exitwhen i > Instances
            if IsUnitInGroup(u,G[i]) then
                return true
            endif
            set i = i + 1
        endloop
        
        return false
    endfunction
    
    //=====================================================================
    public function StartEx takes unit Caster, location Point, location CastPoint, real Range, real Damage, real StunDuration, real Angle, real Area, real Height, real AirTime, string SpikeSfx, string HitSfx, boolean RangeBased, boolean MoveUnit, boolean HideUnit returns boolean
        local Data d = 0
        
        if RangeBased == false then
            if Area < 0.00 or StunDuration < 0.00 or Range <= 0.00 then
                debug call BJDebugMsg("Error: Invalid input in IMPS_Start()")
                return false
            endif
        elseif Area < 0.00 or StunDuration < 0.00 then
            debug call BJDebugMsg("Error: Invalid input in IMPS_Start()")
            return false
        endif
        
        set d = Data.create(Caster,Point,CastPoint,Range,Damage,StunDuration,(Angle * 0.01745328),Area,Height,AirTime,SpikeSfx,HitSfx,RangeBased,MoveUnit,HideUnit)
        
        set Instances = Instances + 1
        set G[Instances] = CreateGroup()
        call TimerStart(Timer,SPIKE_INTERVAL,true,function SpawnSpikes)
        call TimerStart(Timer2,INTERVAL,true,function Call_Flying)
        call TimerStart(Timer3,0.03,true,function Call_Stun)
        set Dt[Instances] = d
        if HideUnit then
            call ShowUnit(Caster,false)
        endif
        
        return true
    endfunction
    
    public function Start takes unit Caster, location Point, real Range, real Damage, real StunDuration, real Angle returns nothing
        call IMPS_StartEx(Caster,Point,null,Range,Damage,StunDuration,Angle,AREA,HEIGHT,AIRTIME,SPIKE_SFX,HIT_SFX,false,false,false)
    endfunction
    
    //====================================================================
    private function InitTrig takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer index = 0
        loop
            call TriggerRegisterPlayerUnitEvent(t,Player(index),EVENT_PLAYER_UNIT_DEATH,null)
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t,Condition(function Check_Dummy))
        call TriggerAddAction(t,function Remove_Stun)
    endfunction
    
    endlibrary


    EDIT: just a question.. if i use a global dummy <which i use in all map for everything> this system may bug? because it just check if unit type die
     
  12. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    Does it really do anything if you use UnitUserData with a dummy that will die in a few seconds? And where am I using location except d.point? Maybe some users want to use location instead of x,y.
     
  13. Laiev

    Laiev Hey Listen!!

    Ratings:
    +187 / 0 / -0
    :rolleyes:
     
  14. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    - EDIT: suggestion: if you don't want to remove location, just ok but make a new function which support x/y, most of people like it and is more safe then location, also a little bit faster

    Sure. I will make a new function

    - EDIT: just a question.. if i use a global dummy <which i use in all map for everything> this system may bug? because it just check if unit type die

    That's true! Guess I have to fix it or you could just create a new dummy, but if your dummy's UserData is 0 then it wont affect this system.
     
  15. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    Updated! Version 1.30. (Damn, Double Post!)
     
  16. Laiev

    Laiev Hey Listen!!

    Ratings:
    +187 / 0 / -0
    he do what i say :eek: sweettttttt [​IMG]

    now just need to remove the user data and use hashtable and fix the 'bug' with global dummys :rolleyes:
     
  17. Executor

    Executor I see you

    Ratings:
    +57 / 0 / -0
    JASS:
    private function Stun takes nothing returns nothing
        local real xx
        local real yy
        
        set xx = GetUnitX(GetEnumUnit())
        set yy = GetUnitY(GetEnumUnit())
        call SetUnitPosition(GetEnumUnit(),xx,yy)
    endfunction


    JASS:
    private function Stun takes nothing returns nothing
        local unit u  = GetEnumUnit()
        local real xx = GetUnitX(u)
        local real yy = GetUnitY(u)
    
        call SetUnitPosition(u,xx,yy)
    endfunction


    JASS:
    private function Stun takes nothing returns nothing
        local unit u  = GetEnumUnit()
        call SetUnitPosition(u,GetUnitX(u),GetUnitY(u))
    endfunction
     
  18. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    B... U... M... P!
     
  19. Deaod

    Deaod Member

    Ratings:
    +6 / 0 / -0
    • Using locations
    • NOT using GroupUtils
    • Those non private constants for models are completely unnecessary. Either you let users choose the model, or you dont. If you choose not to, you dont provide such constants.
    • How about giving those timers a descriptive name?
    • How about you reuse code from xe (the dummy unit, the fly height enabler ability, ...)?
    • Global variables with single-letter lower-case names. Good job.
    • call SaveReal(h,I[Loop2],Loop2,LoadReal(h,I[Loop2],Loop2) + (SquareRoot(height[Loop2]) * 2.00) / (airtime[Loop2] / INTERVAL))
      What the hell does that do? Why doesnt it use arrays?
    • Checking if group is empty is easy: FirstOfGroup(<group>)==null
    • Using SetUnitPathing directly is not exactly smart, if you want to avoid compatibility issues.
    • Your Check_Units function leaks references.
    • Your array of active instances gets filled starting with index 1 instead of 0.
    • Using ShowUnit directly is not a good idea.
    • You restart all timers whenever a new instance is created. Seriously, why?
    • Use a decent name for your library. Then, use a decent name for your currently public function and drop the public key word.
    • Yay, inlined CountUnitsInGroup. Not all BJs are bad.
    • Stunning by resetting a units position? ARE YOU KIDDING? There are multiple libraries out there that facilitate stunning units (at least one here, and one over at wc3c.net). Btw, it fails with instant casts like windwalk and beserk.
     
  20. Angel_Island

    Angel_Island Much long, many time, wow

    Ratings:
    +56 / 0 / -0
    • Maybe some users want to use locations and there is no location use in the code except in the usable functions.
    • Diffrence?
    • Instead of typing in "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl" all the time they could just use SPIKE_SFX. Simple.
    • call TimerStart(Timer,SPIKE_INTERVAL,true,function SpawnSpikes) Isn't "SpawnSpikes" enough information on what it does already?
    • What?
    • Good or bad?
    • If you read it, you can see it saves the real that is in the hashtable h in I[Loop2] of Loop2 + (SquareRoot(height[Loop2]) * 2.00) / (airtime[Loop2] / INTERVAL). Why should it use arrays?
    • Good Idea.
    • How should I do it then?
    • What references?
    • Diffrence?
    • How should I do it then?
    • Good point. Will change it.
    • What is wrong with the name it already has?
    • If you read the other posts, they say I should remove all BJs.
    • Maybe you're right, but I wanted to not be needed to use other systems.
     

Share This Page