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:
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 = 039;A003039;
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 < 500 and secs < 2.5then
set dist = dist + 15
endif
set secs = secs + TIMER_PERIOD
if secs >= 2.50 then
set dist = dist - 15
if dist <= 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 = "war3mapImported\\BlueMissile.mdx"
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( "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdx", 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 <= -90.*bj_DEGTORAD then
call this.sfx.hiddenReset( "", this.sfx.xyangle + 180* bj_DEGTORAD)
set this.sfx.fxpath = "Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdx"
set this.pitchAdder = -6
endif
if this.pitch > 90*bj_DEGTORAD then
call this.sfx.hiddenReset( "", this.sfx.xyangle + 180 * bj_DEGTORAD)
set this.sfx.fxpath = "Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdx"
set this.pitchAdder = 6
endif
set this.cd = this.cd + this.cspd
if this.cd >= 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 <= this.tz and this.z >= this.tz) or (this.sfx.z >= this.tz and this.z <= 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 = "Abilities\\Spells\\Human\\StormBolt\\StormBoltMissile.mdx"
set this.d = SquareRoot( tempX*tempX+tempY*tempY )
if this.d > 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 = ""
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 <= distance then
if count != 0 then
loop
exitwhen d >= 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 > 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( "Actual count: " + I2S( R2I(distance / this.unitEveryX) ) )
call BJDebugMsg( "Number of chains: " + 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 >= 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>