• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Electric Walls v1.2

  • Like
Reactions: Doomlord
-------------------------------------------
E L E T R I C W A L L S

I/ Spell Information:
untitl68.jpg

II/ Spell Code:
JASS:
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//          E L E C T R I C    W A L L S
//                                  - Spell Create By:
//                                                      + Elphis
//*************************************************************************************
library ElectricWalls /*                   
*/                                      requires /*
//                                              -*/ DelFX /* http://www.hiveworkshop.com/forums/spells-569/delfx-delayed-effects-1-4-2-a-116064/?prev=search%3DDel%2520Effect%26d%3Dlist%26r%3D20%26c%3D112
//                                              -*/ TimerUtils /* http://www.wc3c.net/showthread.php?t=101322
//                                              -*/ SpellEffectEvent /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
//                                              -*/ SJS /* Spell staus library 
//                                              -*/ xebasic /* http://www.wc3c.net/showthread.php?t=101150
//                                              -*/ xedamage /* http://www.wc3c.net/showthread.php?t=101150
//                                              -*/ xecast /* http://www.wc3c.net/showthread.php?t=101150
//                                              -*/ Table /* http://www.wc3c.net/showthread.php?t=101246 */
//*************************************************************************************
//          - Spell Information:
//                              - Create a lightning walls, but this walls does'nt block, this walls will protect all allies in 600 AOE
//                                and chain lightning deals 15/30/45/60 damage to all enemies coming, when enemies nearly walls, this walls
//                                will make emeies paralysis in 4 seconds last 7/8/9/10 seconds
//        //****************************NOTIICE****************************
//        //- Damage chain lightning, you can change it in Object -> Ability -> Chain Lightning -> Change Damage per Target
//        //***************************************************************
//*************************************************************************************
//          - Installation:
//                                - Import/copy the required libraries and Electric Walls code to your map
//                                - Import/copy the custom ability and unit to your map and change the SPELL_ID, ABI_SLOW_ID, ABI_CHAIN_ID if needed
//                                - You may view the raw ID of the objects by pressing CTRL+D in the object editor
//                                - You may play with the configurables below
//*************************************************************************************
    //
    globals
        //==================================CONFIGURABLES=============================================//
        //Spell rawcode, change if needed
        private     constant        integer     SPELL_ID               =       'A000'
        //Ability slow rawcode, change if needed
        private     constant        integer     ABI_SLOW_ID            =       'A001'
        //Ability chain lightning rawcode, change if needed
        private     constant        integer     ABI_CHAIN_ID           =       'A002'
        //Orb of lightning created count
        private     constant        integer     ORB_OF_LIGHTNING_C     =       5
        //Periodic Timer
        private     constant        real        LOOP_TIMER             =       0.031250
        //Height per orb of lightning create
        private     constant        real        ORB_PER_HEIGHT         =       100.
        //Orb angle
        private     constant        real        ORB_ANGLE              =       -90.
        //Orb column distance between
        private     constant        real        ORB_COLUMN             =       400.
        //Laser orb move speed
        private     constant        real        ORB_LASER_SPEED        =       7.
        //Height of first orb
        private     constant        real        ORB_HEIGHT_BASE        =       100.
        //Orb duration
        private     constant        real        ORB_DURATION           =       10.
        //This value is optional (Effect Only)
        private     constant        real        SAFE_TIMER             =       2.
        //This value is optional (Effect Only)
        private     constant        real        ORB_TIMER              =       0.7
        //Orb Slow and Damage Radius
        private     constant        real        ORB_SLOW_RADIUS        =       200.
        //Orb Slow and Damage Radius
        private     constant        real        ORB_CHAIN_LIGHTNING_R  =       600.
        //Damage per target when enemies come nearly electic walls
        private     constant        real        DAMAGE_PER_TARGET      =       15.
        //---------------------------ORB COLOR---------------------------
        //Red color of orb
        private     constant        integer     ORB_RED                =       255
        //Green color of orb
        private     constant        integer     ORB_GREEN              =       255
        //Blue color of orb
        private     constant        integer     ORB_BLUE               =       0
        //Orb alpha
        private     constant        integer     ORB_ALPHA              =       255
        //Orb casting ability intevar, decrease if you want to dummies cast faster
        private     constant        real        ORB_CAST_INTEVAR       =       0.3
        //Model orb of lightning
        private     constant        string      ORB_MODEL              =       "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
        //Attach model orb
        private     constant        string      ORB_ATTACH             =       "origin"
        //Order of Slow
        private     constant        string      SLOW_ORDER             =       "slow"
        //Order of Chain Lightning
        private     constant        string      CHAIN_LIGHTNING_ORDER  =       "chainlightning"
        //
        private     constant        attacktype  ATTACKTYPE             =       ATTACK_TYPE_HERO
        private     constant        damagetype  DAMAGETYPE             =       DAMAGE_TYPE_COLD
        private     constant        weapontype  WEAPONTYPE             =       WEAPON_TYPE_METAL_HEAVY_BASH
        //                                  NON-CONFIGURABLES
        private     constant        group       GROUP                  =       CreateGroup()
        //==================================CONFIGURABLES=============================================//
        //
    endglobals
    //
    struct ElectricWalls
        //Table
        Table dummy
        //
        real tarx
        real tary
        boolean fade
        real reach
        real facing
        real duration
        real intevar
        real dam
        real offsetx
        real offsety
        player p
        //xe
        xecast xec
        xedamage xed
        //
        //Duration of Orb
        static method onDuration takes unit u returns real
            return ORB_DURATION + GetUnitAbilityLevel(u,SPELL_ID)
        endmethod
        //Damage per target
        static method onDamage takes unit u returns real
            return DAMAGE_PER_TARGET * GetUnitAbilityLevel(u,SPELL_ID)
        endmethod
        //Check Enemies
        static method filterUnit takes unit caster, unit u returns boolean
        return /*
        */ IsUnitEnemy(u, GetOwningPlayer(caster)) and /* Target is an enemy of caster
        */ not IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId(u) != 0 and /* Target is alive
        */ not IsUnitType(u, UNIT_TYPE_STRUCTURE) /* Target is not a structure
        */
        endmethod
        //Periodic, call every times
        static method onPeriodic takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            local real x
            local real y
            local unit f
            local unit d
            local integer i = 0
            //
            if not fade then
                set reach = reach + ORB_LASER_SPEED
                if reach >= ORB_COLUMN then
                    set fade = true
                endif
            else
                set reach = reach - ORB_LASER_SPEED
                if reach <= 0 then
                    set fade = false
                endif
            endif
            //
            //This loop make all dummies moving
            loop
            //
            exitwhen i >= ORB_OF_LIGHTNING_C
            //
                if not fade then
                    set x = GetUnitX(dummy.unit[i]) + offsetx
                    set y = GetUnitY(dummy.unit[i]) + offsety
                    call SetUnitPosition(dummy.unit[i],x,y)
        
                else
                    set x = GetUnitX(dummy.unit[i]) - offsetx
                    set y = GetUnitY(dummy.unit[i]) - offsety
                    call SetUnitPosition(dummy.unit[i],x,y)
                endif
            set i = i + 1
            //
            endloop
            //
            if intevar < ORB_CAST_INTEVAR then //Intevar increase per seconds before dummies cast
                set intevar = intevar + LOOP_TIMER
            else
            //
            set intevar = 0
            //  //Begin make dummies casting ability
                call GroupEnumUnitsInRange(GROUP,x,y,ORB_CHAIN_LIGHTNING_R,null)
                loop
                    set f = FirstOfGroup(GROUP)
                    exitwhen f == null
                    //
                    set d = dummy.unit[GetRandomInt(0,ORB_OF_LIGHTNING_C)]
                    //
                    if not IsUnitInRange(dummy.unit[0],f,ORB_SLOW_RADIUS) and filterUnit(dummy.unit[0],f) then
                        //if enemies not in range of ORB_SLOW_RADIUS dummies will casting chain lightning/deals damage to enemies
                        if d != null then
                            set x = GetUnitX(d)
                            set y = GetUnitY(d)
                            set xec.abilityid = ABI_CHAIN_ID
                            set xec.orderstring = CHAIN_LIGHTNING_ORDER
                            call xed.damageTarget(d,f,dam)
                        endif
                    else
                        //if enemies in range of ORB_SLOW_RADIUS dummies will casting slow but no damage deals to enemies
                            set xec.abilityid = ABI_SLOW_ID
                            set xec.orderstring = SLOW_ORDER
                    endif
                    //
                    call xec.setSourcePoint(x,y,GetUnitFlyHeight(d))
                    call xec.castOnTarget(f)
                    //
                    call GroupRemoveUnit(GROUP,f)
                endloop
            //
            endif
            //
            if IsUnitType(dummy.unit[0],UNIT_TYPE_DEAD) and GetUnitTypeId(dummy.unit[0]) != 0 then
                //Destroy Leaks....
                call ReleaseTimer(t)
                call xec.destroy()
                call xed.destroy()
                set p = null
                call dummy.destroy()
                call destroy()
            endif
        endmethod
        //Setup spell if any unit casting this ability
        static method onCast takes nothing returns nothing
            local thistype this = allocate()
            //unit
            local unit u = GetTriggerUnit()
            //real
            local unit d
            local unit d1
            local real h = ORB_HEIGHT_BASE
            local real f = GetUnitFacing(u)
            local real tarx = GetSpellTargetX()
            local real tary = GetSpellTargetY()
            local real o = tarx + ORB_COLUMN * Cos((f+ORB_ANGLE)*0.01747)
            local real z = tary + ORB_COLUMN * Sin((f+ORB_ANGLE)*0.01747)
            //integer
            local integer i = 0
            local integer abilevel = GetUnitAbilityLevel(u,SPELL_ID) //Check ability level of caster
            //Begin config spell ability
            set dummy = Table.create() //install Table
            set duration = onDuration(u) //Check duration of orb per level of caster
            set intevar = 0
            set p = GetTriggerPlayer()
            set fade = false
            set reach = 0
            set dam = onDamage(u)
            //Xe install
            set xec = xecast.create()
            set xec.owningplayer = p
            set xec.level = abilevel
            set xec.recycledelay = 1.
            //
            set xed = xedamage.create()
            set xed.dtype = DAMAGETYPE
            set xed.atype = ATTACKTYPE
            set xed.wtype = WEAPONTYPE
            set xed.exception = UNIT_TYPE_STRUCTURE
            set xed.damageEnemies = true
            set xed.damageTrees   = false
            //Begin run spell ability
            loop
            //
            exitwhen i >= ORB_OF_LIGHTNING_C
            //
                //
                set d = CreateUnit(p,'xeca',tarx,tary,0.)
                //Dummies call
                set dummy.unit[i] = CreateUnit(p,XE_DUMMY_UNITID,tarx,tary,0.)
                call J.Jumping(0.,true,duration-SAFE_TIMER,dummy.unit[i],h,"","",false,false,true,0.)
                call CreateDelayedEffectTarget(ORB_MODEL,dummy.unit[i],ORB_ATTACH,0.,duration-SAFE_TIMER+ORB_TIMER)
                call SetUnitVertexColor(dummy.unit[i],ORB_RED,ORB_GREEN,ORB_BLUE,ORB_ALPHA)
                //
                set d1 = CreateUnit(p,XE_DUMMY_UNITID,o,z,ORB_ANGLE)
                set facing = Angle(GetUnitX(dummy.unit[i]),GetUnitY(dummy.unit[i]),o,z)
                call LL.LLSU(0.,d,d1,"CLPB",duration-SAFE_TIMER+ORB_TIMER)
                call J.Jumping(0.,true,duration-SAFE_TIMER,d,h,"","",false,false,false,0.) 
                call J.Jumping(0.,true,duration-SAFE_TIMER,d1,h,"","",false,false,false,0.) 
                call CreateDelayedEffectTarget(ORB_MODEL,d,ORB_ATTACH,0.,duration-SAFE_TIMER+ORB_TIMER)
                call CreateDelayedEffectTarget(ORB_MODEL,d1,ORB_ATTACH,0.,duration-SAFE_TIMER+ORB_TIMER)
                //Increase height per orb
                set h = h + ORB_PER_HEIGHT
            //
            set i = i + 1
            endloop
            //
            //Set dummies move angle
            set offsetx = ORB_LASER_SPEED * Cos(facing*0.01747)
            set offsety = ORB_LASER_SPEED * Sin(facing*0.01747)
            //
            //Remove varriables
            set d = null
            set d1 = null
            set u = null
            //
            call TimerStart(NewTimerEx(this),LOOP_TIMER,true,function thistype.onPeriodic)
        endmethod
        //
        static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
        endmethod
    //
    endstruct
endlibrary
[/HIDDEN]
JASS:
//! zinc
//
library SJS requires TimerUtils,AaD
{
constant                real                            time            =           .032;
        public struct J
        {
            real Fly;
            real Dis;
            real ins;
            boolean kill;
            unit U;
            real High;
            real d;
            real Highsettings;
            real Timer;
            boolean Ag;
            real ag;
            boolean Jumpag;
            boolean rem;
            string EfEnd;
            //
            real savehigh;
            boolean blockhig;
            real timeblocking;
        //
        static method onLoopJ()
        {
                thistype this = GetTimerData(GetExpiredTimer());
                if(IsUnitType(U, UNIT_TYPE_DEAD) != true && GetUnitTypeId(U) != 0)
                {
                    if(d > 0)
                        d = d - time;
                    else
                    {
                        if (Fly > 0)
                        {
                            if(Fly >= savehigh)
                            {
                                 Timer = Timer + 180/(Dis / 30.);
                                 Fly   = Sin(Timer*bj_DEGTORAD)*Highsettings*1.3;
                                 if(blockhig && Fly > savehigh)
                                     savehigh = Fly;
                                 if (Ag == false)
                                     SetUnitFlyHeight(U,Fly,0.);
                                 else
                                     SetUnitFlyHeight(U,Fly/ag,0.);
                            }
                            else
                            {
                                if(timeblocking > 0)
                                    timeblocking = timeblocking - .032500000;
                                else
                                {
                                    blockhig = false;
                                    savehigh = 0.;
                                }
                            }
                        }
                        else
                            if (Jumpag == true)
                            {
                                Ag = true;
                                ag = ag + 1;
                                Fly = 1.;
                                Timer = 1.;
                                if (ag > 3.)
                                {
                                    if(kill && !rem)
                                        KillUnit(U);
                                    if(!kill && rem && ins <= 0)
                                        RemoveUnit(U);
                                    if(!kill && rem && ins > 0)
                                        Dum.Remove(U,ins);
                                     UnitAddAbility(U,'Amrf');
                                     UnitRemoveAbility(U,'Amrf');
                                     SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
                                     DestroyEffect(AddSpecialEffect(EfEnd,GetUnitX(U),GetUnitY(U)));
                                     U = null;
                                     EfEnd = null;
                                     ReleaseTimer(GetExpiredTimer());
                                     destroy();
                                }
                            }
                            else
                            {
                                 if(kill && !rem)
                                    KillUnit(U);
                                 if(!kill && rem && ins <= 0)
                                    RemoveUnit(U);
                                 if(!kill && rem && ins > 0)
                                    Dum.Remove(U,ins);
                                 UnitAddAbility(U,'Amrf');
                                 UnitRemoveAbility(U,'Amrf');
                                 SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
                                 DestroyEffect(AddSpecialEffect(EfEnd,GetUnitX(U),GetUnitY(U)));
                                 U = null;
                                 EfEnd = null;
                                 ReleaseTimer(GetExpiredTimer());
                                 destroy();
                            }
                        }
                }
                        else
                            {
                                 if(kill && !rem)
                                    KillUnit(U);
                                 if(!kill && rem && ins <= 0)
                                    RemoveUnit(U);
                                 if(!kill && rem && ins > 0)
                                    Dum.Remove(U,ins);
                                 UnitAddAbility(U,'Amrf');
                                 UnitRemoveAbility(U,'Amrf');
                                 SetUnitFlyHeight(U,0.,GetUnitDefaultFlyHeight(U));
                                 U = null;
                                 EfEnd = null;
                                 ReleaseTimer(GetExpiredTimer());
                                 destroy();
                            }
       }
        //
        static method Jumping(real delay,boolean blockhe,real pauhe,unit wunit,real hei,string XJ,string EJ,boolean jumpags,boolean rems,boolean kills,real inss) 
        {
             thistype this;
             if(IsUnitType(wunit, UNIT_TYPE_DEAD) != true && GetUnitTypeId(wunit) != 0 && GetUnitFlyHeight(wunit) <= GetUnitDefaultFlyHeight(wunit)+10)
             {
                 this = allocate();
                 U = wunit;
                 Timer = 0.;
                 Fly = 1.;
                 blockhig = blockhe;
                 timeblocking = pauhe;
                 ins = inss;
                 d = delay;
                 rem = rems;
                 kill = kills;
                 Dis = hei;
                 savehigh = 0.;
                 Jumpag = jumpags;
                 Ag = false;
                 ag = 0.5;
                 EfEnd = EJ;
                 DestroyEffect(AddSpecialEffect(XJ,GetUnitX(U),GetUnitY(U)));
                 High = 0.4;
                 Highsettings = Dis*High;
                 UnitAddAbility(U,'Amrf');
                 UnitRemoveAbility(U,'Amrf');
                 TimerStart(NewTimerEx(this),.032500000,true,function thistype.onLoopJ);
             }
             
        }
    }
}
//
library AaD
{
    public function Distance(real xa,real ya,real xb,real yb) -> real
    {
        real dx = xb - xa;
        real dy = yb - ya;
        return SquareRoot(dx * dx + dy * dy);
    }
    //
    public function Angle(real xa,real ya,real xb,real yb) -> real
    {
        return bj_RADTODEG * Atan2(yb - ya, xb - xa);
    }
}
//
library DummRemove requires TimerUtils
{
    public struct Dum
    {
        unit u;
        //
        static method Loop()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            RemoveUnit(u);
            u = null;
            ReleaseTimer(GetExpiredTimer());
            destroy();
        }
        //
        static method Remove(unit whatunit,real dura) -> unit
        {
            thistype this = allocate();
            u = whatunit;
            TimerStart(NewTimerEx(this),dura,false,function thistype.Loop);
            return whatunit;
        }
    }
}
//
library Linked requires TimerUtils
{
    public struct LL
    {
        unit u;
        unit tg;
        lightning l;
        boolean linked;
        real time;
        real x;
        real y;
        real w;
        //
        static method onPeriodic()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            boolean release = false;
            //
            if(w > 0)
                w = w - .04;
            else
            {
                if(!linked)
                {
                    if(IsUnitType(u,UNIT_TYPE_DEAD) != true && GetUnitTypeId(u) != 0)
                        MoveLightningEx(l,true,GetUnitX(u),GetUnitY(u),GetUnitFlyHeight(u),x,y,0.);
                    else
                        release = true;
                }
                else
                {
                    if(IsUnitType(u,UNIT_TYPE_DEAD) != true && GetUnitTypeId(u) != 0 && IsUnitType(tg,UNIT_TYPE_DEAD) != true && GetUnitTypeId(tg) != 0)
                        MoveLightningEx(l,true,GetUnitX(u),GetUnitY(u),GetUnitFlyHeight(u),GetUnitX(tg),GetUnitY(tg),GetUnitFlyHeight(tg));
                    else
                        release = true;
                }
                //
                if(time > 0)
                    time = time - .04;
                else
                    release = true;
                //
            }
            //
            if(release)
            {
                DestroyLightning(l);
                ReleaseTimer(GetExpiredTimer());
                u = null;
                destroy();
            }
        }
        //
        static method LLSU(real wait,unit us,unit tgs,string ls,real times)
        {
            thistype this = allocate();
            u = us;
            tg = tgs;
            time = times;
            w = wait;
            linked = true;
            l = AddLightning(ls,true,GetUnitX(u),GetUnitY(u),x,y);
            TimerStart(NewTimerEx(this),.04,true,function thistype.onPeriodic);
        }
    }
}
//! endzinc[/HIDDEN]
III/ Spell Look Like:

screen10.jpg

screen11.jpg


IV/ Credits:
Click to view library DelFX
Click to view Timer Utils
Click to view library SpellEffectEvent
Click to view library Table
Click to view library xecast, xedamage
-------------------------------------------


Keywords:
lightning,walls,2,laser
Contents

Electric Walls (Map)

Reviews
15:30, 23rd Aug 2013 PurgeandFire: Approved and recommended. An cool-looking, lightning-tastic spell.

Moderator

M

Moderator

15:30, 23rd Aug 2013
PurgeandFire: Approved and recommended. An cool-looking, lightning-tastic spell.
 
Since it selects targets in a cirular AOE, I kind of fail to see the point of having it as a wall of lightning, it may as well be a mana burn sphere effect and save all the lightning creations and those lightning orbs - they don't do anything. you'd cut the code in well over half and nothing would really change.

I know you move an orb across the "wall" but you only need one of those, don't need all the others and argueably not that either, also object editor damage really isn't good. I think half of the code could've been put to better use with creating an actual "lazer" for the "wall" rather than creating some redundant effects which may have a good feel, but don't actually reprisent anything (incidentally I think the name "lightning lazer" is unfitting for this spell in it's current state)
 
Well, thanks tank about your suggestion but i writed lightning laser, i don't write lightning lazer, please look carefully.

well I would correct my spelling to laser (because lazer isn't actually a word and it's just one of those spellings I always slip up on) doesn't exactly change my comment nor is the "difference" between lazer and laser pertinant to my point. Of course, it's your spell and you can do what you like with it, though the point remains.
 
well I would correct my spelling to laser (because lazer isn't actually a word and it's just one of those spellings I always slip up on) doesn't exactly change my comment nor is the "difference" between lazer and laser pertinant to my point. Of course, it's your spell and you can do what you like with it, though the point remains.

Well, i see i'm was wrong, i'm sorry so much, Tank ;), please forgive me T.T!.
 
Review:
  • In the method onCast, you have this:
    JASS:
    set x = tarx + 0 * Cos(0.01747)
    set y = tary + 0 * Sin(0.01747)
    0 * n = 0, so it can be simplified to:
    JASS:
    set x = tarx 
    set y = tary
    You can actually just remove the local variables "x" and "y" and use "tarx" and "tary" instead.
  • In the method onCast, these lines:
    JASS:
    set o = tarx + ORB_COLUMN * Cos((f+ORB_ANGLE)*0.01747)
    set z = tary + ORB_COLUMN * Sin((f+ORB_ANGLE)*0.01747)
    Can be precalculated since all of it is constant. Just put it below the declarations of tarx and tary:
    JASS:
    local real tarx = GetSpellTargetX()
    local real tary = GetSpellTargetY()
    local real o = tarx + ORB_COLUMN * Cos((f+ORB_ANGLE)*0.01747)
    local real z = tary + ORB_COLUMN * Sin((f+ORB_ANGLE)*0.01747)
  • In the method onCast, you should set u = null.
  • In the method onPeriodic, you can precalculate some more calculations. Check out these lines:
    JASS:
                    if not fade then
                        set x = GetUnitX(dummy.unit[i]) + ORB_LASER_SPEED * Cos(facing*0.01747)
                        set y = GetUnitY(dummy.unit[i]) + ORB_LASER_SPEED * Sin(facing*0.01747)
                        call SetUnitPosition(dummy.unit[i],x,y)
            
                    else
                        set x = GetUnitX(dummy.unit[i]) - ORB_LASER_SPEED * Cos(facing*0.01747)
                        set y = GetUnitY(dummy.unit[i]) - ORB_LASER_SPEED * Sin(facing*0.01747)
                        call SetUnitPosition(dummy.unit[i],x,y)
                    endif
    ORB_LASER_SPEED * Cos(facing * 0.01747) is a constant. So is the one multiplied by sin. Thus, you can actually make two real members of the struct and store those:
    JASS:
    real offsetX
    real offsetY
    // declare the members in your struct
    In the method onCast, you would define them:
    JASS:
    //Set dummies move angle
    set facing = Angle(GetUnitX(dummy.unit[i]),GetUnitY(dummy.unit[i]),o,z)
    //
    set offsetX = ORB_LASER_SPEED * Cos(facing * 0.01747)
    set offsetY = ORB_LASER_SPEED * Sin(facing * 0.01747)
    Or even better:
    JASS:
    //Set dummies move angle
    set facing = Angle(GetUnitX(dummy.unit[i]),GetUnitY(dummy.unit[i]),o,z) * 0.01747
    //
    set offsetX = ORB_LASER_SPEED * Cos(facing)
    set offsetY = ORB_LASER_SPEED * Sin(facing)
    Then in the method onPeriodic, you would just use offsetX and offsetY:
    JASS:
                    if not fade then
                        set x = GetUnitX(dummy.unit[i]) + offsetX
                        set y = GetUnitY(dummy.unit[i]) + offsetY
                        call SetUnitPosition(dummy.unit[i],x,y)
            
                    else
                        set x = GetUnitX(dummy.unit[i]) - offsetX
                        set y = GetUnitY(dummy.unit[i]) - offsetY
                        call SetUnitPosition(dummy.unit[i],x,y)
                    endif
  • In the method filterUnit, you have this line:
    IsUnitEnemy(u, GetTriggerPlayer())
    Since you are checking GetTriggerPlayer() in the timer loop, it might return null (iirc). Instead you should check:
    IsUnitEnemy(u, GetOwningPlayer(caster))

Other than that, it looks good. :thumbs_up: Another eye-candy spell.
 
Top