• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Damage events

Status
Not open for further replies.
Level 12
Joined
May 22, 2015
Messages
1,051
I heard multiple damage events can fire for a unit on the same frame if they happen to take damage from multiple sources on that frame.

If it happens, is it run like:
damage1 event (fire triggers)
damage1 applied (reduce the unit's health)
damage2 event
damage2 applied

or like:
damage1 event
damage2 event
damage1 applied
damage2 applied
 
Damage detection systems are engineered to run in the correct order (the first one you mentioned).

The problem is that the "cheat death" ability that adds a boatload of HP to the unit in case it would die from the damage must be removed after a nulltimer expires.

A nulltimer, will always expire at the bottom of the current trigger stack, which means that any damage event after the first that happens in the very same moment (for example from a unit that has a proc attack that deals 2 damage types at once) will run before the timer expired.


Single consecutive damage event:
damage1 event
damage1 dealt
timer1 expires
damage2 event
damage2 dealt
timer2 expires

Double damage event:
damage1 event
damage1 dealt
damage2 event
damage2 dealt
timer1 expires
timer2 expires


So, why (and when) does this matter? As long as the ability is removed again, all's good, right? Wrong! As soon as an attack deals percentual damage based on the target's health, things will bug out:

Event1 fires --> unit health is low --> system adds the cheat death ability
Event2 fires --> unit already has cheat death ability --> Any maxhealth checks in the damage trigger will return the wrong value
Timer expires --> cheat death ability is cleared
 
Level 12
Joined
May 22, 2015
Messages
1,051
Only in poorly engineered damage detection systems.

The problem is that the "cheat death" ability that adds a boatload of HP to the unit in case it would die from the damage must be removed after a nulltimer expires.

A nulltimer, however, will always expire at the bottom of the current trigger stack, which means that any damage event after the first that happens in the very same moment (for example from a unit that has a proc attack that deals 2 damage types at once) will run before the timer expired.


Single consecutive damage event:
damage1 event
timer expires
damage2 event
timer expires

Double damage event:
damage1 event
damage2 event
timer expires
timer expires


So, why (and when) does this matter? As long as the ability is removed again, all's good, right? Wrong! As soon as an attack deals percentual damage based on the target's health, things will bug out:

Event1 fires --> unit health is low --> system adds the cheat death ability
Event2 fires --> unit already has cheat death ability --> Any maxhealth checks in the damage trigger will return the wrong value
Timer expires --> cheat death ability is cleared

Is a nulltimer different from a timer that expires after 0 seconds?

And I understand this issue at least decently. In the double damage event, though:
Double damage event:
damage1 event
damage2 event
timer expires
timer expires

When does the actual damage happen (not the triggers that fire or the timers that expire, the actual normal damage that caused the triggers to fire).

Example with 1 damage event (the damage done will be 100) that fires one timer:
damage1 event - the trigger runs
100 damage dealt
timer expires

I am pretty sure this is the case, but when two events fire, I am not sure what happens. Is it like this? Assume the first damage event is 100 damage and the second is 50:
damage1 event - the trigger runs
100 damage dealt
damage2 event - the trigger runs
50 damage dealt
timer expires
timer expires

Or does it happen like this?
damage1 event - the trigger runs
damage2 event - the trigger runs
100 damage dealt
50 damage dealt
timer expires
timer expires
 
Is a nulltimer different from a timer that expires after 0 seconds?
A nulltimer is a timer that expires after 0 seconds (it's just a term I personally use).

And I understand this issue at least decently. In the double damage event, though:
Double damage event:
damage1 event
damage2 event
timer expires
timer expires

When does the actual damage happen (not the triggers that fire or the timers that expire, the actual normal damage that caused the triggers to fire).
Right after the event and before the second event fires.

I am pretty sure this is the case, but when two events fire, I am not sure what happens. Is it like this? Assume the first damage event is 100 damage and the second is 50:
damage1 event - the trigger runs
100 damage dealt
damage2 event - the trigger runs
50 damage dealt
timer expires
timer expires
This one is correct.
 
Level 12
Joined
May 22, 2015
Messages
1,051
A nulltimer is a timer that expires after 0 seconds (it's just a term I personally use).


Right after the event and before the second event fires.


This one is correct.

Cool. That's what I needed to know :D

BTW, what do the damage detection systems do to deal with that problem (max health when the unit has the cheat death health bonus)?

I am doing something I probably shouldn't do haha but I've been making my own built-in damage system for my map. I know it's better to just use ones already made (as a programmer, I know that is what you should always try to do), but I find it fun to work through the logic problems it presents.

Anyway, when I was messing around with some nulltimers (I'll use your term because it is easier to use in sentences lol) to deal delayed damage or healing after damage, I noticed that the unit health bars would flicker sometimes as if they draw more frequently than everything else in the game. I don't know if I just happened to mess up with something or if it means I can't use delayed healing to prevent damage after it has been dealt. Anyway, I am worried that adding the cheat death ability will make the unit's health bar jump around in a similar manner (depending on what I do with it - they will either appear to have full health or they will appear to be almost dead).

To make it more clear:
Damage event dealing X damage
X damage applied
timer expires and heals X health

I want to note that this is no longer how it is doing it, but just something I tested out. I already see a problem where the unit's health dips too far down so they may die from a second damage event before the timer expires.

Anyway, while messing around with this, I could still see units' health bars drop below full health. It didn't happen every time, and it was always for a very short time (probably 1 frame), but it looked bad and is not something I want. I suspect the same issue (though a little different) will arise when I try to do stuff with the cheat death ability.

Is this a problem damage systems face and have to deal with? How do they deal with it, usually?
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
DThe problem is that the "cheat death" ability that adds a boatload of HP to the unit in case it would die from the damage must be removed after a nulltimer expires.
First of all it is not a "nulltimer" but a "0s timer" ;)
A null timer would be a timer variable pointing at null
Also, that is only the case for DDS that do not have health event triggers to reset the health immediately after the damage has been taken.
It is like... a billion times better than 0s timers.

Can you elaborate on the unitstateevent trick?
You have to understand how WC3 works behind the scenes and when the events are given.

First you have a unit that attacks another unit.
As soon as the attack hits its target, any effects (armor, armor types, spells, etc) will be applied on the attack and calculate the final damage.

Then the unit is damaged.
First you get the event.
Immediately after that, your unit will be damaged.
(This event is used in all proper DDS.)

As soon as your unit is damaged, his life changes.
But ofcourse the life changes after you applied the damage.
This means that if you as the last thing that you do in the onDamage event, create a trigger and create the "targets life becomes below current life -x" (x should be half of the damage taken with a minimum of 0.0625 (iirc))
Then your damage will trigger that event because the life became less than that. (Ofcourse there come some cases where it wouldnt properly work... life boundaries (min or max), negative damage, damage that is lower than 0.0625, etc)

In any case, you have an event that fires directly after the health has been taken.
So you have:

Unit1 is damaged. -> Damage event fired.
Damage taken. -> Health event fired.
Health reset.
Unit2 is damaged. -> Damage event fired.
Damage taken. -> Health event fired.
Health reset.
etc.

This means that you also have proper data in your trigger/script when you do:
Unit - Damage target...
Set X = Life of target.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Man that is good way to set it up. Thanks for this! +rep to everyone except Zwiebelchen and Bribe I already gave rep to haha.
 
Level 13
Joined
Jan 2, 2016
Messages
978
Level 12
Joined
May 22, 2015
Messages
1,051
So these "unit life" event triggers to fire right after the actual damage is done, I want to create and destroy these every time, right? I imagine trying to reuse them would cause major problems.

I set up the 200% magic resistance trick so that magic damage can be detected and modified the damage trigger to then flip the damage back (using this unit life event trick) and it seems to be working properly. I ran around flame striking everything on my map and it was like nothing changed (after working out some funny bugs lol).
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
Well... re-using them would be 100% more efficient than making a new trigger each time. (100% as in "no doubt")
However, there is the same problem with the "A unit is damaged" event, you cannot remove events from a trigger, so you have to re-create the trigger each time to avoid unexpected executions.

I hear you are making a DDS yourself... May I ask why?
 
Level 12
Joined
May 22, 2015
Messages
1,051
Well... re-using them would be 100% more efficient than making a new trigger each time. (100% as in "no doubt")
However, there is the same problem with the "A unit is damaged" event, you cannot remove events from a trigger, so you have to re-create the trigger each time to avoid unexpected executions.

I hear you are making a DDS yourself... May I ask why?

It's not meant to be a library or anything, I am just coding it myself for fun. I enjoy the challenge and I find it interesting to learn about.

So reusing it is obviously the best thing to do, if possible, but I don't see a way I can do that without creating other bugs. Are you saying it would be more efficient and I should do it, or that it would definitely be more efficient, but is not possible?
 
I'll give you this information since you seem to be coding for fun and seem to be interested in combat systems right now : ).


A DDS by itself is not enough to do a proper combat system. A DDS is good for altering damage from the defender's point of view, but it's not at all good for applying things like attack bonuses. The reason is that the damage should be calculated at the point that the attack is made, not when the damage is applied. If a unit launches a projectile and that unit has 20 damage, then the unit suddenly gets a code buff that adds 100 damage, then the projectile hits, the target will be hit for 120 damage instead of the correct 20 damage.

This is where you use both the attack event and damage event. Making the damage event refer back to the attack event is tricky. For this, you need what's called an attack indexer. For the longest time, people have tried to solve how to create an attack indexer. Several attempts at a library have been made. In the past couple of years, someone came up with a solution. While we now all know how to make an attack indexer, the problem is that nobody has sat down and actually written it yet ; P. It's like "what a pain," lol. With this, you'll be able to link instances of vanilla warcraft 3 attacks to damage events.

The solution is to use a bonus library to modify the unit's damage be a unique integer that can be used with arrays to store data. When the target takes damage, use the damage it took in the event to access the arrays to retrieve the actual attack data. You would have to change all armor types to have no damage reduction, reduce all armor to 0, and forsake object editor attack values. You would store all of this information in code instead and have to figure out another way to display unit information, like attack type, armor type, attack, and defense. The pro is that you will be free to do literally whatever you like. 100 custom attack types? No problem. Layered armor? A-Ok.


The other thing is that you probably want unit specific damage/attack events and global damage/attack events, and you want these to run in a specific order.




Long story short, if you make an attack indexer, we will all <3.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
I made one... but it doesnt link WC3 attacks because I refuse to use almost every standard WC3 feature.

The damage instance doesnt necessarily have to be created when the missile is launched.
You maybe wont even be dealing damage with it.
So I say, you just store the variables of your damage and damage type etc and create the actual damage instance on hit.
 
Level 12
Joined
May 22, 2015
Messages
1,051
That is sort of more than I am aiming to do. Maybe one day, but I don't think I will need it for my map.

Anyway, I set up all the damage modification cases (bonus damage, reduced damage, negative damage flipped for magic damage). Seems like it is all working properly, so I decided to stress test it. I set the damage to 0 at the end of the damage trigger (just before it figures out how to handle the damage when it is different from the original damage) - negating all damage if it works correctly.

It worked almost perfectly - I noticed a couple spots where a unit took damage (I am wondering if that happens when the damage trigger is rebuilt). Other than 2 of those within the first 10ish minutes, nothing bad happened. After that, though, some craaaazy things started happening. The kill count for one of the players (would be index 0 of an array, I think) started just shooting up super fast (a few thousand after a couple minutes). A couple units didn't lose the cheat death ability so they had 50000 bonus health. I suppose it wasn't too bad since that is all that happened, but it was very strange.

I remember reading somewhere (might have been a post by DSG) that deleting triggers can be dangerous. Is that maybe what caused this?

Anyway, I don't plan to negate all damage in my map all the time (and the units did pile up more than usual since no units were dying - though there are unit caps for both teams so it wasn't ridiculous). However, I am curious what might have caused such strange errors.
 
Level 12
Joined
May 22, 2015
Messages
1,051
How are you handling recursion and life of units who possess the cheat death ability? Are there triggers we can see to help you debug this?

I can't post them right now (not at home).

I have a global flag variable. If I set it to true, damage dealt is ignored (function returns before doing anything).

I set up my damage triggers to always do damage after a 0s timer (if they have a special effect that deals some separate damage - like 10 bonus magic damage or something). It is set up now so that setting the damage global will modify the current damage and it is all handled at the very end of the damage trigger.

The case that I think is breaking is when damage needs to be prevented and prehealing the unit (healing them before the actual damage is dealt) will put them above their max life. In this case, I:
- store their current life
- add the damageSponge ability (adds 50000 life)
- set their current life to the stored value + the amount to preheal
- Create a trigger with the event "life drops below (life + preheal) - (damage / 2)"

In that trigger, I:
- store the unit's current life.
- remove the damageSponge ability
- set the unit's current life to the stored value
- destroy triggering trigger

_____________________________

Anyway, I wanted to ask about it in case someone knew quickly what the problem was. I will do more thorough debugging myself when I get the chance. I'll post the trigger up if I am having problems with it and can't figure anything out.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
That is only a problem if the check is done on a point that exceeds floating points (10,000,000 times lower at least) or when it is below the smallest difference possible (~0.0625 iirc).

The other problem is that the health has to be higher than the check and has to be below the check after the damage.
This means that you have to check with maximum health on negative damage and minimum health on damage. However, during that time, your unit has 500k more health... it shouldnt be a big problem at that point.
 
Level 12
Joined
May 22, 2015
Messages
1,051
A DDS should be using a timer at all except if you use a timer to refesh the trigger every once in a while.

Hmm I might have worded it wrong. The timers are so that damaging effects on damage happen afterwards - as a separate damage event. At no point do I damage any units while handling a damage event because it would cause a headache's-worth of bugs / edge cases or even infinite loops / game crashes. I don't want to just turn off the DDS because it would ignore all of the effects handled by the DDS (such as flipping negative magic damage, potentially amplifying or reducing damage, or applying effects like a custom bash).

I guess what I want to say is the DDS doesn't use timers, but some of the code that uses the DDS uses timers and I specifically handled separate damage events in those cases by having them happen after a 0s timer (these cases are basically always on-hit, which is checked with a buff, so the damage afterwards won't fire the on-hit effects unless I specify for them to).

The only case that this is not the case is in the DDS itself when I want damage to be amplified - I just do:
set udg_ignore = true
*do the bonus damage*
set udg_ignore = false

The bonus damage in this case has to be pure damage (as in, goes through armour and magic resistance) because it would be inaccurate when compared with the damage variable (the variable holding the amount of damage the unit takes). This would cause things like 10% life steal to get an inaccurate number.

EDIT:
I guess you edited your post :D

The magic damage flip is handled separately earlier in the trigger. Basically, if the incoming damage is negative, it sets up a different trigger.
- Checks if it can pre-damage the unit (set left lower) without killing it
- If it can, it does that
- If not, it checks if the unit will be healed over its max health and adds the damage sponge ability
- a boolean is set depending on the outcome of the above (called preDamaged indicating the unit has already been predamaged)
- builds a trigger to fire when the unit is above current life + damage / 2

Then the trigger:
- if not pre-damaged, it does the damage now
- removes the damage sponge ability (storing and setting life like the damage reduction trigger)
- sets the magicDamage flag to true and deals true damage equal to the damage
- destroys itself

^ I wonder if this is another possible point of failure. The trigger remains until the new damage event resolves. I don't know if there is some obscure case where the unit's health can go down and up again before finishing.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Then you dont understand the concepts of a DDS.
Any DDS should be working perfectly if the damage is dealt on hit.
If you do something else, then you have a glitching DDS no matter what you think.

Could be. I will think over my ideas more. I have thought about it and usually get stumped by the cases where dealing bonus damage would kill the unit when the unit is supposed to be able to block all damage (or enough damage that they should not die). Turning off the DDS would mean the damage prevention can't happen.

I am wondering:
does it work like a stack where dealing damage fires the event and basically works like a function call?

Could I do something like
JASS:
local unit s = udg_source
local unit v = udg_victim
local real d = udg_damage

// Do some damage here

set udg_source = s
set udg_victim = v
set udg_damage = d

The thinking would be that the code after "Do some damage here" would not run until the damage event caused by that line is fully resolved (assuming that line was actually a damage function). Maybe this could help me work through the problem. Since I don't have a full grasp of what happens behind the JASS code I see, it is hard for me to do these things. I don't want to write broken stuff. I'd rather have slightly hacky things where I know what is happening.
 
That would be fine if in-game damage processing is all you care about. But the only "pure" damage is to use SetWidgetLife to a minimum of 0.41 and to let the source unit deal the rest of the damage if it needs to kill it.

I was messing with a vJass version of Damage Engine, which you can find in The Lab; in it, I made a way where you can add to or subtract from the damage by the formula: DamageAmount +/- AdditiveValue*DamageAmount/OriginalDamage. This is good so you don't have to worry about adding an amount to an amount which was fully blocked, and lets the amount get amplified/reduced based on the ratio of previous modification. If you don't do it this way, you have to prioritize your damage modification events. That is tedious and prone to errors.

Edit:

JASS:
local unit s = udg_source
local unit v = udg_victim
local real d = udg_damage

// Do some damage here

set udg_source = s
set udg_victim = v
set udg_damage = d

While that works to an extent, you will need to use a stack+arrays to pass those arguments to the AfterDamageEvent recursively. If you rely on locals only, the AfterDamageEvent will not have the correct data unless you attached all that data to the dynamic trigger using a hashtable (which is much less efficient).
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
Then you are using a variable cache...
I suggest you to index the damage instances instead.
Because caching would mean that any of the user implemented variables are not valid any more when you have nested damage.

You will eventually have to cache the index though but with that index, you then access all user implemented variables from arrays.

EDIT:
@Bribe
Unless you have two separate things:
1, Bonus Damage.
2, Damage Factor.

Then it doesnt matter in which order they run.
Blocking damage shouldnt be done by simply setting it to 0.
Instead setting a boolean to true should do the job.
 
Level 12
Joined
May 22, 2015
Messages
1,051
That would be fine if in-game damage processing is all you care about. But the only "pure" damage is to use SetWidgetLife to a minimum of 0.41 and to let the source unit deal the rest of the damage if it needs to kill it.

I was messing with a vJass version of Damage Engine, which you can find in The Lab; in it, I made a way where you can add to or subtract from the damage by the formula: DamageAmount +/- AdditiveValue*DamageAmount/OriginalDamage. This is good so you don't have to worry about adding an amount to an amount which was fully blocked, and lets the amount get amplified/reduced based on the ratio of previous modification. If you don't do it this way, you have to prioritize your damage modification events. That is tedious and prone to errors.

Oh I see. This might be the answer for me. I have the flat bonuses and multiplier bonuses separate as well as a final trigger that runs everything that can be run any time or need to be run after udg_damage is the final damage it will be set to. I can probably just tweak some stuff to get it to work like this.

Just something like "damageFactor" which I can set after the multiplier modifications.
 
Instead setting a boolean to true should do the job.

While true, the user has to check that boolean per registered code or the system has to short-circuit the event evaluator if the damage hits 0.

There are two key phases of damage modification: one is strictly modifying damage, the other uses a limited-value shield or debuff to modify any remaining damage. Mana Shield and Anti-Magic Shell were re-coded to work with Damage Engine in order to allow this.

The last phases are the damage-calculated event (safe to show a text tag) and the AfterDamgeEvent (safe to deal damage back to the souce unit from the target).

Honestly, SAUS, there exist so many DDS's already. The work has already been done for you.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
While true, the user has to check that boolean per registered code or the system has to short-circuit the event evaluator if the damage hits 0.
No.
Nowhere, where I do anything to the damage engine, I have to check if the boolean is true.
If that boolean is true, the value of the damage is never used.
Any effects that would apply if the damage would be applied run on the afterDamage event.
 
No.
Nowhere, where I do anything to the damage engine, I have to check if the boolean is true.
If that boolean is true, the value of the damage is never used.
Any effects that would apply if the damage would be applied run on the afterDamage event.

What if the user didn't know the damage reached 0 and didn't know they needed to set the boolean, then some other modifier amped it up again? Obviously, a "perfect" user doesn't run this risk.

Even if the boolean worked, you still need to have a second phase of damage modification for value-limited shields. It wouldn't be fair to have a mana shield deduct points for damage which would later get reduced to a lower amount. That's why the damage handling should be done on those phases I mentioned earlier:

Raw modification
Shield modification
Damage calculated (this one can be skipped in favor of the following)
After damage event
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
You have to add the event via actions.
"Trigger - Add to <trigger> the event (<unit>'s life becomes <operator> <value>)"
However, if you dont remove that event when you dont need it any more, then you have leaks.

First of all, I never tell someone to block the damage by setting the value to 0. So they will not assume it blocks the damage that way.
And there is only one user... me :D

I assume that you are referring to the WC3 standard shields like the basic Mana Shield spell.
In that case, no mine does NOTHING related to those.
Simply because I don't want to use them.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Really? o.o
I thought the event would trigger only upon the variable changing its value. Didn't think it will work if the value it's compared to is the one changed :p

This is what was suggested to me earlier in this thread :D

Then you are using a variable cache...
I suggest you to index the damage instances instead.
Because caching would mean that any of the user implemented variables are not valid any more when you have nested damage.

You will eventually have to cache the index though but with that index, you then access all user implemented variables from arrays.

EDIT:
@Bribe
Unless you have two separate things:
1, Bonus Damage.
2, Damage Factor.

Then it doesnt matter in which order they run.
Blocking damage shouldnt be done by simply setting it to 0.
Instead setting a boolean to true should do the job.

What do you mean by user implemented variables?

Do you mean every udg_myVariable that I use in the damage triggers will have problems? I understand that. I don't use any other variables except the damage event ones which are basically just:
udg_damage = GetEventDamage()
udg_source = GetDamageSource() // Don't remember if that's the exact function name.
udg_victim = GetTriggerUnit()

So the index idea is to make these arrays and index the damage events. Am I understanding that correctly? I will admit I don't know all the steps to indexing things like this, so I will have to figure that out.

I have some flag variables that would also need to be set up as arrays, but I can find all the ones that need to be changed on my own.

Do other variables need to be arrays, or just the global ones used in the damage system?
 
You have to add the event via actions.
"Trigger - Add to <trigger> the event (<unit>'s life becomes <operator> <value>)"
However, if you dont remove that event when you dont need it any more, then you have leaks.

Well, to be specific you need to destroy the trigger which expunges all events which were affiliated with it. If there was a way to destroy a single event from a trigger, it would revolutionize damage engines.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
I don't use any other variables except the damage event ones which are basically just:
udg_damage = GetEventDamage()
udg_source = GetDamageSource() // Don't remember if that's the exact function name.
udg_victim = GetTriggerUnit()
"GetEventDamageSource()" but ok.
The problem is that YOU may not have any more variables, but YOU can NEVER know what variables I use.
So instead of telling me to use normal variables, you tell me to use arrays instead.

So the index idea is to make these arrays and index the damage events. Am I understanding that correctly? I will admit I don't know all the steps to indexing things like this, so I will have to figure that out.
You just use the same indexing that you always use... EXCEPT that when an index drops out, you MAY NOT replace it with the latest index.
The indices MUST ALWAYS remain the same as long as the instance runs.

I have some flag variables that would also need to be set up as arrays, but I can find all the ones that need to be changed on my own.

Do other variables need to be arrays, or just the global ones used in the damage system?
Only variables that are related to the damage instance.
 
Level 13
Joined
Jan 2, 2016
Messages
978
I tried to do:
JASS:
function Trig_Damage_Block_Actions takes nothing returns nothing
    call SetUnitLifeBJ( udg_DmgBlock, udg_Temp_Health )
endfunction

//===========================================================================
function InitTrig_Damage_Block takes nothing returns nothing
    set gg_trg_Damage_Block = CreateTrigger(  )
    call TriggerRegisterUnitLifeEvent( gg_trg_Damage_Block, udg_DmgBlock, LESS_THAN, udg_Temp_Health )
    call TriggerAddAction( gg_trg_Damage_Block, function Trig_Damage_Block_Actions )
endfunction
but it didn't work xP
Oh, I had one extra "udg_DmgBlock" there, but even after removing it - it doesn't do anything

EDIT: I added a display message to the actions of the trigger, but it doesn't show it, so I guess the event doesn't run correctly :(
 
Level 12
Joined
May 22, 2015
Messages
1,051
"GetEventDamageSource()" but ok.
The problem is that YOU may not have any more variables, but YOU can NEVER know what variables I use.
So instead of telling me to use normal variables, you tell me to use arrays instead.


You just use the same indexing that you always use... EXCEPT that when an index drops out, you MAY NOT replace it with the latest index.
The indices MUST ALWAYS remain the same as long as the instance runs.


Only variables that are related to the damage instance.

Keep in mind this "system" is just for myself :p I am doing it for fun. There's no point for me to try competing with what's out there, already.

I tried to do:
JASS:
function Trig_Damage_Block_Actions takes nothing returns nothing
    call SetUnitLifeBJ( udg_DmgBlock, udg_Temp_Health )
endfunction

//===========================================================================
function InitTrig_Damage_Block takes nothing returns nothing
    set gg_trg_Damage_Block = CreateTrigger(  )
    call TriggerRegisterUnitLifeEvent( gg_trg_Damage_Block, udg_DmgBlock, LESS_THAN, udg_Temp_Health, udg_DmgBlock )
    call TriggerAddAction( gg_trg_Damage_Block, function Trig_Damage_Block_Actions )
endfunction
but it didn't work xP

I think you have too many parameters in the register event part.

call TriggerRegisterUnitLifeEvent( gg_trg_Damage_Block, udg_DmgBlock, LESS_THAN, udg_Temp_Health, udg_DmgBlock )
 
Level 13
Joined
Jan 2, 2016
Messages
978
Yeah, I fixed the parameter part, but it still doesn't work...
JASS:
function Trig_Damage_Block_Actions takes nothing returns nothing
    call SetUnitLifeBJ( udg_DmgBlock, udg_Temp_Health )
    call DisplayTextToForce(GetPlayersAll(),R2S(udg_Temp_Health))
endfunction

function InitTrig_Damage_Block takes nothing returns nothing
    set gg_trg_Damage_Block = CreateTrigger(  )
    call TriggerRegisterUnitLifeEvent( gg_trg_Damage_Block, udg_DmgBlock, LESS_THAN, udg_Temp_Health)
    call TriggerAddAction( gg_trg_Damage_Block, function Trig_Damage_Block_Actions )
endfunction
It doesn't display the text either..
 
Level 12
Joined
May 22, 2015
Messages
1,051
What is udg_Temp_Health?

Since this is in an InitTrig function, that means this code is run when the map is loading. Unless you set this variable somewhere else during this time, it will be 0. Life doesn't go below 0 afaik. It is most likely just never firing because it can't happen.

Similarly, udg_DmgBlock is probably a null unit at this point, so it has no unit to check and never fires because of that as well.

@Wietlol,
so does the nested damage event resolve just like a function call on a stack? Is that code I had there safe assuming those were the only variables it is possible to have?

Do you manage the damage event index by doing the same thing, except you only need to store and reset the index and ignore the other event variables? Then you would just refer to everything like:
udg_source[udg_damageIndex]
udg_victim[udg_damageIndex]
udg_damage[udg_damageIndex]
 
Status
Not open for further replies.
Top