• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Detecting healing ( amount) and modifying it ?

Status
Not open for further replies.

Ardenian

A

Ardenian

Systems like PDD or Ruler's Damage Modifications system allow to modify spell damage before it is dealt, don't they ?

How is healing detected in the the PDD ? Is it possible to also modify it before it is applied ? Or would one have to trigger it and modify it before ?
 
Level 12
Joined
May 22, 2015
Messages
1,051
I don't know if you can detect healing the same way. You could maybe make healing spells damage units (dealing 0 damage or something) and then use the damage detection system to heal the units the correct amount.

On my map, I am triggering all healing effects, including health regeneration, so that I can control effects how I want to. Note that I am only triggering hero health regeneration, since doing all units would probably be very taxing.
 

Ardenian

A

Ardenian

Hm, so I would add 'spell damage' of 0, detecting the event and set the PDD_DamageAmount to a negative value, wouldn't I ?
 
Level 12
Joined
May 22, 2015
Messages
1,051
Yes, probably. I haven't used any damage detection systems. You need to make sure that the negative value will indeed result in a heal. Keep in mind that this would trigger other on-damage effects, which may be unwanted.

I am not sure if there are healing systems out there, but I have a super basic system for my map. It basically is just a function that I run when I want a unit to heal. I have a trigger that I add to to make new effects. The main problem is I have to find everything in my map that causes healing and make sure it is triggered to use this function.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
Using a triggered heal for abilities and items would be easier than detecting w3 heal, because there is so much things can go wrong.
 

Ardenian

A

Ardenian

Hm, seems triggered one is the best solution.
Thank you guys!
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
You are unable to modify it, but here is something that I just made:
JASS:
library hcdSystem
    
    globals
        
        real            udg_HCD_HEALTH_REGEN_MAX                        = 1
        
        boolexpr        udg_HCD_HealthChanged
        real array      udg_HCD_OldHealth
        unit array      udg_HCD_Units
        timer array     udg_HCD_Timers
        trigger array   udg_HCD_Triggers
        
    endglobals
    
    function ChechDeadOrRemoved takes nothing returns nothing
        local integer id = GetTimerData(GetExpiredTimer())
        
        if IsUnitType(udg_HCD_Units[id], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_HCD_Units[id]) == 0 then
            call ReleaseTimer(udg_HCD_Timers[id])
            call DestroyTrigger(udg_HCD_Triggers[unitId])
            set udg_HCD_Units[id] = null
            set udg_HCD_Timers[id] = null
            set udg_HCD_Triggers[unitId] = null
        endif
    endfunction
    
    function AddUnitHealthChangeDetection takes unit whichUnit, real checkDuration returns nothing
        local real health = GetWidgetLife(whichUnit)
        local integer unitId = GetUnitUserData(whichUnit)
        set udg_HCD_Triggers[unitId] = CreateTrigger()
        call TriggerRegisterUnitStateEvent(udg_HCD_Triggers[unitId], whichUnit, UNIT_STATE_LIFE, GREATER_THAN, health +0.0625)
        call TriggerRegisterUnitStateEvent(udg_HCD_Triggers[unitId], whichUnit, UNIT_STATE_LIFE, LESS_THAN, health -0.0625)
        call TriggerAddCondition(udg_HCD_Triggers[unitId], udg_HCD_HealthChanged)
        
        set udg_HCD_Units[unitId] = whichUnit
        set udg_HCD_OldHealth[unitId] = health
        
        if checkDuration > 0. then
            if udg_HCD_Timers[unitId] == null then
                set udg_HCD_Timers[unitId] = NewTimerEx(unitId)
            endif
            call TimerStart(udg_HCD_Timers[unitId], checkDuration, tue, function ChechDeadOrRemoved)
        endif
    endfunction
    
    function HealthChanged takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local real health = GetWidgetLife(u)
        local real oldHealth = udg_HCD_OldHealth[GetUnitUserData(u)]
        local real difference = health - oldHealth
        call DestroyTrigger(GetTriggeringTrigger())
        call AddUnitHealthChangeDetection(u, 0)
        
        if difference < udg_HCD_HEALTH_REGEN_MAX and difference > -udg_HCD_HEALTH_REGEN_MAX then
            set u = null
            return false
        endif
        
        if difference < 0 then
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetUnitName(u) + " is damaged for " + R2S(oldHealth-health) + " damage.")
        else
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, GetUnitName(u) + " is health for " + R2S(health-oldHealth) + " health.")
        endif
        
        set u = null
        return false
    endfunction
    
endlibrary

function HealthChangeUnitRegion takes nothing returns boolean
    call AddUnitHealthChangeDetection(GetFilterUnit(), 60)
    return false
endfunction

function Init_HealthChangeDetection takes nothing returns nothing
    local unit FoG
    local group g
    local region r = CreateRegion()
    local rect r2 = GetWorldBounds()
    
    call RegionAddRect(r, r2)
    call TriggerRegisterEnterRegion(CreateTrigger(), r, Filter(function HealthChangeUnitRegion))
    call RemoveRect(r2)
    
    set g = CreateGroup()
    call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
    loop
        set FoG = FirstOfGroup(g)
        exitwhen FoG == null
        call GroupRemoveUnit(g, FoG)
        
        call AddUnitHealthChangeDetection(FoG, 60)
    endloop
    set g = null
    
    call DestroyTimer(GetExpiredTimer())
endfunction


//===========================================================================
function InitTrig_Health_Change_Detection takes nothing returns nothing
    call TimerStart(CreateTimer(), 0, false, function Init_HealthChangeDetection)
    
    set udg_HCD_HealthChanged = Filter(function HealthChanged)
endfunction

It uses Unit Indexer and TimerUtils (which are both definately worth implementing in your map).

What this system does is detect when a unit's life is changed.
You can make a global real variable to make an event.

You could also rewrite this to add the units to a group and have only one timer, but this should work as well without problems.

Note that this is not thoroughly tested so it might bug out some time and you are also unable to modify the values as they are already applied.
Triggering all heals in your map is better but this could work for a few workarounds.
 

Ardenian

A

Ardenian

So I could use this and get the value of the health regeneration, adding via trigger the required amount of the percentage additional health regeneration ?
 

Ardenian

A

Ardenian

Hupa, confused it with the other thread.

So, this would get me the healing value ? Then I would have to add influences via trigger ? For example, healed for 100 health, get the value and add ( if 10% more heal efficiency) 10 via trigger ?

Hm, I think triggering it from the very beginning is easier for me, but thank you!
 
Status
Not open for further replies.
Top