the Immortal
I know, I know...
- Reaction score
- 51
A hack-ish way to disable unit's life regeneration. Has its cons, and as such, I suppose, non-suitable for approval. But still worth the submission imo, as I haven't seen a better way to disable a unit's HP regeneration (actually haven't seen any).
Requires AIDS
Optionally uses Damage
API / Usage / Cons list and everything is in the script.
Also, if someone is willing to take a look, I had to re-start the timer instead of resuming it as resuming actually runs the timer 2-3 times and then stops. Had the same issue in another project of mine.
Not that it matters performance-wise.
Oh, and yes, the test map sucks. I know.
Requires AIDS
Optionally uses Damage
API / Usage / Cons list and everything is in the script.
JASS:
library ToggleHPRegen initializer onInit requires AIDS optional Damage
/*
Overview:
Allows toggling of unit's life regeneration / healing.
Uses kinda hack-ish method but works without problems from what I observed.
Optionally uses Damage to register for onDamage events.
API:
ToggleRegen(unit u, boolean disable)
- disables or enables the unit's regeneration.
SetUnitLifeEx(unit whichUnit, real newLife)
- sets whichUnit's life to newLife. Works when its regen is disabled
How to import:
- Make sure you have a vJASS compiler (JassHelper) and then simply
- Copy this script into any trigger object
Inner workings:
Mantains a stack with all units who have their regens disabled and re-sets
their life several times per second (default - 33) to a value. Thus regeneration
(and respectively any heal) gets disabled. That value also gets updated each
time the unit takes damage so it doesnt become immune to damage.
Cons:
- life regeneration over ~100/sec gets visible at default PERIOD (0.03)
FIX: use smaller period.
- Any heals also get disabled. Not sure if it counts as a 'con' though.
Still, the SetUnitLifeEx function is here for such heals.
Can also add a SetWidgetLife/SetUnitState hook if someone thinks it'd be useful
Thx to:
- J4L's nicey systems
- Tyrande_Ma3x for original idea.
*/
globals
//How often to update unit's HP
//33 fps should be pretty enough for most maps
private constant real PERIOD = 0.03
endglobals
//----------------------------------------------------------------------------------------
private struct RegData extends array
real HP
boolean e
integer num
trigger trgOnDmg
private method AIDS_onDestroy takes nothing returns nothing
set e = false
endmethod
// Really just better/faster with AIDS_RegisterOnLeave(..)
// but J4L said not to use it!! Q_Q
//! runtextmacro AIDS()
endstruct
globals
private trigger trgOnDamage = CreateTrigger()
private timer timPeriodic = CreateTimer()
private unit array ug
private integer uc = 0
private RegData rd
endglobals
private function onPeriod takes nothing returns nothing
set rd = 0 //use as iterator. -1 var!
loop
exitwhen rd == uc
call SetWidgetLife(ug[rd], RegData[ug[rd]].HP)
set rd = rd + 1
endloop
endfunction
private function onDamage takes nothing returns boolean
set rd = RegData[GetTriggerUnit()]
static if LIBRARY_Damage then
if rd.e then
set rd.HP = rd.HP - GetEventDamage()
call SetWidgetLife(GetTriggerUnit(), rd.HP) //fixes cheat death bug
endif
else //no need for check since only units with disabled regen trigger this
set rd.HP = rd.HP - GetEventDamage()
call SetWidgetLife(GetTriggerUnit(), rd.HP) //fixes cheat death bug
endif
return false
endfunction
function SetUnitLifeEx takes unit whichUnit, real newLife returns nothing
set RegData[whichUnit].HP = newLife
call SetWidgetLife(whichUnit, newLife)
endfunction
function ToggleRegen takes unit u, boolean stop returns nothing
set rd = RegData<u>
if rd.e == stop then
return
endif
set rd.e = stop
if stop == true then
set rd.HP = GetWidgetLife(u)
if uc == 0 then
//ResumeTimer bugs? :/
call TimerStart(timPeriodic, PERIOD, true, function onPeriod)
endif
set ug[uc] = u
set rd.num = uc
set uc = uc + 1
static if not LIBRARY_Damage then
if rd.trgOnDmg == null then
set rd.trgOnDmg = CreateTrigger()
call TriggerAddCondition(rd.trgOnDmg, Condition(function onDamage))
call TriggerRegisterUnitEvent(rd.trgOnDmg, u, EVENT_UNIT_DAMAGED)
endif
endif
else
set uc = uc - 1
set RegData[ug[uc]].num = rd.num
set ug[rd.num] = ug[uc]
static if not LIBRARY_Damage then
call DestroyTrigger(rd.trgOnDmg)
set rd.trgOnDmg = null
endif
if uc == 0 then
call PauseTimer(timPeriodic)
endif
endif
endfunction
private function onInit takes nothing returns nothing
static if LIBRARY_Damage then
call Damage_RegisterEvent(trgOnDamage)
endif
call TriggerAddCondition(trgOnDamage, Condition(function onDamage))
call TimerStart(timPeriodic, PERIOD, true, function onPeriod)
call PauseTimer(timPeriodic)
endfunction
endlibrary</u>
Also, if someone is willing to take a look, I had to re-start the timer instead of resuming it as resuming actually runs the timer 2-3 times and then stops. Had the same issue in another project of mine.
Not that it matters performance-wise.
Oh, and yes, the test map sucks. I know.