constant function ReturnAbilId takes nothing returns integer
return 'A000' //THIS NEEDS TO BE CHANGED to the rawcode of your spell!
endfunction
// ===========================
function H2I takes handle h returns integer
return h
return 0
endfunction
// ===========================
function LocalVars takes nothing returns gamecache
// Replace InitGameCache("jasslocalvars.w3v") with a global variable!!
return InitGameCache("jasslocalvars.w3v")
endfunction
function SetHandleHandle takes handle subject, string name, handle value returns nothing
if value==null then
call FlushStoredInteger(LocalVars(),I2S(H2I(subject)),name)
else
call StoreInteger(LocalVars(), I2S(H2I(subject)), name, H2I(value))
endif
endfunction
function SetHandleInt takes handle subject, string name, integer value returns nothing
if value==0 then
call FlushStoredInteger(LocalVars(),I2S(H2I(subject)),name)
else
call StoreInteger(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function SetHandleBoolean takes handle subject, string name, boolean value returns nothing
if value==false then
call FlushStoredBoolean(LocalVars(),I2S(H2I(subject)),name)
else
call StoreBoolean(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function SetHandleReal takes handle subject, string name, real value returns nothing
if value==0 then
call FlushStoredReal(LocalVars(), I2S(H2I(subject)), name)
else
call StoreReal(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function SetHandleString takes handle subject, string name, string value returns nothing
if value==null then
call FlushStoredString(LocalVars(), I2S(H2I(subject)), name)
else
call StoreString(LocalVars(), I2S(H2I(subject)), name, value)
endif
endfunction
function GetHandleHandle takes handle subject, string name returns handle
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleInt takes handle subject, string name returns integer
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleBoolean takes handle subject, string name returns boolean
return GetStoredBoolean(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleReal takes handle subject, string name returns real
return GetStoredReal(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleString takes handle subject, string name returns string
return GetStoredString(LocalVars(), I2S(H2I(subject)), name)
endfunction
function GetHandleUnit takes handle subject, string name returns unit
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleTimer takes handle subject, string name returns timer
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleTrigger takes handle subject, string name returns trigger
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleEffect takes handle subject, string name returns effect
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleGroup takes handle subject, string name returns group
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleLightning takes handle subject, string name returns lightning
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function GetHandleWidget takes handle subject, string name returns widget
return GetStoredInteger(LocalVars(), I2S(H2I(subject)), name)
return null
endfunction
function FlushHandleLocals takes handle subject returns nothing
call FlushStoredMission(LocalVars(), I2S(H2I(subject)) )
endfunction
function GetAngleBetweenPoints takes real x1, real y1, real x2, real y2 returns real //A remake of Blizzard's AngleBetweenPoints() function only with coordinates instead of locations and more efficient
return bj_RADTODEG * Atan2( y2 - y1, x2 - x1 )
endfunction
function Heal_Over_Time takes nothing returns nothing
local timer t = GetExpiredTimer()
local group g = GetHandleGroup( t, "g2" ) //save "g2" (the group with units in it) to local variable g
local group g2 = GetHandleGroup( t, "g" ) //save "g" (empty group) to local variable g2
//yes, I know the names are confusing, but it will make sense later
local unit u
local real tohealsmall = GetHandleReal( t, "tohealsmall" )
local real life
local real maxlife
//once again, we loop through every unit in group g (remember, it was saved as g2 in the timer so this is the group with units in it)
loop
set u = FirstOfGroup( g )
exitwhen ( u == null )
set life = GetUnitState( u, UNIT_STATE_LIFE )
set maxlife = GetUnitState( u, UNIT_STATE_MAX_LIFE )
if ( life >= 0.405 ) then //make sure the unit is alive; no sense in healing dead units
if ( life + tohealsmall >= maxlife ) then
call SetUnitState( u, UNIT_STATE_LIFE, maxlife )
else
call SetUnitState( u, UNIT_STATE_LIFE, life + tohealsmall )
endif
call GroupAddUnit( g2, u ) //save the unit to g2 (empty group), so that the trigger may use it later
endif
call GroupRemoveUnit( g, u )
endloop
//this is why i swapped the variable names, so that it makes more sense here when I swap the saved handles (why do I have to swap them? because the function assumes the group saved as "g2" is the one with units in it - take a look at the local var declarations at the beginning)
call SetHandleHandle( t, "g2", g2 )
call SetHandleHandle( t, "g", g )
//cleanup
set t = null
set g = null
set g2 = null
endfunction
function Cone_Of_Healing_Actions takes nothing returns nothing
local timer t = CreateTimer()
local group g = CreateGroup()
local group g2 = CreateGroup()
local unit caster = GetTriggerUnit()
local unit u
local player owner = GetOwningPlayer( caster )
local real casterx = GetUnitX( caster )
local real castery = GetUnitY( caster )
local real facing = GetUnitFacing( caster )
local real angle
local real life
local real maxlife
local real toheal = GetHeroInt( caster, true ) * 50.00 //this is how much the initial heal is
local real tohealsmall = GetHeroInt( caster, true ) * 5.00 //this is how much it heals every interval for the healing over time
local real distance = 250.00 //How far you want the "cone" to project from the caster
call GroupEnumUnitsInRange( g, casterx, castery, distance, null ) //We select all units around the caster within a radius equal to the distance specified
//Now we loop through every unit in the group
loop
set u = FirstOfGroup( g )
exitwhen ( u == null )
set angle = GetAngleBetweenPoints( casterx, castery, GetUnitX( u ), GetUnitY( u ) ) //We get the angle between the selected unit and the caster
if ( IsUnitAlly( u, owner ) and ( angle - facing ) <= 45.00 and ( angle - facing ) >= -45.00 ) then //Weed out enemies (you don't want to heal those surely) and also any units whose angle they make with the caster do not fall within a certain interval (here its -45.00 to 45.00 degrees with the caster's facing angle as 0.00 ). In essence, we weed out any units not within a cone defined by two straight lines projecting out from the caster's position - one x degrees to the right of the caster's facing angle and one x degrees to the left - and also the border of the circle with center at the caster and radius equal to the distance specified earlier.
set life = GetUnitState( u, UNIT_STATE_LIFE )
set maxlife = GetUnitState( u, UNIT_STATE_MAX_LIFE )
if ( life + toheal >= maxlife ) then
call SetUnitState( u, UNIT_STATE_LIFE, maxlife )
else
call SetUnitState( u, UNIT_STATE_LIFE, life + toheal )
endif
call GroupAddUnit( g2, u ) //we add all units that pass our test to a second unit group to be used later for the healing over time
endif
call GroupRemoveUnit( g, u )
endloop
call TimerStart( t, 1.00, true, function Heal_Over_Time ) //start the timer that controls when the healing over time actions occur (you could use loops and TriggerSleepAction() and that would be more efficient, but timers are more accurate and they allow for waits less than 0.27 seconds)
call SetHandleHandle( t, "g", g ) //save the group g (now empty) to the timer...why am i saving an empty group? Look at the timer's callback function and you will see.
call SetHandleHandle( t, "g2", g2 ) //save the group g2 (now with all the units to be healed over time) to the timer
call SetHandleReal( t, "tohealsmall", tohealsmall ) //save the amount of healing to be done on each interval to the timer
call TriggerSleepAction( 5.10 ) //How long you want the healing over time to last (it's best to add 0.10 seconds to make sure the timer fires correctly the last time)
//cleanup
call DestroyGroup( g )
call DestroyGroup( g2 )
call FlushHandleLocals( t )
call DestroyTimer( t )
set t = null
set g = null
set g2 = null
set caster = null
endfunction
function Cx takes nothing returns boolean
return ( GetSpellAbilityId() == ReturnAbilId() )
endfunction
//===========================================================================
function InitTrig_Cone_Of_Healing takes nothing returns nothing
set gg_trg_Cone_Of_Healing = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Cone_Of_Healing, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_Cone_Of_Healing, Condition( function Cx ) )
call TriggerAddAction( gg_trg_Cone_Of_Healing, function Cone_Of_Healing_Actions )
endfunction