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

Lightning Walls v1.1

  • Like
Reactions: Doomlord
Spell Information
a17.jpg


JASS:
//**********************************************************************************************************************
//**********************Spell Create By:
//                               -Elphis
//*********************Requires:
//                               - SimpleJumpSystem
//                               - Linked Lightning
//                               - DummyRemoved
//                               - DamageDestructable
//                               - SpellEffectEvent - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
//                               - TimerUtils - http://www.wc3c.net/showthread.php?t=101322
//                               - GroupUtils - http://www.wc3c.net/showthread.php?t=104464
//                               - DelDX - 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
//*********************Optional:
//                               - xebasic - http://www.wc3c.net/showthread.php?t=101150
//************Spell Information:
//                                - Blocking all enemies and allies within certain, making them unable to pass through
//                                - Level 1: Block in 4 seconds
//                                - Level 2: Block in 5 seconds
//                                - Level 3: Block in 6 seconds
//                                - Level 4: Block in 7 seconds
//*****************Installation:
//                                - Import/copy the required libraries and Lightning Walls code to your map
//                                - Import/copy the custom ability and unit to your map and change the SPELL_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
//***********************************************************************************************************************
library LightningWalls initializer Init uses DestructableHurt,SJS,DummRemove,CheckRawcodeAvailable,Linked,DelFX optional xebasic
        //==================================CONFIGURABLES==================================//
    globals
        //Rawcode of Spell
        private     constant        integer         SPELL_ID              =      'LNWA'
        //Pathing Block Unit
        private     constant        integer         PATHING_BLOCK         =      'YTpc'
        //Wall Count
        private     constant        integer         WALLS_COUNT           =      10
        //Lightning Ball Effect
        private     constant        string          LIGHTNING_BALL        =      "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
        //Combine with Ball
        private     constant        string          LIGHTNING_BALL_COMBINE=      "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl"
        //Effect when lightning destroyed
        private     constant        string          LIGHTNING_EXPLORE     =      "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
        //Lightning Attach
        private     constant        string          LIGHTNING_ALT         =      "CLPB"
        // Attachment of lightning ball
        private     constant        string          ATTACH_BALL           =       "chest"
        // Attachment of lightning ball effect
        private     constant        string          ATTACH_BALL_EFFECT    =       "chest"
        // Duration of Walls
        private     constant        real            DURATION_BASE         =      3.
        // Wall Size
        private     constant        real            WALLS_SIZE            =      1.5
        // Distance Between walls created
        private     constant        real            WALLS_DISTANCE        =      125.
        // HEIGHT of Balls
        private     constant        real            HEIGHT                =      700.
        // Safe Timer Will Destroy with Balls (Effect Only)
        private     constant        real            SAFE_TIMER            =      2.
        // Angle of Walls Created
        private     constant        real            WALLS_ANGLE           =      -90.
        //==================================CONFIGURABLES==================================//
    endglobals
        //
    //==================================Do not edit anything below==================================//
    private function onDuration takes unit u returns real
        return DURATION_BASE+GetUnitAbilityLevel(u,SPELL_ID)
    endfunction
    //
    private function onCast takes nothing returns nothing
        local integer i = WALLS_COUNT-1
        local unit u = GetTriggerUnit()
        local real tarx = GetSpellTargetX()
        local real tary = GetSpellTargetY()
        local real cos = Cos((GetUnitFacing(u)+WALLS_ANGLE)*3.14159/180)
        local real sin = Sin((GetUnitFacing(u)+WALLS_ANGLE)*3.14159/180)
        local real e = -WALLS_DISTANCE*WALLS_COUNT/2
        local real dur = onDuration(u) + SAFE_TIMER
        local unit d
        local real x
        local real y
        local unit dd
        local destructable des
        //
        loop
            exitwhen i < 0
            //
            set e = e + WALLS_DISTANCE
            set x = tarx + e * cos
            set y = tary + e * sin
            if RawcodeUnit(XE_DUMMY_UNITID) != null then
            set d = CreateUnit(Player(15),XE_DUMMY_UNITID,x,y,bj_UNIT_FACING)
            call CreateDelayedEffectTarget(LIGHTNING_BALL,d,ATTACH_BALL,0.,dur)
            call CreateDelayedEffectTarget(LIGHTNING_BALL_COMBINE,d,ATTACH_BALL,0.,dur)
            call SetUnitScale(d,WALLS_SIZE,WALLS_SIZE,WALLS_SIZE)
            set dd = CreateUnit(Player(15),XE_DUMMY_UNITID,x,y,bj_UNIT_FACING)
            call CreateDelayedEffectTarget(LIGHTNING_BALL,dd,ATTACH_BALL,0.,dur)
            call CreateDelayedEffectTarget(LIGHTNING_BALL_COMBINE,dd,ATTACH_BALL,0.,dur)
            call SetUnitScale(dd,WALLS_SIZE,WALLS_SIZE,WALLS_SIZE)
            set des = CreateDestructable(PATHING_BLOCK,x,y,0.,1.,0)
            call J.Jumping(1.,true,dur-SAFE_TIMER,d,HEIGHT,"",LIGHTNING_EXPLORE,false,true,false,0.)
            call LL.LLSU(0.,d,dd,LIGHTNING_ALT,dur)
            call D.DesHurt(dur,des)
            call Dum.Remove(dd,dur)
            else
                debug BJDebugMsg("Error: Rawcode of this DUMMY is not Available, please check this rawcode !!")
            endif
            //
            set i = i - 1
        endloop
        //
        set des = null
        set u = null
        set d = null
        set dd = null
    endfunction
    //
    private function Init takes nothing returns nothing
        call RegisterSpellEffectEvent(SPELL_ID,function onCast)
    endfunction
    //
endlibrary
[/HIDDEN]

JASS:
//I Created xe dummy by Vexorian in your Object, Just create trigger and copy this in your trigger: //! runtextmacro RunXeUnit()
//! textmacro RunXeUnit
//! external ObjectMerger w3u ewsp xeca unam "xe unit" uhpm 1 uabi Aloc,Aeth, umdl "war3mapImported\dummy.mdx" uico "ReplaceableTextures\CommandButtons\BTNtemp.blp" usid 1 usin 1 unsf "(Caster System?)" uble 0.00 ucbs 0.00 umxp 0.00 umxr 0.00 uimz 0.00 ulpz 0.00 uprw 1.00 uspa "" udty Divine umvs 522 ucol 0.00 ufoo 0 uhom 1 umpi 1000 umpm 1000 umpr 1.00 urac Commoner utyp "" ubui "" upgr "" utub "http://wc3campaigns.net/vexorian-External By Elphis" utip ""
//! endtextmacro
//---------------------------------------------
//
//
//! zinc
//
//
//---------------------------------------------
//
library DestructableHurt requires TimerUtils
{
    public struct D
    {
        destructable d;
        //
        static method Loop()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            if(GetWidgetLife(d) > 0.425)
            {
                RemoveDestructable(d);
                ReleaseTimer(GetExpiredTimer());
                d = null;
                destroy();
            }
        }
        //
        static method DesHurt (real wait,destructable p) 
        {
            thistype this;
            if (GetWidgetLife(p) > 0.425)
            {
                this = allocate();
                d = p;
                TimerStart(NewTimerEx(this),wait,false,function thistype.Loop);
            }
            
        }
    }
}
//
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]

Keywords:
walls,lightning
Contents

Lightning Walls (Map)

Reviews
22:28, 8th Aug 2013 PurgeandFire: Approved. Cool spell. Review: http://www.hiveworkshop.com/forums/2396237-post7.html

Moderator

M

Moderator

22:28, 8th Aug 2013
PurgeandFire: Approved. Cool spell.

Review:
http://www.hiveworkshop.com/forums/2396237-post7.html
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Hi, I will do a short review of this spell to practice reading vJASS codes ^^

Here is the library pack for those interested.
JASS:
//I Created xe dummy by Vexorian in your Object, Just create trigger and copy this in your trigger: //! runtextmacro RunXeUnit()
//! textmacro RunXeUnit
//! external ObjectMerger w3u ewsp xeca unam "xe unit" uhpm 1 uabi Aloc,Aeth, umdl "war3mapImported\dummy.mdx" uico "ReplaceableTextures\CommandButtons\BTNtemp.blp" usid 1 usin 1 unsf "(Caster System?)" uble 0.00 ucbs 0.00 umxp 0.00 umxr 0.00 uimz 0.00 ulpz 0.00 uprw 1.00 uspa "" udty Divine umvs 522 ucol 0.00 ufoo 0 uhom 1 umpi 1000 umpm 1000 umpr 1.00 urac Commoner utyp "" ubui "" upgr "" utub "http://wc3campaigns.net/vexorian-External By Elphis" utip ""
//! endtextmacro
//---------------------------------------------
//
//
//! zinc
//
//
//---------------------------------------------
//
library DestructableHurt requires TimerUtils
{
    public struct D
    {
        real dur;
        real damage;
        real w;
        real l;
        destructable d;
        effect e;
        //
        static method Loop()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            if(GetWidgetLife(d) > 0.425)
            {
                if(w > 0)
                    w = w - l;
                else
                {
                    dur = dur - l;
                    SetDestructableLife(d,GetDestructableLife(d) - damage);
                    if (dur <= 0)
                    {
                        ReleaseTimer(GetExpiredTimer());
                        DestroyEffect(e);
                        d = null;
                        destroy();
                    }
                }
            }
            else
            {
                ReleaseTimer(GetExpiredTimer());
                DestroyEffect(e);
                d = null;
                destroy();
            }
        }
        //
        static method DesHurt (real wait,destructable p,real dura,real dam,real ls,string ef) 
        {
            thistype this;
            if (GetWidgetLife(p) > 0.425)
            {
                this = allocate();
                dur = dura;
                damage = dam;
                d = p;
                l = ls;
                w = wait;
                e = AddSpecialEffect(ef,GetDestructableX(d),GetDestructableY(d));
                TimerStart(NewTimerEx(this),l,true,function thistype.Loop);
            }
            
        }
    }
}
//
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(GetWidgetLife(U) > 0.425)
                {
                    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(GetWidgetLife(wunit) > 0.425 && 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 Loop()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            if(GetWidgetLife(u) > 0.425)
            {
                if(w > 0)
                    w = w - .04;
                else
                {
                    if(!linked)
                        MoveLightningEx(l,true,GetUnitX(u),GetUnitY(u),GetUnitFlyHeight(u),x,y,0.);
                    else
                        MoveLightningEx(l,true,GetUnitX(u),GetUnitY(u),GetUnitFlyHeight(u),GetUnitX(tg),GetUnitY(tg),GetUnitFlyHeight(tg));
                    //
                    if(time > 0)
                        time = time - .04;
                    else
                    {
                        DestroyLightning(l);
                        ReleaseTimer(GetExpiredTimer());
                        u = null;
                        destroy();
                    }
                }
            }
            else
            {
                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.Loop);
        }
    }
}
//
library CheckRawcodeAvailable
{
    public struct Check
    {
        //This system check rawcode unit available in your object
        static method RawcodeUnit(integer i) -> unit
        {
            unit u;
            //
            u = CreateUnit(Player(15),i,0,0,0);
            if(u != null)
            {
                RemoveUnit(u);
                debug BJDebugMsg("This rawcode not null");
            }
            else
                debug BJDebugMsg("This rawcode is null");
            return u;
        }
    }
}
//! endzinc

REVIEW
  1. General
    • Credit is missing in the description.
    • You should add links to the required libraries for those who do not want to open the test map to get them.
  2. Pros
    • Global block is lined up beautifully.
    • The spell is quite unique and has good effects.
    • Configuration range is high enough.
  3. Cons
    • Tooltip can and should be improved.
    • You need to add importing instructions.
    • xe is missing from the list of required libraries (it is required for your library pack).
    • Here we have a preference for putting your vJASS spell codes inside a struct. I am not saying your way of doing it is wrong. It is just that we prefer a distinctive coding style to distinguish vJASS spells from vanilla JASS ones.
    • Your indentation for the private functions is incorrect. It should be linear with the global block.
      JASS:
      scope LightningWalls initializer Init
      
          globals
              // Some globals here
          endglobals
      
          private function getBlah takes nothing returns nothing
              // Blah blah blah
          endfunction
      
          private function getBlahSecond takes nothing returns nothing
              // Some more blah
          endfunction
      endscope
    • Actually, GLOBAL_CONSTANTS_LIKE_THIS, globalVariablesLikeThis, localVariablesLikeThis, StructsLikeThis, ModulesLikeThis, FunctionsLikeThis, etc...

      JPAG - Read this
    • Your global block could be improved for readability.
      Compare your current code and this
      JASS:
          globals
              // Rawcode of Spell
              private     constant        integer         SPELLID              =      'LNWA' 
              // Pathing Block Unit
              private     constant        integer         PathingBlock         =      'YTpc' 
              // Wall Count
              private     constant        integer         WallsCount           =      10 
              
              // Lightning Ball Effect
              private     constant        string          LightningBall        =      "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
              // Combine with Ball
              private     constant        string          LightningBallCombine =      "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl" 
              // Effect when lightning destroyed
              private     constant        string          LightningExplore     =      "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl" 
          endglobals

      Much more readable, don't you think?
    • LightningAlt global is the lightning type. You should let users know that.
    • In the Spells Staus library pack, GetWidgetLife(u) > 0.425 is not the best thing to use for checking if a unit is alive or not since some dead units can still have more than 0.405 health. I would recommend not IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId(u) != 0
    • Lightnings don't connect the two orbs together. It looks really weird if you change the camera angle.
    • The pathing check is a bit weird somehow since some lightning instances are not created despite the terrain there being absolutely fine.

I wish I could review more aspects of the spell but unfortunately I am not familiar at all with the libraries used here. But I guess your code is well-executed enough.

That is all I can see for now. Feel free to speak up if you feel like I misread your code somewhere :)
 
Last edited:
Review:
  • In "onCast", you can set some of the locals right when you declare them:
    JASS:
    local unit u = GetTriggerUnit()
    // ... 
    local real dur = onDuration(u) + SAFE_TIMER
  • In "onCast", in the loop, you use:
    JASS:
    set x = GetSpellTargetX() + e * Cos(GetUnitFacing(u) * bj_DEGTORAD)
    set y = // ...
    However, you should store the constant values:
    JASS:
    local real tarx = GetSpellTargetX()
    local real tary = GetSpellTargetY()
    local real cos = Cos(GetUnitFacing(u) * bj_DEGTORAD)
    local real sin = Sin(GetUnitFacing(u) * bj_DEGTORAD)
    And when you set x and y:
    JASS:
    set x = tarx + e * cos
    set y = tary + e * sin

That's it. :)
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
I don't think it's a good idea to always keep checking if the xe dummy rawcode is available whenever the spell is cast. Something like this should be done at map time and inform the map author when debug is enabled.

This is minor, but you could remove the I2R in onDuration since DURATION_BASE is a real.

I'm not really a fan of your coding style.
Most of the variable names are too short and not descriptive.
I don't understand why the indentation became inconsistent with the if in your loop in onCast().
Whitespace would be nice in function calls.
 
I don't think it's a good idea to always keep checking if the xe dummy rawcode is available whenever the spell is cast. Something like this should be done at map time and inform the map author when debug is enabled.

This is minor, but you could remove the I2R in onDuration since DURATION_BASE is a real.

I'm not really a fan of your coding style.
Most of the variable names are too short and not descriptive.
I don't understand why the indentation became inconsistent with the if in your loop in onCast().
Whitespace would be nice in function calls.

..Sure, i'll fix that, thanks a lot :)
 
Level 11
Joined
Oct 11, 2012
Messages
711
..Sure, i'll fix that, thanks a lot :)

Hi there. I am using your Lightning Walls spell, it is a really nice spell. However, I have found a bug with it. It seems your spell will contradict with the timers in my map. Here is the problem: couple minutes after the Lightning Wall disappear, the invisible road blocks will reappear at the location where the Lightning Wall was. The dummies do not reappear, just the invisible road blocks and that makes the units cannot go through. Do you know what causes that? Thanks a lot. :)


Update: The problem is not caused by the spell. It is caused by one trigger that I use to revive destructables. Sorry, nhocklanhox6. :)
I really love this spell. :)
 
Last edited:
Hi there. I am using your Lightning Walls spell, it is a really nice spell. However, I have found a bug with it. It seems your spell will contradict with the timers in my map. Here is the problem: couple minutes after the Lightning Wall disappear, the invisible road blocks will reappear at the location where the Lightning Wall was. The dummies do not reappear, just the invisible road blocks and that makes the units cannot go through. Do you know what causes that? Thanks a lot. :)

Read visitor messages: Click Here
 
Top