Lightning Duplicate

Status
Not open for further replies.

BlackRose

Forum User
Reaction score
239
Ok. Now I need help. For some reason after one instace of a spell is destroyed, it bugs up and the rest don't work.

Sorry if the code is hard to understand or is terrible to read:

JASS:
library LightningHammer initializer onInit requires SpellEvent, KT, xefx, GroupUtils, OneLocation, LightningChain

    globals
        private constant integer ABILITY_ID = 'A003'
        
        private constant real SPEED = 30.
        private constant real TIMER_PERIOD = 0.03125
        
        private constant string LIGHTNING_TYPE = "CLPB"
        
        private constant integer LIGHTNING_COUNT = 1
    endglobals


function GetParabolaZ takes real x,real d,real h returns real
    return 4 * h * x * (d - x) / (d * d)
endfunction

function ZAngle takes real x,real d,real h returns real
    return Atan((4*h/d)*((-2*x/d)+1))
endfunction

private function BJDebugReal takes real x, real y returns nothing
    call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdx", x, y ) )
endfunction

    private struct LightningRotation
        unit source
    
        Chain array chain[LIGHTNING_COUNT]
        
        real array x1[LIGHTNING_COUNT]
        real array x2[LIGHTNING_COUNT]
        real array y1[LIGHTNING_COUNT]
        real array y2[LIGHTNING_COUNT]
        
        real array angle[LIGHTNING_COUNT]
        
        real dist = 0.00
        
        real secs = 0.00
        
        xefx sfx
        
        private method onDestroy takes nothing returns nothing
            local integer i = 0
            
            loop
                exitwhen i == LIGHTNING_COUNT
                call this.chain<i>.destroy()
                set i = i + 1
            endloop
            
            call this.sfx.destroy()
            
            set source = null
        endmethod
        
        static method periodic takes nothing returns boolean
            local thistype this = KT_GetData()
            local integer  i    = 0
            
            loop
                exitwhen i == LIGHTNING_COUNT
                
                set this.x2<i> = this.x1<i> + this.dist * Cos( this.angle<i> )
                set y2<i> = y1<i> + dist * Sin( angle<i> )
                
                set angle<i> = angle<i> + 5*bj_DEGTORAD
                
                call chain<i>.MoveChainEx( x1<i>, y1<i>, sfx.z, x2<i>, y2<i>, 0 )
              
                set i = i + 1
            endloop
            
            if dist &lt; 500 and secs &lt; 2.5then
                set dist = dist + 15
            endif
            
            set secs = secs + TIMER_PERIOD
            if secs &gt;= 2.50 then
                set dist = dist - 15
                if dist &lt;= 0 then
                    call this.destroy()
                    return true
                endif
            endif
            
            return false
        endmethod
        
        static method create takes xefx sourceSFX, unit whichCaster returns thistype
            local thistype this   = thistype.allocate()
            local integer  i      = 0
            local real angle      = 0.00
            local real angleAdder = 360 / LIGHTNING_COUNT
            local real x
            local real y
            
            set this.source = whichCaster
            set this.sfx    = sourceSFX
            set x = sourceSFX.x
            set y = sourceSFX.y
            
            loop
                exitwhen i == LIGHTNING_COUNT
                
                set this.angle<i> = angle * bj_DEGTORAD
                
                set this.x1<i> = x
                set this.y1<i> = y
                set this.x2<i> = x + this.dist * Cos( angle * bj_DEGTORAD )
                set this.y2<i> = y + this.dist * Sin( angle * bj_DEGTORAD )
                
                set this.chain<i> = Chain.create( .x1<i>, .y1<i>, 0, .x2<i>, .y2<i>, 0, 100 )
                set this.chain<i>.setModelPath = &quot;war3mapImported\\BlueMissile.mdx&quot;
                
                set angle         = angle + angleAdder
                set i = i + 1
            endloop
            
            return this
        endmethod
    endstruct

    private struct Data
    
        unit caster
        xefx sfx
        
        real x
        real y
        real z
        real angle
    
        real tx
        real ty
        real tz
        
        real cd = 0.
        real d
        real cspd = SPEED
        
        real pitch = 0.
        real pitchAdder = 4.
        real xvel
        real yvel
        real zvel
        
        real dist    = 39.
        real seconds = 0.00
        
        private method onDestroy takes nothing returns nothing
            call KT_Add( function LightningRotation.periodic, LightningRotation.create( this.sfx, this.caster ), TIMER_PERIOD )
            set this.caster = null
        endmethod
        
        static method arcingHammer takes nothing returns boolean
            local thistype this = KT_GetData()
            
            set this.sfx.x = this.sfx.x + this.cspd * Cos( this.angle )
            set this.sfx.y = this.sfx.y + this.cspd * Sin( this.angle )
            set this.sfx.z = GetParabolaZ( this.cd, this.d * 2, 400 ) + this.z
            
            //call DestroyEffect( AddSpecialEffectZ( &quot;Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdx&quot;, this.sfx.x, this.sfx.y, this.sfx.z ) )
            
            set this.pitch = this.pitch - bj_DEGTORAD*this.pitchAdder
            set this.sfx.zangle = this.pitch
            if this.pitch &lt;= -90.*bj_DEGTORAD then
                call this.sfx.hiddenReset( &quot;&quot;, this.sfx.xyangle + 180* bj_DEGTORAD)
                set this.sfx.fxpath = &quot;Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdx&quot;
                set this.pitchAdder = -6
            endif
            
            if this.pitch &gt; 90*bj_DEGTORAD then
                call this.sfx.hiddenReset( &quot;&quot;, this.sfx.xyangle + 180 * bj_DEGTORAD)
                set this.sfx.fxpath = &quot;Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdx&quot;
                set this.pitchAdder = 6
            endif
            
            set this.cd = this.cd + this.cspd
            if this.cd &gt;= this.d then
                call this.destroy()
                return true
            endif
     
            return false
        endmethod
    
        /*static method hammer takes nothing returns boolean
            local thistype this = KT_GetData()
            
            set this.sfx.x = this.sfx.x + this.xvel
            set this.sfx.y = this.sfx.y + this.yvel
            set this.sfx.z = this.sfx.z + this.zvel
            
            if (this.sfx.z &lt;= this.tz and this.z &gt;= this.tz) or (this.sfx.z &gt;= this.tz and this.z &lt;= this.tz) then
                call this.preLightning()
                return true
            endif

            return false
        endmethod*/
    
        static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
            local real tempX
            local real tempY
            local real tempZ
        
            set this.caster = SpellEvent.CastingUnit
            set this.x      = GetUnitX( this.caster )
            set this.y      = GetUnitY( this.caster )
            set this.z      = GetUnitFlyHeight( this.caster ) + 90
            
            set this.tx     = SpellEvent.TargetX
            set this.ty     = SpellEvent.TargetY
            set this.tz     = 200.
            
            set tempX = this.tx - this.x
            set tempY = this.ty - this.y
            set tempZ = this.tz - this.z
            set this.angle      = Atan2( tempY, tempX )
            set this.sfx        = xefx.create( this.x, this.y, this.angle )
            set this.sfx.z      = this.z
            set this.sfx.fxpath = &quot;Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdx&quot;
            
            set this.d = SquareRoot( tempX*tempX+tempY*tempY )
            
            if this.d &gt; 200 then
                call KT_Add( function thistype.arcingHammer, this, TIMER_PERIOD )
            /*else
                set this.pitch = Atan2( tempZ, this.d )
                set this.xvel = Cos( this.pitch ) * Cos( this.angle ) * SPD
                set this.yvel = Cos( this.pitch ) * Sin( this.angle ) * SPD
                set this.zvel = Sin( this.pitch ) *                     SPD
                set this.sfx.zangle = this.pitch
                call KT_Add( function thistype.hammer, this, TIMER_PERIOD )*/
            endif
        
            return 0
        endmethod
    endstruct

    private function onEffect takes nothing returns nothing
        call Data.create()
    endfunction

    private function onInit takes nothing returns nothing
        call RegisterSpellEffectResponse( ABILITY_ID, onEffect )
    endfunction

endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


JASS:
library LightningChain requires xefx

    struct Chain
        xefx array sfx[90]
        string fxpath = &quot;&quot;
        real   scale  = 1.00
        
        real distance
        real unitEveryX
        integer unitCount = 0
        
        method onDestroy takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i == this.unitCount
                call this.sfx<i>.destroy()
                set i = i + 1
            endloop
        endmethod
        
        method operator setModelPath= takes string s returns nothing
            local integer i = 0
            loop
                exitwhen i == this.unitCount
                set this.sfx<i>.fxpath = s
                set i = i + 1
            endloop
            set this.fxpath = s
        endmethod
                
        method operator setModelScale= takes real r returns nothing
            local integer i = 0
            loop
                exitwhen i == this.unitCount
                set this.sfx<i>.scale = r
                set i = i + 1
            endloop
            set this.scale = r
        endmethod
        
        method MoveChainEx takes real x1, real y1, real z1, real x2, real y2, real z2 returns nothing
            local real tempX = x2 - x1
            local real tempY = y2 - y1
            local real tempZ = z2 - z1
            
            local real distance = SquareRoot( tempX*tempX+tempY*tempY )
            local real angle    = Atan2( tempY, tempX )
            local real zAngle   = Atan2( tempZ, distance )
            local real d = 0.00
            local integer i = 0
            
            local real x
            local real y
            local real z = z1
            
            local real count = R2I( distance / this.unitEveryX )

            if this.distance &lt;= distance then
                if count != 0 then
                loop
                    exitwhen d &gt;= distance
                    set x  = x1 + d * Cos( angle )
                    set y  = y1 + d * Sin( angle )
                    set z1 = z1 + (tempZ/count)

                    if this.sfx<i> == 0 then
                        set this.sfx<i> = xefx.create( x, y, angle )
                        set this.sfx<i>.fxpath = this.fxpath
                        set this.sfx<i>.scale  = this.scale
                        set this.unitCount     = this.unitCount + 1
                    else
                        set this.sfx<i>.x = x
                        set this.sfx<i>.y = y
                        set this.sfx<i>.xyangle = angle
                    endif
                    set this.sfx<i>.z      = z1
                    set this.sfx<i>.zangle = zAngle
                    set d = d + (distance/count)
                    set i = i + 1
                endloop
                endif

                set i = 0
                set d = 0
                loop
                    exitwhen i == this.unitCount
                    set x = x1 + d * Cos( angle )
                    set y = y1 + d * Sin( angle )
                    set d = d + (distance/this.unitCount)
                    
                    set sfx<i>.x = x
                    set sfx<i>.y = y
                    set i = i + 1
                endloop

            elseif this.distance &gt; distance then

                set i = 0
                loop
                    exitwhen i == count
                    
                    set x = x1 + d * Cos( angle )
                    set y = y1 + d * Sin( angle )
                    set z1 = z1 + (tempZ/count)
                    
                    set d = d + (distance/count)
                    
                    set this.sfx<i>.x       = x
                    set this.sfx<i>.y       = y
                    set this.sfx<i>.z       = z1
                    set this.sfx<i>.xyangle = angle
                    
                    set i = i + 1
                endloop
                
                loop
                    exitwhen i == this.unitCount
                    set this.sfx<i>.x = 0.
                    set this.sfx<i>.y = 0.
                    set i = i + 1
                endloop
            endif
            
            call BJDebugMsg( &quot;Actual count: &quot; + I2S( R2I(distance / this.unitEveryX) ) )
            call BJDebugMsg( &quot;Number of chains: &quot; + I2S( this.unitCount ) )
            set this.distance = distance
        endmethod
        
        static method create takes real x1, real y1, real startHeight, real x2, real y2, real endHeight, real distBetween returns thistype
            local thistype this = thistype.allocate()
            local real d = 0.00
            local integer i = 0
            
            local real tempX = x2 - x1
            local real tempY = y2 - y1
            local real tempZ = endHeight - startHeight
            
            local real distance = SquareRoot( tempX*tempX+tempY*tempY )
            local real angle  = Atan2( tempY, tempX )
            local real cos    = Cos( angle )
            local real sin    = Sin( angle )
            local real zAngle = Atan2( tempZ, distance )
            
            local real x
            local real y
            local real z = startHeight
            
            local integer count = R2I(distance / distBetween)
            
            loop
                exitwhen d &gt;= distance
                set x = x1 + d * cos
                set y = y1 + d * sin
                set this.sfx<i>        = xefx.create( x, y, angle )
                
                set this.sfx<i>.z      = (startHeight/count) * i
                set this.sfx<i>.zangle = zAngle

                set this.unitCount     = this.unitCount + 1
                set i = i + 1
                set d = d + distBetween
            endloop
                
            set this.unitCount  = i
            set this.distance   = distance
            set this.unitEveryX = distBetween
                
            return this
        endmethod
    endstruct
    
//+------------------------------------------------------------------------------------------------------------------------+
    
endlibrary</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
 
Status
Not open for further replies.
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top