• 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.

Detecting a Melee Attack

Status
Not open for further replies.
Level 11
Joined
Feb 11, 2010
Messages
199
Detecting a Melee Attack (UNSOLVED)

Alright, so basically I'm working on a spell that has proved surprisingly tricky. Essentially, I want to create a version of the Wind Walk spell where the hero deals bonus damage based on their Agility. Seems simple enough: I just need to detect when the unit finishes an attack and set the damage myself (complete with floating text, etc). However, a problem arises.

  • Night Stalker
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • ((Attacking unit) has buff Night Stalker) Equal to True
    • Actions
      • Set NightStalkerCaster[0] = (Attacking unit)
      • Set NightStalkerTarget[0] = (Attacked unit)
      • Set NightStalkerLevel[0] = (Level of Night Stalker for NightStalkerCaster[0])
      • Set NightStalkerDamage[0] = (((Real((Agility of NightStalkerCaster[0] (Include bonuses)))) x 3.00) + (((Real(NightStalkerLevel[0])) x 50.00) + 0.00))
      • Unit - Cause NightStalkerCaster[0] to damage NightStalkerTarget[0], dealing NightStalkerDamage[0] damage of attack type Hero and damage type Normal
      • Set NightStalkerPoint[0] = (Position of NightStalkerTarget[0])
      • Floating Text - Create floating text that reads ((String((Integer(NightStalkerDamage[0])))) + !) at NightStalkerPoint[0] with Z offset 20.00, using font size 10.00, color (100.00%, 0.00%, 0.00%), and 0.00% transparency
      • Floating Text - Change (Last created floating text): Disable permanence
      • Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
      • Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
      • Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
      • Custom script: call RemoveLocation(udg_NightStalkerPoint[0])
      • Unit - Remove Wind Walk buff from NightStalkerCaster[0]
Now here's the big glaring problem: Event - Unit is Attacked. This event suffers the same problems as "A unit begins casting a spell" as opposed to "A unit starts the effect of an ability." In short, the damage "procs" before the unit ACTUALLY attacks (but rather when it begins animating).

Equally problematic is using "Unit takes damage" as an event, since that damage could be from any source.

So how would I replicate Wind Walk? I've been looking high and low for a solution to this using searches, and I've had no luck at all so far. +rep for anyone who can help, of course! :thumbs_up:
 
Last edited:
Level 2
Joined
Jun 1, 2010
Messages
13
MIght be wrong, but wont 'Unit takes damage' be the best option?
Just use if\then\else, or just place a condition in the trigger.

Edit:
  • Melee Initialization
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Attacked unit) Equal to Black Spider 0001 <gen>
    • Actions
      • Game - Display to (All players) the text: TEST
This worked for me, the "TEST" text shows up when the Mountain King deals his damage to the enemy unit.
 
Level 11
Joined
Feb 11, 2010
Messages
199
MIght be wrong, but wont 'Unit takes damage' be the best option?
See the issue I mentioned in the first post. How would you know that the damage taken was from a melee attack and not some other source?

Just use if\then\else, or just place a condition in the trigger.

Edit:
  • Melee Initialization
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Attacked unit) Equal to Mountain King 0002 <gen>
    • Actions
      • Game - Display to (All players) the text: TEST
This worked for me, the "TEST" text shows up when the Mountain King deals his damage to the enemy unit.

I'm sorry, but you're completely missing the point. It runs, but it does so WITHOUT attacking the enemy. Try ordering your unit to attack the enemy then cancel the order before they make an attack, and you'll still get TEST. I did of course mention this issue in the first post...
 
Level 14
Joined
Nov 18, 2007
Messages
816
Oh well.
IDDS can detect normal attacks by requiring the user to trigger all Spell damage himself.
The alternative to that would be to make each unit have a buff placing orb. Obviously, that leads to certain complications, as orbs dont stack by default. But if you trigger all orbs yourself, you can make them stack again.
 
Level 11
Joined
Feb 11, 2010
Messages
199
But if you trigger all orbs yourself, you can make them stack again.

Okay. How do I trigger an orb effect myself if I can't detect an attack (which is what causes an orb effect to be applied) without an orb effect? Seems like this is just going in circles.

Can I get a more complete answer?
 
Last edited:
Level 9
Joined
Jun 25, 2009
Messages
427
Okay. How do I trigger an orb effect myself if I can't detect an attack (which is what causes an orb effect to be applied) without an orb effect? Seems like this is just going in circles.

Can I get a more complete answer?

Ill try to :/
  • Blah Blah Trigger
    • Events:
      • Unit - A unit Is attacked
    • Conditions:
      • (Attacking Unit) has Night Stalker
    • Actions:
      • Set Night_Stalker=(Attacking Unit)
      • Set Night_Stalked=(Triggering Unit)
      • Set Night_Stalker_Damage=(3 x Agility of (Triggering Unit) Including Bonuses)
      • Trigger - Add Unit - Night Stalked takes damage to Blah Blah 2 <gen>
      • Unit - Remove Night Stalker from (Night_Stalker)

  • Blah Blah 2
    • Events:
    • Conditions:
      • (Damage source) Equal to (Night_Stalker)
    • Actions:
      • Set Night_Stalker_Pos=(Position of (Night_Stalker))
      • Unit - Create 1 Night Dummy for (Owner of (Night_Stalker)) at Night_Stalker_Pos facing Default building facing degrees
      • Unit - Cause (Last Created Unit) to damage (Night_Stalked) dealing Night_Stalker_Damage of type Hero and damage type Normal
      • Unit - Add 1.00 seconds Generic expiration timer to (Last Created Unit)
      • Set Night_Stalker=No Unit
      • Set Night_Stalked=No Unit
Dang that was >.> it actually should work, but careful not to use the spell 1k+ times not to get 1k+ events :D

Tiche3:grin:
 
Level 11
Joined
Feb 11, 2010
Messages
199
Ill try to :/
  • Blah Blah Trigger
    • Events:
      • Unit - A unit Is attacked
    • Conditions:
      • (Attacking Unit) has Night Stalker
    • Actions:
      • Set Night_Stalker=(Attacking Unit)
      • Set Night_Stalked=(Triggering Unit)
      • Set Night_Stalker_Damage=(3 x Agility of (Triggering Unit) Including Bonuses)
      • Trigger - Add Unit - Night Stalked takes damage to Blah Blah 2 <gen>
      • Unit - Remove Night Stalker from (Night_Stalker)

  • Blah Blah 2
    • Events:
    • Conditions:
      • (Damage source) Equal to (Night_Stalker)
    • Actions:
      • Set Night_Stalker_Pos=(Position of (Night_Stalker))
      • Unit - Create 1 Night Dummy for (Owner of (Night_Stalker)) at Night_Stalker_Pos facing Default building facing degrees
      • Unit - Cause (Last Created Unit) to damage (Night_Stalked) dealing Night_Stalker_Damage of type Hero and damage type Normal
      • Unit - Add 1.00 seconds Generic expiration timer to (Last Created Unit)
      • Set Night_Stalker=No Unit
      • Set Night_Stalked=No Unit
Dang that was >.> it actually should work, but careful not to use the spell 1k+ times not to get 1k+ events :D

Tiche3:grin:

That spell you gave doesn't work for all the reasons already mentioned. :hohum:

I could still activate that trigger and deal the bonus damage without ever completing a single attack (just any source of damage whatsoever). Your spell cannot stand up to the simple test of, for example, "I don't want immolation or flame strike to be able to activate the bonus damage."
 
Level 9
Joined
Jun 25, 2009
Messages
427
That spell you gave doesn't work for all the reasons already mentioned. :hohum:

I could still activate that trigger and deal the bonus damage without ever completing a single attack (just any source of damage whatsoever). Your spell cannot stand up to the simple test of, for example, "I don't want immolation or flame strike to be able to activate the bonus damage."

Did you even test it? huh....

I will do it for you, and we will see i HOPE. :hohum:

EDIT: Tested it and guess what? It works, DUH, but you say that you can abuse it? f*** it you can't no matter if you stop, then immolation on, whatever your target will still get your agility 3x damage, so anyway, why the hell you must abuse it in the first place? >.> And last time i checked, wind walk deals backstab damage AND you go off the invisibility by using UNIT IS ATTACKED, try it :)

The a bit changed triggers.

  • Night Stalk
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • ((Attacking unit) has buff Frenzy) Equal to True
    • Actions
      • Set Night_Stalker = (Attacking unit)
      • Set Night_Stalked = (Triggering unit)
      • Set Night_Stalker_Damage = (3.00 x (Real((Strength of Night_Stalker (Include bonuses)))))
      • Unit - Remove Frenzy buff from (Attacking unit)
      • Trigger - Add to Night Stalked <gen> the event (Unit - Night_Stalked Takes damage)
      • Trigger - Turn off (This trigger)
  • Night Stalked
    • Events
    • Conditions
      • ((Damage source) is A melee attacker) Equal to True
      • (Damage source) Equal to Night_Stalker
    • Actions
      • Set Night_Stalker_Pos = (Position of Night_Stalker)
      • Unit - Create 1 Chain Link Dummy :) for (Owner of Night_Stalker) at Night_Stalker_Pos facing Default building facing degrees
      • Unit - Cause (Last created unit) to damage (Triggering unit), dealing Night_Stalker_Damage damage of attack type Hero and damage type Normal
      • Floating Text - Create floating text that reads (String((Integer(Night_Stalker_Damage)))) at Night_Stalker_Pos with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
      • Floating Text - Change the color of (Last created floating text) to (100.00%, 0.00%, 0.00%) with 0.00% transparency
      • Floating Text - Change (Last created floating text): Disable permanence
      • Floating Text - Set the velocity of (Last created floating text) to 50.00 towards 90.00 degrees
      • Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
      • Floating Text - Change the fading age of (Last created floating text) to 1.75 seconds
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Set Night_Stalked = No unit
      • Set Night_Stalker = No unit
      • Custom script: call RemoveLocation(udg_Night_Stalker_Pos)
      • Trigger - Turn on Night Stalk <gen>
 
Level 20
Joined
Oct 21, 2006
Messages
3,230
im detecting physical damage by triggering every spell and using few booleans so the damage counter runs correctly based on what the spell/ability was

eg: cast stormbolt -> before stormbolt dummy deals damage we set damage=magical boolean and now the trigger knows what will come
 
Level 11
Joined
Feb 11, 2010
Messages
199
I still like the "use orbs, and make an orb stacking system" suggestion. The only part I wasn't sure about was "How do I make an orb stacking system if I don't know how to make an attack?" My guess would be to just have pretty much all attacks give the orb buff, then check what items/abilities the unit has in order to apply all of them whenever a unit receives that orb buff. I'll try that now, actually...
 
Level 14
Joined
Nov 18, 2007
Messages
816
You dont need to try this, it already works. Look at the OrbStacking library in my sig.

No, i dont have a GUI version, and i dont want to create a GUI version. In fact, itd probably be better for all of us, if you just learned some vJass and tried not to do everything in GUI.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I completely forgot that the IsUnitType(unit, UNIT_TYPE_MELEE_ATTACKER) and IsUnitType(unit, UNIT_TYPE_RANGED_ATTACKER) comparisons were available. I'm curious as to what they give when a unit has two available attack indexes for melee attacks on ground units and ranged attacks on air units.
 
Level 6
Joined
Jun 30, 2006
Messages
230
My guess is that it would know which attack is used, seeing as this is in a trigger that detects an attack. As for if it were outside of such an event... test it; I'd be interested to know.
 
1. Create the required hashtable

  • Create Hashtables
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set PowerAgilityStrikeHash = (Last created hashtable)
2. Detect the attack, and add the attacked unit to a new "the unit takes damage" event

  • Agility Strike
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Level of Agility Strike for (Attacking Unit)) Greater than 0
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Load 0 of (Key (Attacked unit)) from AbilityAgilityStrikeHash) Equal to True
        • Then - Actions
        • Else - Actions
          • Hashtable - Save True as 0 of (Key (Attacked unit)) in PowerAgilityStrikeHash
          • Trigger - Add to Agility Strike Damage <gen> the event (Unit - (Attacked unit) Takes damage)
3. When the unit takes damage, remove the buff and deal 1x agility in damage.

  • Agility Strike Damage
    • Events
    • Conditions
      • (Level of Agility Strike for (Damage source)) Greater than 0
      • ((Triggering unit) has buff Agility Strike (Dummy)) Equal to True
    • Actions
      • Unit - Remove Agility Strike (Dummy) buff from (Triggering unit)
      • Unit - Cause (Damage source) to damage (Triggering unit), dealing (Real((Agility of (Damage source) (Include bonuses)))) damage of attack type Hero and damage type Normal
4. Upon death, clear anything left in the hashtable (if there is anything)

  • Hashtable Cleanup
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Load 0 of (Key (Dying unit)) from PowerAgilityStrikeHash) Equal to True
        • Then - Actions
          • Hashtable - Clear all child hashtables of child (Key (Dying unit)) in PowerAgilityStrikeHash
        • Else - Actions
create a power based of a poison attack or anything passive that places a buff. Name the buff agility strike (dummy) and set the duration to 0.01 seconds. It works flawlessly (I hope I made it clear enough).
 
Last edited:
  • Create Hashtables
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set PowerAgilityStrikeHash = (Last created hashtable)

  • Agility Strike
    • Events
      • Unit - A unit Is attacked
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Load 0 of (Key (Attacked unit)) from AbilityAgilityStrikeHash) Equal to True
        • Then - Actions
        • Else - Actions
          • Hashtable - Save True as 0 of (Key (Attacked unit)) in PowerAgilityStrikeHash
          • Trigger - Add to Agility Strike Damage <gen> the event (Unit - (Attacked unit) Takes damage)
  • Agility Strike Damage
    • Events
    • Conditions
      • (Level of Agility Strike for (Damage source)) Greater than 0
      • ((Triggering unit) has buff Agility Strike (Dummy)) Equal to True
    • Actions
      • Unit - Cause (Damage source) to damage (Triggering unit), dealing (Real((Agility of (Damage source) (Include bonuses)))) damage of attack type Hero and damage type Normal
  • Hashtable Cleanup
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Load 0 of (Key (Dying unit)) from PowerAgilityStrikeHash) Equal to True
        • Then - Actions
          • Hashtable - Clear all child hashtables of child (Key (Dying unit)) in PowerAgilityStrikeHash
        • Else - Actions
create a power based of a poison attack or anything passive that places a buff. Name the buff agility strike (dummy) and you get this. It works flawlessly.

You forgot to save the Handle of the (Attacking unit) to the (Attacked unit) and make a check if the Damage source is Equal to the Attacking unit.

  • Hashtable - Save Handle of (Attacking unit) as 1 of (Key (Attacked unit)) in PowerAgilityStrikeHash
and the load:
  • Agility Strike Damage
    • Events
    • Conditions
      • (Level of Agility Strike for (Damage source)) Greater than 0
      • ((Triggering unit) has buff Agility Strike (Dummy)) Equal to True
      • (Damage source) Equal to (Load 1 of (Key(Triggering unit)) in PowerAgilityStrikeHash)
    • Actions
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
The leaks aren't really a big issue. The trigger can be destroyed and then re-initialized after a predefined amount of executions, or based on a timer, or whatever, but the point is that they don't really leak. Once the trigger is destroyed the events associated with it will be cleared.

I really don't know why you wouldn't just use a damage-detection engine, so this can be completely avoided.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I'm quite certain that a damage-detection system would still leak events, though (which by the way barely hinders any performance at all). I'm curious how a damage-detection system should be made though without leaking events, or destroying triggers. Since destroying a trigger is the only way to clear a trigger's events, and even in a damage-detection system you're going to need to be registering units without being able to unregister them.
 
Level 14
Joined
Nov 18, 2007
Messages
816
You could at least minimize the number of events you register to one per unit. The current solution registers multiple for the same unit.

You cant destroy events without destroying the trigger they belong to. But destroying triggers can lead to handle-stack-corruption under certain circumstances. Thats why LLDD only destroys its trigger after waiting 10 minutes (10 minutes of it being inactive).
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I'm quite sure that most of those handle stack problems come from bad logic. Perhaps there is a small problem or glitch somewhere but in my 6 years of editing I have never experienced a handle stack corruption.

If you have waits in your trigger then that may provoke a handle stack corruption when destroying the trigger, but so long as you're being logical about where you are destroying your trigger then the chances of experiencing problems is very low, so low that I have yet to see one.

I'm curious what the trigger queue natives return when a handle stack is corrupted.
 
Level 11
Joined
Feb 11, 2010
Messages
199
Hmm...only

:grin: Indeed.

The leaks aren't really a big issue. The trigger can be destroyed and then re-initialized after a predefined amount of executions, or based on a timer, or whatever, but the point is that they don't really leak. Once the trigger is destroyed the events associated with it will be cleared.

I really don't know why you wouldn't just use a damage-detection engine, so this can be completely avoided.

Well this is interesting... how do I re-initialize a trigger after destroying it? Also, what damage detection engine are you suggesting?

You could at least minimize the number of events you register to one per unit. The current solution registers multiple for the same unit.

You cant destroy events without destroying the trigger they belong to. But destroying triggers can lead to handle-stack-corruption under certain circumstances. Thats why LLDD only destroys its trigger after waiting 10 minutes (10 minutes of it being inactive).

LLDD? And how do I destroy an event?

Oh god. I can think of a few better ways to do this, even in GUI. On thehelper.net there was some GUI damage detection system. Look into how to use that one. What youre doing here is just bullshit (it leaks tons of events).

I don't suppose you'd be willing to give a link to that, would you? Google didn't seem to want to find it.

_____________

Anyways, here's my attempt at making a decent GUI attack detection system so far. It at least works better than the other GUI ones I've seen (at least in my testing thus far), yet turned out to be surprisingly short. However, I'm sure you guys will find some crippling error with it. Of course, +rep for anyone who can tell me how to improve this trigger (or just tell me if it fails utterly and why).

  • Tenderizer Attack
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Level of Attack Detect Orb for (Attacking unit)) Greater than 0
    • Actions
      • Set TenderizerTarget[0] = (Attacked unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (TenderizerTarget[0] is in TenderizerTargetGroup[0]) Equal to False
        • Then - Actions
          • Unit Group - Add TenderizerTarget[0] to TenderizerTargetGroup[0]
          • Trigger - Add to Tenderizer Damage <gen> the event (Unit - TenderizerTarget[0] Takes damage)
        • Else - Actions
  • Tenderizer Damage
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Triggering unit) has buff Attack Detect (Non-stacking)) Equal to True
          • (Level of Slow Poison for (Damage source)) Greater than 0
        • Then - Actions
          • Unit - Remove Attack Detect (Non-stacking) buff from (Triggering unit)
          • Game - Display to (All players) the text: DETECTED
        • Else - Actions
It only adds the unit once, it only adds units who have been targeted, and it will only ever detect attack completion (not anything else, like immolation. And no guesswork or predicting involved, it will go off the instant the enemy is hit with an orb-placing attack), and I can make stacking orb effects by checking the abilities of damage source and applying the effects myself.

I would make it clear events or destroy/reinitialize every so often, but I don't know how to do that :(
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Because ranged units aren't restricted to a certain distance, they can be as close as melee units can. Not only that, but melee attacks can be executed outside of a "melee range" after the unit starts swinging.
 
Status
Not open for further replies.
Top