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

[Solved] Problem with attachment on unit health %

Status
Not open for further replies.
Level 3
Joined
Dec 23, 2005
Messages
29
Hello all, i've hit a problem with a trigger i'm trying to make in my RPG map and can't seem to figure it out on my own.

The triggers intention is so when HEROP1's health gets to a certain health percentage, an icon appears above his head.

This works to a varying degree, it seems as though the trigger is malfunctioning, sometimes showing the Gold icon when its supposed to be the Red or Green. It also rapidly switches between the icons randomly when it approaches the percentages in the trigger. When the unit reaches 100% health, the icon does not disappear.

Things to note:
-the variable HEROP1 is assigned to the 'Cleric 0018' Unit in another trigger.
-The event timer is a looping timer set up in another trigger which plays every 0.03s. I was playing around with periodic timer and this timer to see if there was an issue there.
- I've tried placing the 'If/Then/Else' triggers into one large trigger, with each 'If/Then/Else' being placed into the 'Else' fields.



  • Untitled Trigger 013 Copy Copy Copy
    • Events
      • Time - IconHealthTimer expires
    • Conditions
    • Actions
      • Special Effect - Destroy PlayerIconOverhead[1]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Percentage life of HEROP1) Equal to 100.00
        • Then - Actions
          • Special Effect - Destroy PlayerIconOverhead[1]
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Percentage life of HEROP1) Less than or equal to 30.00
        • Then - Actions
          • Special Effect - Destroy PlayerIconOverhead[1]
          • Special Effect - Create a special effect attached to the overhead of Cleric 0118 <gen> using war3mapImported\ICONminimap-red-haunted.mdx
          • Set PlayerIconOverhead[1] = (Last created special effect)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Percentage life of HEROP1) Less than or equal to 75.00
          • And - All (Conditions) are true
            • Conditions
              • (Percentage life of HEROP1) Greater than 30.00
        • Then - Actions
          • Special Effect - Destroy PlayerIconOverhead[1]
          • Special Effect - Create a special effect attached to the overhead of Cleric 0118 <gen> using war3mapImported\ICONminimap-gold-haunted.mdx
          • Set PlayerIconOverhead[1] = (Last created special effect)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Percentage life of HEROP1) Greater than 75.00
          • And - All (Conditions) are true
            • Conditions
              • (Percentage life of HEROP1) Not equal to 100.00
        • Then - Actions
          • Special Effect - Destroy PlayerIconOverhead[1]
          • Special Effect - Create a special effect attached to the overhead of Cleric 0118 <gen> using war3mapImported\ICONminimap-green-haunted.mdx
          • Set PlayerIconOverhead[1] = (Last created special effect)
        • Else - Actions


Any help would be greatly appreciated!
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
  • You can use a periodic event instead of a timer expire event: Time - Every 0.03 seconds of game-time. 0.03 is probably much faster than this needs to be updated; I would use maybe 0.2.
  • All conditions are automatically 'AND'ed together, there is no need to make a separate AND grouping that only has one condition in it.
  • You will benefit greatly from using player-number-indexed array variables instead of separate variables for each player. I mean to do HEROES[1], HEROES[2] instead of HEROP1 HEROP2. This will allow you to loop over all players' variables in integer loops to improve your code.
  • Don't be afraid to use some variables to set up your health breakpoints to make it easy to modify. (see below triggers)
  • You have lots of duplicate code. Instead of having the create/destroy/set lines in every if block, you can just set a string variable = the effect you want to use, then use that variable in your effect creation.
  • This trigger destroys and re-creates the same effect many times a second as long as the unit is in the same hp range. If you really wanted to you could set an integer flag to tell you what hp range it was in the last time you checked, and only change the effect if it's different. I've done that below.
  • Events
    • Time - Elapsed game-time is 0.50 seconds
  • Conditions
  • Actions
    • Set HP_BREAK_COUNT = 3 //not 4, the 4th breakpoint is just for consistency at 100% and to make the icon disappear then.
    • Set HP_BREAK[1] = 0.00 //from 0 to 30
    • Set HP_BREAK[2] = 30.00 //from 30 to 75
    • Set HP_BREAK[3] = 75.00 //from 75 to 100
    • Set HP_BREAK[4] = 100.00
    • Set HP_EFFECT[1] = "war3mapImported\ICONminimap-red-haunted.mdx"
    • Set HP_EFFECT[2] = "war3mapImported\ICONminimap-gold-haunted.mdx"
    • Set HP_EFFECT[3] = "war3mapImported\ICONminimap-green-haunted.mdx"
  • Events
    • Time - Every 0.20 seconds of game-time
  • Conditions
  • Actions
    • For each (Integer A) from 1 to NumberOfPlayersThatHaveHeroes do (Actions)
      • Loop - Actions
        • Set HP_PCT = (Percentage Life of HEROES[(Integer A)])
        • For each (Integer B) from 1 to HP_BREAK_COUNT do (Actions)
          • Loop - Actions
            • If (All conditions are true) then do (then actions) else do (else actions)
              • If - Conditions
                • HP_PCT greater than or equal to HP_BREAK[(Integer B)]
                • HP_PCT less than than HP_BREAK[((Integer B) + 1)]
              • Then - Actions
                • Set EffectString = HP_EFFECT[(Integer B)]
                • Set NewHPState = (Integer B)
              • Else - Actions
        • If (All conditions are true) then do (then actions) else do (else actions)
          • If - Conditions
            • NewHPState not equal to PlayerHPState[(Integer A)]
          • Then - Actions
            • Special Effect - Destroy PlayerIconOverhead[(Integer A)]
            • Set PlayerHPState[(Integer A)] = NewHPState
            • If (All conditions are true) then do (then actions) else do (else actions)
              • If - Conditions
                • HP_PCT less than HP_BREAK[(HP_BREAK_COUNT + 1)]
              • Then - Actions
                • Special Effect - Create an effect attached to the overhead of HEROES[(Integer A)] using EffectString
                • Set PlayerIconOverhead[(Integer A)] = (Last created special effect)
              • Else - Actions
          • Else - Actions
 
Level 3
Joined
Dec 23, 2005
Messages
29
Thank you for the quick reply! I've copied your trigger over and i must have done something wrong along the way. The red Icon appears when starting the game, then taking some damage removes the icon until the unit dies, then it appears as red over the units corpse.

This is how i've made the trigger

  • ini new
    • Events
      • Time - Elapsed game time is 0.50 seconds
    • Conditions
    • Actions
      • Set HP_BREAK_COUNT = 3
      • Set HP_BREAK[1] = 0.00
      • Set HP_BREAK[2] = 30.00
      • Set HP_BREAK[3] = 75.00
      • Set HP_BREAK[4] = 100.00
      • Set HP_EFFECT[1] = war3mapImported\ICONminimap-red-haunted.mdx
      • Set HP_EFFECT[2] = war3mapImported\ICONminimap-gold-haunted.mdx
      • Set HP_EFFECT[3] = war3mapImported\ICONminimap-green-haunted.mdx

  • hp icon trigger
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 1, do (Actions)
        • Loop - Actions
          • Set HP_PCT = (Percentage life of HEROP1)
          • For each (Integer B) from 1 to HP_BREAK_COUNT, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • HP_PCT Greater than or equal to HP_BREAK[(Integer B)]
                  • HP_PCT Less than HP_BREAK[((Integer B) + 1)]
                • Then - Actions
                  • Set EffectString = HP_EFFECT[(Integer B)]
                  • Set NewHPState = (Integer B)
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • NewHPState Not equal to PlayerHPState[(Integer A)]
        • Then - Actions
          • Special Effect - Destroy PlayerIconOverhead[(Integer A)]
          • Set PlayerHPState[(Integer A)] = NewHPState
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • HP_PCT Less than HP_BREAK[(HP_BREAK_COUNT + 1)]
            • Then - Actions
              • Special Effect - Create a special effect attached to the overhead of HEROP1 using EffectString
            • Else - Actions
        • Else - Actions

The Variables i've copied from yours may not be the same, i apologize for my lack of knowledge here :(
This is how i imported and used the variables in your trigger


HP_PCT - Real
HP_EFFECT - String Array (3)
HP_BREAK_COUNT - Integer
HP_BREAK - Real Array (4)
NewHPState - Integer
PlayerHPState - Integer Array (1)

I'm using the array on some of these triggers to paste your references to [(Integer A/B)]

Thank you very much for your time to help me out!
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
  • Slight error in my method: also set HP_BREAK[5] = 101.00 (or any number greater than 100). It’s failing to detect the full health state because at 100% hp the HP_PCT is >= 100.00 but not also < 0.00 (since break point 5 was never set it’s defaulted to 0).
  • Slight improvement to my method: change the HP_PCT less than HP_BREAK[HP_BREAK_COUNT + 1] in the lowermost if block to NewHPState Not Equal to HP_BREAK_COUNT.
  • You’re not assigning PlayerIconOverhead[] after creating the effect, so it can never be destroyed.
  • The other NewHPState checking if block (and everything inside it) should be inside the Integer A loop, not outside it.
 
Level 3
Joined
Dec 23, 2005
Messages
29
I've applied those changes and it seems to work a little better now, the only problem being that the icon seems to take some time to change between the health % states. Sometimes when going above the 75% break, the icon remains yellow for a few seconds before turning green. When the Units health is in the 30 - 75% area, it flickers between yellow and red. The icon does remove now at 100%, after 4 or 5 seconds. It just seems like the Icon takes a while to update.

I understand you've spent some time trying to help me with this trigger and i very much appreciate it. I'll leave the triggers here again incase you want to see them, but i'm a little out of my depth here as you could see with my previous triggering :)

  • ini new
    • Events
      • Time - Elapsed game time is 0.50 seconds
    • Conditions
    • Actions
      • Set HP_BREAK_COUNT = 4
      • Set HP_BREAK[1] = 0.00
      • Set HP_BREAK[2] = 30.00
      • Set HP_BREAK[3] = 75.00
      • Set HP_BREAK[4] = 100.00
      • Set HP_BREAK[5] = 101.00
      • Set HP_EFFECT[1] = war3mapImported\ICONminimap-red-haunted.mdx
      • Set HP_EFFECT[2] = war3mapImported\ICONminimap-gold-haunted.mdx
      • Set HP_EFFECT[3] = war3mapImported\ICONminimap-green-haunted.mdx

  • hp icon trigger Copy
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 1, do (Actions)
        • Loop - Actions
          • Set HP_PCT = (Percentage life of HEROP1)
          • For each (Integer B) from 1 to HP_BREAK_COUNT, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • HP_PCT Greater than or equal to HP_BREAK[(Integer B)]
                  • HP_PCT Less than HP_BREAK[((Integer B) + 1)]
                • Then - Actions
                  • Set EffectString = HP_EFFECT[(Integer B)]
                  • Set NewHPState = (Integer B)
                • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • NewHPState Not equal to PlayerHPState[(Integer A)]
            • Then - Actions
              • Special Effect - Destroy PlayerIconOverhead[(Integer A)]
              • Set PlayerHPState[(Integer A)] = NewHPState
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • NewHPState Not equal to HP_BREAK_COUNT
                • Then - Actions
                  • Special Effect - Create a special effect attached to the overhead of HEROP1 using EffectString
                  • Set PlayerIconOverhead[(Integer A)] = (Last created special effect)
                • Else - Actions
            • Else - Actions


EDIT:

Here is a gif of how it displays in-game

 
Last edited by a moderator:
Level 38
Joined
Feb 27, 2007
Messages
4,951
It appears the damage being dealt to the player hero is out of sync with the skeletons attacks. I would recommend changing the skeleton's damage point in the OE to be later so when it connects with the swing its target takes damage.

That being said, my best guess is that the effect you are using for HP display doesn't have a proper death animation and it is simply lingering past when it is explicitly destroyed. When effects are destroyed they automatically play their death animation; not having one means the effect plays through its full stand loop instead (however long that is). You can test if this is the case by using some default wc3 projectiles as models for the hp display and then see if they are being destroyed properly at the right time, or by putting some Game - Display to all players the text "TEXT" debug messages in the parts of the trigger that destroy/create effects to see when they run (or what the value of some variables like PlayerHPState are).

If this is the case you will need to add a 1-frame death animation to the model to get it to disappear instantly.
 
Level 3
Joined
Dec 23, 2005
Messages
29
After changing the model to a model with a death animation, i can confirm that you are 100% correct about it being the model. I'll try and add a death animation to these models and then they should work perfectly.

Thank you very much for you patience and your help!

EDIT: And also thank you on picking up the attack damage point ;)
 
Status
Not open for further replies.
Top