• 🏆 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.

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
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!
Why not use Unit Event? It's superior to GUI Unit Indexer and helps Heal Event perform better with regards to dead/transporting/reincarnating units. If Heal Event were modified to use Unit Indexer, you'd get a +600 Heal Event showing wherever a 600 HP unit is revived.
 
Level 4
Joined
Apr 22, 2022
Messages
31
Why not use Unit Event? It's superior to GUI Unit Indexer and helps Heal Event perform better with regards to dead/transporting/reincarnating units. If Heal Event were modified to use Unit Indexer, you'd get a +600 Heal Event showing wherever a 600 HP unit is revived.
I already use GUI unit indexer 1.4 on my map for a respawn system. Heal event comes with a unit indexer but that indexer doesn't seem to work with my respawn system and unit indexer 1.4 doesn't work with heal event lol. Was just curious if it is possible to have them work together.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
I already use GUI unit indexer 1.4 on my map for a respawn system. Heal event comes with a unit indexer but that indexer doesn't seem to work with my respawn system and unit indexer 1.4 doesn't work with heal event lol. Was just curious if it is possible to have them work together.
Just delete Unit Indexer. Unit Event integrates it already.
 
Level 7
Joined
Aug 16, 2019
Messages
61
Hey Bribe tried this out together with Damage Engine 5.9 and Unit Event (not Unit Indexer) and have some questions. First I seem to have the same issue as Ugabunda described on the last page: random healing text showing up when units take damage (quoted below). And actually that's the only healing text I get, nothing from healing abilities (Priest Heal, Healing Wave etc.) or regen (I'm using the default On Heal text creator). I can tell its the Heal Adjust triggers causing the random text and when I add the "heal_inSys[(Custom value of DamageEventTarget)] Equal to True" condition they stop showing up, but still got no real heal text though.

Also, assuming I can get it to work, I need to be able to register healing for buildings/units with no movement speed in my map, what would I have to change to do that?

Lastly, am I correct in understanding that since GUI Unit Event uses Custom Values I'll be unable to use that for anything myself? I was hoping to use it to track the original owner of each unit.

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,464
In "Heal Add Unit" there is a condition that checks if the movement speed is not equal to 0. That's the one to remove.

Ideally, this system should just be filtering out "useless units" from being added to the pool - so spellcaster dummies/unit-as-projectile kind of stuff. So the conditions in that trigger should vary between maps.

I was hoping to use it to track the original owner of each unit.

You can do that while being kind to Unit Indexer. Custom values are used by the indexer to create array-friendly integers that are simply unique to that unit, so these integers are used as entry points into parallel arrays. Therefore, you'll need an array for tracking the original owning player, and use the custom value as the index point to slot into the array, rather than modifying the custom value directly.

The text tags will work - provided that your map isn't overwriting custom values and that you tailor the "Heal Add Unit" conditions appropriately.
 
Level 7
Joined
Aug 16, 2019
Messages
61
In "Heal Add Unit" there is a condition that checks if the movement speed is not equal to 0. That's the one to remove.

Ideally, this system should just be filtering out "useless units" from being added to the pool - so spellcaster dummies/unit-as-projectile kind of stuff. So the conditions in that trigger should vary between maps.



You can do that while being kind to Unit Indexer. Custom values are used by the indexer to create array-friendly integers that are simply unique to that unit, so these integers are used as entry points into parallel arrays. Therefore, you'll need an array for tracking the original owning player, and use the custom value as the index point to slot into the array, rather than modifying the custom value directly.

The text tags will work - provided that your map isn't overwriting custom values and that you tailor the "Heal Add Unit" conditions appropriately.
Well alright the conditions are simple enough I see, that should be fine now, but there's definitely something wrong in my map cause it seems both versions of HealEvent never trigger unless its manual healing from the Heal Unit trigger (and I'm not currently overwriting custom values, I've checked and I don't use it anywhere atm). And the healing amounts are pretty large so they should definitely not fall below the thresholds
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Well alright the conditions are simple enough I see, that should be fine now, but there's definitely something wrong in my map cause it seems both versions of HealEvent never trigger unless its manual healing from the Heal Unit trigger (and I'm not currently overwriting custom values, I've checked and I don't use it anywhere atm). And the healing amounts are pretty large so they should definitely not fall below the thresholds
Please send me your map, I'll see if I can find the culprit. I'm guessing there is a vJass lib somewhere in your map that conflicts with the custom value.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Steps I took:
1) Downloaded and opened map
2) See that there are 1999 triggers that need to load (you might think it would be hard to find the problem at this point).
3) Object Manager > Functions (admittedly this normally takes a long time, but sheesh).
4a) Found two places in the code that are setting the custom value:
1689515684309.png

4b) Found this:
Unit - Set the custom value of ConfusionUnit[1] to (Player number of (Owner of ConfusionUnit[1]))
--This needs to be changed to use the parallel array that I mentioned.
4c) Found this:
Unit - Set the custom value of (Triggering unit) to (Player number of (Owner of (Triggering unit)))
--Same deal - needs to be refactored to use the parallel array with existing unit's custom value as the index.
5) Checking for Function Call references:
1689515955076.png

These are fine.
6a) Check for it in the war3map.j file - produce an error:
1689516107785.png

6b) View error:
1689516217533.png


6c) Select all and copy into Notepad++
7) Search for SetUnitUserData... two results found?? What about UnitIndex or Unit Event? Were those disabled?
8) Search for GetUnitUserData... found in Heal Event triggers, yep, as expected. But also found in Unit Event.
9) Checked Unit Event for where it would call SetUnitUserData - this part is missing!

Conclusions:
  • You still have a couple of areas of your code to clean up the setting of the custom value (and I've now pointed out where those are in a screenshot).
  • You need to update to the latest version of vJass Unit Event, because you're using a version I made prior to integrating Unit Indexer into it.
 
Level 7
Joined
Aug 16, 2019
Messages
61
Steps I took:
1) Downloaded and opened map
2) See that there are 1999 triggers that need to load (you might think it would be hard to find the problem at this point).
3) Object Manager > Functions (admittedly this normally takes a long time, but sheesh).
4a) Found two places in the code that are setting the custom value:
View attachment 440318
4b) Found this:
Unit - Set the custom value of ConfusionUnit[1] to (Player number of (Owner of ConfusionUnit[1]))
--This needs to be changed to use the parallel array that I mentioned.
4c) Found this:
Unit - Set the custom value of (Triggering unit) to (Player number of (Owner of (Triggering unit)))
--Same deal - needs to be refactored to use the parallel array with existing unit's custom value as the index.
5) Checking for Function Call references:
View attachment 440319
These are fine.
6a) Check for it in the war3map.j file - produce an error:
View attachment 440320
6b) View error:
View attachment 440327

6c) Select all and copy into Notepad++
7) Search for SetUnitUserData... two results found?? What about UnitIndex or Unit Event? Were those disabled?
8) Search for GetUnitUserData... found in Heal Event triggers, yep, as expected. But also found in Unit Event.
9) Checked Unit Event for where it would call SetUnitUserData - this part is missing!

Conclusions:
  • You still have a couple of areas of your code to clean up the setting of the custom value (and I've now pointed out where those are in a screenshot).
  • You need to update to the latest version of vJass Unit Event, because you're using a version I made prior to integrating Unit Indexer into it.
Alright thanks I'll take a look at it. Weird thing is I did check for SetUnitUserData by intentionally producing an error and couldn't find anything then, but oh well. I just used the Unit Event that was included here, guess that one only works when you also have Unit Indexer, but I'll try with the newest one now.
 
Top