System Heal

Discussion in 'Systems and Snippets' started by kingkingyyk3, Dec 16, 2009.

  1. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    JASS:
    /*
     
        Heal v2.0.0
            by kingking
        
        - Library that transforms healing into a breeze, allowing full control on healing.
        
        CreateHealType()-> HealType
        ~ Generate a heal type.
        
        HealUnit(unit a, unit b,real,HealType)
        ~ Heal the unit + fire event.
        ~ Unit a -> Healer
        ~ Unit b -> Target
        
        RegisterHealEvent(trigger,integer)
        ~ trigger - Trigger to be registered, integer - priority
        
        UnregisterHealEvent(trigger)
        ~ trigger - Trigger to be registered
        
        RegisterHealUnitEvent(trigger,unit,integer)
        ~ trigger - Trigger to be registered, unit - healer, integer - priority
        ~ Fires if the unit heals anything.
        
        UnregisterHealUnitEvent(trigger,unit)
        ~ trigger - Trigger to be registered, unit - healer
        
        RegisterUnitHealedEvent(trigger,unit,integer)
        ~ trigger - Trigger to be registered, unit - healed, integer - priority
        ~ Fires if the unit is healed by anything.
        
        UnregisterUnitHealedEvent(trigger,unit)
        ~ trigger - Trigger to be registered, unit - healed
        
        GetHealAmount() -> real
        ~ Get the amount of healing at the moment.
        
        SetHealAmount(real)
        ~ Update the amount of healing.
        
        GetHealType()-> HealType
        ~ Get the type of healing.
        
        GetHealer() -> unit
        ~ Get healer.
        
        GetHealedUnit()-> unit
        ~ Get healed unit.
        
        Requires : A vJass complier
    */
    library Heal
        
        struct HealType extends array
        endstruct
        
        globals
            HealType HEAL_TYPE_NORMAL=1
            private integer HealTypeCount=1
            private real Final=0.0
            private unit Healer=null
            private unit Target=null
            private HealType CurrHealType=1
            private key GenericCallback
            private key HealUnitCallback
            private key UnitHealedCallback
            private integer array TrigType
            private unit array HealedUnitList
            private unit array HealerList
            private trigger array Trig
            private integer array Next
            private integer array Prev
            private integer array Priority
            private integer array IndexStack
            private integer IndexStackMax=0
            private integer IndexMax=0
        endglobals
        
        function CreateHealType takes nothing returns HealType
            set HealTypeCount=HealTypeCount+1
            return HealTypeCount
        endfunction
        
        function GetHealer takes nothing returns unit
            return Healer
        endfunction
        
        function GetHealedUnit takes nothing returns unit
            return Target
        endfunction
        
        function GetHealType takes nothing returns HealType
            return CurrHealType
        endfunction
        
        function GetHealAmount takes nothing returns real
            return Final
        endfunction
        
        function SetHealAmount takes real r returns nothing
            set Final=r
        endfunction
        
        private function FireEvent takes unit healer, unit target, real amount, HealType htype returns nothing
            local unit oldhealer=Healer
            local unit oldtarget=Target
            local real oldamount=Final
            local HealType oldhealtype=CurrHealType
            local integer i=Next[0]
            local boolean ToFire
            set Healer=healer
            set Target=target
            set Final=amount
            set CurrHealType=htype
            loop
            exitwhen i==0
                set ToFire=false
                if TrigType[i]==GenericCallback then
                    set ToFire=true
                elseif TrigType[i]==HealUnitCallback and HealerList[i]==healer then
                    set ToFire=true
                elseif TrigType[i]==UnitHealedCallback and HealedUnitList[i]==target then
                    set ToFire=true
                endif
                if ToFire==true and IsTriggerEnabled(Trig[i]) and TriggerEvaluate(Trig[i]) then
                    call TriggerExecute(Trig[i])
                endif
                set i=Next[i]
            endloop
            if Final>amount then
                call SetWidgetLife(target,GetWidgetLife(target)+(Final-amount))
            elseif Final<amount and Final>=0.0 then
                call SetWidgetLife(target,GetWidgetLife(target)-(amount-Final))
            endif
            set Healer=oldhealer
            set Target=oldtarget
            set Final=oldamount
            set CurrHealType=oldhealtype
            set oldhealer=null
            set oldtarget=null
        endfunction
        
        function HealUnit takes unit healer, unit target, real amount, HealType htype returns nothing
            local real result
            if GetWidgetLife(target)>.405 then
                set result=GetWidgetLife(target)+amount
                call SetWidgetLife(target,result)
                call FireEvent(healer,target,amount,htype)
            endif
        endfunction
        
        function RegisterHealEvent takes trigger trig, integer prio returns nothing
            local integer head
            local integer i
            local boolean isAdded
            if trig!=null then
                if IndexStackMax==0 then
                    set IndexMax=IndexMax+1
                    set i=IndexMax
                else
                    set i=IndexStack[IndexStackMax]
                    set IndexStackMax=IndexStackMax-1
                endif
                set Trig[i]=trig
                set Priority[i]=prio
                set TrigType[i]=GenericCallback
                set isAdded=false
                set head=Next[0]
                loop
                    if prio>Priority[head] then
                        set Next[Prev[head]]=i
                        set Prev[i]=Prev[head]
                        set Next[i]=head
                        set Prev[head]=i
                        set isAdded=true
                        set head=Prev[0]
                    endif
                    set head=Next[head]
                exitwhen head==0
                endloop
                if isAdded==false then
                    set Next[Prev[head]]=i
                    set Prev[i]=Prev[head]
                    set Next[i]=head
                    set Prev[head]=i
                endif
            endif
        endfunction
        
        function UnregisterHealEvent takes trigger trig returns nothing
            local integer i=Next[0]
            loop
            exitwhen i==0
                if Trig[i]==trig and TrigType[i]==GenericCallback then
                    set Next[Prev[i]]=Next[i]
                    set Prev[Next[i]]=Prev[i]
                    set IndexStackMax=IndexStackMax+1                
                    set IndexStack[IndexStackMax]=i
                    return
                endif
                set i=Next[i]
            endloop
        endfunction
        
        function RegisterHealUnitEvent takes trigger trig, unit u, integer prio returns nothing
            local integer head
            local integer i
            local boolean isAdded
            if trig!=null then
                if IndexStackMax==0 then
                    set IndexMax=IndexMax+1
                    set i=IndexMax
                else
                    set i=IndexStack[IndexStackMax]
                    set IndexStackMax=IndexStackMax-1
                endif
                set Trig[i]=trig
                set Priority[i]=prio
                set TrigType[i]=HealUnitCallback
                set HealerList[i]=u
                set isAdded=false
                set head=Next[0]
                loop
                    if prio>Priority[head] then
                        set Next[Prev[head]]=i
                        set Prev[i]=Prev[head]
                        set Next[i]=head
                        set Prev[head]=i
                        set isAdded=true
                        set head=Prev[0]
                        set isAdded=true
                    endif
                    set head=Next[head]
                exitwhen head==0
                endloop
                if isAdded==false then
                    set Next[Prev[head]]=i
                    set Prev[i]=Prev[head]
                    set Next[i]=head
                    set Prev[head]=i
                endif
            endif
        endfunction
        
        function UnregisterHealUnitEvent takes trigger trig, unit u returns nothing
            local integer i=Next[0]
            loop
            exitwhen i==0
                if Trig[i]==trig and HealerList[i]==u then
                    set Next[Prev[i]]=Next[i]
                    set Prev[Next[i]]=Prev[i]
                    set HealerList[i]=null
                    set IndexStackMax=IndexStackMax+1                
                    set IndexStack[IndexStackMax]=i
                    return
                endif
                set i=Next[i]
            endloop
        endfunction
        
        function RegisterUnitHealedEvent takes trigger trig, unit u, integer prio returns nothing
            local integer head
            local integer i
            local boolean isAdded
            if trig!=null then
                if IndexStackMax==0 then
                    set IndexMax=IndexMax+1
                    set i=IndexMax
                else
                    set i=IndexStack[IndexStackMax]
                    set IndexStackMax=IndexStackMax-1
                endif
                set Trig[i]=trig
                set Priority[i]=prio
                set TrigType[i]=UnitHealedCallback
                set HealedUnitList[i]=u
                set isAdded=false
                set head=Next[0]
                loop
                    if prio>Priority[head] then
                        set Next[Prev[head]]=i
                        set Prev[i]=Prev[head]
                        set Next[i]=head
                        set Prev[head]=i
                        set isAdded=true
                        set head=Prev[0]
                        set isAdded=true
                    endif
                    set head=Next[head]
                exitwhen head==0
                endloop
                if isAdded==false then
                    set Next[Prev[head]]=i
                    set Prev[i]=Prev[head]
                    set Next[i]=head
                    set Prev[head]=i
                endif
            endif
        endfunction
        
        function UnregisterUnitHealedEvent takes trigger trig, unit u returns nothing
            local integer i=Next[0]
            loop
            exitwhen i==0
                if Trig[i]==trig and HealedUnitList[i]==u then
                    set Next[Prev[i]]=Next[i]
                    set Prev[Next[i]]=Prev[i]
                    set HealedUnitList[i]=null
                    set IndexStackMax=IndexStackMax+1                
                    set IndexStack[IndexStackMax]=i
                    return
                endif
                set i=Next[i]
            endloop
        endfunction
        
    endlibrary
    [I]
    [/I]

    Heal
    v1.0.0 - Release
    v1.0.1 - Changed Healable from a boolean into an integer stack.
    v1.0.2 - Changed Healable to Heal_Block/Heal_BlockAll.
    v1.0.3 - Fixed bug that caused the system ignore the amount of healing.
    v1.0.4 - Added heal type, it is useful for spell making.
    v1.0.5 - Fixed heal type's bug. Changed Heal_GetTriggerUnit() to Heal_Target().
    v1.0.6 - Removed useless parameter in Heal_BlockAll(). Fixed block healing code.
    v1.0.7 - Moved initializer into module to fix bug (Heal_RegisterEvent did not work in struct initializers) which is caused by jasshelper.
    v1.0.8 - Removed stack, replaced with local variables. A little efficiency gain in getting source/target/amount/type and adding block. Removed the usage of UnitAlive to avoid problem from map optimizer.
    v2.0.0 - Rewrote whole library from scratch. Added prioritized event firing, ability to register heal events for particular unit, and modify amount of healing. Heal can never be done so easily before this!
     

    Attached Files:

    • Heal.w3x
      File size:
      31.9 KB
      Views:
      383
    • Like Like x 2
  2. Sickle

    Sickle New Member

    Ratings:
    +13 / 0 / -0
    You have gone way overboard. You took a simple function that should maybe be attached to an event and turned it into a mess.

    Make it cleaner. Make it faster. Make it sane.

    Edit:

    This is the kind of thing I want to see.
    JASS:
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\\
    //:: Heal                                                                           ::\\
    //::                                                                                ::\\
    //:: by your friendly neighborhood Sickle.                                          ::\\
    //::                                                                                ::\\
    //:: What?                                                                          ::\\
    //::   1. Heal lets you heal units using a certain function.                        ::\\
    //::   2. It is recommended that all healing in your map be done with this function.::\\
    //::                                                                                ::\\
    //:: Why?                                                                           ::\\
    //::   1. Heal fires an event when a unit is healed.                                ::\\
    //::   2. It provides a clean, standard healing function.                           ::\\
    //::   3. Why should I need another reason?                                         ::\\
    //::                                                                                ::\\
    //:: How?                                                                           ::\\
    //::   These functions are available to you.                                        ::\\
    //::                                                                                ::\\
    //::     Heal(unit toHeal, real amount) returns nothing                             ::\\
    //::       This function heals the unit for the given amount and fires an event.    ::\\
    //::                                                                                ::\\
    //::     GetHealedUnit(nothing) returns unit                                        ::\\
    //::       This function returns the unit healed in the event.                      ::\\
    //::                                                                                ::\\
    //::     GetHealAmount(nothing) returns real                                        ::\\
    //::       This function returns how much a unit was healed for.                    ::\\
    //::                                                                                ::\\
    //::     TriggerRegisterHealEvent(trigger whichTrigger) returns nothing             ::\\
    //::       This function causes the trigger to fire when a unit is healed via Heal. ::\\
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\\
    
    library Heal requires Event
    
    globals
        private unit u = null
        private Event e
        private real r = 0
    endglobals
    
    function TriggerRegisterHealEvent takes trigger t returns nothing
        call e.register(t)
    endfunction
    
    function GetHealedUnit takes nothing returns unit
        return u
    endfunction
    
    function GetHealAmount takes nothing returns real
        return r
    endfunction
    
    native UnitAlive takes unit id returns boolean
    
    function Heal takes unit lu, real lr returns nothing
        if not UnitAlive(lu) then
           return
        endif
        set r = lr
        set u = lu
        call SetWidgetLife(lu, GetWidgetLife(lu) + lr)
        call e.fire()
        set r = 0
        set u = null
    endfunction
    
    private struct Sickle extends array
    static method onInit takes nothing returns nothing
        set e = Event.create()
    endmethod
    endstruct
    
    endlibrary


    Edit II: Maybe, just maybe, this.
    JASS:
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\\
    //:: Heal                                                                           ::\\
    //::                                                                                ::\\
    //:: by your friendly neighborhood Sickle.                                          ::\\
    //::                                                                                ::\\
    //:: What?                                                                          ::\\
    //::   1. Heal lets you heal units using a certain function.                        ::\\
    //::   2. It is recommended that all healing in your map be done with this function.::\\
    //::                                                                                ::\\
    //:: Why?                                                                           ::\\
    //::   1. Heal fires an event when a unit is healed.                                ::\\
    //::   2. It provides a clean, standard healing function.                           ::\\
    //::   3. Why should I need another reason?                                         ::\\
    //::                                                                                ::\\
    //:: How?                                                                           ::\\
    //::   These functions are available to you.                                        ::\\
    //::                                                                                ::\\
    //::     Heal(unit toHeal, real amount) returns nothing                             ::\\
    //::       This function heals the unit for the given amount and fires an event.    ::\\
    //::                                                                                ::\\
    //::     HealEx(unit healer, unit toHeal, real amount) returns nothing              ::\\
    //::       This function heals the unit for the given amount and fires an event.    ::\\
    //::                                                                                ::\\
    //::     GetHealedUnit(nothing) returns unit                                        ::\\
    //::       This function returns the unit healed in the event.                      ::\\
    //::                                                                                ::\\
    //::     GetHealer(nothing) returns unit                                            ::\\
    //::       This function returns the healer (if any) in the event.                  ::\\
    //::                                                                                ::\\
    //::     GetHealAmount(nothing) returns real                                        ::\\
    //::       This function returns how much a unit was healed for.                    ::\\
    //::                                                                                ::\\
    //::     TriggerRegisterHealEvent(trigger whichTrigger) returns nothing             ::\\
    //::       This function causes the trigger to fire when a unit is healed via Heal. ::\\
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\\
    
    library Heal requires Event
    
    globals
        private unit u = null
        private unit h = null
        private Event e
        private real r = 0
    endglobals
    
    function TriggerRegisterHealEvent takes trigger t returns nothing
        call e.register(t)
    endfunction
    
    function GetHealedUnit takes nothing returns unit
        return u
    endfunction
    
    function GetHealAmount takes nothing returns real
        return r
    endfunction
    
    function GetHealer takes nothing returns unit
        return h
    endfunction
    
    native UnitAlive takes unit id returns boolean
    
    function Heal takes unit lu, real lr returns nothing
        if not UnitAlive(lu) then
           return
        endif
        set r = lr
        set u = lu
        call SetWidgetLife(lu, GetWidgetLife(lu) + lr)
        call e.fire()
        set r = 0
        set u = null
    endfunction
    
    function HealEx takes unit lh, unit lu, real lr returns nothing
        if not UnitAlive(lu) then
           return
        endif
        set r = lr
        set u = lu
        set h = lh
        call SetWidgetLife(lu, GetWidgetLife(lu) + lr)
        call e.fire()
        set r = 0
        set u = null
        set lh = null
    endfunction
    
    private struct Sickle extends array
    static method onInit takes nothing returns nothing
        set e = Event.create()
    endmethod
    endstruct
    
    endlibrary
     
  3. Narks

    Narks Vastly intelligent whale-like being from the stars

    Ratings:
    +92 / 0 / -0
    ugly interface is ugly
     
  4. Lyerae

    Lyerae I keep popping up on this site from time to time.

    Ratings:
    +105 / 0 / -0
    Yeah, it's pretty ugly.
     
  5. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    He is going to use his version of Heal to crush your map by making the functionality of GetWidgetLife > .405 fails. :p
     
  6. Sickle

    Sickle New Member

    Ratings:
    +13 / 0 / -0
    Here. Let me fix that then. Import this and find and replace GetWidgetLife(u) > .405 with IsUnitAlive(u). Alternatively, I updated my script.

    JASS:
    library IsUnitAlive
    
    native UnitAlive takes unit id returns boolean
    
    function IsUnitAlive takes unit u returns boolean
        return UnitAlive(u)
    endfunction
    
    function IsUnitDead takes unit u returns boolean
        return not UnitAlive(u)
    endfunction
    
    endlibrary
     
  7. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    JASS:
    library HealCrusher initializer Init requires Heal
        
        private function Cond takes nothing returns boolean
            call Heal(GetHealedUnit(),100.)
            return false
        endfunction
        
        private function Init takes nothing returns nothing
              local trigger trig = CreateTrigger()
              call TriggerRegisterHealEvent(trig)
              call TriggerAddCondition(trig,Condition(function Cond))
        endfunction
    endlibrary

    Put this library into a map.
    Make a healing spell with your library, then cast it. See what happen.

    JASS:
    library HealCrusher initializer Init requires Heal
        
        private function Cond takes nothing returns boolean
            call HealUnit(Heal_GetSource(),Heal_GetTriggerUnit(),100.)
            return false
        endfunction
        
        private function Init takes nothing returns nothing
              local trigger trig = CreateTrigger()
              call Heal_RegisterEvent(trig)
              call TriggerAddCondition(trig,Condition(function Cond))
        endfunction
    endlibrary

    Use this with my library. Test the spell. Compare them.
     
  8. Sickle

    Sickle New Member

    Ratings:
    +13 / 0 / -0
    Whoop dee doo. Yours works recursively. Somewhat.

    I could achieve what your system does with a single check. But that would be stupid. Recursive healing is madness.
     
  9. Darthfett

    Darthfett Super Mod

    Ratings:
    +614 / 0 / -0
    Apparently you didn't test it. Yours causes an infinite loop.
     
  10. Sickle

    Sickle New Member

    Ratings:
    +13 / 0 / -0
    Yes. I know.

    His is recursively defined. Somewhat.

    I could add a single check and mine is fixed.
     
  11. Viikuna

    Viikuna No Marlo no game.

    Ratings:
    +265 / 0 / -0
    Somethign like this is indeed useful, since it makes it easy to create for example some buff types that make unit unhealable or something, or some thingies that incerease healing done or whatever.

    But its so simple, that it might be easier for user to make it himself. Dont really know.
     
  12. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    Updated to v1.0.1
     
  13. Weep

    Weep Godspeed to the sound of the pounding

    Ratings:
    +400 / 0 / -0
    Uh, what? Negative target damage only works with spell-type damage (otherwise is 0) and can be detected by EVENT_UNIT_DAMAGED just fine.
     
  14. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    Uh, what? Negative target damage only works with spell-type damage (otherwise is 0) and can be detected by EVENT_UNIT_DAMAGED just fine.
    Oh, ya. Forget to update it, it works just fine.

    However, some damage detection systems do GetEventDamage() > 0. filtration before executing triggers.
     
  15. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Post in the threads of such systems and complain. I don't think we have any at TheHelper.
    JASS:
    Heal_Enable(unit, flag)

    Heal_Bock(amount) makes much more sense, because it can be totally conditional.
     
  16. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    Heal_Bock(amount) makes much more sense, because it can be totally conditional.
    Okay. :)
     
  17. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    v1.0.2, added Heal_Block and Heal_BlockAll.
     
  18. Advice D.

    Advice D. New Member

    Ratings:
    +11 / 0 / -0
    Just a few things I noticed:
    Should be "HealUnit"?
    This ends up fully healing regardless of the amount used in the function call. Add a hp check, perhaps?
    EDIT: Just tested it without the maxlife-life line and it worked fine. Is there any reason for it to be in at all?
     
    • Like Like x 1
  19. XeNiM666

    XeNiM666 I lurk for pizza

    Ratings:
    +138 / 1 / -0
    Hmmm. Nice system. Just what I needed for a spell... XD

    May I suggest a "Heal over time" function?
     
  20. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    @Advice D.
    Should be "HealUnit"?
    That was a typo. >< My bad.

    This ends up fully healing regardless of the amount used in the function call. Add a hp check, perhaps?
    EDIT: Just tested it without the maxlife-life line and it worked fine. Is there any reason for it to be in at all?

    I will look into it. :p

    @XeNiM666
    3 flavors here for you to choose. :)

    JASS:
    /////////////////////////////////////////////////////////////
    //
    //                  Timed Healing (Blue)
    //                        v1.0.0
    //  
    //                  An add-on for Heal.
    //
    //     It enables "healing over time" can be done easily.
    //
    //  Functions provided :
    //  TimedHealUnit(healer,target,amount,period,duration,effect)
    //
    //  Info :
    //  Blue   : Uses KT2
    //  Red    : Uses T32 (For speed freaks)
    //  Purple : Uses TimerUtils (For those who does not like KT2)
    //
    //  Blue and Purple flavor are able to deal with any period.
    //  Red flavor is only able to heal every .03125 (T32's period)
    //////////////////////////////////////////////////////////////
    library_once TimedHealing requires Heal, KT
    
        private struct Data
            unit healer
            unit target
            real amount
            real tick
            effect eff
            
            method onDestroy takes nothing returns nothing
                call DestroyEffect(.eff)
                set .eff = null
            endmethod
            
        endstruct
        
        private function Handler takes nothing returns boolean
            local Data d = KT_GetData()
            if d.tick > 0 then
                set d.tick = d.tick - 1
                if HealUnit(d.healer,d.target,d.amount) == false then
                    call d.destroy()
                    return true
                endif
                return false
            endif
            call d.destroy()
            return true
        endfunction
    
        function TimedHealUnit takes unit healer, unit target, real totalAmount, real period, real duration, effect eff returns nothing
            local Data d = Data.create()
            set d.healer = healer
            set d.target = target
            set d.tick = R2I(duration / period)
            set d.amount = totalAmount / period
            set d.eff = eff
            call KT_Add(function Handler,d,period)
        endfunction
    endlibrary


    JASS:
    /////////////////////////////////////////////////////////////
    //
    //                  Timed Healing (Red)
    //                        v1.0.0
    //  
    //                  An add-on for Heal.
    //
    //     It enables "healing over time" can be done easily.
    //
    //  Functions provided :
    //  TimedHealUnit(healer,target,amount,period,duration,effect)
    //
    //  Info :
    //  Blue   : Uses KT2
    //  Red    : Uses T32 (For speed freaks)
    //  Purple : Uses TimerUtils (For those who does not like KT2)
    //
    //  Blue and Purple flavor are able to deal with any period.
    //  Red flavor is only able to heal every .03125 (T32's period)
    //////////////////////////////////////////////////////////////
    library_once TimedHealing requires Heal, T32
    
        private struct Data
            unit healer
            unit target
            real amount
            real tick
            effect eff
            
            method onDestroy takes nothing returns nothing
                call DestroyEffect(.eff)
                set .eff = null
            endmethod
            
            method periodic takes nothing returns nothing
                if .tick >= T32_Tick then
                    if HealUnit(.healer,.target,.amount) == false then
                        call .destroy()
                        call .stopPeriodic()
                    endif
                else
                    call .destroy()
                    call .stopPeriodic()
                endif
            endmethod
            
            implement T32x
            
            static method add takes unit healer, unit target, real totalAmount, real duration, effect eff returns nothing
                local thistype this  = thistype.create()
                set .healer = healer
                set .target = target
                set .tick = T32_Tick + R2I(duration / T32_PERIOD)
                set .amount = totalAmount / T32_PERIOD
                set .eff = eff
                call .startPeriodic()
            endmethod
        endstruct
    
        function TimedHealUnit takes unit healer, unit target, real totalAmount, real duration, effect eff returns nothing
            call Data.add(healer,target,totalAmount,duration,eff)
        endfunction
    endlibrary


    JASS:
    /////////////////////////////////////////////////////////////
    //
    //                  Timed Healing (Purple)
    //                        v1.0.0
    //  
    //                  An add-on for Heal.
    //
    //     It enables "healing over time" can be done easily.
    //
    //  Functions provided :
    //  TimedHealUnit(healer,target,amount,period,duration,effect)
    //
    //  Info :
    //  Blue   : Uses KT2
    //  Red    : Uses T32 (For speed freaks)
    //  Purple : Uses TimerUtils (For those who does not like KT2)
    //
    //  Blue and Purple flavor are able to deal with any period.
    //  Red flavor is only able to heal every .03125 (T32's period)
    //////////////////////////////////////////////////////////////
    library_once TimedHealing requires Heal, TimerUtils
    
        private struct Data
            unit healer
            unit target
            real amount
            real tick
            effect eff
            timer t
            
            method onDestroy takes nothing returns nothing
                call ReleaseTimer(.t)
                call DestroyEffect(.eff)
                set .eff = null
            endmethod
            
        endstruct
        
        private function Handler takes nothing returns boolean
            local Data d = GetTimerData(GetExpiredTimer())
            if d.tick > 0 then
                set d.tick = d.tick - 1
                if HealUnit(d.healer,d.target,d.amount) == false then
                    call d.destroy()
                endif
                return false
            endif
            call d.destroy()
            return true
        endfunction
    
        function TimedHealUnit takes unit healer, unit target, real totalAmount, real period, real duration, effect eff returns nothing
            local Data d = Data.create()
            set d.healer = healer
            set d.target = target
            set d.tick = R2I(duration / period)
            set d.amount = totalAmount / period
            set d.eff = eff
            set d.t = NewTimer()
            call SetTimerData(d.t,d)
            call TimerStart(d.t,period,true,function Handler)
        endfunction
    endlibrary


    Update :
    v1.0.3 released. Credits to Advice D. for finding out the bug.
     

Share This Page