• 🏆 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!
  • ✅ HD Level Design Contest #1 POLL is now OPEN! Check out the stunning visuals of the final entries. 🔗Click here to cast your vote!

Problems with Takes Damage event

Status
Not open for further replies.
Level 6
Joined
May 15, 2009
Messages
191
Hello fellow Hive members. Oddly it has been a while since I asked for help in creating a trigger/ability for my map. However, I am now in need of some help.

This time around I've tried to create a custom shield spell(Like anti-magic shell, but this should work for all kinds of damage) that will absorb a set amount of damage per level.

Ofc I needed to see how much damage was dealt to the hero(in order to "heal" it) so I found myself using the (Unit takes damage) event. I heard some talk saying that the event was triggered before the damage was dealt - or something, and that might be my problem. But here is the triggers.

  • Death Shroud Apply
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Death Shroud
    • Actions
      • Set DeathShroud_Value = ((((Level of Death Shroud for (Triggering unit)) x 100) x (Integer(0.70))) + 30)
  • Death Shroud Damage
    • Events
      • Unit - Underworld Knight 0043 <gen> Takes damage
    • Conditions
      • ((Triggering unit) has buff Death Shroud ) Equal to True
    • Actions
      • Set DeathShroud_Value = (DeathShroud_Value - (Integer((Damage taken))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DeathShroud_Value Greater than 0
        • Then - Actions
          • Unit - Set life of (Triggering unit) to ((Life of (Triggering unit)) + (Damage taken))
        • Else - Actions
          • Unit - Remove Death Shroud buff from (Triggering unit)
However, the damage dealt to the hero is simply not healed. If (Unit takes Damage) does not immediatly record the damage taken, Im guessing I have to do a (Turn on Trigger) function to find another way of healing it. Thx in advance for help guys and gals.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,171
The event fires before the damage is applied in the flow of the program.
Units can not have more than maximum life in health.
Units will be killed if life drops below 0.405.

This means....
If you reheal immediatly (in handler for trigger) you will not be able to compensate for damage at high life values (where the life of the unit is greater than max life of the unit minus the damage dealt).
If you reheal after a delay (using a timer with 0 timeout) you will not be able to compensate for damage at low life values (where the life of the unit is less than the sum of damage taken during the delay +0.405) cause the unit will die.

The only real solution to this is to reheal the unit and even boost the maximum life of the unit until the delay handler is run to set the life correctly. This is no easy task as you have to keep track of all damage dealt to the unit, its life it should have as well as the amount to absorb. Let us not forget that a unit can take multiple damage hits in the time a 0 duration timer takes to expire.
 
Level 6
Joined
May 15, 2009
Messages
191
Well from all this information im starting to think, that I might have overestimated myself. However I will try to do what you guys said (Raise health and fix Integer to make it a real). But if I can't make it work without too much effort, I will come up with another ability for that hero.
And btw how much extra health? Can it be any value or does it need to be specific?


Ps. Maker, I have already added your name to the special credits of my map, I hope you do not mind.
 
Level 13
Joined
Mar 16, 2008
Messages
941
The event fires before the damage is applied in the flow of the program.
Units can not have more than maximum life in health.
Units will be killed if life drops below 0.405.

This means....
If you reheal immediatly (in handler for trigger) you will not be able to compensate for damage at high life values (where the life of the unit is greater than max life of the unit minus the damage dealt).
If you reheal after a delay (using a timer with 0 timeout) you will not be able to compensate for damage at low life values (where the life of the unit is less than the sum of damage taken during the delay +0.405) cause the unit will die.

The only real solution to this is to reheal the unit and even boost the maximum life of the unit until the delay handler is run to set the life correctly. This is no easy task as you have to keep track of all damage dealt to the unit, its life it should have as well as the amount to absorb. Let us not forget that a unit can take multiple damage hits in the time a 0 duration timer takes to expire.

You can easily split the heal in two parts. At full HP you could survive everything that deals 1 damage less then your maximum HP. At 1 HP you could survive everything that deals 1 damage less then the double amount of your HP. Only if this fails you need the HP boost.
 
Level 6
Joined
May 15, 2009
Messages
191
So, the answer to my problem is?
Im not meaning to be rude, but only Maker has given me something solid to change (Integer to Real) and I really want this spell to work. So...

1. How do I make the heal? Would I need to turn on another trigger after 1 second to do the healing? Or Something else?

2. If needed, how much extra health must be added?
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,171
1. How do I make the heal? Would I need to turn on another trigger after 1 second to do the healing? Or Something else?
No you just make a timer with 0 timeout run a function which does the healing.

If needed, how much extra health must be added?
Depends on the damage in your map. Usually a huge value is used but none at all could work as long as you reheal the unit enough.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
To be honest with information guys above gave you, you could that by yourself. Don't judge, since I see you haven't undertood they have been talking to you.

Hope this solves your problem. Uses Unit Indexer and GDD. Configure duration and amount of damage block as desired, and ofcourse you can change formulas I have used in 'Main' trigger.

Note: SacredLife is a custom ability based on item's one that increases life permanently as long as item is hold. Set the value of added life to maximum what means 99999.

  • Configuration
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • Set BaseDuration = 10.00
      • Set BaseBlock = 300.00
  • Main
    • Events
      • Unit - A unit Starts the effect of ability
    • Conditions
      • (Ability being cast) Equal to Sacred Shield
    • Actions
      • Set TempInt = (Level of Sacred Shield for (Triggering unit))
      • Unit Group - Add (Target of ability being cast) to ShieldGroup
      • Set key = (Custom value of (Triggering unit))
      • Set RealDuration[key] = (BaseDuration + (TempInt x 5))
      • Set RealBlock = (BaseBlock + (TempInt x 100))
      • Trigger - Turn on Loop <gen>
  • Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in ShieldGroup and do Actions
        • Loop - Actions
          • Set key (Custom value of (Picked unit))
          • Set RealDuration[key] = (RealDuration[key] - 0.03)
          • If (All conditions are true) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is Dead) Equal to True
              • RealDuration[key] Less or equal to 0.00
            • Then - Actions
              • Unit Group - Remove (Picked unit) from ShieldGroup
            • Else - Actions
  • Get Damage
    • Events
      • GDD_Event becomes Equal to 0.00
    • Conditions
      • (GDD_DamagedUnit is in ShieldGroup) Equal to True
    • Actions
      • Set key = (Custom value of (DGG_DamagedUnit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDD_Damage Greater than RealBlock[key]
        • Then - Actions
          • Unit Group - Remove GDD_DamagedUnit from ShieldGroup
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (RealBlock[key] + (Life of GDD_DamagedUnit)) Less or equal to (Maximum life of GDD_DamagedUnit)
            • Then - Actions
              • Unit - Set life of GDD_DamagedUnit to ((Life of GDD_DamagedUnit) + RealBlock[key])
            • Else - Actions
              • Unit - Add SacredLife to GDD_DamagedUnit
              • Unit - Set life of GDD_DamagedUnit to ((Life of GDD_DamagedUnit) + RealBlock[key])
              • Unit Group - Add GDD_DamagedUnit to DelayBlockGroup
              • Timer - Start DelayBlock as a One shoot timer that will expire in 0.00 seconds
          • Set RealBlock[key] = 0.00
        • Else - Actions
          • Set RealBlock[key] = (RealBlock[key] - GDD_Damage)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (GDD_Damage + (Life of GDD_DamagedUnit)) Less or equal to (Maximum life of GDD_DamagedUnit)
            • Then - Actions
              • Unit - Set life of GDD_DamagedUnit to ((Life of GDD_DamagedUnit) + GDD_Damage)
            • Else - Actions
              • Unit - Add SacredLife to GDD_DamagedUnit
              • Unit - Set life of GDD_DamagedUnit to ((Life of GDD_DamagedUnit) + GDD_Damage)
              • Unit Group - Add GDD_DamagedUnit to DelayBlockGroup
              • Timer - Start DelayBlock as a One shoot timer that will expire in 0.00 seconds
  • Block Damage
    • Events
      • Time - DelayBlock expires
    • Conditions
    • Actions
      • Unit Group - Pick every unit in DelayBlockGroup and do (Actions)
        • Loop - Actions
          • Unit - Remove SacredLife from (Picked unit)
          • Unit Group - Remove (Picked unit) from DelayBlockGroup
 
Level 6
Joined
May 15, 2009
Messages
191
Thx for all the help guys. Will try out this sometime, but I think I can make my original trigger work with the advice.

Ps. Spinnaker, I did at no point mean to judge or in any way offend the good Dr. and the others, I just did not quite understand their posts. Since really, I can only do basic ability triggering. Like, AoE life steal, or damage based on hero intelligence.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
That looks pretty good Spinnaker, but it might still bug when the unit is attacked by multiple units. The unit can take damage more than once between starting the timer and the timer expiring.

You can test it by ordering about 15 ranged units to attack the buffed unit. Order the buffed unit to move around so the attack intervals become pseudo random.

You can keep track of how many times the timer has expired and how many times the unit has been damaged by updating integer values. Though the difference should manifest itself clearly when observing the health of the unit.

The solution is to use a hit count check of sorts, you must check whether the unit has taken damage but not have the extra health removed yet and then recalculate the new health.

I had some trouble with this kind of system for my Powerslave map, but managed to solve it.
 
Level 6
Joined
May 15, 2009
Messages
191
Thx for all the help, but I prefer to make the systems by myself somehow, instead of copying. Else I will never learn. My trigger(s) now look like this. But it still won't heal the damage. I guess I should possibly stick to simpler spells, until I get better at this.

Anyway, if you know what the problem is, help is much appreciated.

  • Death Shroud Appliance
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Death Shroud
    • Actions
      • Set DeathShroud_Caster = (Triggering unit)
      • Set DeathShroud_Value = ((((Real((Level of Death Shroud for (Triggering unit)))) x 100.00) x 0.70) + 30.00)
  • Death Shroud Damage
    • Events
      • Unit - Underworld Knight 0043 <gen> Takes damage
    • Conditions
      • ((Triggering unit) has buff Death Shroud ) Equal to True
    • Actions
      • Set DeathShroud_Value = (DeathShroud_Value - (Damage taken))
      • Countdown Timer - Start DeathShroud_Timer as a One-shot timer that will expire in 0.00 seconds
  • Death Shroud Heal
    • Events
      • Time - DeathShroud_Timer expires
    • Conditions
      • (DeathShroud_Caster has buff Death Shroud ) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DeathShroud_Value Greater than 0.00
        • Then - Actions
          • Unit - Set life of DeathShroud_Caster to ((Life of DeathShroud_Caster) + (Damage taken))
        • Else - Actions
          • Unit - Remove Death Shroud buff from DeathShroud_Caster
Thats what I've got so far, with no healing at all(Note, the hero will not take more than his max health in damage)
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
You have to save (Damage taken) into variable in order to be able to healheal given unit after expiration of the timer. Since trigger with expiration timer has event 'timer expires' thus it doesn't provide proper responce for (Damage taken) therefore (Damage taken) returns null.

Why don't you try my solution? It's not perfect as you could hear because of multiple attack issues but isn't bad either. Will fix the issue later.
 
Level 6
Joined
May 15, 2009
Messages
191
Duuuuhhh should have thought of that. I forgot that changing the event will delete any Event Response... Dumb flaw there. Btw I tested it, and neither setting the Damage Taken as an integer, or a real seems to work. I can't make sense of it.

Ps. Spinnaker, the reason that I do not use your solution is bc I want to learn how to do this myself.
 
Last edited:
Status
Not open for further replies.
Top