• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Detect basic (ranged) attack is fired?

Status
Not open for further replies.
Level 5
Joined
Oct 16, 2007
Messages
67
I think your best bet is the unit attacks event, but it trigger before the projectile is fired. So it still can be canceld by the Player.
Otherwise you could register if a unit was hit and work with a buff/invisible ability on the attacking unit.
 
I think your best bet is the unit attacks event, but it trigger before the projectile is fired. So it still can be canceld by the Player.
Otherwise you could register if a unit was hit and work with a buff/invisible ability on the attacking unit.

I don't really like that soultion. And I really need to handle the case where the target dies before the projectile hits and I don't want it to be able to fire multiple times of the other weapon.
The Night Elf - War Club is basically what I want (With 1 maximum attacks), but the "pick up a tree"-part makes it really hard to work with (and I don't want a tree attached to the unit).
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,596
Unless you code your own combat system from the ground up I imagine you have two Events to work with:

1) A unit is attacked

2) A unit takes damage

Event 1 has the issue of being cancelled/exploited by the player, causing the trigger to run multiple times. It can also get interrupted and run the trigger without the attack actually hitting.

Event 2 has the issue of allowing multiple ranged attacks to occur since there's no guarantee that the first attack's projectile will hit before the second attack is made.

A unit is attacked seems like your best bet. There will be cases when it gets interrupted and you lose your 1 ranged attack but that's better than the alternative.
 
Last edited:
Level 8
Joined
Mar 19, 2017
Messages
248
This could be, in some regard, be done with 1.31+ and without data storage, by refering the attack point unit real field. Take all this with a grain of salt, because i havent tested this myself.
Setting unit weapon fields don't seem to work neither on 1.31 or 1.32, but they can be read with the respective get functions (ie. you can't set a unit's attack range but you can get the value). I have tested this with a great deal of fields, but i havent tested it with the attack point value.
Similar to the attack system presented above, you use an attack event to start a non repetitive timer ("launch timer") with an interval equal to the unit weapon real field. Timers are very light weight so you could potentially use a unit indexer plus a timer for each unit. The callback of the timer is the attack launch functions/event system.
But you also need a order event, so you clean any unit that, altough fired its launch timer, issued an incompatible order (ie. stop) while timer still has some seconds remaining. I suppose here you simply pause the launch timer, so the callback never fires for these units.
 
you use an attack event to start a non repetitive timer ("launch timer") with an interval equal to the unit weapon real field. Timers are very light weight so you could potentially use a unit indexer plus a timer for each unit. The callback of the timer is the attack launch functions/event system.
But you also need a order event, so you clean any unit that, altough fired its launch timer, issued an incompatible order (ie. stop) while timer still has some seconds remaining. I suppose here you simply pause the launch timer, so the callback never fires for these units.

I use 1.31.
This can be done, and even very easy if I currently only care about 1 unit, after using an ability.
I was hoping to set some weapon fields, but will have to trigger that damage (because it mostly was damage, but I hoped it was possible because then the UI would show an increasing amount of damage while channeling up the empowered attack).
 
Level 8
Joined
Mar 19, 2017
Messages
248
Damage can't be set with the unit weapon field functions, but base damage can be set with BlzSetUnitBaseDamage. Green/mod damage can be "set" just by adding a item ability that increases damage, and you can even modify the damage by using the ability field modification functions.
 
Ok, so for heroes, as far as I know, it's impossible to get the "current attack speed". You can only get the base attack speed.
But as for the attack, I guess that I have a fairly short timer that works on level 1 without items, and make the weapon 2 attack cooldown fairly long and it should be possible to use the (backswing point)-long timer and as long as nothing cancel the attack, change weapon back to 1.

Will have to test it more, but afaik it's impossible to get the current attack speed.
 
Level 8
Joined
Mar 19, 2017
Messages
248
The data you really want is not attack speed but attack point or rather "animation damage point" in the editor. In JASS it would be "BlzGetUnitWeaponRealField(unitVar, UNIT_WEAPON_RF_ATTACK_DAMAGE_POINT, attackIndex)" and in GUI you can search it on the Unit functions (EDIT: i mean, as an integer type; Integer> Unit - Get Unit Weapon Integer Field). Previously, if someone wanted to atempt something like this they would have to store values for each unit type themselves (ie. with a hashtable).

In your attack event, you start a timer with that data as timeout. It will be wiser to have a constant timer instead of creating a timer each time the unit attacks. In the order event (ie. the unit issued a stop order and its launch timer fired) you pause the timer (so it will never fire the events).

One limitation is that animation damage point is modified based on the attack speed modifiers the unit may have (ie. endurance aura) so that weaponrealfield function will not be accurate unless you know the formula that WC3 uses for modifyng attack damage points. I think the formula is already known so you could, in theory, make an accurate timeout.

For example:
My hero unit is a Rifleman that has an animation damage point of 0.170. If the function i pointed out works (as far as i know most unit weapon field functions can be read but not be set), each time the Rifleman does an attack, a timer with an interval of 0.170 will fire. Should this Rifleman stop the animation, an order event that detects such compromising orders will pause the timer mid-time so it will never fire the attack launch event.
Now let's say that this Rifleman is affected by Endurance Aura. As i said, and as far as i know, attack speed modifiers mess with damage point of units (ie. if they have positive attack speed modifiers this data will be reduced and viceversa). To fire the timer with an appropiate timeout you NEED to know how attack speed modifiers affect the damage point in the WC3 Engine (i read somewhere that there is a formula, so you could in theory actually make this work, but i'm not sure about this), otherwise it will not be accurate. In this example, Endurance Aura will reduce (as it grants attack speed) damage point of the Rifleman (let's say it reduces it from 0.170 to 0.100), so if i start the timer with a 0.170 timeout, i will not fire the events properly.
 
Last edited:
The data you really want is not attack speed but attack point or rather "animation damage point" in the editor...

One limitation is that animation damage point is modified based on the attack speed modifiers the unit may have (ie. endurance aura) so that weaponrealfield function will not be accurate unless you know the formula that WC3 uses for modifyng attack damage points. I think the formula is already known so you could, in theory, make an accurate timeout.

These 2 sentences kind of contradicts each other, and the latter is the reason why I wanted to get the current attack speed modifiers ("get current attack speed modifiers" does not exist unfortunately).

But because it's a hero and there are many attack speed modifiers in the map I'm making this for, I have to make assumptions and probably use "Event - A unit is attacked", and always disable the 2nd weapon after "animation damage point"-time.

Best case scenario is that the weapon fires and swap back to weapon 1 slightly after the projectiles is in the air.
Worst case scenario is that the unit has some crazy temporary attack-speed boost and are able to fire more than once (should be preventable by having long attack-cooldown on weapon 2), or animation cancel and loses the special attack slightly after the animation cancel (The player will learn that animation cancel this attack is bad and not repeat).

This is my current though.
 
Level 8
Joined
Mar 19, 2017
Messages
248
That is true, in order to make this kind of system work you either need to trigger yourself all attack speed bonuses or not use attack speed bonuses at all, atleast those that you don't know their value for sure. For example, you will need to create your buffs from scratch and with a buff system (a very painful cost if you only want to detect attack launch incidentally). The other approach (very convoluted) is to leave these special attacks that you want to know when they are launched to a dummy attacker unit. The hero attacks, you interrupt the attack (ie. stop the attacker) and simulate a cooldown (you give the unit Cargo Hold ability so it can't attack for some seconds), and create a dummy attacker that performs a single attack and then pauses. All data analysis passes to this dummy attacker that you know can't be affected by attack speed. If the hero attacks multiple times, then you just creating as many dummy attackers as needed (you can do recycle system so you don't create and destroy attackers every time).

About attack speed, agility attack speed is perhaps the easier one to control and read as you just need to know the agility of the hero and the bonus attack speed per point (this last data is available on Game Constants). BlzGetUnitAttackCooldown can easily retrieve the vanilla attack speed of the unit, so you can get an estimate of the attack speed of an hero. The moment this hero is affected by Bloodlust or else, then you start getting into painfully hardcoded triggers.
But still and as you already noted, even if you have all your attack speed bonuses triggered and accessible, you always need to know how attack speed bonuses affect attack damage point.

So yeah, this kind of system (one of the most recquested of all time) is very hard to create with what we have right now, atleast if you want some WC3 features like buffs and auras. Still, before the unit weapon field functions, should one want to atempt the basics of the system, one would recquire to manually register the attack points of each unit type.
 
Level 8
Joined
Mar 19, 2017
Messages
248
The instant attack + DDS + missile system + custom events is indeed the best workaround for a fully controllable attack system. That system also doesn't break with attack speed bonuses.

Since the more elegant solution (the thread starter is just asking for a vanilla WC3 attack launch event) breaks when addressing attack speed bonuses, he might consider that more systemic solution.

About the formula regarding on how attack speed bonuses affect attack damage point, i think it is (searched on liquipedia): Attack Point ÷ (1 + (Increased Attack Speed ÷ 100)). Attack point is a variable accessible with BlzGetUnitWeaponRealField (just tested this on 1.32, you can read that value, no need for making tables and such) so if you know the attack speed bonuses (which we can't unless we hardcode stuff, atleast for buffs and auras; we can know the IAS for agility though), you could technically make an accurate timer timeout.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,596
I think the solution mentioned by @Bribe on that thread is now doable (since patch 1.31+).
So I used the solution that Bribe mentioned in that thread to create ThompZon's ability:
  • Setup
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • Unit - Create 1 Blademaster for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Set VariableSet Ranged_Hero = (Last created unit)
      • -------- --------
      • -------- Enable ranged attack --------
      • Unit - Set Unit: Ranged_Hero's Weapon Boolean Field: Attacks Enabled ('uaen')at Index:0 to Value: False
      • Unit - Add Enable Attack 2 to Ranged_Hero
      • -------- --------
      • -------- Adds the passive ability --------
      • Unit - Add Ranged Attack (Icon) to Ranged_Hero
  • Damage
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • IsDamageRanged Equal to True
      • DamageEventSource Equal to Ranged_Hero
    • Actions
      • -------- Create attack dummy --------
      • Unit - Create 1 Ranged Dummy for (Owner of Ranged_Hero) at (Position of DamageEventSource) facing Default building facing degrees
      • Unit - Set Base Damage of (Last created unit) to (Integer((DamageEventAmount - 1.00))) for weapon index: 0
      • Unit - Order (Last created unit) to Attack DamageEventTarget
      • Unit - Add a 0.25 second Generic expiration timer to (Last created unit)
      • -------- --------
      • -------- Set the hero's damage dealt to 0 (Dummy will deal the real damage) --------
      • Set VariableSet DamageEventAmount = 0.00
      • -------- --------
      • -------- Puts the passive ability on cooldown --------
      • Unit - For Unit Ranged_Hero, start cooldown of ability Ranged Attack (Icon) " over "5.00 seconds.
      • -------- --------
      • -------- Disable ranged attack --------
      • Unit - Remove Enable Attack 2 from Ranged_Hero
      • Unit - Set Unit: Ranged_Hero's Weapon Boolean Field: Attacks Enabled ('uaen')at Index:0 to Value: True
      • -------- Wait for cooldown --------
      • Wait 5.00 seconds
      • -------- Enable ranged attack --------
      • Unit - Set Unit: Ranged_Hero's Weapon Boolean Field: Attacks Enabled ('uaen')at Index:0 to Value: False
      • Unit - Add Enable Attack 2 to Ranged_Hero
Some flaws:
-The attack gets interrupted when switching weapon types.
-I couldn't figure out how to display the 2nd weapon but I know there's a way. I tried Showing Weapon Index 1 but it didn't work.
-Ranged Dummy can miss but I think you can work around this by giving it an ability with No Miss enabled.
-I suppose in very rare cases the Ranged Dummy's target can die before the dummy gets it's attack off. This may cause it to autoattack a random enemy within range. Maybe Permanent Invisibility with auto-acquire targets disabled or Worker classification can fix this.
-Not MUI, but it's fairly easy to make this adjustment.

Also, I realize there's some Point leaks.

Notes:
The passive ability Ranged Attack (Icon) is used to show a cooldown and is optional.
The Enable Attack 2 ability is based on the old Orb of Lightning ability. This is used to enable the Blademaster's ranged attack.
 

Attachments

  • Detect Ranged Attack.w3m
    56.8 KB · Views: 36
Last edited:
Level 8
Joined
Mar 19, 2017
Messages
248
This is my hastily made map on the ranged attack projectile launch. It works for everything except for IAS affected by buffs (very painful but, it works and can be done without the systems it has imported, credits Vexorian and Bribe).
 

Attachments

  • TEST.w3m
    32.1 KB · Views: 32
I tested around a bit and DamageEvent (Bribes Damage Engine) does not become 1 if the attack misses (obviously, since no damage is being dealt).

I do not want the "attack" to be able to miss (evasion, high-ground and curse exists on my map), so I'll probably have to do it fully triggered on "A unit is attacked" event.

Ok. So my ability is along the lines of:
Channel to charge up the weapon. Attack to release the current charge.
Every 0.25 seconds charging costs X mana and stores a charge.
Each charge increases AoE, Damage, Armor Pierced.
Charge is kept until a basic attack is fired.
You can store up to X charges.

This is on a hero that are very likely to have various attack-speed buffs and items, at least later in the game.

Due to DamageEvent will not fire on miss/evade and I want it to hit even when "missed" (would feel bad to charge up for a few seconds and then miss!).
I will probably fire a projectile (dummy spell) on "A unit is attacked"-event and switch back to weapon 1 after a short duration (0.2 seconds?) and trigger the effect when the projectile hits.
This will fire regardless of animation cancel and will never miss.

Thanks for the help though, a few ideas and ways of doing things were ruled out and details on how to do this were thanks to you guys :)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,596
You can give your Units an ability that has Never Miss to prevent attacks from missing. I explained this in my post.

[Spell] - Attack never miss

My solution actually looks to do exactly what you want, it just suffers from flaws that I was too lazy to fix myself. But most if not all all of them are fixable.
 
Last edited:
You can give your Units an ability that has Never Miss to prevent attacks from missing. I explained this in my post.

[Spell] - Attack never miss

My solution actually looks to do exactly what you want, it just suffers from flaws that I was too lazy to fix myself. But most if not all all of them are fixable.

Ohh, sorry. I didn't read it again when I had time to sit down and tinker with WE and missed it.
Thanks for the help. This will simplify this ability :)
 
Well, it doesn't seem to work on 1.31
I read through patch notes and guess that it's fixed in Patch_1.32.4 (Warcraft III/Patch 1.32.4)
  • Several fixes have been applied to Instance API natives related to unit attacks.
I get the orb-effect, but attack-range and type is still that of weapon 1 (I.E. not instant, as my weapon 2 is). Yes, I disabled weapon 1 from triggers like you did.

I more or less recreated what you did Uncle (+added a 100% critial hit in disabled spellbook, where I enable/disable the crit-effect whenever I want 100% hit-chance).
Saw that you used negative button positions (first time I see it, useful trick).

Maybe I'll go with the "on attack" as trigger, and then add a spell that I throw... Hmm...
 
Status
Not open for further replies.
Top