scope FlameShackles initializer Init_FlameShackles
globals
private constant integer ABILITY_ID = 'A0KO'
private constant integer DUMMY_ID = 'u00Q'
private constant string LIGHTNING = "LEAS"
private constant real RADIUS = 360.00000
private constant real GRAB_MAX_STEP = 009.00000
private constant real DURATION = 005.50000
private constant real MAX_HEIGHT = 200.00000
private constant real RISE_TIME = 001.50000
private constant real GRAB_INTERVAL = 000.03125//000.15000
private constant real ORIGIN_OFFSET = 032.00000
private constant real TIMER_INTERVAL = 000.03125
private integer index = 0
private integer array swap
private constant hashtable hash = InitHashtable()
private constant timer tim = CreateTimer()
endglobals
private struct flame extends array
player owner
unit dummy
unit caster
real cast_x
real cast_y
real dummy_z
real duration
real grab_counter
real a
integer count
implement Alloc
static method filter takes player owner, unit u returns boolean
return IsUnitEnemy(u,owner) and IsUnitType(u,UNIT_TYPE_GROUND) and GetWidgetLife(u) > .305
endmethod
static method rise takes nothing returns nothing
local thistype this
local integer i = 0
local integer j
local integer k
local lightning l
local unit u
local real x1
local real y1
local real z1
local real x2
local real y2
local real z2
local real dx
local real dy
local real dist
local real face
local real step
loop
exitwhen i >= index
set this = swap[i]
set this.grab_counter = this.grab_counter - TIMER_INTERVAL
set this.duration = this.duration - TIMER_INTERVAL
if this.duration > 0.0 then
set x1 = this.cast_x
set y1 = this.cast_y
set z1 = this.dummy_z
if z1 < MAX_HEIGHT then
set z1 = z1 + MAX_HEIGHT * TIMER_INTERVAL/RISE_TIME
call SetUnitFlyHeight(this.dummy,z1,0.0)
set this.dummy_z = z1
endif
call GroupEnumUnitsInRange(bj_lastCreatedGroup,x1,y1,RADIUS,null)
set j = 1
loop // Remove Old Units from the newely picked group
exitwhen j >= this.count
set u = LoadUnitHandle(hash,this,j)
call GroupRemoveUnit(bj_lastCreatedGroup,u)
set j = j + 1
endloop
set j = this.count
loop // Add Lightning to the new units and add them to the counter
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u == null
if filter(this.owner,u) then
set j = j + 1
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set z2 = GetUnitZ(u) + ORIGIN_OFFSET
set l = AddLightningEx(LIGHTNING,false,x1,y1,z1,x2,y2,z2)
call SaveUnitHandle ( hash , this , j , u )
call SaveLightningHandle( hash , this , -j , l )
endif
call GroupRemoveUnit(bj_lastCreatedGroup,u)
endloop
set this.count = j
set j = 1
loop // Check all the units we picked either in range or outside
set u = LoadUnitHandle(hash,this,j)
exitwhen u == null
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set dx = x2 - x1
set dy = y2 - y1
set dist = SquareRoot(dx*dx + dy*dy)
set face = Atan2(dy,dx)
set l = LoadLightningHandle(hash,this,-j)
if dist <= RADIUS then // the unit is still in the range of the orb
if not LoadBoolean(hash,this,j) then // Just in case the exiting unit re-entered
call SetLightningColor(l,1,1,1,1)
call SaveBoolean(hash,this,j,true)
endif
// grab the units
if this.grab_counter <= 0.0 then // if the grab interval has ticked then we pull them back
set step = this.a * dist // this equation calculates the strength of the drag
call SetUnitX(u,x1 + (dist - step) * Cos(face))
call SetUnitY(u,y1 + (dist - step) * Sin(face))
endif
set z2 = GetUnitZ(u) + ORIGIN_OFFSET
call MoveLightningEx(l,false,x1,y1,z1,x2,y2,z2)
else // the unit has moved out of the orb range
call SaveBoolean(hash,this,j,false) // Flag the unit as out-of-Range
call SetLightningColor(l,1,1,1,0)
endif
set j = j + 1
endloop
if this.grab_counter <= 0.0 then // Reset the grab counter only when all units are checked and the counter has ticked
set this.grab_counter = GRAB_INTERVAL
endif
else
set index = index - 1
set swap[i] = swap[index]
set i = i - 1
call KillUnit(this.dummy)
set this.dummy = null
set j = 1
loop
set l = LoadLightningHandle(hash,this,-j)
exitwhen l == null
call DestroyLightning(l)
set j = j + 1
endloop
call FlushChildHashtable(hash,this)
call .deallocate()
if index == 0 then
call PauseTimer(tim)
endif
endif
set u = null
//set l = null
set i = i + 1
endloop
endmethod
static method start takes unit caster, real x1, real y1 returns nothing
local thistype this = thistype.allocate()
local unit u
local lightning l
local integer i = 0
local real x2
local real y2
local real z2
set swap[index] = this
set this.owner = GetOwningPlayer(caster)
set this.duration = DURATION
set this.grab_counter = GRAB_INTERVAL
set this.a = GRAB_MAX_STEP/RADIUS
set this.count = 0
set this.caster = caster
set this.cast_x = x1
set this.cast_y = y1
set this.dummy_z = 0.0
set this.dummy = CreateUnit(this.owner,DUMMY_ID,x1,y1,0)
call ShakeCamera(GetOwningPlayer(caster), 3.00)
call GroupEnumUnitsInRange(bj_lastCreatedGroup,x1,y1,RADIUS,null)
loop
set u = FirstOfGroup(bj_lastCreatedGroup)
exitwhen u == null
if filter(this.owner,u) then
set i = i + 1
set x2 = GetUnitX(u)
set y2 = GetUnitY(u)
set z2 = GetUnitZ(u) + ORIGIN_OFFSET
set l = AddLightningEx(LIGHTNING,false,x1,y1,0,x2,y2,z2)
call SaveUnitHandle ( hash , this , i , u )
call SaveLightningHandle( hash , this , -i , l )
call SaveBoolean ( hash , this , i , true)
endif
call GroupRemoveUnit(bj_lastCreatedGroup,u)
endloop
set this.count = i
//call BJDebugMsg(I2S(this.count))
if index == 0 then
call TimerStart(tim,TIMER_INTERVAL,true,function flame.rise)
endif
set index = index + 1
endmethod
endstruct
private function FlameShackles_Conditions takes nothing returns boolean
if GetSpellAbilityId() == ABILITY_ID then
call flame.start(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
endif
return false
endfunction
private function Init_FlameShackles takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,function FlameShackles_Conditions)
set t = null
endfunction
endscope