System Lightning

Lyncor

New Member
Reaction score
8
Lightning​
Version 1.01​

Lightning is an end-point tracker and fader for lightning effects, built using T32. It is a highly efficient implementation.
Requirements:
- Jass NewGen
- T32

JASS:
//
//      _    ___  ___ _   _ _____ __  _ ___ __  _  ___
//     | |  |_ _|/ __| |_| |_   _|  \| |_ _|  \| |/ __|
//     | |__ | || (_ |  _  | | | | \ \ || || \ \ | (_ |
//     |____|___|\___|_| |_| |_| |_|\__|___|_|\__|\___|
//                                   By Lyncor. v1.01.
//
//      What is Lightning?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//           Lightning is an efficient end-point tracker and fader for lightning
//          effects in Warcraft III.
//          
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//           Simply create a new trigger object called Lightning, go to 'Edit -> Convert
//          to Custom Text', and replace everything that's there with this script.
//          
//      Lightning Codes (Thanks to Flare):
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          "CLPB" - Chain Lightning Primary
//          "CLSB" - Chain Lightning Secondary
//          "DRAB" - Drain
//          "DRAL" - Drain Life
//          "DRAM" - Drain mana
//          "AFOD" - Finger of Death
//          "FORK" - Forked Lightning
//          "HWPB" - Healing Wave Primary
//          "HWSB" - Healing Wave Secondary
//          "CHIM" - Lightning Attack
//          "LEAS" - Magic Leash
//          "MBUR" - Mana Burn
//          "MFPB" - Mana Flare
//          "SPLK" - Spirit Link
//
//      Functions:
//     ¯¯¯¯¯¯¯¯¯¯¯¯
//          For the creation functions:
//              - "string code"   is the lightning type as a string.
//              - "real duration" is how long the lightning should last.
//              - "boolean fade"  is true if the lightning should fade over its duration.
//          
//          function Lightning_UnitUnit takes string code, unit from, unit to,
//           real duration, boolean fade returns nothing
//              - Creates and tracks lightning from one unit to another.
//          
//          function Lightning_CoordsUnit takes string code, real x, real y, real z,
//           unit to, real duration, boolean fade returns nothing
//              - Creates and tracks lightning from coordinates to a unit.
//          
//          function Lightning_UnitCoords takes string code, unit from,
//           real x, real y, real z, real duration, boolean fade returns nothing
//              - Creates and tracks lightning from a unit to coordinates.
//          
//          function Lightning_ColorLast takes real r, real g, real b returns nothing
//              - Sets the colour of the last created lightning to the red,
//                greed and blue values passed into the function (r, g, b).
//              - The values are real numbers ranging from 0 to 1.
//              - This must only be called immediately after calling a
//                creation function.
//
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Jesus4Lyf for assistance and writing T32.
// 

library Lightning uses T32
    globals
        // This offset is applied for all unit lightning links.
        private constant real HEIGHT_OFFSET=56.0
    endglobals
    
    //===========================================================
    // DATA DECLARATION:
    //
    //  The basic data for a link of lightning. This is so there
    // is minimal array declaration, and faster recycling of unit
    // handle ids.
    // 
    
    private struct Link //extends array // JassHelper won't allow this with inheritance.
        // Allocator that won't lose efficiency with inheritance.
        // Faster than vJass allocator.
        private static thistype array recycled
        private static integer recycledMax=0
        private static integer lastAlloc=0
        static method alloc takes nothing returns thistype
            if thistype.recycledMax==0 then
                set thistype.lastAlloc=thistype.lastAlloc+1
                return thistype(thistype.lastAlloc)
            endif
            set thistype.recycledMax=thistype.recycledMax-1
            return thistype.recycled[thistype.recycledMax]
        endmethod
        method dealloc takes nothing returns nothing
            set thistype.recycled[thistype.recycledMax]=this
            set thistype.recycledMax=thistype.recycledMax+1
        endmethod
        
        // Data
        lightning link
        
        real x // Don't need 2 sets of these,
        real y // because if it was linking coords
        real z // to coords, it wouldn't move.
        
        unit sU
        unit eU
        
        integer ticks
        
        real r
        real g
        real b
        real a
        real aSlide
    endstruct
    
    //===========================================================
    // CALLBACK DECLARATION:
    //
    //  This is all the data and code segments used in the links'
    // callback functions. Textmacros are brilliant, because they
    // provide functional decomposition without any efficiency
    // penalty.
    // 
    //  Globals have been used to shorten code (locals also have
    // terribly ugly declarations) and provide an efficiency
    // boost, as well as eliminate nulling concerns for the unit.
    // 
    //  T32 has been used to complete the razor sharp efficiency.
    // 
    
    globals
        private location LOC=Location(0,0)
    endglobals
    
    globals//locals
        private real X1
        private real Y1
        private real Z1
        
        private real X2
        private real Y2
        // Don't need Z2, can inline into the MoveLightning call.
        
        private unit Unit
    endglobals
    
    //===========================================================
    // Callback Snippets
    // 
    
    //! textmacro LGHT_CB__LoadUnit1
        set Unit=this.sU
        set X1=GetUnitX(Unit)
        set Y1=GetUnitY(Unit)
        call MoveLocation(LOC,X1,Y1)
    //! endtextmacro
    
    //! textmacro LGHT_CB__LoadUnit2
        set Unit=this.eU
        set X2=GetUnitX(Unit)
        set Y2=GetUnitY(Unit)
        call MoveLocation(LOC,X2,Y2)
    //! endtextmacro
    
    //! textmacro LGHT_CB__EscapeClause
        if this.ticks==0 then
            call DestroyLightning(this.link)
            call this.dealloc()
            return true
        endif
        set this.ticks=this.ticks-1 // Is effectively at the end of the periodic function.
    //! endtextmacro
    
    //! textmacro LGHT_CB__AlphaUpkeep
        call SetLightningColor(this.link,this.r,this.g,this.b,this.a)
        set this.a=this.a-this.aSlide
    //! endtextmacro
    
    //===========================================================
    // T32 Callbacks
    // 
    //  One for with alpha fading and one without for each cross
    // of unit/coords. For free efficiency if you don't fade.
    // 
    // Semantics:
    //  "U" means "Unit". "XY" means "Coordinates".
    //  "a" is for "alpha". Therefore:
    //  - UU means Unit to Unit, no alpha fade.
    //  - XYUa means Coordinates to Unit, with alpha fade.
    //  - etc.
    // 
    
    private struct LinkUUa extends Link
        private method periodic takes nothing returns boolean
            //! runtextmacro LGHT_CB__EscapeClause()
            
            //! runtextmacro LGHT_CB__LoadUnit1()
            set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
            //! runtextmacro LGHT_CB__LoadUnit2()
            
            call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
            //! runtextmacro LGHT_CB__AlphaUpkeep()
            
            return false
        endmethod
        implement T32
    endstruct
    private struct LinkUU extends Link
        private method periodic takes nothing returns boolean
            //! runtextmacro LGHT_CB__EscapeClause()
            
            //! runtextmacro LGHT_CB__LoadUnit1()
            set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
            //! runtextmacro LGHT_CB__LoadUnit2()
            
            call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
            
            return false
        endmethod
        implement T32
    endstruct
    
    private struct LinkXYUa extends Link
        private method periodic takes nothing returns boolean
            //! runtextmacro LGHT_CB__EscapeClause()
            
            call MoveLocation(LOC,this.x,this.y)
            set Z1=GetLocationZ(LOC)+this.z
            //! runtextmacro LGHT_CB__LoadUnit2()
            
            call MoveLightningEx(this.link,true,this.x,this.y,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
            //! runtextmacro LGHT_CB__AlphaUpkeep()
            
            return false
        endmethod
        implement T32
    endstruct
    private struct LinkXYU extends Link
        private method periodic takes nothing returns boolean
            //! runtextmacro LGHT_CB__EscapeClause()
            
            call MoveLocation(LOC,this.x,this.y)
            set Z1=GetLocationZ(LOC)+this.z
            //! runtextmacro LGHT_CB__LoadUnit2()
            
            call MoveLightningEx(this.link,true,this.x,this.y,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(Unit)+HEIGHT_OFFSET)
            
            return false
        endmethod
        implement T32
    endstruct
    
    private struct LinkUXYa extends Link
        private method periodic takes nothing returns boolean
            //! runtextmacro LGHT_CB__EscapeClause()
            
            //! runtextmacro LGHT_CB__LoadUnit1()
            set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
            call MoveLocation(LOC,this.x,this.y)
            
            call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,this.x,this.y,GetLocationZ(LOC)+this.z)
            //! runtextmacro LGHT_CB__AlphaUpkeep()
            
            return false
        endmethod
        implement T32
    endstruct
    private struct LinkUXY extends Link
        private method periodic takes nothing returns boolean
            //! runtextmacro LGHT_CB__EscapeClause()
            
            //! runtextmacro LGHT_CB__LoadUnit1()
            set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(Unit)
            call MoveLocation(LOC,this.x,this.y)
            
            call MoveLightningEx(this.link,true,X1,Y1,Z1+HEIGHT_OFFSET,this.x,this.y,GetLocationZ(LOC)+this.z)
            
            return false
        endmethod
        implement T32
    endstruct
    
    //===========================================================
    // PUBLIC INTERFACE:
    // 
    //  This is the declaration of all functionality exposed to
    // end users. Once again, a global struct variable has been
    // used to remove the ugly local declaration, and textmacros
    // have been used for efficient functional decomposition.
    // 
    
    globals//locals
        private Link data
    endglobals
    
    //===========================================================
    // Interface Snippets
    // 
    
    //! textmacro LGHT_I__Unit1
        set X1=GetUnitX(from)
        set Y1=GetUnitY(from)
        call MoveLocation(LOC,X1,Y1)
    //! endtextmacro
    
    //! textmacro LGHT_I__Unit2
        set X2=GetUnitX(to)
        set Y2=GetUnitY(to)
        call MoveLocation(LOC,X2,Y2)
    //! endtextmacro
    
    //! textmacro LGHT_I__Start takes WHICH
        set data.r=1.0
        set data.g=1.0
        set data.b=1.0
        set data.ticks=R2I(duration/T32_PERIOD)
        if fade then
            set data.a=1.0
            set data.aSlide=1/duration*T32_PERIOD
            call Link$WHICH$a(data).startPeriodic()
        else
            call Link$WHICH$(data).startPeriodic()
        endif
    //! endtextmacro
    
    //===========================================================
    // Interface
    // 
    
    public function UnitUnit takes string whichCode, unit from, unit to, real duration, boolean fade returns nothing
        set data=Link.alloc()
        set data.sU=from
        set data.eU=to
        
        //! runtextmacro LGHT_I__Unit1()
        set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(from)
        //! runtextmacro LGHT_I__Unit2()
        
        set data.link=AddLightningEx(whichCode,true,X1,Y1,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(to))
        //! runtextmacro LGHT_I__Start("UU")
    endfunction
    public function CoordsUnit takes string whichCode, real x, real y, real z, unit to, real duration, boolean fade returns nothing
        set data=Link.alloc()
        set data.x=x
        set data.y=y
        set data.z=z
        set data.eU=to
        
        call MoveLocation(LOC,x,y)
        set Z1=GetLocationZ(LOC)+z
        //! runtextmacro LGHT_I__Unit2()
        
        set data.link=AddLightningEx(whichCode,true,x,y,Z1,X2,Y2,GetLocationZ(LOC)+GetUnitFlyHeight(to))
        //! runtextmacro LGHT_I__Start("XYU")
    endfunction
    public function UnitCoords takes string whichCode, unit from, real x, real y, real z, real duration, boolean fade returns nothing
        set data=Link.alloc()
        set data.sU=from
        set data.x=x
        set data.y=y
        set data.z=z
        
        //! runtextmacro LGHT_I__Unit1()
        set Z1=GetLocationZ(LOC)+GetUnitFlyHeight(from)
        call MoveLocation(LOC,x,y)
        
        set data.link=AddLightningEx(whichCode,true,X1,Y1,Z1,x,y,GetLocationZ(LOC)+z)
        //! runtextmacro LGHT_I__Start("UXY")
    endfunction
    
    // Let's not clutter our interfaces.
    public function ColorLast takes real r, real g, real b returns nothing
        set data.r=r
        set data.g=g
        set data.b=b
        call SetLightningColor(data.link,r,g,b,1.0)
    endfunction
    
    //===========================================================
    // Note to users:
    // 
    //  Keep smiling. God loves you. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
    //  Happy mapping.
endlibrary


Updates:
- Version 1.01: Fixed Unit #2 terrain offset bug and added HEIGHT_OFFSET constant.
- Version 1.00: Release.
ChainLightning​
Version 1.00​

ChainLightning is a flexible implementation of the Warcraft III spell, Chain Lightning. It allows for getting the damage type through Damage, specifying your own custom behavior on bounce, or changing the colour of the Lightning.
Requirements:
- Jass NewGen
- Lightning (see above)
- T32
- Recycle
- Damage

JASS:
//
//       ___ _   _   _   ___ __  _ 
//      / __| |_| | /_\ |_ _|  \| |
//     | (__|  _  |/ _ \ | || \ \ |
//      \___|_| |_/_/_\_\___|_|\__|______ __  _ ___ __  _  ___
//             | |  |_ _|/ __| |_| |_   _|  \| |_ _|  \| |/ __|
//             | |__ | || (_ |  _  | | | | \ \ || || \ \ | (_ |
//             |____|___|\___|_| |_| |_| |_|\__|___|_|\__|\___|
//                                           By Lyncor. v1.00.
//
//      What is ChainLightning?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//           ChainLightning is a vJass implementation of the Warcraft III spell,
//          Chain Lightning.
//          
//           Its colour and action on jump can both be customised.
//          
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//           Simply create a new trigger object called ChainLightning, go to &#039;Edit -&gt;
//          Convert to Custom Text&#039;, and replace everything that&#039;s there with this script.
//          
//      Lightning Codes (Thanks to Flare):
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          &quot;CLPB&quot; - Chain Lightning Primary
//          &quot;CLSB&quot; - Chain Lightning Secondary
//          &quot;DRAB&quot; - Drain
//          &quot;DRAL&quot; - Drain Life
//          &quot;DRAM&quot; - Drain mana
//          &quot;AFOD&quot; - Finger of Death
//          &quot;FORK&quot; - Forked Lightning
//          &quot;HWPB&quot; - Healing Wave Primary
//          &quot;HWSB&quot; - Healing Wave Secondary
//          &quot;CHIM&quot; - Lightning Attack
//          &quot;LEAS&quot; - Magic Leash
//          &quot;MBUR&quot; - Mana Burn
//          &quot;MFPB&quot; - Mana Flare
//          &quot;SPLK&quot; - Spirit Link
//
//      Functions:
//     ¯¯¯¯¯¯¯¯¯¯¯¯
//          For the creation functions:
//              - &quot;string whichCode&quot;   is the lightning type as a string.
//          
//          function ChainLightning takes unit caster, unit source, unit target,
//           string whichCode, real damage, integer hops returns nothing
//              - Casts a simple damage chain lightning, dealing less damage each
//                bounce.
//              - The caster is the damage source (the unit dealing the damage).
//              - The source is where the first hop comes from (usually the caster).
//              - The target is where the first hop will land.
//              - The damage is the damage on the first hop. After that, it will
//                reduce by the hop damage factor on each hop - either the default
//                or that explicitly set by using the SetLast function.
//          function ChainLightning_SetLastHopDamageFactor takes real factor returns nothing
//              - Use this to set the damage factor for the ChainLightning instance
//                last created. Does not work with ChainLightningEx.
//              - This must only be called immediately after calling ChainLightning.
//          
//      The following chunk relates to ChainLightningEx explicitly:
//          
//          function ChainLightningEx takes unit caster, unit source, string whichCode,
//           ChainLightning_Callback onHop, boolean hitsEnemies, integer hops
//           returns integer
//              - Similar to above, but takes a ChainLightning_Callback which
//                will be called on each hop, passing in the target.
//              - &quot;boolean hitsEnemies&quot; is true for hitting enemies, and false for
//                hitting allies (healing wave, etc).
//              - The integer returned is an index for attaching data to. It will
//                be between 1 and 8191, and will be passed into the onHop callback
//                when it is called.
//          function interface ChainLightning_Callback takes integer id, unit target
//           returns nothing
//              - This is for passing a callback into ChainLightningEx. The callback
//                passed in will be called every hop.
//              - &quot;integer id&quot; is the integer returned from the ChainLightningEx
//                call.
//              - &quot;unit target&quot; is the unit being hopped to.
//          function ChainLightning_StartLastEx takes unit target returns nothing
//              - To be called after ChainLightningEx, and after all data has been
//                attached to be used in the callback.
//              - Only call this once for each ChainLightningEx.
//              - This is necessary for the first hop (which occurs immediately).
//                Otherwise, it would not be possible to pass the data to the onHop
//                callback.
//          function ChainLightning_Sound takes unit target returns nothing
//              - For use in your callback, if you wish to have the lightning sound.
//          
//      The following relates to either ChainLightning call:
//          
//          function ChainLightning_ColorLast takes real r, real g, real b returns nothing
//              - Sets the colour of the last created chain lightning to the red,
//                greed and blue values passed into the function (r, g, b).
//              - The values are real numbers ranging from 0 to 1.
//              - This must only be called immediately after calling ChainLightning
//                or ChainLightning_StartLastEx.
//          
//          function ChainLightning_SetLastTimeBetweenHops takes real time returns nothing
//              - This sets the time between hops.
//              - This must only be called immediately after calling ChainLightning
//                or ChainLightning_StartLastEx.
//          
//          function ChainLightning_SetlastMaxHopDistance takes real distance returns nothing
//              - Sets the maximum distance a chain lightning instance will bounce
//                to get a new target.
//              - This must only be called immediately after calling ChainLightning
//                or ChainLightning_StartLastEx.
//
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Jesus4Lyf for code assistance.
// 

library ChainLightning initializer OnInit uses Lightning, T32, Recycle, Damage

    //===========================================================
    // DEFAULT CONSTANTS:
    //
    //  The default values used by this system are found here for
    // ease of maintenance.
    // 
    
    globals
        private constant    real DEFAULT_MAX_HOP_DISTANCE    = 300.0
        private constant    real DEFAULT_TIME_BETWEEN_HOPS   = 0.25
        private constant    real DEFAULT_FADE_TIME           = 1.0
        private constant    real DEFAULT_HOP_FACTOR          = 0.8 // Drops 20% per hop.
        private constant  string DEFAULT_LIGHTNING_TYPE      = &quot;CLPB&quot;
        
        private constant integer SOUND_VOLUME               = 85 // out of 127.
    endglobals
    
    //===========================================================
    // FUNCTION INTERFACE: ChainLightning_Callback
    //
    //  This callback is used for each hop made stemming from a
    // ChainLightningEx call.
    // 
    
    public function interface Callback takes integer id, unit target returns nothing
    
    //===========================================================
    // NON-CONFIGURABLE CONSTANTS:
    //
    //  These are constants which are not configurables.
    // 
    //  If your map already has a global group named &quot;GROUP&quot;, you
    // may wish to remove the private declaration for it.
    // 
    
    globals
        private constant integer DEFAULT_TICKS_BETWEEN_HOPS = R2I(DEFAULT_TIME_BETWEEN_HOPS/T32_PERIOD)
        private group GROUP=CreateGroup() // For those who don&#039;t have this.
    endglobals
    
    //===========================================================
    // IsUnitAlive:
    //
    //  This is here because the normal check for a unit being
    // alive is not as effective as this method. Should be inline
    // friendly.
    // 
    
    private function IsUnitAlive takes unit whichUnit returns boolean
        return GetWidgetLife(whichUnit)&gt;0.405
    endfunction
    
    //===========================================================
    // ZAP SOUND:
    //
    //  The basic data for a link of lightning. This is so there
    // is minimal array declaration, and faster recycling of unit
    // handle ids.
    // 
    
    globals
        private sound ZapSound
    endglobals
    //! textmacro CL__ZapSound takes TARGET
        set ZapSound=CreateSound(&quot;Abilities\\Spells\\Orc\\LightningBolt\\LightningBolt.wav&quot;,false,true,true,10,10,&quot;SpellsEAX&quot;)
        call SetSoundDuration(ZapSound,2136)
        call SetSoundVolume(ZapSound,SOUND_VOLUME)
        call AttachSoundToUnit(ZapSound,$TARGET$)
        call StartSound(ZapSound)
        call KillSoundWhenDone(ZapSound)
    //! endtextmacro
    
    //===========================================================
    // FROM CALLBACK SNIPPETS (later):
    // 
    //  The globals//locals block from the callback snippets are
    // relocated to here due to JassHelper parser limitations.
    // 
    
    //! runtextmacro CL__CallbackGlobals()
    
    //===========================================================
    // DATA DECLARATION:
    //
    //  The basic data for an instance of ChainLightning. This is
    // so there is minimal array declaration, and unit handle ids
    // are recycled faster.
    // 
    
    private struct Instance //extends array // JassHelper won&#039;t allow this with inheritance.
        // Allocator that won&#039;t lose efficiency with inheritance.
        // Faster than vJass allocator.
        private static thistype array recycled
        private static integer recycledMax=0
        private static integer lastAlloc=0
        static method alloc takes nothing returns thistype
            if thistype.recycledMax==0 then
                set thistype.lastAlloc=thistype.lastAlloc+1
                return thistype(thistype.lastAlloc)
            endif
            set thistype.recycledMax=thistype.recycledMax-1
            return thistype.recycled[thistype.recycledMax]
        endmethod
        method dealloc takes nothing returns nothing
            set thistype.recycled[thistype.recycledMax]=this
            set thistype.recycledMax=thistype.recycledMax+1
        endmethod
        
        // Data
        integer hopsLeft
        integer ticksToHop
        integer ticksPerHop
        real fadeTime
        
        real maxHopDistance
        unit source
        unit caster
        real damage
        real reductionFactor
        player owner
        group hit
        
        real r
        real g
        real b
        string which
        
        Callback onHop
        boolean hitsEnemies
        
        // Filterfuncs.
        //! runtextmacro CL__OnAoE(&quot;Enemy&quot;,&quot;ENEMY&quot;)
        //! runtextmacro CL__OnAoE(&quot;Ally&quot;,&quot;ALLY&quot;)
        static method init takes nothing returns nothing
            set thistype.FILTER_ON_AOE_ENEMY=Filter(function thistype.onAoEEnemy)
            set thistype.FILTER_ON_AOE_ALLY=Filter(function thistype.onAoEAlly)
        endmethod
    endstruct
    
    // This OnInit function is used to initialise filterfuncs, since
    // JassHelper has a shortfall in not letting modules have private
    // initializers (causing T32 to steal the onInit method).
    private function OnInit takes nothing returns nothing
        call Instance.init()
    endfunction
    
    //===========================================================
    // CALLBACK DECLARATION:
    //
    //  This is all the data and code segments used in the T32
    // callback methods. Textmacros are brilliant, because they
    // provide functional decomposition without any efficiency
    // penalty.
    // 
    //  Globals have been used to shorten code (locals also have
    // terribly ugly declarations) and provide an efficiency
    // boost, as well as eliminate nulling concerns for the unit.
    // 
    //  T32 has been used for high efficiency.
    // 
    
    //! textmacro CL__CallbackGlobals
        // This block is moved
        globals//locals
            private unit Unit
            private unit Target
            private player Owner
            private group Hit
            private real X
            private real Y
            private real X2
            private real Y2
            private real ThisRange
            private real Range
        endglobals
    //! endtextmacro
    
    //===========================================================
    // Callback Snippets
    // 
    
    //! textmacro CL__OnAoE takes DIPLOMACY, DIPLOMACY_CAPS
        private static method onAoE$DIPLOMACY$ takes nothing returns boolean
            set Unit=GetFilterUnit()
            if IsUnit$DIPLOMACY$(Unit,Owner) and IsUnitAlive(Unit) then
                if not (IsUnitInGroup(Unit,Hit) or IsUnitType(Unit,UNIT_TYPE_MAGIC_IMMUNE)) then
                    set X2=GetUnitX(Unit)-X
                    set Y2=GetUnitY(Unit)-Y
                    set ThisRange=X2*X2+Y2*Y2
                    if ThisRange&lt;Range then
                        set Range=ThisRange
                        set Target=Unit
                    endif
                endif
            endif
            return false
        endmethod
        static boolexpr FILTER_ON_AOE_$DIPLOMACY_CAPS$
    //! endtextmacro
    //! textmacro CL__GetTarget takes DIPLOMACY_CAPS
        set Hit=this.hit
        set Owner=this.owner
        set X=GetUnitX(this.source)
        set Y=GetUnitY(this.source)
        set Range=this.maxHopDistance*this.maxHopDistance
        set Target=null
        call GroupEnumUnitsInRange(GROUP,X,Y,this.maxHopDistance,thistype.FILTER_ON_AOE_$DIPLOMACY_CAPS$)
        if Target==null then
            call Group.release(this.hit)
            set this.ticksToHop=0
            call this.dealloc()
            return true
        endif
    //! endtextmacro
    
    //! textmacro CL__JumpTo takes THIS, TARGET
        call Lightning_UnitUnit(&quot;CLPB&quot;,$THIS$.source,$TARGET$,$THIS$.fadeTime,true)
        call Lightning_ColorLast($THIS$.r,$THIS$.g,$THIS$.b)
        set $THIS$.source=$TARGET$
        call GroupAddUnit($THIS$.hit,$TARGET$)
        set $THIS$.ticksToHop=$THIS$.ticksToHop+$THIS$.ticksPerHop
        set $THIS$.hopsLeft=$THIS$.hopsLeft-1
        if $THIS$.hopsLeft==0 then
            call Group.release($THIS$.hit)
            set $THIS$.ticksToHop=0
            call $THIS$.dealloc()
        //endif
    //! endtextmacro
    
    //! textmacro CL__DefaultJumpAction takes THIS, TARGET
        call Damage_Spell($THIS$.caster,$TARGET$,$THIS$.damage)
        set $THIS$.damage=$THIS$.damage*$THIS$.reductionFactor
    //! endtextmacro
    
    //! textmacro CL__UpkeepStart
        set this.ticksToHop=this.ticksToHop-1
        loop
            exitwhen this.ticksToHop&gt;0
        //endloop
    //! endtextmacro
    
    //===========================================================
    // T32 Callbacks
    // 
    //  One for default Chain Lightning (simple damage which is
    // also reduced each hop) and one for an Explicit version,
    // in which the user to specify the behavior for each hop.
    // 
    
    private struct InstanceStandard extends Instance
        private method periodic takes nothing returns boolean
            //! runtextmacro CL__UpkeepStart()
            // loop: Starts for Jumping.
                //! runtextmacro CL__GetTarget(&quot;ENEMY&quot;)
                
                // Zap unit for damage.
                //! runtextmacro CL__ZapSound(&quot;Target&quot;)
                //! runtextmacro CL__DefaultJumpAction(&quot;this&quot;,&quot;Target&quot;)
                
                // Move instance to unit.
                //! runtextmacro CL__JumpTo(&quot;this&quot;,&quot;Target&quot;)
                // if: No more hops after jump.
                    return true
                endif
            endloop
            return false
        endmethod
        implement T32
    endstruct
    
    private struct InstanceSpecial extends Instance
        private method periodic takes nothing returns boolean
            //! runtextmacro CL__UpkeepStart()
            // loop: Starts for Jumping.
                if this.hitsEnemies then
                    //! runtextmacro CL__GetTarget(&quot;ENEMY&quot;)
                else
                    //! runtextmacro CL__GetTarget(&quot;ALLY&quot;)
                endif
                
                call this.onHop.evaluate(this,Target)
                
                // Move instance to unit.
                //! runtextmacro CL__JumpTo(&quot;this&quot;,&quot;Target&quot;)
                // if: No more hops after jump.
                    return true
                endif
            endloop
            return false
        endmethod
        implement T32
    endstruct
    
    //===========================================================
    // PUBLIC INTERFACE:
    // 
    //  This is the declaration of all functionality exposed to
    // end users. Once again, a global struct variable has been
    // used to remove the ugly local declaration, and textmacros
    // have been used for efficient functional decomposition.
    // 
    
    globals//locals
        private Instance Data
    endglobals
    
    //===========================================================
    // Interface Snippets
    // 
    
    //! textmacro CL__Create
        set Data=Instance.alloc()
        set Data.hopsLeft=hops
        //set this.ticksToHop=0 // Should always be.
        set Data.ticksPerHop=DEFAULT_TICKS_BETWEEN_HOPS
        set Data.fadeTime=DEFAULT_FADE_TIME
        
        set Data.maxHopDistance=DEFAULT_MAX_HOP_DISTANCE
        set Data.source=source
        set Data.caster=caster
        set Data.owner=GetOwningPlayer(caster)
        set Data.hit=Group.get()
        
        set Data.r=1.0
        set Data.g=1.0
        set Data.b=1.0
        set Data.which=whichCode
    //! endtextmacro
    
    //===========================================================
    // Interface
    // 
    
    function ChainLightning takes unit caster, unit source, unit target, string whichCode, real damage, integer hops returns nothing
        //! runtextmacro CL__Create()
        set Data.damage=damage
        set Data.reductionFactor=DEFAULT_HOP_FACTOR
        
        // Zap unit for damage.
        //! runtextmacro CL__ZapSound(&quot;target&quot;)
        //! runtextmacro CL__DefaultJumpAction(&quot;Data&quot;,&quot;target&quot;)
        
        // Move instance to unit.
        //! runtextmacro CL__JumpTo(&quot;Data&quot;,&quot;target&quot;)
        // if: No more hops after jump.
        else
            call InstanceStandard(Data).startPeriodic()
        endif
    endfunction
    
    function ChainLightningEx takes unit caster, unit source, string whichCode, Callback onHop, boolean hitsEnemies, integer hops returns integer
        //! runtextmacro CL__Create()
        set Data.onHop=onHop
        set Data.hitsEnemies=hitsEnemies
        
        return Data
    endfunction
    public function StartLastEx takes unit target returns nothing
        call Data.onHop.evaluate(Data,target)
        
        // Move instance to unit.
        //! runtextmacro CL__JumpTo(&quot;Data&quot;,&quot;target&quot;)
        // if: No more hops after jump.
        else
            call InstanceSpecial(Data).startPeriodic()
        endif
    endfunction
    public function Sound takes unit target returns nothing
        //! runtextmacro CL__ZapSound(&quot;target&quot;)
    endfunction
    
    // Let&#039;s not clutter our interfaces.
    public function ColorLast takes real r, real g, real b returns nothing
        set Data.r=r
        set Data.g=g
        set Data.b=b
        call Lightning_ColorLast(r,g,b)
    endfunction
    
    public function SetLastTimeBetweenHops takes real time returns nothing
        set Data.ticksPerHop=R2I(time/T32_PERIOD)
        set Data.ticksToHop=Data.ticksPerHop
    endfunction
    
    public function SetlastMaxHopDistance takes real distance returns nothing
        set Data.maxHopDistance=distance
    endfunction
    
    public function SetLastHopDamageFactor takes real factor returns nothing
        set Data.damage=Data.damage/Data.reductionFactor*factor
        set Data.reductionFactor=factor
    endfunction
    
    //===========================================================
    // Note to users:
    // 
    //  Keep smiling. God loves you. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
    //  Happy mapping.
endlibrary


Updates:
- Version 1.00: Release.
 

Attachments

  • Lightning.w3x
    69.9 KB · Views: 441

Romek

Super Moderator
Reaction score
963
Other than the code and subtitles, your post contains nothing.
Mind posting what this is? How to use it? Why to use it? Etc.

Reminds me of J4Ls stuff though. ;)
 

Jesus4Lyf

Good Idea™
Reaction score
397
Wow...

I really like what you did with the commenting and textmacros. Dunno that you quite got "functional decomposition" with the textmacros, as they can't call eachother, but the idea is neat. :thup:

Hm. Some of the function names are a bit long for the SetLast stuff.

I'm pretty sure... that you didn't use any local variables?
And managed to give a struct type multiple T32 callbacks?

I'm pretty impressed. Lol @ the custom allocator. XD

Edit:
>Reminds me of J4Ls stuff though.
Yeah, he's my DotA buddy and friend IRL. He comments his code! XD
 

Renendaru

(Evol)ution is nothing without love.
Reaction score
309
Wasn't this style Nestharus's one? :eek:

No, Look at the variable setting. "Variable=Value" Stuff.

I'm pretty sure it's similar since Lyncor is Jesus's friend, so Jesus probably taught him. :p
 

Lyncor

New Member
Reaction score
8
Added descriptions. :)

>Mind posting what this is? How to use it? Why to use it? Etc.
The rest of that is in the documentation.
 

Viikuna

No Marlo no game.
Reaction score
265
Its cool, but I think that good lightning system kinda requires easy overtime color fading and posibilities to move lightning target points over time and stuff like that. ( I think that that Flares lightning system already has that stuff )

Also, I dont really like those user functions. Some vJass Lightning type would be cool, dont you think?
 

Lyncor

New Member
Reaction score
8
>Its cool, but I think that good lightning system kinda requires easy overtime color fading

I thought about it, but then I decided that rainbow lightning wasn't really my thing.

More seriously, though, it gets complicated exposing the struct because of the typecasting for multiple T32 periodic functions. I suppose it's possible, but then the user needs to store the lightning in a variable and such also.

>and posibilities to move lightning target points over time and stuff like that. ( I think that that Flares lightning system already has that stuff )

Is that often useful? I couldn't immediately think of a use for it.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Some vJass Lightning type would be cool, dont you think?
Probably end up over-engineered.

Flare's does it, yeah. But this has chain lightning also and is generally written much more for efficiency.

Edit:
>More seriously, though, it gets complicated exposing the struct
Yeah, I actually like it this way because you don't have to store the struct also. But Viikuna is a struct person and I'm not. Suppose it's just preference.
 

Viikuna

No Marlo no game.
Reaction score
265
Im going to try some Lightning struct thingy, and see how it works.

Also, chain lightning is cool and everything, but efficiency means nothing if system does less stuff. ( Well, Flares system does lot of really useless stuff too.., but still.. )

Good user functions ( and how easy the system is to use in general ) are way more important that small speed differencies, at least in my opinion.

And:
I thought about it, but then I decided that rainbow lightning wasn't really my thing.

Whats your thing has nothing to do with it.

Is that often useful? I couldn't immediately think of a use for it.

Really rarely probably, yea.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>efficiency means nothing if system does less stuff
Then why did I bother making T32...

We can make systems to do everything, but I detest it. You'll end up with Spawn.

Here's the problem with the struct idea. You can implement the colour fade, but then what if people want to implement colour setting during the lightning? So you let them do a setColor method. And they fade the lightning manually. But then they need a timer system! In fact, the setColor method becomes a native wrapper, and your system is useless because they may as well do the positioning manually also.

This nicely automates something commonly needed. To me, the efficiency is quite an attraction. I can fire 24 instances of ChainLightning without lag. Each is a single function call, or two if I want colour.

Approved.
 

Viikuna

No Marlo no game.
Reaction score
265
T32 is not a system in same sense as lightning system, or a knockback system that do some stuff that actually affects the game and does some visible stuff. It is more like an utility thingy that makes that stuff possible.

I actually think Ive found a very neat way to control colour fading, so you can easily fade your lightning both in and out, or do some lightning that constantly fades in and out again and again and stuff like that. ( For ultimate rainbow experience )

And yea, one function call is easier and faster to type than struct thingy, but it also does less stuff. When you need a rainbow lightning, this system has no use for you at all. ( Then again, if you dont need rainbow lightning, this system might work just perfectly for you. )

Ok, yea. I guess it is good to have loads of different options to choose from.
 

BlackRose

Forum User
Reaction score
239
Can you set Chain Lightning height? I'm getting ugly lightnings :(

One on the ground, shouldn't it be at chest?
And the other one is like... o_O
 

Viikuna

No Marlo no game.
Reaction score
265
Well, that requires you to have some height property for each unit Unit types default height + scale changes. Id just add this kind of property to Unit Properties if I were you.

If all lightning movement is done from the same textmacro, it should be easy enough to modify this to work properly for your map, since you only have to change just one line.
 

Lyncor

New Member
Reaction score
8
I updated the system. Enjoy, everyone! :D

Fixed a minor bug to do with secondary unit's terrain height and added a HEIGHT_OFFSET constant which is applied to all units. :)

Thanks for the feedback. Sorry for the delay in updating; been busy with other stuff :)
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top