[System] Heal

Scripts

14 years
edited 8 years
This system efficiently handles healing units instantly and over time.

Code (jass) Select
/************************************************************
*
*   Heal
*   v4.0.0.3
*   By Magtheridon96
*
*   - Heals units instantly or over time.
*   - Can also allow Damage over time with negative heal amount.
*   - Comes with heal events:
*
*       - Heal.ANY
*           - Fires on any healing event.
*           - This would be used for systems like:
*               - Accurate Unit Regeneration Logs
*               - Accurate Damage Logs
*               - Heal Block/Spell Effect Block
*
*       - Heal.INSTANT
*           - Fires on instant heal events.
*           - This would be used for systems like:
*               - Texttag Displays
*
*       - Heal.TIMED
*           - Fires 32x a second during a timed heal.
*           - This was only added for a sense of
*             completeness. It may be useful.
*
*   - Requires:
*
*       - UnitEvent by Nestharus
*           - hiveworkshop.com/forums/jass-resources-412/extension-unit-event-172365/
*       - UnitIndexer by Nestharus
*           - hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
*       - Event by Nestharus
*           - hiveworkshop.com/forums/jass-resources-412/snippet-event-186555/
*       - CTL by Nestharus
*           - hiveworkshop.com/forums/jass-resources-412/snippet-constant-timer-loop-32-a-201381/
*
*   - API:
*     ----
*
*       - struct Heal extends array
*           - readonly static Event ANY
*           - readonly static Event TIMED
*           - readonly static Event INSTANT
*               - Heal events
*
*           - static boolean enabled
*               - Used to enable/disable the system
*
*           - static method healUnit takes unit source, unit target, real amount returns nothing
*           - static method healUnitOverTime takes unit source, unit target, real amount, real duration returns nothing
*               - Heal a unit instantly or over time
*
*       - function RegisterInstantHealEvent takes code c returns nothing
*       - function RegisterTimedHealEvent takes code c returns nothing
*       - function RegisterAnyHealEvent takes code c returns nothing
*           - These functions register specific heal events that fire differently.
*
*       - function GetHealingUnit takes nothing returns unit
*       - function GetHealingUnitId takes nothing returns integer
*           - These functions are used to get the healing unit or its id.
*
*       - function GetHealedUnit takes nothing returns unit
*       - function GetHealedUnitId takes nothing returns integer
*           - These functions are used to get the healed unit or its id.
*
*       - function GetHealedAmount takes nothing returns real
*       - function GetEffectiveHealedAmount takes nothing returns real
*       - function GetOriginalLife takes nothing returns real
*           - These functions are used to get:
*               - Amount of HP intended to be healed.
*               - Amount of HP actually healed.
*               - Original HP before healing.
*
*       - function HealUnit takes unit source, unit target, real amount returns nothing
*       - function HealUnitOverTime takes unit source, unit target, real amount, real duration returns nothing
*           - These are the wrappers used for healing units.
*
************************************************************/
library Heal requires UnitIndexer, UnitEvent, Event, CTL

    private module Init
        private static method onInit takes nothing returns nothing
            set INSTANT = CreateEvent()
            set TIMED = CreateEvent()
            set ANY = CreateEvent()
        endmethod
    endmodule
   
    struct Heal extends array
   
        readonly static Event INSTANT
        readonly static Event TIMED
        readonly static Event ANY
       
        static boolean enabled = true
       
        static UnitIndex sourceId = 0
        static UnitIndex targetId = 0
       
        static real amount = 0.0
        static real original = 0.0
        static real effective = 0.0
       
        private static unit array source
        private static unit array target
        private static real array regen
        private static real array duration
       
        private static method lock takes nothing returns nothing
            if sourceId != 0 then
                call sourceId.lock()
            endif
            if targetId != 0 then
                call targetId.lock()
            endif
        endmethod
       
        private static method unlock takes nothing returns nothing
            if sourceId != 0 then
                call sourceId.unlock()
            endif
            if targetId != 0 then
                call targetId.unlock()
            endif
        endmethod
       
        implement CTL
       
            local real r
            local integer u
           
        implement CTLExpire
       
            set r = GetWidgetLife(target[this])
            set u = GetUnitUserData(target[this])
           
            if not IsUnitDead(u) and duration[this] <= 0. then
                set duration[this] = duration[this] - 0.03125
                call SetWidgetLife(target[this], r + regen[this])
               
                if enabled then
               
                    set sourceId = GetUnitUserData(source[this])
                    set targetId = u
                    set amount = regen[this]
                    set original = r
                    set effective = GetWidgetLife(target[this]) - r
                   
                    call lock()
                   
                    call TIMED.fire()
                    call ANY.fire()
                   
                    call unlock()
                   
                endif
            else
                set source[this] = null
                set target[this] = null
               
                call this.destroy()
            endif
           
        implement CTLNull
        implement CTLEnd
       
        static method healUnit takes unit source, unit target, real howMuch returns nothing
            local real r = GetWidgetLife(target)
            local integer u = GetUnitUserData(target)
           
            if not IsUnitDead(u) then
                call SetWidgetLife(target, r + howMuch)
               
                if enabled then
               
                    set sourceId = GetUnitUserData(source)
                    set targetId = u
                    set amount = howMuch
                    set original = r
                    set effective = GetWidgetLife(target) - r
                   
                    call lock()
                   
                    call INSTANT.fire()
                    call ANY.fire()
                   
                    call unlock()
                   
                endif
            endif
        endmethod
       
        static method healUnitOverTime takes unit src, unit trgt, real howMuch, real dur returns nothing
            local thistype this = create()
           
            set source[this] = src
            set target[this] = trgt
            set regen[this] = 0.03125 * howMuch / dur
           
            set duration[this] = dur
        endmethod
       
        implement Init
    endstruct
   
    function RegisterInstantHealEvent takes code c returns nothing
        call Heal.INSTANT.register(Filter(c))
        return
    endfunction
   
    function RegisterTimedHealEvent takes code c returns nothing
        call Heal.TIMED.register(Filter(c))
        return
    endfunction
   
    function RegisterAnyHealEvent takes code c returns nothing
        call Heal.ANY.register(Filter(c))
        return
    endfunction
   
    function GetHealingUnit takes nothing returns unit
        return GetUnitById(Heal.sourceId)
    endfunction
   
    function GetHealingUnitId takes nothing returns integer
        return Heal.sourceId
    endfunction
   
    function GetHealedUnit takes nothing returns unit
        return GetUnitById(Heal.targetId)
    endfunction
   
    function GetHealedUnitId takes nothing returns integer
        return Heal.targetId
    endfunction
   
    function GetHealedAmount takes nothing returns real
        return Heal.amount
    endfunction
   
    function GetEffectiveHealedAmount takes nothing returns real
        return Heal.effective
    endfunction
   
    function GetOriginalLife takes nothing returns real
        return Heal.original
    endfunction
   
    function HealUnit takes unit source, unit target, real amount returns nothing
        call Heal.healUnit(source,target,amount)
    endfunction
   
    function HealUnitOverTime takes unit source, unit target, real amount, real duration returns nothing
        call Heal.healUnitOverTime(source,target,amount,duration)
    endfunction
   
endlibrary


Demo Code

Code (jass) Select
struct Tester extends array

    private static unit fighters1
    private static unit fighters2

    private static unit regen

    private static method instant takes nothing returns nothing
        call HealUnit(null, fighters1, 150)
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Healed unit for 150 HP")
    endmethod

    private static method onInit takes nothing returns nothing
       
        set fighters1 = CreateUnit(Player(0), 'Hpal', 128, 0, 180)
        set fighters2 = CreateUnit(Player(1), 'Hpal', -128, 0, 0)
        call TimerStart(CreateTimer(), 10, true, function thistype.instant)
       
        set regen = CreateUnit(Player(0), 'Hpal', 0, 1024, 270)
        call CreateUnit(Player(1), 'Hpal', 0, 1024, 270)
        call SetWidgetLife(regen, GetUnitState(regen, UNIT_STATE_MAX_LIFE) / 2)
       
        // This will regenerate 500000 HP over 50000 seconds meaning 10 HP/sec
        call HealUnitOverTime(null, regen, 500000, 50000)
       
        call PauseUnit(regen, true)
    endmethod

endstruct


Feel free to comment..
14 years
I have something in mind that this script might be useful, I'll test it if it will work ;), thanks for sharing.
14 years
Thanks man :D
Yeah, this is useful because of the events, and you're forced to use it if you want accurate unit regeneration value retrieval :P (If you're also using my GetUnitRegeneration script)
14 years
Hi Magh, remember me??
14 years
Oh yes. I do remember you.
I hope you don't give yourself the same reputation here as you did on Hive.
13 years
Oh yeah..
But, how to heal like this:
Healing targeted unit for 20% of targeted unit maximum HP....
Please give me the codes :D :D
13 years
call HealUnit(null, udg_YOUR_UNIT, 0.2 * GetUnitState(udg_YOUR_UNIT, UNIT_STATE_MAX_LIFE))
13 years
Thunk'z ;) ;)
But why you banned me on Hive?? Y.Y
13 years
Ok ;) ;)