constant function EF_GetDamageRadius takes real level returns real
return level * 150 + 80 //The damage radius of the missile when it reaches its target
endfunction
constant function EF_GetImpactDamage takes real level returns real
return level * 30 + 40 //The damae dealt to enemies in range of the missile
endfunction
constant function EF_DummyModel takes nothing returns string
return "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
endfunction //Selfexplaining
constant function EF_GetImpactSFX takes nothing returns string
return "Abilities\\Weapons\\DemolisherFireMissile\\DemolisherFireMissile.mdl"
endfunction //The Special effect being displayed on an enemy when the missile explodes
constant function EF_Curve takes nothing returns real
return 4.736 //This has incluce on the z-parabola
endfunction
constant function EF_DummyScale takes nothing returns real
return 1.7 //The size of the dummy
endfunction
constant function EF_TimerIntervall takes nothing returns real
return 0.02 //Moving intervall of the missiel. Better do not change
endfunction
constant function EF_GetMoveSpeed takes nothing returns real
return 20. //Moving speed of the missile
endfunction
constant function EF_SID takes nothing returns integer
return 'A000' //The rawcode (spell id) of this ability
endfunction
constant function EF_DID takes nothing returns integer
return 'h000' //The rawcode of the dummy unit
endfunction
constant function EF_IsHoming takes nothing returns boolean
return false //Gets important somwhen later...
endfunction
//Credits to Shadow1500 for this function!
constant function Parabola takes real d, real m, real c returns real
return (-1* ((d * 2) / m - 1) * ((d * 2) / m - 1) + 1) * (m / c)
endfunction //Computes the z-value for the missile depdining on the current (D)istance, the (M)aximal distance and the (C)urve factor
constant function EF_HashKey takes nothing returns integer
return 0x256
endfunction //A key for the hashtable to cache some temporaty data
function EF_CreateDummy takes unit u, real x, real y, real f returns unit
set u = CreateUnit(Player(0),EF_DID(),x,y,f*bj_RADTODEG) //Create a unit with the imported dummy model
call SetUnitScale(u,EF_DummyScale(),EF_DummyScale(),EF_DummyScale()) //Set its size
call SaveEffectHandle(udg_EF_HASH,EF_HashKey(),GetHandleId(u),AddSpecialEffectTarget(EF_DummyModel(),u,"origin"))
//Attatch an effect to the unit; visually AND in the memory
call UnitAddAbility(u,'Aloc') //Make the unit unpickable
call UnitAddAbility(u,'Amrf') //Make the unit flyable
return u //I create the unit on a parameter because they don´t need to be nulled when they are returned
//You should use null if you pass values
endfunction
function EF_AoEDamage takes nothing returns boolean
local unit u = GetFilterUnit() //Gets a unit near to the missile
local unit c = LoadUnitHandle(udg_EF_HASH,EF_HashKey(),1) //Gets the caster from the 'cache'
local real dmg = LoadReal(udg_EF_HASH,EF_HashKey(),2) //GetS the damage from the 'cache'
//If the unit is valid
if IsUnitEnemy(u,GetOwningPlayer(c)) and IsUnitType(u,UNIT_TYPE_DEAD) != true and IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) != true and IsUnitType(u,UNIT_TYPE_STRUCTURE) != true then
call UnitDamageTarget(c,u,dmg,false,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
//Deal damage...
call DestroyEffect(AddSpecialEffect(EF_GetImpactSFX(),GetWidgetX(u),GetWidgetY(u)))
//...and quick destroy/create a special effect
endif
set u = null
set c = null
return false
endfunction
function EF_MoveNormal takes nothing returns nothing
local timer t = GetExpiredTimer() //Gets the timer
local integer id = GetHandleId(t) //Gets its id to acces data from the (H)ash(T)able
local unit u = LoadUnitHandle(udg_EF_HASH,id,1) //Gets the missile from the ht
local location loc = GetUnitLoc(u) //Gets the current position (need location to calcuate z)
local real dis = LoadReal(udg_EF_HASH,id,4) - EF_GetMoveSpeed() //Recalculate the distance
local real z = Parabola(dis,LoadReal(udg_EF_HASH,id,5),EF_Curve()) - GetLocationZ(loc) //Calculates the absulute Z
local unit c = null //Caster (needed when the missile explodes)
call SetUnitX(u,GetLocationX(loc)+LoadReal(udg_EF_HASH,id,2))
call SetUnitY(u,GetLocationY(loc)+LoadReal(udg_EF_HASH,id,3))
//Moving the missile
call SetUnitFlyHeight(u,z,0.)
//Moving the missile trhough the air
call SaveReal(udg_EF_HASH,id,4,dis)
//Save the distance again to the ht
if dis <= EF_GetMoveSpeed() +1. then //If the missile is near to its target point
set c = LoadUnitHandle(udg_EF_HASH,id,0)
set z = GetUnitAbilityLevel(c,EF_SID()) //Re-using a local
call SaveUnitHandle(udg_EF_HASH,EF_HashKey(),1,c)
call SaveReal(udg_EF_HASH,EF_HashKey(),2,EF_GetImpactDamage(z))
//Putting the caster and the damage into the 'cache'
call GroupEnumUnitsInRange(LoadGroupHandle(udg_EF_HASH,EF_HashKey(),0),GetWidgetX(u),GetWidgetY(u),EF_GetDamageRadius(z), Filter( function EF_AoEDamage))
//Loops trhough all unit near the missile and damages them if they are valid
call GroupClear(LoadGroupHandle(udg_EF_HASH,EF_HashKey(),0))
//Clears the group to prevent bugs
call DestroyEffect(AddSpecialEffectLoc(EF_DummyModel(),loc))
//Show the missiles death animation
call DestroyEffect(LoadEffectHandle(udg_EF_HASH,EF_HashKey(),GetHandleId(u)))
//Removes the missile model from the dummy and from the memory
call RemoveUnit(u)
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_EF_HASH,id)
set c = null
//Clearing leaks and save some memory
endif
call RemoveLocation(loc)
set t = null
set loc = null
set u = null
//Cleans the last leaks
endfunction
function EF_OnCastNormal takes nothing returns nothing
local unit u = GetTriggerUnit() //Gets the caster
local real x = GetSpellTargetX() - GetWidgetX(u)
local real y = GetSpellTargetY() - GetWidgetY(u)
//MATH !!!
local real rad = Atan2(y,x) //Gets the angel between the caster and the target point (in radiants !)
local real cos = Cos(rad)*EF_GetMoveSpeed() //Calculates the x direction
local real sin = Sin(rad)*EF_GetMoveSpeed() //Calculates the y direction
local real dis = SquareRoot(x*x+y*y) //Calculates the distance
local timer t = CreateTimer()
local integer id = GetHandleId(t) //Gets a key for the ht
call SaveUnitHandle(udg_EF_HASH,id,0,u) //Attaches the caster to the ht
call SaveUnitHandle(udg_EF_HASH,id,1,EF_CreateDummy(null,GetWidgetX(u),GetWidgetY(u),rad)) //Creates and attaches the dummy du the ht
call SaveReal(udg_EF_HASH,id,2,cos) //attatch x direction
call SaveReal(udg_EF_HASH,id,3,sin) //attatch y direction
call SaveReal(udg_EF_HASH,id,4,dis) //attatch the distance (will be decreasd while moving)
call SaveReal(udg_EF_HASH,id,5,dis) //attatch the distance agian as maximal distance (need for the parabola func)
call TimerStart(t,EF_TimerIntervall(),true, function EF_MoveNormal) //Starts the whole shit
set u = null
set t = null
endfunction
function EF_CastCheck takes nothing returns boolean
return GetSpellAbilityId() == EF_SID() //Checks if the Correct spell is casted
endfunction
//===========================================================================
function InitTrig_Eay_Fireball takes nothing returns nothing
local trigger trig = CreateTrigger()
local integer i = 0
set udg_EF_HASH = InitHashtable() //Creates a hashtable
call SaveGroupHandle(udg_EF_HASH,EF_HashKey(),0,CreateGroup()) //Creates an enum group in the 'cache'
//Trigger register shit beyond this line
call TriggerAddAction( trig, function EF_OnCastNormal )
call TriggerAddCondition(trig, Filter( function EF_CastCheck))
loop //Inlined a BJ (not really necassay but i don´t care really)
exitwhen i == bj_MAX_PLAYER_SLOTS
call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,null)
set i = i +1
endloop
set trig = null
endfunction