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

Life Change Detection v1.00

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: Imadori and Vinz
This system allows you to see the change in the health points of a unit per second.

Please give credits if used!
Requested by kellym0.

How to import:
Copy the triggers, not including the "Test Map"
Paste to your map
If you want to make units to get this floating text too, just add the unit to the "Lifegroup"

Features:
Hides from a player's view if it isn't visible to him/her.
Can be hidden from enemies(configurable)


  • Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Set the font size --------
      • Set FontSize = 7.50
      • -------- Set the font color (1) = positive, (2) = negative --------
      • Set TextColor[1] = |cff00ff00
      • Set TextColor[2] = |cffff0000
      • -------- Show to enemies your units' life change? --------
      • Set ShowtoEnemies = False
  • Check Life
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Lifegroup and do (Actions)
        • Loop - Actions
          • Set cusvalue = (cusvalue + 1)
          • Set Lifeunit[cusvalue] = (Picked unit)
          • Set life[cusvalue] = (Life of Lifeunit[cusvalue])
          • Unit Group - Remove (Picked unit) from Lifegroup
      • For each (Integer A) from 1 to cusvalue, do (Actions)
        • Loop - Actions
          • Set prevlife = life[(Integer A)]
          • Set life[(Integer A)] = (Life of Lifeunit[(Integer A)])
          • If ((life[(Integer A)] - prevlife) Greater than 0.00) then do (Set color = TextColor[1]) else do (Set color = TextColor[2])
          • If ((life[(Integer A)] - prevlife) Equal to 0.00) then do (Set transparancy = 100.00) else do (Set transparancy = 0.00)
          • Floating Text - Create floating text that reads (color + (String((life[(Integer A)] - prevlife)))) above Lifeunit[(Integer A)] with Z offset 0.00, using font size FontSize, color (100.00%, 100.00%, 100.00%), and transparancy% transparency
          • Set LifeText[(Integer A)] = (Last created floating text)
          • Floating Text - Change LifeText[(Integer A)]: Disable permanence
          • Floating Text - Change the lifespan of LifeText[(Integer A)] to 1.00 seconds
          • Player Group - Pick every player in (All players) and do (If ((Lifeunit[(Integer A)] is visible to (Picked player)) Equal to False) then do (Floating Text - Hide LifeText[(Integer A)] for (Player group((Picked player)))) else do (Floating Text - Show LifeText[(Integer A)] for (Player group((Picked player)))))
          • If (ShowtoEnemies Equal to False) then do (Player Group - Pick every player in (All players) and do (If (((Picked player) is an enemy of (Owner of Lifeunit[(Integer A)])) Equal to True) then do (Floating Text - Hide LifeText[(Integer A)] for (Player group((Picked player)))) else do (Do nothing))) else do (Do nothing)
  • Move Text
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to cusvalue, do (Actions)
        • Loop - Actions
          • Floating Text - Change the position of LifeText[(Integer A)] to Lifeunit[(Integer A)] with Z offset 0.00



Keywords:
Life, Change, Detection, Regeneration, Floating, Text, RPG, System, bisnar13
Contents

Life Change Detection (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 22:55, 11th Dec 2012 Magtheridon96: - You're leaking (Player group((Picked player))) - Instead of doing the group enumeration inside the looping trigger every single time, you can do it...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

22:55, 11th Dec 2012
Magtheridon96:

- You're leaking (Player group((Picked player)))
- Instead of doing the group enumeration inside the looping trigger every single time, you can do it when units actually exist in the group:

  • Custom script: if FirstOfGroup(udg_Lifegroup) != null then
  • // group has units in it, so pick them here
  • endif
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
It is still not efficient as it checks health per interval, whether it should checks health per "change of health" event.
You're making it "inaccurate" checks, that is why kelly said "it is delay a bit" because it occurs once every 1 second, whether it should occur not depends on time, but depends on health change.

This is your work, to figure it out what is the algorithm, rather than depending on check per interval.
 
but bribes damage engine doesn't show green floating text for all healing and regeneration--that is what I had searched for, for like over a year, I looked in all the forms spell sections jass vjass gui nothing exists, I requested this for that reason because im not capable of making it my self Radamantus. Until somebody points one out this is what im going to use as my template for healing green floating text...

thank you for doing this request bisnar13

by the way if somebody dos have a green health floating text for both healing spells and regeneration--please point it out. other wise give constructive criticism as to how to make this system better.
 
Also, this system will stop working once the total number of units that appeared on the map exceeds 8192 because you never recycle the indexes... Aside from that, another downside of not recycling is that you can be looping thru unused indexes resulting to wasted processing power/time...

A better thing to do is just use the group itself + a hashtable using the handle id of units as key rather than having a temporary unit group + array... then just don't forget to remove the unit from the group when it dies...
 
I tried to do it but I couldn't get it to work >=( il try again i geuss

EDIT still don't understand how to edit bribes--can you perhaps elaborate on how to do so? I really want green floating text for all healing/regeneration.

EDIT no I dont think he dos explaine how to use healing i looked thru the intire board of 17 pages he says nothing about implementing healing.

perhaps you can give me an example on how to use his system to implement healing.
 
Last edited:
Level 16
Joined
Aug 20, 2009
Messages
1,552
Please read the Unit Indexer.

I read it and i found no explanation of doing Generic life changes event.

I hope you could provide an example how to do that with Unit Indexer.

First, there is no way to Loop through ALL unit indexed,

There is no count to "Total number of unit indexed" Variable in this system.

so we cant do smthing like this.

  • Test
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to UDexTotal, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexUnits[(Integer A)] Not equal to No unit
              • (UDexUnits[(Integer A)] is alive) Equal to True
            • Then - Actions
              • Special Effect - Create a special effect at (Position of UDexUnits[(Integer A)]) using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
            • Else - Actions
i think.

if theres some way, you should explain me, it would be useful.
 
I think using unit indexer, you can loop thru each unit and compare its life with its previous value, if it changes, run an integer change event. probably...

now if this system will use the same idea, it will be better... because right now, your resource only shows life change every 1 second really, but it doesn't provide things like running a specified trigger when life changes... and also, its better to use a shorter time period...

my suggestion is that the system should only do the life change detection itself, then use another trigger to show the text... you can do this on the life change detection:

Set LifeChange = 1
Set LifeChange = 0

then for triggers that should run when a unit's life changes (like the floating text), use this as an event:

LifeChange becomes 1

That is similar to how Bribe lets the user capture the damage events...

I suggest doing that because right now I cannot really call this a Life Change Detection, but rather its just See Life Change...

changing it to a real Life Change Detection system is far more useful...

and also, don't forget that you can only show 100 texttags at a given moment in time...

also, an alternative way to hide the texttag from others is that you hide it for everyone then use a GetLocalPlayer() block to show it locally to the owner...
 
Level 16
Joined
Aug 20, 2009
Messages
1,552
Anyways, i created a working HP and Mana change.

heres the trig using the Unit Indexer by bribe.

  • Unit Indexer
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: call ExecuteFunc("InitializeUnitIndexer")
      • Custom script: endfunction
      • Custom script:
      • Custom script: function ClearUnitIndex takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of UDexUnits[UDex]) Equal to 0
        • Then - Actions
          • Set UnitIndexLock[UDex] = (UnitIndexLock[UDex] - 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UnitIndexLock[UDex] Equal to 0
            • Then - Actions
              • Set UDexNext[UDexPrev[UDex]] = UDexNext[UDex]
              • Set UDexPrev[UDexNext[UDex]] = UDexPrev[UDex]
              • Set UDexPrev[UDex] = 0
              • Set UnitIndexEvent = 0.00
              • Set UnitIndexEvent = 2.00
              • Set UnitIndexEvent = 0.00
              • Set UDexUnits[UDex] = No unit
              • Set UDexNext[UDex] = UDexRecycle
              • Set UDexRecycle = UDex
            • Else - Actions
        • Else - Actions
      • Custom script: endfunction
      • Custom script:
      • Custom script: function IndexUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • Custom script: local integer ndex
      • -------- - --------
      • -------- You can customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UnitIndexerEnabled Equal to True
          • (Custom value of (Matching unit)) Equal to 0
        • Then - Actions
          • Set UDexWasted = (UDexWasted + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexWasted Equal to 15
            • Then - Actions
              • Set UDexWasted = 0
              • Set UDex = UDexNext[0]
              • Custom script: loop
              • Custom script: exitwhen udg_UDex == 0
              • Custom script: set ndex = udg_UDexNext[udg_UDex]
              • Custom script: call ClearUnitIndex()
              • Custom script: set udg_UDex = ndex
              • Custom script: endloop
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexRecycle Equal to 0
            • Then - Actions
              • Set UDex = (UDexGen + 1)
              • Set UDexGen = UDex
            • Else - Actions
              • Set UDex = UDexRecycle
              • Set UDexRecycle = UDexNext[UDex]
          • Set UDexUnits[UDex] = (Matching unit)
          • Unit - Set the custom value of UDexUnits[UDex] to UDex
          • Set UDexPrev[UDexNext[0]] = UDex
          • Set UDexNext[UDex] = UDexNext[0]
          • Set UDexNext[0] = UDex
          • Set UnitIndexLock[UDex] = 1
          • Set UnitIndexEvent = 0.00
          • Set UnitIndexEvent = 1.00
          • Set UnitIndexEvent = 0.00
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • Custom script:
      • Custom script: function InitializeUnitIndexer takes nothing returns nothing
      • Custom script: local integer i = 16
      • Custom script: local boolexpr b = Filter(function IndexUnit)
      • Custom script: local region re = CreateRegion()
      • Custom script: local trigger t = GetTriggeringTrigger()
      • Custom script: local rect r = GetWorldBounds()
      • Custom script: call RegionAddRect(re, r)
      • Custom script: call TriggerRegisterEnterRegion(t, re, b)
      • Custom script: call TriggerClearActions(t)
      • Custom script: call TriggerAddAction(t, function ClearUnitIndex)
      • Set UnitIndexerEnabled = True
      • Custom script: loop
      • Custom script: set i = i - 1
      • Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), b)
      • Custom script: exitwhen i == 0
      • Custom script: endloop
      • Custom script: call RemoveRect(r)
      • Custom script: set re = null
      • Custom script: set r = null
      • Custom script: set t = null
      • Custom script: set b = null
      • Set UnitIndexEvent = 3.00
      • Set UnitIndexEvent = 0.00
  • Property Index
    • Events
      • Game - UnitIndexEvent becomes Equal to 1.00
    • Conditions
    • Actions
      • Set Key = (Custom value of UDexUnits[(Integer A)])
      • Set PrevLife[Key] = (Life of UDexUnits[UDex])
      • Set CurrentLife[Key] = (Life of UDexUnits[UDex])
      • Set CurrentMana[Key] = (Mana of UDexUnits[UDex])
      • Set PrevMana[Key] = (Mana of UDexUnits[UDex])
  • Property Change
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Set CurrentUnitIndex = UDexNext[0]
      • Custom script: loop
      • Custom script: exitwhen udg_CurrentUnitIndex == 0
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UDexUnits[CurrentUnitIndex] Not equal to No unit
          • (UDexUnits[CurrentUnitIndex] is alive) Equal to True
        • Then - Actions
          • Set Key = (Custom value of UDexUnits[CurrentUnitIndex])
          • Set CurrentLife[Key] = (Life of UDexUnits[CurrentUnitIndex])
          • Set LifeDifference = (PrevLife[Key] - CurrentLife[Key])
          • Set CurrentMana[Key] = (Mana of UDexUnits[CurrentUnitIndex])
          • Set ManaDifference = (CurrentMana[Key] - PrevMana[Key])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CurrentLife[Key] Not equal to PrevLife[Key]
              • LifeDifference Not equal to 0.00
              • Or - Any (Conditions) are true
                • Conditions
                  • LifeDifference Greater than 0.99
                  • LifeDifference Less than -0.99
            • Then - Actions
              • Set TempPoint = (Position of UDexUnits[CurrentUnitIndex])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • LifeDifference Greater than 0.00
                • Then - Actions
                  • Floating Text - Create floating text that reads (Substring((String(LifeDifference)), 1, ((Length of (String(LifeDifference))) - 4))) at TempPoint with Z offset 0.00, using font size 10.00, color (100.00%, 0.00%, 0.00%), and 0.00% transparency
                • Else - Actions
                  • Floating Text - Create floating text that reads (+ + (Substring((String(LifeDifference)), 2, ((Length of (String(LifeDifference))) - 4)))) at TempPoint with Z offset 0.00, using font size 10.00, color (0.00%, 100.00%, 0.00%), and 0.00% transparency
              • Floating Text - Hide (Last created floating text) for (All players matching ((UDexUnits[CurrentUnitIndex] is visible to (Matching player)) Equal to False))
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Set the velocity of (Last created floating text) to 70.00 towards 90.00 degrees
              • Floating Text - Change the fading age of (Last created floating text) to 0.10 seconds
              • Floating Text - Change the lifespan of (Last created floating text) to 2.00 seconds
              • Custom script: call RemoveLocation(udg_TempPoint)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CurrentMana[Key] Not equal to PrevMana[Key]
              • ManaDifference Not equal to 0.00
              • Or - Any (Conditions) are true
                • Conditions
                  • ManaDifference Greater than 0.99
                  • ManaDifference Less than -0.99
            • Then - Actions
              • Set TempPoint = (Position of UDexUnits[CurrentUnitIndex])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ManaDifference Less than 0.00
                • Then - Actions
                  • Floating Text - Create floating text that reads (Substring((String(ManaDifference)), 1, ((Length of (String(ManaDifference))) - 4))) at TempPoint with Z offset 0.00, using font size 10.00, color (0.00%, 100.00%, 100.00%), and 0.00% transparency
                • Else - Actions
                  • Floating Text - Create floating text that reads (+ + (Substring((String(ManaDifference)), 2, ((Length of (String(ManaDifference))) - 4)))) at TempPoint with Z offset 0.00, using font size 10.00, color (0.00%, 100.00%, 100.00%), and 0.00% transparency
              • Floating Text - Hide (Last created floating text) for (All players matching ((UDexUnits[CurrentUnitIndex] is visible to (Matching player)) Equal to False))
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Set the velocity of (Last created floating text) to 70.00 towards 90.00 degrees
              • Floating Text - Change the fading age of (Last created floating text) to 0.10 seconds
              • Floating Text - Change the lifespan of (Last created floating text) to 2.00 seconds
              • Custom script: call RemoveLocation(udg_TempPoint)
            • Else - Actions
          • Set PrevLife[Key] = CurrentLife[Key]
          • Set PrevMana[Key] = CurrentMana[Key]
        • Else - Actions
      • Custom script: set udg_CurrentUnitIndex = udg_UDexNext[udg_CurrentUnitIndex]
      • Custom script: endloop
This Works fine 100%.
both healing and Mana,

but somehow it works weird with runes.
 
Last edited:
@Radamantus - thing is it should be damage... now a LifeChange event isn't limited to damage (-damage for healing)... and using a DDS for that is not really a good idea...

razor's triggers are I think quite what I have had in mind... though it is still limited to SHOWING text...

as I said, if you'd make a public Life Change detection, you should just make it change the value of a custom variable, then let the user use that change as an event... because right now, if a user wants to do something else than just showing a text, he needs to go directly into the system's code, which is bad...

something like:

  • If changed life then
    • Set LifeChange = 1.00
    • Set LifeChange = 0.00
  • Events
    • LifeChange becomes equal to 1.00
  • Actions
 
Level 16
Joined
Aug 20, 2009
Messages
1,552
@Radamantus - thing is it should be damage... now a LifeChange event isn't limited to damage (-damage for healing)... and using a DDS for that is not really a good idea...

razor's triggers are I think quite what I have had in mind... though it is still limited to SHOWING text...

as I said, if you'd make a public Life Change detection, you should just make it change the value of a custom variable, then let the user use that change as an event... because right now, if a user wants to do something else than just showing a text, he needs to go directly into the system's code, which is bad...

something like:

  • If changed life then
    • Set LifeChange = 1.00
    • Set LifeChange = 0.00
  • Events
    • LifeChange becomes equal to 1.00
  • Actions

what i made is a request by Kellym0,

which needs to show changes in life and mana,

including giant regenerations.
 
as I said, the comment was only if you're gonna make a PUBLIC resource... though doing it that way even for a specific resource is also a good triggering practice I think...

Once you upload a request here on this section, it becomes public resource. He named it life change detection, so at the very least users should be able to easily do something when this detection happens and not something as hardcoded as this resource has done it... else, you could have just sent it directly to the requester or paste into into a comment on his thread... because resources on the spells section should be for the general public and not just for a specific person... :)

sure, it is a little bit useful as it is, but doing the suggestion will make this system far more useful and will offer lots of other possibilities...
 
Top