Well, I'm learning vJass and i make an spell from DotA, Elune's Arrow of Priestess of the moon.
Does it have any leak? Or something else I should change?
Map download
Here's the code:
Does it have any leak? Or something else I should change?
Map download
Here's the code:
JASS:
scope Elune initializer Init
globals
private hashtable ht = InitHashtable()
private constant integer Spell_Id = 039;A001039; // Spell based on Channel.
private constant integer Stun_Id = 039;A000039; // Stun for the dummy, bassed on thunderbolt.
private constant integer Arrow_Id = 039;h001039; // Arrow.
private constant integer Dummy_Id = 039;h000039; // Dummy that causes the damage and stun.
private constant real ArrowSpeed = .03 // Velocity of the arrow (basically, callback interval), don't put more than .04 (higger number, lower speed)
private constant real Collision = 80. // Radius of collision of the arrow.
private constant integer Max_Range = 3000 // Distance traveled by the arrow
endglobals
private function Elune_Filter takes nothing returns boolean
local timer t=GetExpiredTimer()
local data d=LoadInteger(ht,0,GetHandleId(t))
local unit stunner
local unit stunned=GetFilterUnit()
local player p=GetOwningPlayer(d.caster)
local integer array D
if IsUnitEnemy(stunned,p) and GetWidgetLife(stunned)>.405 and not IsUnitType(stunned,UNIT_TYPE_STRUCTURE) then
set stunner=CreateUnit(p,Dummy_Id,GetUnitX(d.arrow),GetUnitY(d.arrow),0.)
call UnitApplyTimedLife(stunner,039;BTLF039;,.5)
// Calculating the duration of the stun.
set D[0]=R2I(d.distance/150)
set D[1]=10
if D[0]<D[1] then
call SetUnitAbilityLevel(stunner,Stun_Id,D[0])
else
call SetUnitAbilityLevel(stunner,Stun_Id,D[1])
endif
//------------
call IssueTargetOrder(stunner,"thunderbolt",stunned)
call UnitDamageTarget(stunner,stunned,GetUnitAbilityLevel(d.caster,Spell_Id)*90.,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,null)
call KillUnit(d.arrow)
//call RemoveUnit(d.arrow) ???
call RemoveSavedInteger(ht,0,GetHandleId(t))
call d.destroy()
call PauseTimer(t)
call DestroyTimer(t)
endif
set t=null
set stunned=null
set stunner=null
set p=null
return false
endfunction
private function Elune_Callback takes nothing returns nothing
local timer t=GetExpiredTimer()
local data d=LoadInteger(ht,0,GetHandleId(t))
local real nx=GetUnitX(d.arrow)+30.*Cos(d.angle)
local real ny=GetUnitY(d.arrow)+30.*Sin(d.angle)
local rect max=bj_mapInitialPlayableArea
call SetUnitPosition(d.arrow,nx,ny)
set d.distance=d.distance+30
call GroupEnumUnitsInRange(d.g,nx,ny,Collision,Filter(function Elune_Filter))
if d.distance>=Max_Range or GetUnitY(d.arrow)>=GetRectMaxY(max) or GetUnitY(d.arrow)<=GetRectMinY(max) or GetUnitX(d.arrow)>=GetRectMaxX(max) or GetUnitX(d.arrow)<=GetRectMinX(max) then
call KillUnit(d.arrow)
//call RemoveUnit(d.arrow)??
call RemoveSavedInteger(ht,0,GetHandleId(t))
call d.destroy()
call PauseTimer(t)
call DestroyTimer(t)
endif
set max=null
set t=null
endfunction
struct data
unit caster
unit arrow
real angle
integer distance=50
group g=CreateGroup()
timer t=CreateTimer()
static method create takes nothing returns thistype
local data this=.allocate()
local real sx=GetSpellTargetX()
local real sy=GetSpellTargetY()
local real cx
local real cy
set .caster=GetTriggerUnit()
set cx=GetUnitX(.caster)
set cy=GetUnitY(.caster)
set .angle=Atan2(sy-cy,sx-cx)
set .arrow=CreateUnit(GetOwningPlayer(.caster),Arrow_Id,cx,cy,.angle*57.2957795)
call SaveInteger(ht,0,GetHandleId(.t),this)
call TimerStart(.t,ArrowSpeed,true,function Elune_Callback)
return this
endmethod
method onDestroy takes nothing returns nothing
set .caster=null
set .arrow=null
set .g=null
set .t=null
endmethod
endstruct
private function Elune_Conditions takes nothing returns boolean
if GetSpellAbilityId()==Spell_Id then
call data.create()
endif
return false
endfunction
private function Init takes nothing returns nothing
local integer i=0
local trigger t=CreateTrigger()
// Bye bye, BJ.
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
// ---------
call TriggerAddCondition(t,Condition(function Elune_Conditions))
set t=null
endfunction
endscope