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

Trap Lightning v1.2

-------------------------------------------
**
**T R A P**
**
**L I G H T N I N G**
**


I/ Spell Information:
untit208.jpg

II/ Spell Code:
JASS:
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//          T R A P    L I G H T N I N G
//                                  - Spell Create By:
//                                                      + Elphis
//*************************************************************************************
library TrapLightning /*                   
*/                                      requires /*
//                                              -*/ TimerUtils /* http://www.wc3c.net/showthread.php?t=101322
//                                              -*/ SpellEffectEvent /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
//                                              -*/ xedamage /* http://www.wc3c.net/showthread.php?t=101150
//                                              -*/ AbilityPreload /* http://www.wc3c.net/showthread.php?t=101150 */
//                                      Optional:
//                                                GreatLightning.mdx - http://www.hiveworkshop.com/forums/models-530/great-lightning-66381/?prev=search%3DGreat%2520L%26d%3Dlist%26r%3D20
//                                                BoundSentinel - http://www.wc3c.net/showthread.php?t=102576 (You must adding it, this library help you prevent crash the game when lightning outside XY of map.
//*************************************************************************************
//          - Spell Information:
//                              - Use power of lightning call Globe Electric fall out the sky, when it hit a ground,it explore
//                                explosion caused a power deals 40/80/120/160 damage to enemies unit in 500 range
//                                and stun them in 1/1.5/2/2.5|r seconds 
//                                it'll create 2 magnetic balls, it will absorb the force of the ground and launched an intense power 
//                                when enemies inside that AOE
//                                electric current will deals 20/40/60/80 damage to them and when those balls go 1 round
//                                it caused explotion again and deals 40/80/120/160 damage to enemies unit and stun them 1/1.5/2/2.5 seconds
//*************************************************************************************
//          - Installation:
//                                - Import/copy the required libraries and Trap Lightning code to your map
//                                - Import/copy the custom ability and unit to your map and change the SPELL_ID, SPELL_STUN 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
        //Periodic for this spell
        private         constant        real            PERIODIC        =           0.031250000           
        //Spell rawcode, change if needed
        private         constant        integer         SPELL_ID        =           'A000'
        //Spell stun rawcode, change if needed
        private         constant        integer         SPELL_STUN      =           'A001'
        //Dummy Lightning rawcode, change if needed
        private         constant        integer         LIGHTNING_DUMMY =           'e000'
        //Ability allow unit fly
        private         constant        integer         ABI_FLY         =           'Amrf'
        //Size of lightning
        private         constant        real            TRAP_SIZE       =           2.
        //Value effect and damage between 2 orb of lightning, this value must be divisible by two
        private         constant        integer         DATA_COUNT      =           6
        //Height of lightning
        private         constant        real            HEIGHT          =           800.
        //Circle max distance
        private         constant        real            CIRCLE_DISTANCE =           700.
        //Max distance of trap
        private         constant        real            MAX_DIS_BASE    =           500.
        //Base damage of trap
        private         constant        real            DAMAGE_BASE     =           20.
        //Damage radius of trap when enemies inside, do not increase too much because it's very powerful, you know ?
        private         constant        real            DAMAGE_RADIUS   =           50.
        //Damage radius when lightning hit a ground and lightning disapear
        private         constant        real            EXPIRE_RADIUS   =           500.
        //Trap fall out speed
        private         constant        real            TRAP_SPEED      =           50.
        //Trap sort speed
        private         constant        real            TRAP_SORT       =           20.
        //Min height of lightning
        private         constant        real            MIN_HEIGHT      =           50.
        //Trap angle
        private         constant        real            TRAP_ANGLE      =           -90.
        //Trap max rotation angle (Spell expire when reach this value also, if you increase it, this spell will go many round
        //For Example:
        //1 round = 360. => spell expire when go 1 round, 720 = 2 round => spell expire when go 2 round :)
        private         constant        real            TRAP_MAX_ROT    =           360.
        //Damage and effect intevar
        private         constant        real            TRAP_INTEVAR    =           0.15
        //Trap rotation speed.
        private         constant        real            TRAP_ROTATION   =           2.
        //Lightning Model
        private         constant        string          MODEL           =           "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
        //Lightning flush when the trap moving
        private         constant        string          FLUSH_MODEL     =           "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        //Lighning effect when spell expire
        private         constant        string          EFFECT_EXPIRE   =           "war3mapImported\\Great Lightning.mdx"
        //Attachment of Trap
        private         constant        string          ATTACH          =           "origin"
        //Lightning model
        private         constant        string          LIGHTNING_MODEL =           "CLPB"
        //Order of ability stun
        private         constant        string          ORDER_SLAM      =           "stomp"
        //
        private         constant        boolean         DAMAGE_TREE     =           true
        //                         =ATTACK DAMAGE WEAPON TYPE SETTINGHS=
        private     constant            attacktype      ATTACKTYPE      =       ATTACK_TYPE_HERO
        private     constant            damagetype      DAMAGETYPE      =       DAMAGE_TYPE_COLD
        private     constant            weapontype      WEAPONTYPE      =       WEAPON_TYPE_METAL_HEAVY_BASH
        //
    endglobals
    //
    private struct TrapLightning
    //
        //
        //lightning
        lightning ll
        lightning lr
        //unit
        unit caster
        unit dummy
        unit dummyleft
        unit dummyright
        //player
        player p
        //real
        real xx
        real yy
        real h
        real r = 0.
        real al = 0.
        real ar = 0.
        real in = 0.
        real maxdis
        real dam
        //xedamage installing
        xedamage xed
        //
        static method onDamage takes unit caster returns real
            
            return DAMAGE_BASE*GetUnitAbilityLevel(caster,SPELL_ID) //Damage of spell
        endmethod
        //
        static method distanceInc takes unit caster returns real
            return 100.*GetUnitAbilityLevel(caster,SPELL_ID)+MAX_DIS_BASE //Max distance of trap lightning effective
        endmethod
        //
        static method onPeriodic takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            //
            local real logic
            local real di = 0.
            //
            local real x
            local real y
            //
            local integer i = 1
            //
            if h > MIN_HEIGHT then
                //
                //Decrease height of lightning fall out the sky
                //
                set h = h - TRAP_SPEED
                //
                call SetUnitFlyHeight(dummy,h,0.)
                //
            elseif dummyleft == null then
                //
                //Slam ground
                call IssueImmediateOrder(dummy,ORDER_SLAM)
                //This line deals damage to enemies unit when lightning hit ground
                call xed.damageAOE(caster,xx,yy,EXPIRE_RADIUS,dam*2)
                //Begin create a mini lightning
                set dummyleft = CreateUnit(p,LIGHTNING_DUMMY,xx,yy,0.)
                call SetUnitScale(dummyleft,TRAP_SIZE/2,0.,0.)
                set ll = AddLightning(LIGHTNING_MODEL,true,xx,yy,xx,yy)
                //Begin create a mini lightning
                set dummyright = CreateUnit(p,LIGHTNING_DUMMY,xx,yy,0.)
                call SetUnitScale(dummyright,TRAP_SIZE/2,0.,0.)
                set lr = AddLightning(LIGHTNING_MODEL,true,xx,yy,xx,yy)
                //
            else
                if r < maxdis and ar < TRAP_MAX_ROT then
                    set r = r + TRAP_SORT
                    //
                    set x = GetWidgetX(dummyleft) + TRAP_SORT * Cos(.01747*TRAP_ANGLE)
                    set y = GetWidgetY(dummyleft) + TRAP_SORT * Sin(.01747*TRAP_ANGLE)
                    //
                    call SetUnitX(dummyleft,x)
                    call SetUnitY(dummyleft,y)
                    call MoveLightning(ll,true,x,y,xx,yy)
                    call SetUnitX(dummyright,x)
                    call SetUnitY(dummyright,y)
                    call MoveLightning(lr,true,x,y,xx,yy)
                else
                    if ar < TRAP_MAX_ROT then
                    //
                        //
                        set ar = ar + TRAP_ROTATION
                        set al = al - TRAP_ROTATION
                        //
                        set x = GetWidgetX(dummy) + maxdis * Cos((TRAP_ANGLE-ar)*.01747)
                        set y = GetWidgetY(dummy) + maxdis * Sin((TRAP_ANGLE-ar)*.01747)
                        //
                        call SetUnitX(dummyleft,x)
                        call SetUnitY(dummyleft,y)
                        call MoveLightning(ll,true,x,y,xx,yy)
                        //
                        set x = GetWidgetX(dummy) + maxdis * Cos((TRAP_ANGLE-al)*.01747)
                        set y = GetWidgetY(dummy) + maxdis * Sin((TRAP_ANGLE-al)*.01747)
                        //
                        call SetUnitX(dummyright,x)
                        call SetUnitY(dummyright,y)
                        call MoveLightning(lr,true,x,y,xx,yy)
                        //
                        if in < TRAP_INTEVAR then
                            set in = in + PERIODIC
                        else
                            set in = 0.
                            //
                            set logic = maxdis/DATA_COUNT
                            //
                            loop
                                exitwhen i > DATA_COUNT
                                //
                                set x = xx + di * Cos((TRAP_ANGLE-ar)*.01747)
                                set y = yy + di * Sin((TRAP_ANGLE-ar)*.01747)
                                //
                                call DestroyEffect(AddSpecialEffect(FLUSH_MODEL,x,y))
                                //
                                //This line deals damage to enmies unit (Left)
                                call xed.damageAOE(caster,x,y,DAMAGE_RADIUS,dam)
                                //
                                set x = xx + di * Cos((TRAP_ANGLE-al)*.01747)
                                set y = yy + di * Sin((TRAP_ANGLE-al)*.01747)
                                //
                                call DestroyEffect(AddSpecialEffect(FLUSH_MODEL,x,y))
                                //
                                //This line deals damage to enmies unit (Right)
                                call xed.damageAOE(caster,x,y,DAMAGE_RADIUS,dam)
                                //
                                set di = di + logic
                                //
                                set i = i + 1
                            endloop
                        endif
                    //
                    else
                        if r > 0. then
                            set r = r - TRAP_SORT
                            //
                            set x = GetWidgetX(dummyleft) - TRAP_SORT * Cos(.01747*TRAP_ANGLE)
                            set y = GetWidgetY(dummyleft) - TRAP_SORT * Sin(.01747*TRAP_ANGLE)
                            //
                            call SetUnitX(dummyleft,x)
                            call SetUnitY(dummyleft,y)
                            call MoveLightning(ll,true,x,y,xx,yy)
                            call SetUnitX(dummyright,x)
                            call SetUnitY(dummyright,y)
                            call MoveLightning(lr,true,x,y,xx,yy)
                        else
                            //Clean data
                            call xed.damageAOE(caster,xx,yy,EXPIRE_RADIUS,dam*2)
                            //Slam ground
                            call IssueImmediateOrder(dummy,ORDER_SLAM)
                            call ReleaseTimer(t)
                            call DestroyEffect(AddSpecialEffect(EFFECT_EXPIRE,xx,yy))
                            call DestroyLightning(ll)
                            call DestroyLightning(lr)
                            call RemoveUnit(dummyleft)
                            call RemoveUnit(dummyright)
                            call RemoveUnit(dummy)
                            //
                            set caster = null
                            set dummy = null
                            set dummyright = null
                            set dummyleft = null
                            set p = null
                            set ll = null
                            set lr = null
                            //
                            call xed.destroy()
                            call destroy()
                        endif
                    endif
                endif
            endif
            //
            set t = null
            //
        endmethod
        //
        static method onCast takes nothing returns nothing
            local thistype this = allocate()
            //
            set caster = GetTriggerUnit()
            set p = GetTriggerPlayer()
            set h = HEIGHT
            set xed = xedamage.create()
            //Damage settings
            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   = DAMAGE_TREE
            //
            //Max distance configuration
            set maxdis = distanceInc(caster)
            //Damage configuration
            set dam = onDamage(caster)
            //
            set dummy = CreateUnit(p,LIGHTNING_DUMMY,GetSpellTargetX(),GetSpellTargetY(),0.)
            if UnitAddAbility(dummy,ABI_FLY) then
                call UnitRemoveAbility(dummy,ABI_FLY)
            endif
            call SetUnitScale(dummy,TRAP_SIZE,0.,0.)
            //Add ability stun to this dummy and also set ability level = ability caster
            call SetUnitAbilityLevel(dummy,SPELL_STUN,GetUnitAbilityLevel(caster,SPELL_ID))
            //
            set xx = GetWidgetX(dummy)
            set yy = GetWidgetY(dummy)
            //Calling Periodic
            call TimerStart(NewTimerEx(this),PERIODIC,true,function thistype.onPeriodic)
        endmethod
        
        static method onInit takes nothing returns nothing
            call Preload(FLUSH_MODEL)
            call AbilityPreload(SPELL_ID)
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
        endmethod
    endstruct
    //
endlibrary[/HIDDEN]
III/ Spell Look Like:

untit209.jpg

untit211.jpg

untit212.jpg

untit213.jpg


IV/ Credits:
Click to view Timer Utils
Click to view library SpellEffectEvent
Click to view library xebasic, xedamage
Click to view library Bound Sentinel
Click to view library Ability Preload
Click to view model Great Lightning
-------------------------------------------


v1.0: First release version.
v1.1: Remove Table, add library Sentinel, Optimized
v1.2: Optimized.


Keywords:
lightning, trap
Contents

Trap Lightning (Map)

Reviews
Trap Lightning v1.2 | Reviewed by Maker | 11th Oct 2013 APPROVED Approved [tr] There could be only one timer The spell is slightly laggy in its default configuration So many unnecessary repetated calculations here...

Moderator

M

Moderator


Trap Lightning v1.2 | Reviewed by Maker | 11th Oct 2013
APPROVED


126248-albums6177-picture66521.png


  • Approved
126248-albums6177-picture66523.png


  • There could be only one timer
  • The spell is slightly laggy in its default configuration
  • So many unnecessary repetated calculations here
    set x = GetWidgetX(dummyleft) + TRAP_SORT * Cos(.01747*TRAP_ANGLE) set y = GetWidgetY(dummyleft) + TRAP_SORT * Sin(.01747*TRAP_ANGLE)
  • Improve the tooltip description
  • When you create the falling orb, immediately give it flying height
  • The height of the lightnings do not match the flying height of the two dummy orbs
[tr]
 
Trap Lightning v1.1 Review

The lightning is a dangerous element. For example, it can form a trap like in this spell by nhocklanhox6.

Originality: 4/5. This spell has its charm, but it's still not unique to get 5/5. Here are some examples of similar spells to this one:Looks like this spell is just the combined phases of those ones.

Execution: 3.5/5. This code is...well, it can be a lot better. I can give some things I've pointed out here.
  • Bad variable naming. Qt Coding Style is really good example on how to name the variables right. So, according to one of the postulates of Qt, you must name variables depending on for what they are created. unit u is a bad example because we can't deduct what this variable does. unit abilityCaster or unit caster are some good examples of correct variable naming. Please note that, to avoid messing up, local variables must be named from a lowercase letter and global variables must be named from the uppercase letter. For example, unit Caster is a perfect name for a global variable and unit caster is a perfect name for a local variable. But still, you can use local integer i for loops since this abbreviation is very popular.
  • Unsafe 'Amrf' adding and removal. Different people are using different methods to operate dummies and it always needs to be foreseen by the maker of the spell. So, instead of doing:
    JASS:
    call UnitAddAbility(d,'Amrf')
                call UnitRemoveAbility(d,'Amrf')
    do:
    JASS:
    if UnitAddAbility(d,'Amrf') then
                call UnitRemoveAbility(d,'Amrf')
            endif
    Also make 'Amrf' as configurable constant. It's not the only ability that allows to modify flying height.
  • Preloading abilities missing. This one needs some analyzis. For example, imagine that the user wants to make 100 levels of the spell (which means 100 levels of the Stun ability). It might lag during the first cast of the spell then. However, it is preventable. Add this ability to the dummy at the Object Editor, not when the spell is being cast. Then place this dummy owned by Neutral Passive somewhere on the map and remove him when the game will start. Advice the users to use such a method too in documentation if they experience lag during the first cast of the spell. This can make the spell more handy and will also show you as the competent one in such questions. So, remove this code from your spell: call UnitAddAbility(d,SPELL_STUN).
  • GetWidgetX/Y is faster than GetUnitX/Y. It was benchmarked by me multiple times. The key is here:
    JASS:
    type unit extends widget
    type widget extends agent
    type agent extends handle
    The widget type is one level higher than unit so it will execute faster.
  • Unsafe lightning operations. Sometimes destroying a lightning can result a fatal error. To prevent that, use Lightning Utils. It will make code safer. And these lightnings here aren't instantly destroyed anyways.
  • Creating a dummy for Player(15) that can't allow a player to have a vision in the area is plain stupid. Create the dummy for the owner of the ability caster instead.
  • To make the orb's flying more smooth there is a trick allowing to do so, just figure out on how to use rates. This parameter isn't that useless as it seems: it allows to use a lot more intensive timer without much lag. Just experiment with it based on the link I gave you.
  • Pre-init struct variables. All these variables:
    JASS:
            lightning ll
            lightning lr
            //unit
            unit c
            unit d
            unit dl
            unit dr
            //real
            real xx
            real yy
            real h
            real r
            real al
            real ar
            real in
            real maxdis
            real dam
            //xedamage installing
            xedamage xed
    can easily be pre-inited. For example, real r = 0.. It will free you from the need to reinit them all again and again.

Effects: 3.5/5. Not that extraordinary eyecandy but it's pretty fitting in my opinion. I'd added some inner circles and made AOE decrease over time to reach one single point in the end and then *BOOM* here we see the lightning that strikes in the area where the lightnings were focused. It will make sense.

Overall: ((4+3.5+3.5)/3) = 3.7 = 4/5. This spell is a nice one but it needs many improvements in order to become a good coded spell.

4/5: Recommended
 
The lightning is a dangerous element. For example, it can form a trap like in this spell by nhocklanhox6.

Originality: 4/5. This spell has its charm, but it's still not unique to get 5/5. Here are some examples of similar spells to this one:Looks like this spell is just the combined phases of those ones.

Execution: 3.5/5. This code is...well, it can be a lot better. I can give some things I've pointed out here.
  • Bad variable naming. Qt Coding Style is really good example on how to name the variables right. So, according to one of the postulates of Qt, you must name variables depending on for what they are created. unit u is a bad example because we can't deduct what this variable does. unit abilityCaster or unit caster are some good examples of correct variable naming. Please note that, to avoid messing up, local variables must be named from a lowercase letter and global variables must be named from the uppercase letter. For example, unit Caster is a perfect name for a global variable and unit caster is a perfect name for a local variable. But still, you can use local integer i for loops since this abbreviation is very popular.
  • Unsafe 'Amrf' adding and removal. Different people are using different methods to operate dummies and it always needs to be foreseen by the maker of the spell. So, instead of doing:
    JASS:
    call UnitAddAbility(d,'Amrf')
                call UnitRemoveAbility(d,'Amrf')
    do:
    JASS:
    if UnitAddAbility(d,'Amrf') then
                call UnitRemoveAbility(d,'Amrf')
            endif
    Also make 'Amrf' as configurable constant. It's not the only ability that allows to modify flying height.
  • Preloading abilities missing. This one needs some analyzis. For example, imagine that the user wants to make 100 levels of the spell (which means 100 levels of the Stun ability). It might lag during the first cast of the spell then. However, it is preventable. Add this ability to the dummy at the Object Editor, not when the spell is being cast. Then place this dummy owned by Neutral Passive somewhere on the map and remove him when the game will start. Advice the users to use such a method too in documentation if they experience lag during the first cast of the spell. This can make the spell more handy and will also show you as the competent one in such questions. So, remove this code from your spell: call UnitAddAbility(d,SPELL_STUN).
  • GetWidgetX/Y is faster than GetUnitX/Y. It was benchmarked by me multiple times. The key is here:
    JASS:
    type unit extends widget
    type widget extends agent
    type agent extends handle
    The widget type is one level higher than unit so it will execute faster.
  • Unsafe lightning operations. Sometimes destroying a lightning can result a fatal error. To prevent that, use Lightning Utils. It will make code safer. And these lightnings here aren't instantly destroyed anyways.
  • Creating a dummy for Player(15) that can't allow a player to have a vision in the area is plain stupid. Create the dummy for the owner of the ability caster instead.
  • To make the orb's flying more smooth there is a trick allowing to do so, just figure out on how to use rates. This parameter isn't that useless as it seems: it allows to use a lot more intensive timer without much lag. Just experiment with it based on the link I gave you.
  • Pre-init struct variables. All these variables:
    JASS:
            lightning ll
            lightning lr
            //unit
            unit c
            unit d
            unit dl
            unit dr
            //real
            real xx
            real yy
            real h
            real r
            real al
            real ar
            real in
            real maxdis
            real dam
            //xedamage installing
            xedamage xed
    can easily be pre-inited. For example, real r = 0.. It will free you from the need to reinit them all again and again.

Effects: 3.5/5. Not that extraordinary eyecandy but it's pretty fitting in my opinion. I'd added some inner circles and made AOE decrease over time to reach one single point in the end and then *BOOM* here we see the lightning that strikes in the area where the lightnings were focused. It will make sense.

Overall: ((4+3.5+3.5)/3) = 3.7 = 4/5. This spell is a nice one but it needs many improvements in order to become a good coded spell.

4/5: Recommended

Thanks a lot ;).

Spell updated
 
Top