Name | Type | is_array | initial_value |
WateryHeal_Hash | hashtable | No |
// Constants
constant function WateryHeal_AbilityId takes nothing returns integer
return 'A000'
endfunction
constant function WateryHeal_ElementalId takes nothing returns integer
return 'h001'
endfunction
constant function WateryHeal_HealProjectileId takes nothing returns integer
return 'h002'
endfunction
function WateryHeal_StacksCap takes integer abilLevel returns integer
return 3 + 2 * abilLevel
endfunction
constant function WateryHeal_ElemCastAnimTime takes nothing returns real
return 1.167
endfunction
constant function WateryHeal_ElemCastAnimName takes nothing returns string
return "Attack"
endfunction
function WateryHeal_AnimSpeed takes nothing returns real
return 1. / WateryHeal_ElemCastAnimTime()
endfunction
constant function WateryHeal_StackTime takes nothing returns real
return 5.
endfunction
constant function WateryHeal_HealPeriod takes nothing returns real
return 1.
endfunction
constant function WateryHeal_ElemLifeTime takes nothing returns real
return 10.
endfunction
constant function WateryHeal_ElemHealRange takes nothing returns real
return 650.
endfunction
constant function WateryHeal_ElemProjectileSpeed takes nothing returns real
return 40.
endfunction
constant function WateryHeal_CollideDistance takes nothing returns real
return 60.
endfunction
function WateryHeal_GetHealAmount takes integer elemStacks returns real
return 92. + 14. * elemStacks
endfunction
function WateryHeal_IsUnitMatching takes unit abilityCaster, unit enumUnit returns boolean
return IsUnitAlly(abilityCaster,GetOwningPlayer(enumUnit)) and not IsUnitType(enumUnit,UNIT_TYPE_DEAD) and not IsUnitType(enumUnit,UNIT_TYPE_STRUCTURE)
endfunction
constant function WateryHeal_ElemBirthEffect takes nothing returns string
return "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
endfunction
constant function WateryHeal_ElemDeathEffect takes nothing returns string
return "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
endfunction
constant function WateryHeal_ElemHealTarget takes nothing returns string
return "Abilities\\Spells\\Undead\\AbsorbMana\\AbsorbManaBirthMissile.mdl"
endfunction
constant function WateryHeal_DeScaleElem takes nothing returns string
return "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"
endfunction
// Functions
function Trig_WateryHeal_ProjTimer takes nothing returns nothing
local timer healTimer = GetExpiredTimer()
local integer healTimerId = GetHandleId(healTimer)
local unit abilityCaster = LoadUnitHandle(udg_WateryHeal_Hash,healTimerId,0)
local unit healingProjectile = LoadUnitHandle(udg_WateryHeal_Hash,healTimerId,1)
local unit healedUnit = LoadUnitHandle(udg_WateryHeal_Hash,healTimerId,2)
local integer elemStacks = LoadInteger(udg_WateryHeal_Hash,healTimerId,3)
local real projX = GetUnitX(healingProjectile)
local real projY = GetUnitY(healingProjectile)
local real healedX = GetUnitX(healedUnit)
local real healedY = GetUnitY(healedUnit)
local real curDistance = SquareRoot((healedX-projX)*(healedX-projX)+(healedY-projY)*(healedY-projY))
local real curAngle = Atan2(healedY-projY,healedX-projX)
local real newX = projX + WateryHeal_ElemProjectileSpeed() * Cos(curAngle)
local real newY = projY + WateryHeal_ElemProjectileSpeed() * Sin(curAngle)
if curDistance <= WateryHeal_CollideDistance() then
call SetWidgetLife(healedUnit,GetWidgetLife(healedUnit)+WateryHeal_GetHealAmount(elemStacks))
call DestroyEffect(AddSpecialEffect(WateryHeal_ElemHealTarget(),healedX,healedY))
call KillUnit(healingProjectile)
call FlushChildHashtable(udg_WateryHeal_Hash,healTimerId)
call PauseTimer(healTimer)
call DestroyTimer(healTimer)
else
call SetUnitX(healingProjectile,newX)
call SetUnitY(healingProjectile,newY)
endif
set healTimer = null
set abilityCaster = null
set healingProjectile = null
set healedUnit = null
endfunction
function Trig_WateryHeal_HealTimer takes nothing returns nothing
local timer healTimer = GetExpiredTimer()
local integer healTimerId = GetHandleId(healTimer)
local unit abilityCaster = LoadUnitHandle(udg_WateryHeal_Hash,healTimerId,0)
local unit waterElemental = LoadUnitHandle(udg_WateryHeal_Hash,healTimerId,1)
local integer elemHandleId = GetHandleId(waterElemental)
local integer elemStacks = LoadInteger(udg_WateryHeal_Hash,elemHandleId,WateryHeal_AbilityId())
local real timePassed = LoadReal(udg_WateryHeal_Hash,healTimerId,2)+1
local real scalePercent = LoadInteger(udg_WateryHeal_Hash,healTimerId,3)-255/WateryHeal_ElemLifeTime()
local group healGroup
local unit healedUnit
local timer healProjTimer
local integer healProjTimerId
local unit healingProjectile
call SaveReal(udg_WateryHeal_Hash,healTimerId,2,timePassed)
if timePassed <= WateryHeal_ElemLifeTime() then
call SaveInteger(udg_WateryHeal_Hash,healTimerId,3,R2I(scalePercent))
call SetUnitVertexColor(waterElemental,255,255,255,R2I(scalePercent))
call DestroyEffect(AddSpecialEffect(WateryHeal_DeScaleElem(),GetUnitX(waterElemental),GetUnitY(waterElemental)))
call SetUnitAnimation(waterElemental,WateryHeal_ElemCastAnimName())
set healGroup = CreateGroup()
call GroupEnumUnitsInRange(healGroup,GetUnitX(waterElemental),GetUnitY(waterElemental),WateryHeal_ElemHealRange(),null)
loop
set healedUnit = FirstOfGroup(healGroup)
exitwhen healGroup == null
if WateryHeal_IsUnitMatching(abilityCaster,healedUnit) then
set healProjTimer = CreateTimer()
set healProjTimerId = GetHandleId(healProjTimer)
set healingProjectile = CreateUnit(GetOwningPlayer(abilityCaster),WateryHeal_HealProjectileId(),GetUnitX(waterElemental),GetUnitY(waterElemental),0.)
call SaveUnitHandle(udg_WateryHeal_Hash,healProjTimerId,0,abilityCaster)
call SaveUnitHandle(udg_WateryHeal_Hash,healProjTimerId,1,healingProjectile)
call SaveUnitHandle(udg_WateryHeal_Hash,healProjTimerId,2,healedUnit)
call SaveInteger(udg_WateryHeal_Hash,healProjTimerId,3,elemStacks)
call TimerStart(healProjTimer,.04,true,function Trig_WateryHeal_ProjTimer)
endif
call GroupRemoveUnit(healGroup,healedUnit)
endloop
call DestroyGroup(healGroup)
else
call DestroyEffect(AddSpecialEffect(WateryHeal_ElemDeathEffect(),GetUnitX(waterElemental),GetUnitY(waterElemental)))
call FlushChildHashtable(udg_WateryHeal_Hash,elemHandleId)
call KillUnit(waterElemental)
call FlushChildHashtable(udg_WateryHeal_Hash,healTimerId)
call PauseTimer(healTimer)
call DestroyTimer(healTimer)
endif
set healingProjectile = null
set healProjTimer = null
set healGroup = null
set waterElemental = null
set healTimer = null
set abilityCaster = null
endfunction
function Trig_WateryHeal_Conditions takes nothing returns boolean
local unit abilityCaster = GetTriggerUnit()
local real stx = GetSpellTargetX()
local real sty = GetSpellTargetY()
local timer healTimer
local integer healTimerId
local unit waterElemental
local integer heroStacks
local integer heroHandleId
local integer elemHandleId
if GetSpellAbilityId() == WateryHeal_AbilityId() then
// Creating the elemental.
call DestroyEffect(AddSpecialEffect(WateryHeal_ElemBirthEffect(),stx,sty))
set waterElemental = CreateUnit(GetTriggerPlayer(),WateryHeal_ElementalId(),stx,sty,GetRandomReal(0.,360.))
// We need to set proper animation speed for this unit.
call SetUnitTimeScale(waterElemental,WateryHeal_AnimSpeed())
// Adding all the current stacks to the elem.
set heroHandleId = GetHandleId(abilityCaster)
set elemHandleId = GetHandleId(waterElemental)
set heroStacks = LoadInteger(udg_WateryHeal_Hash,heroHandleId,WateryHeal_AbilityId())
call SaveInteger(udg_WateryHeal_Hash,elemHandleId,WateryHeal_AbilityId(),heroStacks)
// Erasing the stacks from caster.
call SaveInteger(udg_WateryHeal_Hash,heroHandleId,WateryHeal_AbilityId(),0)
// Now, setting up the timer for periodic healing
set healTimer = CreateTimer()
set healTimerId = GetHandleId(healTimer)
call SaveUnitHandle(udg_WateryHeal_Hash,healTimerId,0,abilityCaster)
call SaveUnitHandle(udg_WateryHeal_Hash,healTimerId,1,waterElemental)
call SaveReal(udg_WateryHeal_Hash,healTimerId,2,0.)
call SaveInteger(udg_WateryHeal_Hash,healTimerId,3,255)
call TimerStart(healTimer,WateryHeal_HealPeriod(),true,function Trig_WateryHeal_HealTimer)
endif
set waterElemental = null
set healTimer = null
set abilityCaster = null
return false
endfunction
function Trig_WateryHeal_Stacks takes nothing returns nothing
local integer etId = GetHandleId(GetExpiredTimer())
local group tempGroup = CreateGroup()
local unit tempGroupUnit
local integer curStacks
local real timePassed
local integer tguId
call GroupEnumUnitsInRect(tempGroup,bj_mapInitialPlayableArea,null)
loop
set tempGroupUnit = FirstOfGroup(tempGroup)
exitwhen tempGroupUnit == null
if GetUnitAbilityLevel(tempGroupUnit,WateryHeal_AbilityId()) > 0 then
set tguId = GetHandleId(tempGroupUnit)
set timePassed = LoadReal(udg_WateryHeal_Hash,etId,tguId)
if timePassed >= WateryHeal_StackTime() then
// Stack Gain.
set curStacks = LoadInteger(udg_WateryHeal_Hash,tguId,WateryHeal_AbilityId())
if curStacks < WateryHeal_StacksCap(GetUnitAbilityLevel(tempGroupUnit,WateryHeal_AbilityId())) then
call SaveInteger(udg_WateryHeal_Hash,tguId,WateryHeal_AbilityId(),curStacks+1)
endif
call SaveReal(udg_WateryHeal_Hash,etId,tguId,0.)
else
call SaveReal(udg_WateryHeal_Hash,etId,tguId,timePassed+1.)
endif
endif
call GroupRemoveUnit(tempGroup,tempGroupUnit)
endloop
call DestroyGroup(tempGroup)
set tempGroup = null
endfunction
//===========================================================================
function InitTrig_WateryHeal takes nothing returns nothing
local trigger tempTrigger = CreateTrigger()
set udg_WateryHeal_Hash = InitHashtable()
call TriggerRegisterAnyUnitEventBJ(tempTrigger,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(tempTrigger,Condition(function Trig_WateryHeal_Conditions))
call TimerStart(CreateTimer(),1.,true,function Trig_WateryHeal_Stacks)
set tempTrigger = null
endfunction