• 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.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

[Solved] Triggered Damage Being Reflected by Thorns Aura (Even for Ranged Heroes)

KPC

KPC

Level 8
Joined
Jun 15, 2018
Messages
231
Hello, I have some triggers that simulate Area of Effect damage using the following action:
  • Unit - Cause DamageEventSource to damage (Picked unit), dealing MediumDamage damage of attack type Chaos and damage type Normal
  • Unit - Cause DamageEventSource to damage (Picked unit), dealing FullDamage3 damage of attack type Chaos and damage type Normal
The first action is meant to imitate the splash damage effect from Demon Hunter's Metamorphosis.
The second action is meant to imitate a generic splash damage effect from an item for heroes, similar to the old Orb of Fire.
Note: I want both effects to take the target's armor value into account (unlike Cleaving Attack).

The problem I encountered while creating these triggers is that the damage source receives damage from Thorns Aura, regardless of whether the unit dealing the AoE damage is ranged or melee.

From my understanding:
  1. A ranged hero should definitely not receive Thorns damage when dealing AoE damage.
  2. I am also not sure whether any hero (melee or ranged) should receive reflected damage from Thorns when the damage comes from AoE effects.
For example, with Pit Lord's Cleaving Attack, I believe the AoE portion of the damage is not reflected by Thorns Aura and does not return damage to the attacker.

So my questions are:
  • How should this interaction work according to Warcraft III mechanics?
  • Should AoE damage be reflected by Thorns Aura at all?
  • ! What changes should I make to these triggers so that the AoE damage I generate is not reflected back to the hero, (especially when the attacker is ranged?
Any advice or explanation would be appreciated.
 
If you use jass/lua instead of gui action, you then have access to a "damage unit" action with more parameters than what GUI offers:
JASS:
native UnitDamageTarget takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean
The gui action uses constants:
  • attack: true
  • ranged: false
  • weaponType: WEAPON_TYPE_WHOKNOWS

Changing attack to false does not seem to do anything in regards to thorns aura, but changing ranged to true seems to prevent damage from being reflected back at the caster.
It would look like this:
  • Custom script: call UnitDamageTarget(your_damage_source, your_damage_target, udg_MediumDamage, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
 
If you use jass/lua instead of gui action, you then have access to a "damage unit" action with more parameters than what GUI offers:
JASS:
native UnitDamageTarget takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean
The gui action uses constants:
  • attack: true
  • ranged: false
  • weaponType: WEAPON_TYPE_WHOKNOWS

Changing attack to false does not seem to do anything in regards to thorns aura, but changing ranged to true seems to prevent damage from being reflected back at the caster.
It would look like this:
  • Custom script: call UnitDamageTarget(your_damage_source, your_damage_target, udg_MediumDamage, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
That's strange. Even when I set it up like this, my ranged hero still receives reflected damage from Thorns Aura.
  • Custom script: call UnitDamageTarget(udg_DamageEventSource, GetEnumUnit(), udg_FullDamage3, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
 
You may need to rule out 0.00 damage instances, since a lot of things will fire those.
  • Conditions
    • (Damage amount) Greater than 0.00
  • Conditions
    • DamageEventAmount Greater than 0.00
Sorry, I'm not sure what exactly this means or how to achieve it. I thought I was supposed to add that condition to my trigger, but when I did, nothing changed. So I’m probably misunderstanding it or doing it incorrectly.
  • Orb of Fire Splash
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • DamageEventAmount Greater than 0.00
      • IsDamageAttack Equal to True
      • (DamageEventSource has an item of type Orb of Fire) Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource).) Equal to True
    • Actions
      • Set VariableSet TempPoint11 = (Position of DamageEventTarget)
      • Set VariableSet FullDamage3 = (DamageEventPrevAmt x 0.35)
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 250.00 of TempPoint11.) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal to True
              • ((Picked unit) is A structure) Equal to False
              • (Picked unit) Not equal to DamageEventTarget
              • ((Picked unit) belongs to an enemy of (Owner of DamageEventSource).) Equal to True
            • Then - Actions
              • Custom script: call UnitDamageTarget(udg_DamageEventSource, GetEnumUnit(), udg_FullDamage3, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint11)
 
Try to use damage types other than normal, i think its happening because Thorns Aura/Spiked Carapace/Shell are hardcoded to reflect Normal Damage type or Weapon Type Normal in GUI.
instead use this
  • Unit - Cause DamageEventSource to damage (Picked unit), dealing 999999 damage of attack type Chaos and damage type Universal
Also
UnitDamageTarget is extremely weird as of ticking both boolean attack, boolean ranged, true or false doesnt interact with
  • (Damage From Normal Attack) Equal to True
in any way, meaning you cant deal normal attack damage through triggers.
 
Are you on latest version? I tried my solution on latest version before posting it and it does not fire any "unit damaged" events at all, but it may be possible that on older versions the "ranged" parameter does not work the same.
Yes, I am using the latest version of vJass Damage Engine (5.A.0.0) and the Game Data Set is set to Melee (Latest Patch). My Warcraft III on Battlenet is also fully updated.

I attached a test map where I demonstrate the trigger and the behavior I described, including the solution you suggested. However, for some reason it still does not work in my case.

Maybe you could attach your test map as well, so I can compare the differences?
 

Attachments

I got it to work by changing the DAMAGE_TYPE to MAGIC and calculating Armor reduction manually. Seems like the two Booleans have no effect, the game simply checks if it was DAMAGE_TYPE_NORMAL to determine if Thorns damage is dealt. But I could be wrong... Here's a working trigger:
  • Orb of Fire Splash
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • IsDamageAttack Equal to True
      • (DamageEventSource has an item of type Orb of Fire) Equal to True
      • (DamageEventTarget has buff Heal Reduction) Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource).) Equal to True
    • Actions
      • Set VariableSet Orb_Damage = (DamageEventPrevAmt x 0.35)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Orb_Damage Less than or equal to 0.00
        • Then - Actions
          • Skip remaining actions
        • Else - Actions
      • -------- --------
      • Set VariableSet Orb_Owner = (Owner of DamageEventSource)
      • Set VariableSet Orb_Point = (Position of DamageEventTarget)
      • Set VariableSet Orb_Group = (Units within 250.00 of Orb_Point.)
      • Custom script: call RemoveLocation( udg_Orb_Point )
      • -------- --------
      • Unit Group - Pick every unit in Orb_Group and do (Actions)
        • Loop - Actions
          • Set VariableSet Orb_Target = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Orb_Target is alive) Equal to True
              • (Orb_Target is A structure) Equal to False
              • Orb_Target Not equal to DamageEventTarget
              • (Orb_Target belongs to an enemy of Orb_Owner.) Equal to True
            • Then - Actions
              • -------- Recreate the Warcraft 3 standard Armor formula: --------
              • Custom script: set udg_Orb_Armor = BlzGetUnitArmor(udg_Orb_Target)
              • Custom script: set udg_Orb_Splash = udg_Orb_Damage * (1.00 - ((udg_Orb_Armor * 0.06) / (1.00 + udg_Orb_Armor * 0.06)))
              • -------- Deal the reduced damage if any at all: --------
              • Custom script: if udg_Orb_Splash > 0.00 then
              • Custom script: call UnitDamageTarget(udg_DamageEventSource, udg_Orb_Target, udg_Orb_Splash, true, udg_IsDamageRanged, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
              • Custom script: endif
            • Else - Actions
      • -------- --------
      • Custom script: call DestroyGroup( udg_Orb_Group )
Notes:
1. You could also use this instead of UnitDamageTarget() but the manual Armor reduction is still needed:
  • Unit - Cause DamageEventSource to damage Orb_Target, dealing Orb_Splash damage of attack type Chaos and damage type Universal
2. It's up to you to decide whether it's categorized as an Attack or not. Currently I have that set to true since the damage comes from an Attack.
  • udg_Orb_Splash, true, udg_IsDamageRanged,
3. What you were doing with the Temp variables was potentially unsafe. Remember, dealing Damage can kill units. And when you kill a unit the "A unit Dies" Event happens immediately. This Event is unique in that it breaks the normal trigger-queue rules. If in that "A unit Dies" trigger you were to be reusing any of these associated variables you could cause all sorts of issues, like memory leaks in this case.

If you're trying to save on variable usage:
  • Handle your "A unit Dies" and other rule breaking Events (if any exist) with unique variables that you know for certain are never shared.
  • Use Arrays with a unique [index] for each Trigger. So you could have TempPoint[1 to 500] divided amongst 500 triggers. A little more awkward to use, but it'll keep the editor clean.
 

Attachments

Last edited:
The "range: true" flag in UnitDamageTarget does work. It just doesn't work well with Bribe's DDS. I assume the damage pipeline incorrectly sets/passes some values when damage is being reflected and "range: true" flag is set.
@KPC in case of your "Orb of Fire Splash" trigger, when I offset the splash damage by 0.01 seconds (in other words, I don't deal new damage when DDS is currently processing damage done by standard attack with orb of fire), then everything works fine - Blood Mage will stop taking damage from Thorns aura.
  • Orb of Fire Splash
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventSource has an item of type Orb of Fire) Equal to True
      • (DamageEventTarget has buff Heal Reduction) Equal to True
      • IsDamageAttack Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource).) Equal to True
    • Actions
      • Set VariableSet FullDamage3 = (DamageEventPrevAmt x 0.35)
      • Set VariableSet TestLoc = (Position of DamageEventTarget)
      • Set VariableSet TestSource = DamageEventSource
      • Set VariableSet TestTarget = DamageEventTarget
      • Set VariableSet TestAmount = FullDamage3
      • Countdown Timer - Start TestTimer as a One-shot timer that will expire in 0.01 seconds
  • Test Offset
    • Events
      • Time - TestTimer expires
    • Conditions
    • Actions
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 250.00 of TestLoc.) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal to True
              • ((Picked unit) is A structure) Equal to False
              • (Picked unit) Not equal to TestTarget
              • ((Picked unit) belongs to an enemy of (Owner of TestSource).) Equal to True
            • Then - Actions
              • Custom script: call UnitDamageTarget( udg_TestSource, GetEnumUnit(), udg_TestAmount, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
            • Else - Actions
In case of my map, I used only the basic functionality, no systems or anything. I just placed paladin (red) and keeper (blue) and created 3 triggers:
1. Deal damage on pressing Esc
  • Deal Damage
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Set VariableSet src = Paladin 0000 <gen>
      • Set VariableSet trg = Keeper of the Grove 0002 <gen>
      • Custom script: call UnitDamageTarget( udg_src, udg_trg, 50.0, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
2. When Keeper takes damage from Paladin's basic attack, deal additional damage to Keeper as "range" damage. I used this to simulate your scenario.
  • Blue Takes Damage
    • Events
      • Unit - A unit Takes damage
    • Conditions
      • (Owner of (Damage Target)) Equal to Player 2 (Blue)
    • Actions
      • Custom script: if BlzGetEventAttackType() != ATTACK_TYPE_HERO or BlzGetEventDamageType() != DAMAGE_TYPE_NORMAL then
      • Custom script: return
      • Custom script: endif
      • Set VariableSet src = Paladin 0000 <gen>
      • Set VariableSet trg = Keeper of the Grove 0002 <gen>
      • Custom script: call UnitDamageTarget( udg_src, udg_trg, 50.0, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
3. Print damage taken by Paladin so that I can see if paladin took thorns damage or not.
  • Red Takes Damage
    • Events
      • Unit - A unit About to take damage
    • Conditions
      • (Owner of (Damage Target)) Equal to Player 1 (Red)
    • Actions
      • Game - Display to (All players) the text: (Damage event: + (String((Damage taken))))
When I set range parameter as false in UnitDamageTarget in trigger #1 and press Esc, then trigger #3 prints that Paladin took thorns damage. When range is set to true, no damage is taken/printed by trigger #3.

Similarly for trigger #2 where I ordered Paladin to melee attack Keeper, when range is false, then I see damage printed 2 times: once for melee attack and second time for thorns damage. If I set range to true, then trigger #3 prints damage only once: for the standard melee attack but no thorns damage.

Edit: here's the map
 

Attachments

Back
Top