• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Heal Event for GUI, version 1.1.1.1

This system allows you to detect when a unit is healed, and for how much, if the heal is greater than HEAL_THRESHOLD (by default, it's set for 5.00).

Uses minimal custom script (pretty sure just 2 lines to check for Locust) so it should be a lot easier to understand than some of my other systems. To achieve this, I split each task into its own trigger, so - when importing - you'll want to copy the Heal Event trigger category for simplicity.

Game - HealEvent Becomes Equal to 1.00 - the event to use to detect a heal
Game - HealEvent Becomes Equal to 0.50 - the event to use to detect regeneration.
heal_amount - the amount healed
heal_target - the unit who was healed
heal_source - the source of the healing can be detected if you first triggered the heal using the Heal Unit <gen> trigger.

To heal a unit using this system, do the following:

Set NextHealSource = the one doing the healing
Set NextHealTarget = the unit being healed
Set NextHealAmount = the amount to be healed
Trigger - Run Heal Unit <gen> (ignoring conditions)

Requirement: GUI Unit Indexer

Optional Requirements: Damage Engine 3.5 and GUI Unit Event


  • Heal Configuration
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Configurable --------
      • Set HEAL_THRESHOLD = 5.00
      • Set HEAL_CHECK_INTERVAL = 0.05
      • -------- With these current values, a unit with 100 HP regen/sec. could constantly fire off the heal event. --------
      • -------- --------
      • Countdown Timer - Start heal_timer as a Repeating timer that will expire in HEAL_CHECK_INTERVAL seconds
      • -------- --------
      • Set REGEN_STRENGTH_VALUE = 0.05
      • Set REGEN_THRESHOLD = 5.00
      • Set REGEN_EVENT_INTERVAL = 1.00
  • Heal Unit
    • Events
    • Conditions
    • Actions
      • Custom script: local integer id = udg_heal_integer
      • Custom script: local real amount = udg_heal_amount
      • Custom script: local unit source
      • Set heal_target = NextHealTarget
      • Set heal_integer = (Custom value of heal_target)
      • Set heal_life = (Life of heal_target)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • heal_check Equal to True
        • Then - Actions
          • Set heal_check = False
          • Set heal_amount = ((heal_life - ((heal_regen[heal_integer] x (Elapsed time for heal_timer)) / HEAL_CHECK_INTERVAL)) - heal_lastLife[heal_integer])
          • -------- A potential heal still has to exceed HEAL_THRESHOLD --------
          • Set heal_diff = HEAL_THRESHOLD
        • Else - Actions
          • Unit - Set life of heal_target to ((Life of heal_target) + NextHealAmount)
          • Set heal_amount = ((Life of heal_target) - heal_life)
          • -------- If the heal ended up being less than 1.00, ignore the event --------
          • Set heal_diff = 1.00
      • -------- Don't run the event if there was little to nothing to heal --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • heal_amount Greater than or equal to heal_diff
        • Then - Actions
          • -------- Don't let the event for this heal run more than once --------
          • Set heal_lastLife[heal_integer] = (heal_lastLife[heal_integer] + heal_amount)
          • -------- Set the source, if one was assigned --------
          • Custom script: set source = udg_heal_source
          • Set heal_source = NextHealSource
          • -------- Fire the event --------
          • Set HealEvent = 0.00
          • Set HealEvent = 1.00
          • Set HealEvent = 0.00
          • -------- Reset the source, if a previous one was assigned --------
          • Custom script: set udg_heal_source = source
          • Custom script: set source = null
        • Else - Actions
      • -------- Reset variables to their previous states --------
      • Custom script: set udg_heal_amount = amount
      • Custom script: set udg_heal_integer = id
      • Set heal_target = UDexUnits[heal_integer]
      • Set NextHealAmount = 0.00
      • Set NextHealSource = No unit
      • Set NextHealTarget = No unit
  • Heal Check Loop
    • Events
      • Time - heal_timer expires
    • Conditions
    • Actions
      • Set heal_exitwhen = (heal_count - 1)
      • For each (Integer heal_integer) from 0 to heal_exitwhen, do (Actions)
        • Loop - Actions
          • Set heal_integer = heal_indices[heal_integer]
          • -------- --------
          • Set heal_target = UDexUnits[heal_integer]
          • Set heal_life = (Life of heal_target)
          • Set heal_diff = (heal_life - heal_lastLife[heal_integer])
          • Set heal_lastLife[heal_integer] = heal_life
          • -------- --------
          • Set heal_amount = (heal_diff - (Max(0.00, heal_regen[heal_integer])))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • heal_amount Greater than or equal to HEAL_THRESHOLD
            • Then - Actions
              • Set HealEvent = 1.00
              • Set HealEvent = 0.00
            • Else - Actions
              • Set heal_regen[heal_integer] = ((heal_regen[heal_integer] + heal_diff) x 0.50)
              • -------- The next section was added in version 1.1.0.0 to introduce regeneration events. --------
              • Set regen_buildup[heal_integer] = (regen_buildup[heal_integer] + heal_diff)
              • Set regen_timeleft[heal_integer] = (regen_timeleft[heal_integer] - HEAL_CHECK_INTERVAL)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • regen_timeleft[heal_integer] Less than or equal to 0.00
                • Then - Actions
                  • -------- Reset the regen event clock --------
                  • Set regen_timeleft[heal_integer] = REGEN_EVENT_INTERVAL
                  • -------- Analyze the amount regenerated in the past REGEN_CHECK_INTERVAL --------
                  • Set heal_amount = regen_buildup[heal_integer]
                  • Set regen_buildup[heal_integer] = 0.00
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (heal_target is A Hero) Equal to True
                    • Then - Actions
                      • -------- Don't spam the event due to regeneration caused by hero attributes --------
                      • Set heal_diff = (heal_amount - ((Real((Strength of heal_target (Include bonuses)))) x REGEN_STRENGTH_VALUE))
                    • Else - Actions
                      • Set heal_diff = heal_amount
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • heal_diff Greater than or equal to REGEN_THRESHOLD
                    • Then - Actions
                      • Set HealEvent = 0.50
                      • Set HealEvent = 0.00
                    • Else - Actions
                • Else - Actions
          • -------- --------
          • Set heal_integer = heal_indexRef[heal_integer]
  • Heal Adjust On Damage
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
    • Actions
      • Set NextHealTarget = DamageEventTarget
      • Set heal_check = True
      • Trigger - Run Heal Unit <gen> (ignoring conditions)
  • Heal Adjust After Damage
    • Events
      • Game - AfterDamageEvent becomes Equal to 1.00
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DamageEventAmount Greater than 0.00
        • Then - Actions
          • Set TempInteger = (Custom value of DamageEventTarget)
          • Set heal_lastLife[TempInteger] = ((Life of DamageEventTarget) - (heal_regen[TempInteger] x ((Elapsed time for heal_timer) / HEAL_CHECK_INTERVAL)))
        • Else - Actions
          • Set NextHealTarget = DamageEventTarget
          • Set heal_check = True
          • Trigger - Run Heal Unit <gen> (ignoring conditions)
  • Heal Add Unit
    • Events
      • Game - UnitIndexEvent becomes Equal to 1.00
      • Game - DeathEvent becomes Equal to 2.00
    • Conditions
      • heal_inSys[UDex] Equal to False
      • (UDexUnits[UDex] is Mechanical) Equal to False
      • (Default movement speed of UDexUnits[UDex]) Not equal to 0.00
    • Actions
      • Custom script: if GetUnitAbilityLevel(udg_UDexUnits[udg_UDex], 'Aloc') > 0 then
      • Skip remaining actions
      • Custom script: endif
      • Set heal_inSys[UDex] = True
      • Set heal_indices[heal_count] = UDex
      • Set heal_indexRef[UDex] = heal_count
      • Set heal_lastLife[UDex] = (Life of UDexUnits[UDex])
      • Set regen_timeleft[UDex] = REGEN_EVENT_INTERVAL
      • Set regen_buildup[UDex] = 0.00
      • Set heal_count = (heal_count + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • heal_count Equal to 1
        • Then - Actions
          • Trigger - Turn on Heal Check Loop <gen>
        • Else - Actions
  • Heal Remove Unit
    • Events
      • Game - DeathEvent becomes Equal to 0.50
      • Game - DeathEvent becomes Equal to 1.00
      • Game - DeathEvent becomes Equal to 3.00
      • Game - UnitIndexEvent becomes Equal to 2.00
    • Conditions
      • heal_inSys[UDex] Equal to True
    • Actions
      • Set heal_inSys[UDex] = False
      • Set heal_count = (heal_count - 1)
      • Set heal_indices[heal_indexRef[UDex]] = heal_indices[heal_count]
      • Set heal_indexRef[heal_indices[heal_count]] = heal_indexRef[UDex]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • heal_count Equal to 0
        • Then - Actions
          • Trigger - Turn off Heal Check Loop <gen>
        • Else - Actions


Keywords:
heal, healing, heal event, EVENT_PLAYER_UNIT_HEALED
Contents

Just another Warcraft III map (Map)

Reviews
17:20, 17th Oct 2015 This resource has been Approved by BPower. Criticism: Very useful, when you need to detect heal events in your map. As expected very good and polished GUI coding.
Level 1
Joined
Dec 15, 2012
Messages
4
Hey, first of all let me say sorry for being so ignorant and stupid with everything related to triggers.
I have been trying to use your system to make a trigger that detects if the casting hero has an item that is supposed to increase "spell power" and then increase the amount healed by x% when they cast a heal of any sort.
I managed to easily get this to work with your damage engine when it comes to increasing spell damage, however I just can't get this to work for healing, I've tried everything I can think of and it just doesn't work. There is probably something really simple that I'm missing.
Could you explain how I'm supposed to make that trigger work? Thank you!

These are some of the things I managed to break while trying to make it work:
Without checking if the casting hero has the needed item I managed to make every heal heal for a ridiculous amount even though it was only supposed to be 1% increase.
Without checking if the casting hero has the needed item I managed to make every heal heal for only 1% of the original even though it was supposed to be 1% increase.
Without checking if the casting hero has the needed item I managed to make the game crash every time I cast a heal.
While checking if the casting hero has the needed item I managed to make nothing happen in many different ways.

Also sorry for not posting any of my triggers that I tried to do, there just was too many variations that I tried for me to even remember them all.

EDIT: The heals I've been trying to make it work with are just the regular WC3 non triggered heals. Is this my main problem? Do I need to use a trigger for every heal if I want to increase the amount healed when the healer has a certain item?
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Hey, first of all let me say sorry for being so ignorant and stupid with everything related to triggers.
I have been trying to use your system to make a trigger that detects if the casting hero has an item that is supposed to increase "spell power" and then increase the amount healed by x% when they cast a heal of any sort.
I managed to easily get this to work with your damage engine when it comes to increasing spell damage, however I just can't get this to work for healing, I've tried everything I can think of and it just doesn't work. There is probably something really simple that I'm missing.
Could you explain how I'm supposed to make that trigger work? Thank you!

These are some of the things I managed to break while trying to make it work:
Without checking if the casting hero has the needed item I managed to make every heal heal for a ridiculous amount even though it was only supposed to be 1% increase.
Without checking if the casting hero has the needed item I managed to make every heal heal for only 1% of the original even though it was supposed to be 1% increase.
Without checking if the casting hero has the needed item I managed to make the game crash every time I cast a heal.
While checking if the casting hero has the needed item I managed to make nothing happen in many different ways.

Also sorry for not posting any of my triggers that I tried to do, there just was too many variations that I tried for me to even remember them all.

EDIT: The heals I've been trying to make it work with are just the regular WC3 non triggered heals. Is this my main problem? Do I need to use a trigger for every heal if I want to increase the amount healed when the healer has a certain item?
The main issue here is that you can't get the healing source unit unless you trigger the heal.
 
Level 1
Joined
Dec 15, 2012
Messages
4
The main issue here is that you can't get the healing source unit unless you trigger the heal.
Ok, thank you. I mean your reply wasn't exactly "this is how to do what you want" but I think I managed to make something that works somewhat in a way that I want. I'm just not 100% happy with what I made, but I guess it'll have to do.
 
Level 3
Joined
May 17, 2019
Messages
45
Hey

I am using this with the last version of Damage Engine.

It works good at the beginning but after a few minutes playing the healing don't pop up anymore.

Any idea to fix it ?

EDIT: NVM, found out the issue. Some other mod im using is not using Unit Indexer and conflicts with it. I then modified the other mod so it uses Unit Indexer custom values instead of assigning random custom values. So this healing mod was not the issue.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Hi Bribe, do all your system cost some performance? I was thinking that damage engine, unit indexer and now this track all the time what is happening.. wouldn't this slow down the game?
You can definitely use them all together. Big maps with lots of units will perform worse of course, but how many frames per second are we talking about?

Heal event has a timer whose timeout can be edited. Damage Engine has ways to tighten up the code to free up resources in case you don't use everything
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
I personally don't feel any FPS loss yet - but my map contains only a few units still as I want loading times to be small to test better. But OK, will use all together!

Another question/problem though:
I'm using this system to have the nice floating text when a unit is healed. But after installing it I see some random values floating around. I did some testing and the number is always based on the HP of the unit being attacked / summoned. And from what I can tell only for units who have a movement speed of 0 and no locust. Is this a bug...?

***

Here some examples:


The 5000 are coming from my "Damage Tester" unit with 5k life, when it's attacked for the first time:

6289npL.jpg


The 15'000 number is coming from my "Dummy (No Locust)" unit, which has 15k life and no locust (I'm using it to cast Acid Bomb on itself):
Kb2qWKb.jpg



I'm attaching the map so you can verify yourself in-game if you want.
 

Attachments

  • Land of Legends v0.1.20.w3m
    56.3 MB · Views: 57

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
I personally don't feel any FPS loss yet - but my map contains only a few units still as I want loading times to be small to test better. But OK, will use all together!

Another question/problem though:
I'm using this system to have the nice floating text when a unit is healed. But after installing it I see some random values floating around. I did some testing and the number is always based on the HP of the unit being attacked / summoned. And from what I can tell only for units who have a movement speed of 0 and no locust. Is this a bug...?

***

Here some examples:


The 5000 are coming from my "Damage Tester" unit with 5k life, when it's attacked for the first time:

6289npL.jpg


The 15'000 number is coming from my "Dummy (No Locust)" unit, which has 15k life and no locust (I'm using it to cast Acid Bomb on itself):
Kb2qWKb.jpg



I'm attaching the map so you can verify yourself in-game if you want.

Units with no movement speed or who have the locust ability are not indexed by the system.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Are you saying this happens because of the dummy units?

Because currently that's exactly what I'm experiencing (dummy units produce the green healing text). But how can I fix it? I cannot just remove all locust from the dummy units...?
You need to modify the conditions for the "Heal Add Unit" trigger

Also the following:

GetUnitAbilityLevel(udg_UDexUnits[udg_UDex], 'Aloc')

You can edit those 3 lines of custom script out if you want Locusts to be ignored.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Thanks! That fixed it. But why would you add the condition that units with 0 movement speed or locust create a healing tag?

Because it's an example :grin:

In most cases you don't need buildings or locust units to be able to be checked for heals, so to benefit performance I have simply removed it from happening (by default)
 
Level 12
Joined
May 16, 2020
Messages
660
Wait but then it fixed itself for the "wrong reason"!

I never healed the locust units. I just create them. And as soon they get created, the system shows a healing text above the locust unit.

Similarly to units with 0 movement speed. I never healed them in the previous image. I only attacked them via lightning bolt and then the healing text above all unit hit showed up.
 
Level 12
Joined
May 16, 2020
Messages
660
Sorry for the double post - but this really makes no sense to me.

You say locust and buildings should NOT creating a healing tag in the default setting. But for me they DO.
Only after removing the previous lines, locust units to NOT create a heal tag...??
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Upon further inspection it should be:

heal_inSys[(Custom value of DamageEventTarget)] Equal to True

I am actually surprised that it works in your case, but I'm glad it does. Maybe you are running an older version of Damage Engine that uses UDex?

At any rate, my plan is to release a GUI+vJass version of this equipped with the latest Damage Engine which will allow such units to be filtered out more efficiently. I will make sure the GUI-only version is untouched for legacy purposes.
 
Level 12
Joined
May 16, 2020
Messages
660
Mmm I'm using Damage Engine 5.7.0.1 - not the latest, but it's quite new I believe.

And I didn't find any bugs so far; It correcly shows the healing tag with Healing Wave for example and does not show it anymore when I create a locust unit / when I attack enemy buildings / attack units with 0 movements speed.

Is there btw a code I can use to prevent a healing tag in dedicated situations in similar fashion to this?:
  • Set VariableSet NextDamageType = DamageTypeCode
Background: My creeps in my map should gradually get more HP when respawning. The following trigger creates a healing tag, as adjusting the HP from 780 to 780*1.05 basically counts as "heal":
  • Unit - Set Max HP of Creep_UnitTemp to (780 x (Integer(Creep_Multiplier)))
  • Unit - Set Unit: Creep_UnitTemp's Real Field: Hit Points ('uhpc') to Value: (780.00 x Creep_Multiplier)
I want to hide the healing tag in these very specific instances if possible.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
When I made Heal Event the only way to change a unit's max HP was to give it an item like "Periapt of Vitality", which does heal the unit so it was passable to allow it to register with the system.

With this new native, I should edit this system in order to allow it to filter out max HP changes from registering as healing.
 
Level 12
Joined
May 16, 2020
Messages
660
Thanks - that would be very cool!

Just so you're aware: Max HP changes do not register as healing. When you increase the Max HP, the current HP level stays the same. So for example Unit has 1000/1000 HP --> you increase the Max HP to 1200 ---> you end up with 1000/1200 HP.

Only after "increasing" the Current HP to Max HP it counts as heal.
 
Level 12
Joined
May 16, 2020
Messages
660
Hi Bribe, can I use this system to "reduce" the heal received?

I want to implement some kind of healing reduction spell (reducing healing by 50%), but didn't find a "set heal amount to XXX" similarly to "set damage amount to YYY".

Edit: I tried using the "Item Attack Heal Reduction Bonus" (a new ability which Blizzard implemented), but the system as of now doesn't interact with the reduction. If you set:

Set NextHealSource = the one doing the healing
Set NextHealTarget = the unit being healed
Set NextHealAmount = the amount to be healed
Trigger - Run Heal Unit <gen> (ignoring conditions)

... the system ignores the reduction.
 
Last edited:
Level 12
Joined
Mar 13, 2020
Messages
421
@Bribe Hi Bribe.. is there a way without using your method heal unit gen, to detect who is the heal_source (Unit) i ask because I need it for a Heal Meter... the Damage Meter works showing the Damage done by each player with your Damage Engine... it would be nice if you can anwser my question

Sorry for my Bad English
Greetings from Stuttgart (You are Amazing)
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
@Bribe Hi Bribe.. is there a way without using your method heal unit gen, to detect who is the heal_source (Unit) i ask because I need it for a Heal Meter... the Damage Meter works showing the Damage done by each player with your Damage Engine... it would be nice if you can anwser my question

Sorry for my Bad English
Greetings from Stuttgart (You are Amazing)
Hi Pwnica,

sorry, but WC3 lacks the innate ability to detect the healing source unit. I advise triggering everything using the Heal Unit trigger if you need to detect the source.
 
Level 12
Joined
Mar 13, 2020
Messages
421
Hi Pwnica,

sorry, but WC3 lacks the innate ability to detect the healing source unit. I advise triggering everything using the Heal Unit trigger if you need to detect the source.

Hi Bribe again I have 2 Questions

1. is it Possible to Detect the Player Healing?

2. With Unit Gen is it Possible to Create Aoe Heals like with IntegerA ?

to recreate a Healing Wave?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Hi Bribe again I have 2 Questions

1. is it Possible to Detect the Player Healing?

2. With Unit Gen is it Possible to Create Aoe Heals like with IntegerA ?

to recreate a Healing Wave?

You would have to trigger each bounce. Things such as "Healing Spray" can have a negative heal amount and can damage its targets, and you could theoretically use Damage Engine to detect that and convert it into a heal (Thereby knowing the heal source) but I think abilities like "heal" and "healing wave" would not trigger damage events. I've not tested it as thoroughly as possible, so you are welcome to do your own testing on what you might be able to get away with with "negative" damaging heals.
 
Level 12
Joined
May 16, 2020
Messages
660
Hi Bribe, I have a weird issue, which I narrowed down to 2 triggers from this system.

The problem is that in some cases when dealing damage, a heal text tag is created on the enemy unit. However, the healing tag should not have been created, as when checking 2 enemies that are hit by damage (one of them creating a healing tag, and the other doesn't), both have the same HP after the damage.

I couldn't exactly narrow down why some situations cause a healing tag to appear and others don't, but the 2 triggers that cause it are
  • Heal Adjust On Damage
  • Heal Adjust After Damage
When I turn these two triggers off, the wrong healing tag no longer appear.

Do you have an explanation for this?
And what do I "miss out" if I turn off these two triggers?


***

If you want to see what I'm talking about, I attached my map. Just select the Pig Hero at the top lane (Bristleback), and press Q when enemies start appearing. You should soon also see some random healing text tag appear on enemies when they are damaged by the Q ability.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Just putting down my work-in-progress for Lua Heal Event. It's only the core structure at the moment. I wanted to see if I could detect negative healing via a damage event, but it's only triggered by Healing Wave, Healing Spray and Death Coil (yet Death Coil doesn't detect correctly with enemies after doing that).

Lua:
if Timed then --Lua HealEvent version 0.1.1.0
 
local _HEAL_INTERVAL    = 0.05
local _HEAL_THRESHOLD   = 5.00
local _REGEN_INTERVAL   = 1.00
local _REGEN_THRESHOLD  = 5.00
local _STR_BONUS        = 0.05
 
if OnTrigInit then --change to "if false then" if you don't use the GUI initializer
    OnTrigInit(function()
        local func = Trig_Heal_Configuration_Actions
        if func then
            func()
            _REGEN_INTERVAL = udg_REGEN_EVENT_INTERVAL
            _HEAL_THRESHOLD = udg_HEAL_THRESHOLD
            _HEAL_INTERVAL  = udg_HEAL_CHECK_INTERVAL
            _REGEN_THRESHOLD= udg_REGEN_THRESHOLD
            _STR_BONUS      = udg_REGEN_STRENGTH_VALUE
        end
    end)
end
 
if GlobalRemap then
    GlobalRemap("udg_heal_target", function() return Event.args[1] end)
    GlobalRemap("udg_heal_amount", function() return Event.args[2] end)
end
 
local inSys = {}
 
Event.heal = Event.create("udg_HealEvent", EQUAL)
Event.regen = Event.create("udg_HealEvent", LESS_THAN)
 
--===========================================================================
---Add a unit to the heal checking system
---@param index UnitEvent
local function AddUnit(index)
    local u = index.unit
    if not inSys[index] and not IsUnitType(u, UNIT_TYPE_MECHANICAL) and GetUnitDefaultMoveSpeed(u) ~= 0.00 and GetUnitAbilityLevel(u, 'Aloc') > 0 then
        inSys[index] = true
        local lastLife = GetWidgetLife(u)
        local maxLife = GetUnitState(u, UNIT_STATE_MAX_LIFE)
        local regenTimeLeft = _REGEN_INTERVAL
        local regen = 0.00
        local regenBuildup = 0.00
        Timed.echo(function()
            if not inSys[index] then return true end
            local life = GetWidgetLife(u)
            local diff = life - lastLife
            lastLife = life
            local heal = diff - RMaxBJ(0.00, regen)
            local max = GetUnitState(u, UNIT_STATE_MAX_LIFE)
            if max ~= maxLife then
                max, maxLife = maxLife - max, max
                if heal >= max then
                    heal = heal - max --prevent "max life incrase" from triggering a heal.
                end
            end
 
            if heal >= _HEAL_THRESHOLD then
                Event.heal:run(u, heal)
            else
                regen = (regen + diff) * 0.50
                regenBuildup = regenBuildup + diff
                regenTimeLeft = regenTimeLeft - udg_HEAL_CHECK_INTERVAL
                if regenTimeLeft <= 0.00 then
                    regenTimeLeft = _REGEN_INTERVAL
                    heal = regenBuildup
                    regenBuildup = 0.00
                    if IsUnitType(u, UNIT_TYPE_HERO) then
                        diff = heal - (GetHeroStr(u, true)*_STR_BONUS)
                    else
                        diff = heal
                    end
                    if diff >= _REGEN_THRESHOLD then
                        Event.heal:run(u, heal)
                    end
                end
            end
        end, _HEAL_INTERVAL)
    end
end
 
UnitEvent.onCreate(AddUnit)
UnitEvent.onRevival(AddUnit)
 
local function DelUnit(index) inSys[index] = nil end
 
UnitEvent.onRemoval(DelUnit)
UnitEvent.onDeath(DelUnit)
UnitEvent.onReincarnate(DelUnit)
 
end
 
Last edited:
Level 4
Joined
Apr 22, 2022
Messages
31
Hey @Bribe just wondering how I could go about factoring in max life gain so it doesn't show as a heal as per your earlier posts. The whole system works perfectly, but I am having an issue when a unit gains a level or picks up an item with +strength or +max life on it and showing as a heal.
I could also add a Max-life variable and factor in max life gain with any heading gain to see if there's any difference. If not, it's not a heal.
With this new native, I should edit this system in order to allow it to filter out max HP changes from registering as healing.
I am trying to create the comparison at the moment, but not sure how it can detect the unit's max hp before and after the level gain or item pickup. Also not sure what I should be comparing against (heal_diff, heal_amount, or create Max life before & after variables) Thanks.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Hey @Bribe just wondering how I could go about factoring in max life gain so it doesn't show as a heal as per your earlier posts. The whole system works perfectly, but I am having an issue when a unit gains a level or picks up an item with +strength or +max life on it and showing as a heal.


I am trying to create the comparison at the moment, but not sure how it can detect the unit's max hp before and after the level gain or item pickup. Also not sure what I should be comparing against (heal_diff, heal_amount, or create Max life before & after variables) Thanks.
Hi Radksi,

I came across a design problem when I was coding this max life change in Lua (hence why this got delayed, as I couldn't come up with a good solution). Basically, there isn't a good way to check if the unit's CURRENT life changed as well as the MAX LIFE, because the max life can be changed without triggering a heal, then some other heal might've done it to full health in the same "moment", do I ignore the event?

I've been giving this a lot of thought. Based on feedback received from others, it might be a good idea to include a "healing abilities spellpack" so that it can show people how to proper trigger heals (since that's the only way to track a healing source anyway).
 
Level 4
Joined
Apr 22, 2022
Messages
31
I managed to get it to work, although it is a bit of a workaround. Just added 2 real variables of Max life before and Max life difference, both of them are arrays since my map is 3 player, and had a trigger to set Max life before to the life of the unit every .03 sec. Made the heal check loop trigger player-specific and added a condition above the heal_amount greater than or equal to threshold, which checks if Max life difference less than or equal to 0. Then any trigger I had that I did or didn't want to show the heal I just changed my variable accordingly. I also checked when a unit gains a level and when a unit acquires an item to set Max life difference = (Max life of unit - Max life before)

You are right and it can really only be achieved through a triggered heal source, knowing that really helped me and hopefully my explanation is useful in some way to anyone having the same issue. I'm sure my way isn't the best, but it works for me. Thanks a ton Bribe, your efforts do not go unnoticed.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
I managed to get it to work, although it is a bit of a workaround. Just added 2 real variables of Max life before and Max life difference, both of them are arrays since my map is 3 player, and had a trigger to set Max life before to the life of the unit every .03 sec. Made the heal check loop trigger player-specific and added a condition above heal_amount greater than threshold which checks if Max life difference less than or equal to 0. Then any trigger I had that I did or didn't want to show the heal I just changed my variable accordingly. I also checked when a unit gains a level and when a unit acquires an item to set Max life difference = (Max life of unit - Max life before)

You are right and it can really only be achieved through a triggered heal source, knowing that really helped me and hopefully my explanation is useful in some way to anyone having the same issue. I'm sure my way isn't the best, but it works for me. Thanks a ton Bribe, your efforts do not go unnoticed.
Nice that you found a workaround! I think I might need to double check if a unit state event will trigger if a unit’s max life changes. I’d rather not have to be constantly checking every single unit’s max life every single time.
 
Level 4
Joined
Apr 22, 2022
Messages
31
Just found after a bit of play testing that I have been running into issues of memory leaks after about 10 mins of killing and spawning mobs (the spawns are leak-free). I believe my issue is that my map has respawn triggers for units owned by neutral hostile that are preplaced or respawn and die again, and those respawn triggers use and set the custom value of the units, which I feel is conflicting with the unit indexer from Heal Event. I turned it off and my leaks seem to go away so that must be the culprit. Wondering how I can make my respawn triggers use the unit indexer system rather than its own setting of custom values. Any help is appreciated!
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Just found after a bit of play testing that I have been running into issues of memory leaks after about 10 mins of killing and spawning mobs (the spawns are leak-free). I believe my issue is that my map has respawn triggers for units owned by neutral hostile that are preplaced or respawn and die again, and those respawn triggers use and set the custom value of the units, which I feel is conflicting with the unit indexer from Heal Event. I turned it off and my leaks seem to go away so that must be the culprit. Wondering how I can make my respawn triggers use the unit indexer system rather than its own setting of custom values. Any help is appreciated!
You’d have to attach a map or the respawn trigger so we know what the problem is. But basically instead of it setting and getting the user data you use an array with the actual user data:

Set CreepRespawnValue[(custom value of unit)] = something
 
Level 4
Joined
Apr 22, 2022
Messages
31
Yeah I sort of thought of that after I had posted lol. This is part of the first trigger that runs at map initialization to store all of the preplaced units
  • Set VariableSet Creeps = (Units owned by Neutral Hostile.)
  • Unit Group - Pick every unit in Creeps and do (Actions)
    • Loop - Actions
      • Set VariableSet I = (I + 1)
      • Unit - Set the custom value of (Picked unit) to I
      • Set VariableSet Angle[I] = (Facing of (Picked unit))
      • Set VariableSet Position = (Position of (Picked unit))
      • Set VariableSet X[I] = (X of Position)
      • Set VariableSet Y[I] = (Y of Position)
      • Custom script: call RemoveLocation(udg_Position)
  • Custom script: call DestroyGroup(udg_Creeps)
  • Set VariableSet I = 0
and this last bit is from the respawn trigger itself for when a unit owned by neutral hostile dies
  • Set VariableSet I = (I + 1)
  • Set VariableSet Creep[I] = (Dying unit)
  • Wait 417.00 game-time seconds
  • Set VariableSet Position = (Center of (Entire map))
  • Set VariableSet J = (J + 1)
  • Unit - Create 1 (Unit-type of Creep[J]) for Neutral Hostile at (Position offset by (X[(Custom value of Creep[J])], Y[(Custom value of Creep[J])])) facing Angle[(Custom value of Creep[J])] degrees
  • Custom script: call RemoveLocation(udg_Position)
  • Unit - Set the custom value of (Last created unit) to (Custom value of Creep[J])
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • I Greater than or equal to 8000
    • Then - Actions
      • Set VariableSet I = 0
    • Else - Actions
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • J Greater than or equal to 8000
    • Then - Actions
      • Set VariableSet J = 0
    • Else - Actions
I know "Wait xx game-time seconds" has a small leak, and the respawn system is a bit janky, but it all works and it doesn't cause me any issues. My issue happens when I have the heal event and unit indexer system enabled.

I also have my Damage Tag trigger which calls on
  • Custom script: call ArcingTextTag.createEx(udg_DmgStr, udg_DamageEventTarget, udg_DmgDuration, udg_DmgSize, GetLocalPlayer())
and my On Heal trigger which calls on
  • Custom script: call ArcingTextTag.createEx(udg_DmgStr, udg_heal_target, udg_DmgDuration, udg_DmgSize, GetLocalPlayer())
Could this possibly cause issues with arcing text tag? Since there are a lot of damage and healing targets/sources going out all around the same time which is causing lots of numbers. Just trying ideas of why I am experiencing leaks / performance issues.
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Wow that respawn system is absolutely terrible. Just use one of the approved ones on The Hive.

Here are the problems I’ve seen:

(Entire map) is a region (known as rect in code) and leaks. Use (playable map area) instead which doesn’t leak.
The location the unit is created at leaks. Set it to its own position variable so it can be removed.

Like I said, use an array instead of the custom value.

There is no identifiable problem with anything else. An incorrect custom value can cause an infinite loop on the Unit Indexer script, so it all stems from this terrible respawn system that should definitely not be setting custom values.
 
Level 4
Joined
Apr 22, 2022
Messages
31
Yeah I had a feeling the respawn system is bad hahaha I had found it when I originally started making my map and just left it in there. Every other respawn system I have found looks similar to this and also uses custom values which is no good for me now. Any suggestions on a respawn system? The location the unit is created at is a variable called Position and I use Custom script: call RemoveLocation(udg_Position) after I am done using it unless I did that wrong too. I am still somewhat of a noob when it comes to triggering and code, but how would I use an array instead of the custom value? Like just make a variable that is an array and replace custom value anywhere it is used with the variable array? Thanks for the help!
 
Last edited:
Level 11
Joined
Jul 4, 2016
Messages
626
So does this system detect any heal outside the box or are you required to use the system itself to heal in order to have heal detection?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
So does this system detect any heal outside the box or are you required to use the system itself to heal in order to have heal detection?
It detects any life gain (separate from damage) on a unit, but does not automatically detect the heal source unit. All healing must be triggered for that to happen.

This old thread on TheHelper lays out some custom healing spells (using a different system): System - Heal

My next plan is to try to detect when a unit gets a healing buff and map the buff to a specific totem/spell which is then pointing to the unit who cast it. This is projected to happen sometime later this month.
 
Last edited:
Level 11
Joined
May 7, 2008
Messages
300
Can someone help me , i am trying to register the amount of heal of heal user for all players but it only registers it for red player.
View attachment 404885
Am i doing something wrong?
(it works fine if using heal_target)

Heal Event does not work like that sadly (already checked with Bribe about a month ago) since WC3 can't recognize who was the Source unless you declare who it is via the 3 variables inside the system (NextHealSource, NextHealTarget, NextHealAmount).

Instead you will have to register and custom code every healing spell in order to fully take control of the system.

Few example of how I use Bribe's Heal Event:

  • On Heal
    • Events
      • Game - HealEvent becomes Equal to 1.00
    • Conditions
      • ((Owner of heal_source) controller) Equal to User
    • Actions
      • -------- Set the Total Count of Heal for Every Player --------
      • Set VariableSet Heal_Total[(Player number of (Owner of heal_source))] = (Heal_Total[(Player number of (Owner of heal_source))] + heal_amount)
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Hide_HealText Equal to False
        • Then - Actions
          • Floating Text - Create floating text that reads ((PlayerColors[(Player number of (Owner of heal_source))] + +|r) + (String((Integer((heal_amount + 0.50)))))) above heal_target with Z offset 0.00, using font size (Random real number between 7.00 and 9.00), color (5.00%, 100.00%, 10.00%), and 0.00% transparency
          • Custom script: call SetTextTagPos(bj_lastCreatedTextTag, GetUnitX(udg_heal_target) - 32.00, GetUnitY(udg_heal_target), GetRandomReal(-32.00, 10.00))
          • Floating Text - Set the velocity of (Last created floating text) to (Random real number between 50.00 and 100.00) towards (Random real number between 45.00 and 135.00) degrees
          • Floating Text - Change (Last created floating text): Disable permanence
          • Floating Text - Change the lifespan of (Last created floating text) to 1.70 seconds
          • Floating Text - Change the fading age of (Last created floating text) to 1.25 seconds
        • Else - Actions
  • Heal 1
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Heal 1 Holy
    • Actions
      • -------- --------
      • Set VariableSet NextHealSource = (Triggering unit)
      • Set VariableSet NextHealTarget = (Target unit of ability being cast)
      • Set VariableSet NextHealAmount = Heal_1_Value[(Level of (Ability being cast) for (Triggering unit))]
      • -------- --------
      • Trigger - Run Heal Unit <gen> (ignoring conditions)
      • -------- --------
  • Repentance
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Repentance
    • Actions
      • Set VariableSet Iron_Integer = (Level of (Ability being cast) for (Triggering unit))
      • -------- --------
      • Set VariableSet RepentancePoint = (Target point of ability being cast)
      • -------- --------
      • Set VariableSet RepentanceAllies = (Units within Repentance_AoE[Iron_Integer] of RepentancePoint matching (((Matching unit) belongs to an ally of (Owner of (Triggering unit)).) Equal to True).)
      • Set VariableSet RepentanceEnemy = (Units within Repentance_AoE[Iron_Integer] of RepentancePoint matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit)).) Equal to True).)
      • -------- --------
      • Special Effect - Create a special effect at RepentancePoint using war3mapImported\Sacred Storm.mdx
      • Special Effect - Destroy (Last created special effect)
      • -------- --------
      • Special Effect - Create a special effect at RepentancePoint using war3mapImported\Empyrean Nova.mdx
      • Special Effect - Set Scale of (Last created special effect) to 0.60
      • Special Effect - Destroy (Last created special effect)
      • -------- --------
      • Custom script: call RemoveLocation(udg_RepentancePoint)
      • -------- --------
      • Unit Group - Pick every unit in RepentanceAllies and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is dead) Equal to False
              • (Unit-type of (Picked unit)) Not equal to |cff8080ffHealing Well|r
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is Mechanical) Equal to False
              • (Percentage life of (Picked unit)) Less than 99.00
            • Then - Actions
              • -------- Heal by given ammount --------
              • Set VariableSet NextHealSource = (Triggering unit)
              • Set VariableSet NextHealTarget = (Picked unit)
              • Set VariableSet NextHealAmount = (Repentance_Value[Iron_Integer] + ((Real((Intelligence of NextHealSource (Include bonuses)))) x Repentance_IntBonus[Iron_Integer]))
              • -------- --------
              • Trigger - Run Heal Unit <gen> (ignoring conditions)
              • -------- --------
              • Special Effect - Create a special effect attached to the origin of (Picked unit) using war3mapImported\Heal Gold.mdx
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
      • -------- --------
      • Custom script: call DestroyGroup(udg_RepentanceAllies)
      • -------- --------
      • Unit Group - Pick every unit in RepentanceEnemy and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is dead) Equal to False
            • Then - Actions
              • Unit - Cause (Triggering unit) to damage (Picked unit), dealing (Repentance_Value[Iron_Integer] + ((Real((Intelligence of (Triggering unit) (Include bonuses)))) x Repentance_IntBonus[Iron_Integer])) damage of attack type Magic and damage type Normal
              • -------- --------
              • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Other\Incinerate\IncinerateBuff.mdl
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
      • -------- --------
      • Custom script: call DestroyGroup(udg_RepentanceEnemy)
  • Fountain of Wealth Dummy
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Fountain of Wealth (Dummy)
    • Actions
      • Set VariableSet Paladin_Point = (Position of (Triggering unit))
      • Set VariableSet Paladin_Integer = (Level of (Ability being cast) for (Triggering unit))
      • -------- --------
      • Set VariableSet Paladin_Group = (Units within Paladin_AoE_Well[Paladin_Integer] of Paladin_Point matching ((((Matching unit) belongs to an ally of (Owner of (Triggering unit)).) Equal to True) and ((((Matching unit) is alive) Equal to True) and ((((Matching unit) is A structure) Equal to Fa
      • Set VariableSet Paladin_Random_Unit = (Random unit from Paladin_Group)
      • -------- --------
      • Custom script: call RemoveLocation(udg_Paladin_Point)
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Paladin_Random_Unit has buff |cffa08cffBlessing of Protection ) Equal to True
              • (Paladin_Random_Unit has buff |cffff8080Divinity|r ) Equal to True
        • Then - Actions
          • -------- Main Heal --------
          • Set VariableSet NextHealSource = (Triggering unit)
          • Set VariableSet NextHealTarget = Paladin_Random_Unit
          • Set VariableSet NextHealAmount = (Paladin_Well_Heal[Paladin_Integer] + Paladin_Well_Heal_Bonus[Paladin_Integer])
          • -------- - --------
          • Trigger - Run Heal Unit <gen> (ignoring conditions)
          • -------- --------
          • Special Effect - Create a special effect attached to the origin of Paladin_Random_Unit using war3mapImported\Holy Light Void.mdx
          • Special Effect - Destroy (Last created special effect)
        • Else - Actions
          • -------- Main Heal --------
          • Set VariableSet NextHealSource = (Triggering unit)
          • Set VariableSet NextHealTarget = Paladin_Random_Unit
          • Set VariableSet NextHealAmount = Paladin_Well_Heal[Paladin_Integer]
          • -------- - --------
          • Trigger - Run Heal Unit <gen> (ignoring conditions)
          • -------- --------
          • Special Effect - Create a special effect attached to the origin of Paladin_Random_Unit using war3mapImported\Heal.mdx
          • Special Effect - Destroy (Last created special effect)
      • -------- --------
      • Custom script: call DestroyGroup(udg_Paladin_Group)
 
Level 31
Joined
Aug 6, 2015
Messages
628
  • On Heal
    • Events
      • Game - HealEvent becomes Equal to 1.00
    • Conditions
      • ((Owner of heal_source) controller) Equal to User
    • Actions
      • -------- Set the Total Count of Heal for Every Player --------
      • Set VariableSet Heal_Total[(Player number of (Owner of heal_source))] = (Heal_Total[(Player number of (Owner of heal_source))] + heal_amount)
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Hide_HealText Equal to False
        • Then - Actions
          • Floating Text - Create floating text that reads ((PlayerColors[(Player number of (Owner of heal_source))] + +|r) + (String((Integer((heal_amount + 0.50)))))) above heal_target with Z offset 0.00, using font size (Random real number between 7.00 and 9.00), color (5.00%, 100.00%, 10.00%), and 0.00% transparency
          • Custom script: call SetTextTagPos(bj_lastCreatedTextTag, GetUnitX(udg_heal_target) - 32.00, GetUnitY(udg_heal_target), GetRandomReal(-32.00, 10.00))
          • Floating Text - Set the velocity of (Last created floating text) to (Random real number between 50.00 and 100.00) towards (Random real number between 45.00 and 135.00) degrees
          • Floating Text - Change (Last created floating text): Disable permanence
          • Floating Text - Change the lifespan of (Last created floating text) to 1.70 seconds
          • Floating Text - Change the fading age of (Last created floating text) to 1.25 seconds
        • Else - Actions
Would this even work? (if we can't detect the heal_source ?)
Because i am using a similar thing and it doesn't
  • On Heal
    • Events
      • Game - HealEvent becomes Equal to 1.00
      • Game - HealEvent becomes Equal to 0.50
    • Conditions
    • Actions
      • Set VariableSet ScorePL = (Player number of (Owner of heal_source))
      • Set VariableSet CR_Game_Healed[ScorePL] = (CR_Game_Healed[ScorePL] + (Integer(heal_amount)))
 
Level 4
Joined
Apr 22, 2022
Messages
31
Any chance of updating heal event to work with GUI Unit Indexer 1.4.0.0 ? I was having issues awhile back and had to remove heal event from my map as it wasn't working with the 1.4 indexer, really like the system so would be great to add back in!
 
Top