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

[vJASS] [System] Physical Damage Detection

Level 24
Joined
Aug 1, 2013
Messages
4,657
The calculation is damage = damage * (1-SpellDamageReduction) right?
0.33: damage = damage * (1-0.33) = damage * 0.67
1: damage = damage * (1-1) = damage * 0
2: damage = damage * (1-2) = damage * -1
1.67: damage = damage * (1-1.67) = damage * -0.67
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
LFH, that runed bracers trick is a godsend. What a great find!

Thx :)

Luckily the bracers ability plays quite well with DDS and the game in general... The only real problems are life drain and finger of death but those can be easily recoded if required.

I have updated GUI Damage Engine to use this trick and the results are great. While studying your resource I have found some improvements that I want to share with you:

Thanks for the feedback, I will have a look at those suggestions.

I think the reason why it works is because when a unit has 2 abilities that can't stack, the one added most recently takes priority.

Correct, thats also the reason why bracers have to be coded manually in the genereal case. However thats not really a limitation because if you want to have stacking behavior (which is most likely the case if multiple bracer-like items with different spell damage reduction are used), you have to code them anyways.

You only need one unitdamagetarget, regardless of if it was ethereal or if it has the spell detect ability.

Well, thats the problem of dealing damage independent of custom armor tables and such things... You may read about the Hidden Attack Type, which was the reason why this distinction was made. The advantage is, that it is independent of custom armor values. Only disadvantage is that it does not work for ethereal units due to its basic type being of physical nature.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
looking_for_help said:
Correct, thats also the reason why bracers have to be coded manually in the genereal case. However thats not really a limitation because if you want to have stacking behavior (which is most likely the case if multiple bracer-like items with different spell damage reduction are used), you have to code them anyways.

Right, which is why the DDS's responsibility it to ensure that the user has to change their map only if necessary. If the user has done something like manually adjust the spell resistance via triggers, it would be easy to adapt that to use a DDS. However, if the user has multiple different runed bracers abilities, they simply need to change their values from value to 2-value.



Well, thats the problem of dealing damage independent of custom armor tables and such things... You may read about the Hidden Attack Type, which was the reason why this distinction was made. The advantage is, that it is independent of custom armor values. Only disadvantage is that it does not work for ethereal units due to its basic type being of physical nature.

Well, without getting into attacktype7, I can say that attacktype0 (null) has no problem hitting ethereal nor corporeal. With DAMAGE_TYPE_UNIVERSAL, you also break through spell immunity. With negative damage being dealt, you break through the engine's negative damage so you deal positive damage. Therefore, you don't need to remove the ability to deal damage, and you don't need to check whether or not it is ethereal.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Neshtarus: "why does my DDS bug if you say that the unit state event detected damage?"
I didnt said that your DDS bugs.
I said that your test scenario is either not good enough explained or there is something wrong with your WC3.

What could happen (that your dds didnt detect the damage) is that you compare "GetEventDamage() == 0" instead of "GetEventDamage() == 0."
Which means that GetEventDamage() is converted to an integer to match the parameter types of "real == integer".
Thats why you have to place the point behind the 0.

It might be the problem that <1 and >-1 are not detected.
But even then, a basic attack cannot deal less than 1 damage except when editted by spells or triggers.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
Well, without getting into attacktype7, I can say that attacktype0 (null) has no problem hitting ethereal nor corporeal. With DAMAGE_TYPE_UNIVERSAL, you also break through spell immunity. With negative damage being dealt, you break through the engine's negative damage so you deal positive damage. Therefore, you don't need to remove the ability to deal damage, and you don't need to check whether or not it is ethereal.

That can fail for the following condition:

  • The user sets any of the armor table constants for spell damage to zero

With using attacktype 7 and the compariosn for ethereal units it can fail for the following condition:

  • The user sets any of the armor table constants of ethereal units for spell damage to zero

which is a bit less restrictive than the former. The idea was to give the user as much flexibility as possible when modifing the armor table, even allowing zero values whenever possible.

What could happen (that your dds didnt detect the damage) is that you compare "GetEventDamage() == 0" instead of "GetEventDamage() == 0."

No, because then this wouldn't work as well:

JASS:
local real r = 0.1
if r == 0 then
    call BJDebugMsg("0 equal 0.1!")
else
    call BJDebugMsg("0 NOT equal to 0.1!")
endif

but it works, because the integer is promoted to real.

But even then, a basic attack cannot deal less than 1 damage except when editted by spells or triggers.

Well, but we want to detect all damages anyway, so that doesn't really matter, right? With spirit link for example its easily possible to let a basic physical attack deal 0.04 damage or even less.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
That can fail for the following condition:

  • The user sets any of the armor table constants for spell damage to zero

With using attacktype 7 and the compariosn for ethereal units it can fail for the following condition:

  • The user sets any of the armor table constants of ethereal units for spell damage to zero

If the user had set the spell damage constant to 0, they wouldn't have triggered the spell damage event in the first place. And in the event of physical damage, that function isn't even evoked since you simply let the already-launched damage kill the unit.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
If the user had set the spell damage constant to 0, they wouldn't have triggered the spell damage event in the first place. And in the event of physical damage, that function isn't even evoked since you simply let the already-launched damage kill the unit.

This is not necessarily related to a spell damage event at all.

Lets consider the following scenario:

  • We have an enemy unit, lets call it target, with 15 hitpoints and armor type "hero"
  • We have customized the damage table such that spell damage deals no damage to armor type "hero"
  • You have setup an onDamage handler that doubles all damage
  • Now some unit attacks target with 10 damage of attacktype piercing

What should happen? The unit will deal 10 damage. Then, because of our onDamage handler, the system has to deal another 10 damage to acount for the doubling of damage. So the system will deal additional 10 damage of attacktype "spell", resulting in 20 damage and kill the unit.

What will actually happen? The unit will deal 10 damage, the system tries to deal the remaining 10 damage using attacktype "spell". Because of the modified armor table, this damage won't be applied, resulting in 10 damage and not killing the unit.

See? No spell damage involved in the first place at all. Just dealing piercing damage to a hero. But your method will break.
 
Level 11
Joined
Dec 3, 2011
Messages
366
Sorry if these info are old: I used the system and the dead unit is considered by GetUnitLife(u)>1 rather than 0.405. And I also tested that Locust Swarm with Locust's att type set to Hero worked like normal (Default AT - Spells still need negative Return damage factor) (I didn't try the rest)
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
About the Locust Swarm, you are indeed correct, but that would result in physical damage being applied, which is not really what you want in most cases.

The GetUnitLife() > 1 is Blizzards fault.
IsUnitDeadBJ() checks using 1, however a unit dies when his health drops to 0.405 or lower.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
That's actually not correct. Maybe that's how you have it in your system, but in mine during that situation I simply set the target health to 0.41 and let the original piercing damage kill the target.

Well, your system actually fails in some basic situations. For example

JASS:
call UnitDamageTarget(u1, u2, 2000.0, true, false, null, DAMAGE_TYPE_UNIVERSAL, null)

will kill u2 even if I setup a DamageModifierEvent and set all damage to 10 (in this scenario, u2 has less than 2000 max HP but enough to survive the 10 damage). However, that should work.

I also have to comment a few things...

The only times that the cheat death ability is used is when the unit's max hp is lower than the damage amount AND it had to have come from physical damage.

I don't really get that argument, sry. If something like this can happen at all, is very unlikely to happen or will happen in 90% of the time is totally map specific? Its not uncommon that in RPG like maps you can one-hit enemies. As long as a system uses timers for after damage events, it needs special functions. Otherwise its impossible to ensure correctness, which should always have highest priority IMO.

You also do not need any "UnitDamageTargetEx" things in your map.

Because it doesn't support recursion, right? At least from what I can tell from the code, it just throws a warning if it detects a direct loop (no general loops though)?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Well, your system actually fails in some basic situations. For example

JASS:
call UnitDamageTarget(u1, u2, 2000.0, true, false, null, DAMAGE_TYPE_UNIVERSAL, null)

will kill u2 even if I setup a DamageModifierEvent and set all damage to 10 (in this scenario, u2 has less than 2000 max HP but enough to survive the 10 damage). However, that should work.

Since you've dealt spell damage, that means that you deal negative damage, effectively healing the unit. This doesn't kill the unit - what I think it does, however, is heal the unit for 2000-unitMaxHP with the way I have my system set up. I have to test it to see if it tried to heal beyond the max HP or if it worked fine when using SetWidgetLife in a single thread.

Its not uncommon that in RPG like maps you can one-hit enemies.

OK, and as I said - in those cases, the unit will be given the +HP ability and will not be killed (if the damage was set low enough that it shouldn't die, that is).


Because it doesn't support recursion, right? At least from what I can tell from the code, it just throws a warning if it detects a direct loop (no general loops though)?

You can issue a UnitDamageTarget command from within another damage event no problem - the system caches all variables regardless. What the system filters out is a repeat of the exact same: damage amount, target and source. As long as any one of those 3 things changes from within a nested UnitDamageTarget, everything is fine. I just tried to prevent the map from crashing in case the user does something s/he is not supposed to.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
This doesn't kill the unit - what I think it does, however, is heal the unit for 2000-unitMaxHP with the way I have my system set up.

That shouldn't kill the unit though.

OK, and as I said - in those cases, the unit will be given the +HP ability and will not be killed (if the damage was set low enough that it shouldn't die, that is).

How is that related to the problem?
It will cause bugs on some maps, thats the relevant thing.

Custom get/set life functions didn't exist in DamageEngine 2 and no one complained even after 3 or 4 years. I think their significance is blown out of proportion.

I was asked to add them to my system and quite some problems people had with the system were related to them not using those functions but the native ones.

Imagine some kind of "vampire" ability, that heals the attacker by, say 2% of the enemies max health. Random healing every now and then, a nightmare to debug if you don't know where you have to look at.

You can issue a UnitDamageTarget command from within another damage event no problem - the system caches all variables regardless.

Uhm yes. You can do that too in PDDS or any other DDS. Just avoiding recursion is trivial.

But thats not the point of UnitDamageTargetEx. Its purpose is to deal the damage in the order it was applied, even when being used from an onDamage handler. Your system lacks this functionality and there is no way to achieve something similar for the user.

What the system filters out is a repeat of the exact same: damage amount, target and source. As long as any one of those 3 things changes from within a nested UnitDamageTarget, everything is fine.

Hm, I'm not sure if this is desirable... First a user might want to deal exactly the same damage multiple times (recursion is stopped with a counter variable then for example after n damage events). And second there is still the danger of infinite recursion, if the loop spans over multiple units...
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
That shouldn't kill the unit though.

Again, it doesn't.



How is that related to the problem?
It will cause bugs on some maps, thats the relevant thing.

I was asked to add them to my system and quite some problems people had with the system were related to them not using those functions but the native ones.

Imagine some kind of "vampire" ability, that heals the attacker by, say 2% of the enemies max health. Random healing every now and then, a nightmare to debug if you don't know where you have to look at.

I will make a vJass plugin for DamageEngine 3, but it is still a very situational thing. If the unit has the max life ability, just subtract 500,000 HP. As far as the other HP goes, there are several philosophies on what you actually want the tertiary HP to represent. I think it's good to give the user the choice, though, so I'll include it in the vJass version.


But thats not the point of UnitDamageTargetEx. Its purpose is to deal the damage in the order it was applied, even when being used from an onDamage handler. Your system lacks this functionality and there is no way to achieve something similar for the user.

I must not have been around when the significance of this was brought up. This doesn't seem important at all.

Hm, I'm not sure if this is desirable... First a user might want to deal exactly the same damage multiple times (recursion is stopped with a counter variable then for example after n damage events). And second there is still the danger of infinite recursion, if the loop spans over multiple units...

Yeah, I was thinking of this yesterday after I wrote that. I think I'll just set a configurable hard cap at, by default, 16 or so.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
Again, it doesn't.

Lol, do you think I invent such things? Uploaded a testmap.

As far as the other HP goes, there are several philosophies on what you actually want the tertiary HP to represent.

Even if thats the case, the HP with applied max life ability is always wrong, no matter which philosophy.

I must not have been around when the significance of this was brought up. This doesn't seem important at all.

Don't judge too fast ;)

Just because you don't see an importance doesn't mean there is none. Easiest example: damage reflection. Unit A attacks unit B, B reflects damage on A. Both damages are fatal. Who will get the xp?

A should get the xp, because in chronological order he was the first to deal damage. At least this is what many users expect/want to have. However with your method, B will get the xp. This was btw also implemented on users requests.
 

Attachments

  • Damage_Engine_Break.w3x
    30.5 KB · Views: 69
Level 24
Joined
Aug 1, 2013
Messages
4,657
Why not have another variable called the CreditTaker... or something like that.
The source does not always take the credit for the kill.
However the source is always the one that deals the damage.
It is hard to make things flawless when they are set up in a fixed way.
Source is a variable that you use to refer when you are looking for certain conditions for spells for example.

If source has buff <...> then increase damage by 10.
If source is illusion or summoned unit, make CreditTaker be the one who spawned them.
If the source (the summoned unit) does not have the buff but the one who spawned it does, this would break when you dont have a CreditTaker variable.

Ofcourse it is a bit harder to implement in a generic system... but for more specialized system implementations (for a certain project for example), it is one of those things that are required to make things run in the right way.
 
Level 11
Joined
Dec 3, 2011
Messages
366
That bugs in Bribes system, correct.

In PDDS Incinerate works just fine.

I didn't try DamageEngine yet. I prefer PDDS since its a standalone system. In the picture, the damage on exploded unit is 999. Your system detects it as spell but the damaged unit stay alive even with low Hp when they're supposed to dead after just one explosion.
 

Attachments

  • Untitled.jpg
    Untitled.jpg
    111.1 KB · Views: 118
Level 14
Joined
Dec 12, 2012
Messages
1,007
I didn't try DamageEngine yet. I prefer PDDS since its a standalone system. In the picture, the damage on exploded unit is 999. Your system detects it as spell but the damaged unit stay alive even with low Hp when they're supposed to dead after just one explosion.

Can't reproduce, in my tests everything works fine. Upload an example map plz, not a screenshot.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
@Bribe
Instead of making the Get/SetUnitLife, make the 500k hp ability be removed when the health of the target has changed.
Unit State Events fire after the damage has been applied so you will essentially use two normal events to remove the regular damage.
The trigger and event should be made when the unit takes damage though.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
Thank you again, LFH! I have fixed the bug with triggered damage and have also fixed the potentially-buggy recursion issue.

I will work on a Get/SetUnitLife and a GetUnitMaxLife map header script and, later down the line, a vJass implementation.

Nice, will have a look at it :)

Wietlol said:
Unit State Events fire after the damage has been applied so you will essentially use two normal events to remove the regular damage.

Yes, unit state events would solve a lot issues (if not all), but there has to be done some research on this topic first... there is still no reference implementation of the mixed unit state events/timer technique Nestharus mentioned and I'm a bit worried about missing damage events due to float inaccuracy...
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
I dont really understand what you are saying.
How would there be damage events missing?

I mean after damage events. If the damage is too low, the life changed event won't fire. Thats why Nestharus proposed the mixed life changed/timer technique. However, you would have to find the boundaries empirically, which is brittle and in the worst case dependent from the units max life...

I don't say its impossible, but we have to investigate this further.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
The minimum health change that can be seen is 0.0625... any decent map shouldnt have such low values.

However I can see your point...

Not to mention a unit could have had its life changed by a nested SetWidgetLife/UnitDamageTarget and make it seem like it's all good when it's not.
The SetWidgetLife/UnitDamageTarget cannot be called between the trigger with the unit state event is made and when that trigger runs.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
The minimum health change that can be seen is 0.0625... any decent map shouldnt have such low values.

The problem is floating point inaccuracy. Wc3 real datatype (which is used for both health and damage) is internal a 32 bit float.

As such, it has the problem of relative accuracy. Floats have (about, dependes on the concrete value) 6 to 8 significant digits. That means that life changes can only be detected within the first 6 to 8 significant digits. So unfortunatly, the boundary is not 0.0625 (even that would be problematic though), but depends from the units max life.

Create a unit with 5000000 health (not that uncommon for bosses) and let a unit deal, say 2 damage. The after damage event won't fire. And that is already a relevant amount.

Maybe we can trick, by setting the units life before the damage is dealt to an amount that is within the epsilon. But thats still a lot of work and research.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Then I wonder... All units that need this event have a 500k bonus health, so the ussual unit on which I tested this had 501,000 health.
I tested thoroughly on 0.0624 and 0.0625 and that means that the difference is made on the 10th digit.

I do know about floating pointers being not 100% accurate but out of 500 damage tests, none failed to execute the event.

For units who already have a lot of health before the 500k bonus, seem to have their health reduced when the ability is removed.
I dont know why so I dont use base health values over 50k.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
I do know about floating pointers being not 100% accurate but out of 500 damage tests, none failed to execute the event.
.

Well, I already told you one scenario where they fail in 100% of the cases. And its not even an extremly unrealisitc scenario.

Before we can move on, we need to know as much as possible about how the game handles damage and health. Then we can maybe come up with a model that reproduces the exact game behavior.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
Why not an event to detect when the unit's life becomes not equal to its current life?

NOT_EQUAL doesn't work unfortunatly. No idea why, but it just doesn't work when used with a unit state event.

I have done some tests, and the good news is that the unit state event seems to have the same accuracy as the inbuilt real datatype. So we can detect if a damage event will fire or not like this:


JASS:
function onDamage takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local real health = GetWidgetLife(target)
    local real damage = GetEventDamage()
    local real healthBoundary = health - 0.5*damage

    if health == healthBoundary then // check to detect missing events
        // this after damage event wont fire!
        set health = 2*damage
        set healthBoundary = health - 0.5*damage
        call SetWidgetLife(target, health) // this will make the event fire
    endif
    call TriggerRegisterUnitStateEvent(afterDamageTrg, target, UNIT_STATE_LIFE, LESS_THAN, healthBoundary)
    // ...
endfunction


However, there is a problem with this approach.

In especially, we have to correct the units health in the after damage event, because we modified it to make it match the required accuracy. However, we can't subtract the damage value from the widgets life, because that won't change the value because of inaccuracy.

A normal damage event, however does change the value! So I assume that they use a datatype with higher precision iternally (most likely double), but we only have float accuracy available... For now, no idea how to fix this.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
I just tested it with a unit with a bit more redicolously health and I can tell you that WC3 is not made for that.

I made a footman with 1,000,000,000 hp and 0 hp regen.
100 riflemen with 18-24 damage didnt bring his health down.
1 mortar team with 2500-2500 (modified) damage did bring his health down.
So, 1,000,000,000 - 18 = 1,000,000,000. Nice.

So the first question is how much do you think is reasonable.

You cannot have a fully operational game with units with a billion health and units with <100 dmg.
But even at that point, call TriggerRegisterUnitLifeEvent( gg_trg_Untitled_Trigger_002, gg_unit_hfoo_0000, LESS_THAN, 999999999.9375)
Does work.
However, it only works when the unit's life actually changes which does not happen with those riflemans, nor with SetWidgetLife, nor with UnitDamageTarget.

So, it indeed breaks the sysem, but it is unreasonable because it breaks WC3's Damage Engine.
So, until we have a Damage Engine that can handle such values without breaking, only then I will agree on these terms.

But because you are so determined to fix this problem that cannot be solved, you can try to check if the health would be changed.
To do this flawlessly, you can make a real variable and set it to the health of the unit, then remove the damage taken from it and check if the value remains the same.

However, I think it is very stupid because you want to fix a problem that has a problem as a source, and that problem wont be fixed.

Also one more thing... try to make a unit and set it's base max health to something between 999,999,937 - 999,999,999
Just try it.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Imo, the most important thing is to remove the life bonus ability as quickly as possible. In that case, the damage would need to be greater than .5 because otherwise you wouldn't need the life bonus ability in the first place (provided you only give it to the unit in the situation that the damage would kill it)

But you also have to set the life of the target to the life before that original damage has been taken, which has to be done in every case except if the damage wouldnt change the unit's life cause of floating pointers inaccuracy.
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
So the first question is how much do you think is reasonable.

Well, IMO 1,000,000,000 is not reasonable anymore, because the life isn't even displayed correct.

So, it indeed breaks the sysem, but it is unreasonable because it breaks WC3's Damage Engine.
So, until we have a Damage Engine that can handle such values without breaking, only then I will agree on these terms.

Not always.

As mentioned, a unit with 5000000 health does take damage (i.e. its life changes), that can be observed by the displayed health value. However, the life changed event does not fire, because of inaccuracy, although the life does change. So this:

However, it only works when the unit's life actually changes which does not happen with those riflemans, nor with SetWidgetLife, nor with UnitDamageTarget.

is wrong, because the life actually changes, but we are not able to detect that change using a unit state event. That is the problem.

But because you are so determined to fix this problem that cannot be solved, you can try to check if the health would be changed.
To do this flawlessly, you can make a real variable and set it to the health of the unit, then remove the damage taken from it and check if the value remains the same.

I already did that in the snippet I posted.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Does anyone know if the "deflect" parameters in the Defend ability actually do anything? Or if there is a way to make thorns aura affect all types of incoming damage? Basically, I am trying to think of a way to make the damage source get a zero-damage event to fire immediately after its target's damage event.

I had been experimenting with spirit link, but it is too buggy to be useful.
 
Level 19
Joined
Jul 14, 2011
Messages
875
Hmm, I cant seem to understand one thing. How can I deal non-physical damage with UnitDamageTarget? I am (basically) trying to delay the damage a unit deals with his auto-attacks.
It used to work with only null or false for anything except for the damage, target and source (talking about arguments), but I decided to rewrite the whole thing and now that it is ready, doing it causes the event to fire again.
I could do a workaround but I dont think it is needed. I did try to remove the handler, deal the damage and add it back but it did nothing.
I tried to remove it a bit earlier, before the function containing the native is called but that works only for the first time and then it stops again.
I still have an old backup if the map with the old code, and it works like it used to.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
As mentioned, a unit with 5000000 health does take damage (i.e. its life changes), that can be observed by the displayed health value. However, the life changed event does not fire, because of inaccuracy, although the life does change.
A unit with 5,000,000 hp which event is set on 4,999,999.9375 (0.0625 lower) makes the event run when damaged by 1 hp (after being reduced by armor etc).

is wrong, because the life actually changes, but we are not able to detect that change using a unit state event. That is the problem.
A unit with 5,000,000 hp which is damaged for 0.1 hp (coded) 2k times does not have his hp reduced.
When that same unit takes damage of 1 hp, it is reduced.
So the life does not change.

I already did that in the snippet I posted.
sorry missed that part :/
However what I was more thinking about is:
JASS:
function onDamage takes nothing returns nothing
    local real damage = GetEventDamage()
    local unit target
    local real life
    
    if damage == 0. then
        return
    endif
    set target = GetTriggerUnit()
    set life = GetWidgetLife(target)
    
    if life-damage == life then
        //add life bonus ability
        //create trigger + event
    endif
    
endfunction

I mean, if life-damage is equal to life, then the damage doesnt change the life of the target.
This would mean that it doent help to set the life back because the life didnt change.
So this would mean that we dont need the event.
In every single other case (as 0.0625 is detected if the life does change), then the event runs.
So with this "life-damage == life" we filter out the only time it wont work.

Agreed?

Maths:
a - b = a
b != 0
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Hmm, I cant seem to understand one thing. How can I deal non-physical damage with UnitDamageTarget? I am (basically) trying to delay the damage a unit deals with his auto-attacks.
It used to work with only null or false for anything except for the damage, target and source (talking about arguments), but I decided to rewrite the whole thing and now that it is ready, doing it causes the event to fire again.
I could do a workaround but I dont think it is needed. I did try to remove the handler, deal the damage and add it back but it did nothing.
I tried to remove it a bit earlier, before the function containing the native is called but that works only for the first time and then it stops again.
I still have an old backup if the map with the old code, and it works like it used to.

Ofcourse you can go to the object editor and set the "Combat - Attack # - Animation Damage Point (udp1)" a bt higher.
But knowing you came here to ask this thing, I can assume that you already have tried that.
:vw_unimpressed:

But to answer your question, you have to set the AttackType to ATTACK_TYPE_MELEE and DamageType to DAMAGE_TYPE_NORMAL.
The ATTACK_TYPE_NORMAL is actually the spells attack type, so it deals spell damage.
The booleans dont really do shit themselves I am afraid.
Setting attack/damage/weapon types to null makes it not use any attack/damage/weapon type.
This means that it wont be reduced by armor, but also not by spell damage reduction, as well as every other thing that runs on certain types.
 
Top