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

Damage Delay

Status
Not open for further replies.
Level 13
Joined
Jan 2, 2016
Messages
973
I've started making a system, that will register when an attack is actually launched. But now I'm wondering what delay the units actually have.
Is it Animation Backswing Point + Animation Damage Point, or is it only the Animation Backswing Point?

And 1 more question... Is there a way for me to get these values in my trigger, or do I need another trigger to set variables to their values for every unit type, and then load these variables from a hashtable?
 
Level 12
Joined
May 22, 2015
Messages
1,051
Damage point is when the damage is dealt.

You cannot retrieve these values with natives. You have to store it and keep track of it.

There's a bigger problem - I think the damage point might change when you increase or decrease attack speed (just look at the animation). You might also need to keep track of attack speed in a similar way to the damage points. Then there's an even larger problem - you have to keep track of every single attack speed increase or decrease in the entire map (auras, buffs, items, abilities, agility). I think this is all a ton of work that you might not want to get into :/ it would have to be critical to the map for me to bother with it.
 
Level 13
Joined
Jan 2, 2016
Messages
973
Well, I made a really basic one. What do you think?
JASS:
function EventReg takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    set udg_Attacked = LoadUnitHandle(udg_Attack_Table, id, 'atkd')
    set udg_Attacker = LoadUnitHandle(udg_Attack_Table, id, 'atkr')
    call SaveBoolean(udg_Attack_Table, GetHandleId(udg_Attacker), 'bull', false)
    call FlushChildHashtable(udg_Attack_Table, id )
    call DestroyTimer(t)
    set udg_Attack_Launched = 0.00
    set udg_Attack_Launched = 1.00
    set t = null
endfunction

function Delay takes nothing returns boolean
    local integer tid = GetUnitTypeId(GetAttacker())
    local integer uid = GetHandleId(GetAttacker())
    local real del_time = LoadReal(udg_Attack_Table, tid , 'dely')
    local boolean b = LoadBoolean(udg_Attack_Table, uid , 'bull')
    local timer t
    if b then
        set t = LoadTimerHandle(udg_Attack_Table, uid , 'time')
        call TimerStart(t, del_time, false, function EventReg)
        call SaveUnitHandle(udg_Attack_Table, GetHandleId(t), 'atkd', GetTriggerUnit())
    else
        set t = CreateTimer()
        call TimerStart(t, del_time, false, function EventReg)
        call SaveTimerHandle(udg_Attack_Table, uid, 'time', t)
        call SaveBoolean(udg_Attack_Table, uid, 'bull', true)
        call SaveUnitHandle(udg_Attack_Table, GetHandleId(t), 'atkr', GetAttacker())
        call SaveUnitHandle(udg_Attack_Table, GetHandleId(t), 'atkd', GetTriggerUnit())
    endif
    set t = null
    return false
endfunction

function Bullean takes nothing returns boolean
    call SaveBoolean(udg_Attack_Table, GetHandleId(GetTriggerUnit()), 'bull', false)
    return false
endfunction

function AttCancel takes nothing returns boolean
    local boolean b = LoadBoolean(udg_Attack_Table, GetHandleId(GetTriggerUnit()), 'bull')
    local timer t
    if b then
        set t = LoadTimerHandle(udg_Attack_Table, GetHandleId(GetTriggerUnit()), 'time')
        call FlushChildHashtable(udg_Attack_Table, GetHandleId(t))
        call DestroyTimer(t)
        set t = null
        call SaveBoolean(udg_Attack_Table, GetHandleId(GetTriggerUnit()), 'bull', false)
    endif
    return false
endfunction

//===========================================================================
function InitTrig_Test takes nothing returns nothing
    local trigger one = CreateTrigger()
    local trigger two = CreateTrigger()
    set gg_trg_Test = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Test, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_Test, Condition( function Delay ) )
    call TriggerRegisterEnterRectSimple( one, GetPlayableMapRect() )
    call TriggerAddCondition( one, Condition( function Bullean ))
    call TriggerRegisterAnyUnitEventBJ( two, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterAnyUnitEventBJ( two, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerRegisterAnyUnitEventBJ( two, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( two, Condition( function AttCancel ))
    set one = null
    set two = null
endfunction

EDIT: And by the way.... Riflemans have 0.700 Backswing, but when I set the delay time to 0.7 - it happens much later (after the shot).
However, when I set the time to the (Backswing - Damage Point (0.700-0.170)) - the event runs about in the same time as the attack happens..
But when I set NE Archer's time to their backswing time - the event runs earlier than it should...

EDIT 2: When I set the delay to the Damage Point for NE Archers - the event runs when it should.....

EDIT 3: Actually the same goes for Rifleman as well, so I guess the Damage Point is the one that the delay should be set to :p
 
Level 12
Joined
May 22, 2015
Messages
1,051
or you know, just use damage detection system, or if you want to code it, use the techniques they use, which is "Unit event - Unit deals damage" essentially

"I've started making a system, that will register when an attack is actually launched"

DDSs don't do this. Not exactly sure what is trying to be achieved, but this is very possibly quite different from a regular DDS.

It would probably be a good idea to know what is trying to be achieved with this, though.
 
Level 13
Joined
Jan 2, 2016
Messages
973
or you know, just use damage detection system, or if you want to code it, use the techniques they use, which is "Unit event - Unit deals damage" essentially
I AM using a DDS. I just think it's about time that someone created a system, that detects when an attack is launched.

If you check my multishot - it's using DDS to run. BUT it has 2 major drawbacks:
1) I need to make it unable to miss, cuz if I don't do that - the event doesn't run when my unit misses.
- And I can't make it unable to miss allied units, without giving it a ministun, but a ministun will make my unit overpowered.
2) I need to set my unit's attack to 'instant'.
If someone uses my multishot, and adds it to a unit, that isn't supposed to have it - it will look weird, as the unit's missile will lauch, will hit the enemy, and THEN the event will run.
- True that this can be avoided, by giving the unit multishot as default ability. Just set the amount of targets hit to 1. And when you want the multishot to start working as multishot - increase the amount of targets (with a trigger).. But that's not the point.

(I kind a can't afford to use THIS system, which I'm creating now, for my multishot tho, cuz I wouldn't be able to determine the damage it should deal, or at least it will be weird, if I start dealing the unit's damage on its next attack xP, but there could be triggers that don't need to know the damage that should be dealt..)
So... I don't want to create another DDS, I want to create another type of system, that registers its event BEFORE the DDS.
It can even enchance DDS, if people use both.
 
Level 12
Joined
May 22, 2015
Messages
1,051
You should just add in your custom multishot library a big comment describing how to use it (should also mention it in the thread it is posted).

Basically, just say "the unit using the multishot should have instant attack type and ....". Implementing an "attack start" event would be really hard - and worse, it would be even more complicated for someone to set up (they'd have to manually enter the data into the hashtable and it will still be unreliable due to weird attack speed things).

You can just mention that a limitation is that it is not compatible with the built-in evasion in wc3.
 
Level 13
Joined
Jan 2, 2016
Messages
973
Well, I already have written what preperations need to be done for my multishot (in the thread), tho I haven't given the example with what people should do if they want to add the multishot later on in the game.

Anyways.. Entering the data into the hashtable isn't so hard, since people only need to do it for units that are going to use this event, and there aren't too many cases in which people will need to use this event. Unless someone is making some kind of map, entirily based on this event, but that's hardly believable at this point. Entering it for each unit takes only 1-2 rows of code. 1 if you do write the unit type id manually and 2 if you set a variable to it.

Anyways.. I tested the attack speed bonus issue. With a 15% bonus attack speed - the event still launches ALMOST when it should. Higher values of the bonus may indeed break it tho. But players can still use it if they don't intend to add any attack speed bonuses on their map, or if the units that are going to use this event don't have anywhere to get such bonus from.

And well, my multishot doesn't miss enemies, only allies. I've based it on Critical with 100% chance to happen, and always hits set to true.
The issue now is that it CAN'T miss :D
I will trigger the miss eventually, but I don't have time for that at the moment.
 

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
Some simple facts:
It's important of being aware of the fact that Animation Damage Point is the time when the attack anim begins, till it shoots/does damage. For the rifleman it is 0.170 sec

That means it takes very short time for the rifleman to actually shoot after its attack anim starts.

Animation Backswing Point of 0.700 is the value for rifleman, as the name indicates is the time used to kinda end the animation of the attack anim. Mostly this value is only meant to make animation look good ingame. This is noticable when a unit runs away, your rifleman "pauses" in 0.7 sec after attacking before starting chasing the fleeing unit it is attacking. Professional melee players kinda learns the trick of ordering quickly, because you can order a unit during Animation Backswing Point period and actually move, in that way they reduce the dead time of Animation Backswing Point.


The attack animation of the rifleman lasts 0.867 sec
0.170 + 0.700 = 0.870 sec is very close to the value.


To put it simple:

Animation Damage Point is the delay from when the unit start to initiate attack anim to shoot/damage release. Interuption will abort the attack, but will still be registered by: Unit - A unit Is attacked event

Animation Backswing Point is the time after shoot/damage release anim. Interuption here will not matter triggerwise. Ordering a move after Attack Damage Point during backswing period will end the short stand still "pause" period of Animation Backswing Point.




If you are using this:
  • Attack Detect
    • Events
      • Unit - A unit Is attacked
You should be aware of this events weaknesses. It will register from the point unit is starting its animation before Animation Damage Point and if you interupt the unit before it reaches the point of Animation Damage Point, it will start attacking again and you will run the trigger again, before the unit actually attacked. For example issuing stop order will sometimes cause this or moving the unit before damage point.

Using 0.001 for damage point will solve that problem, but will look weird for certain models other than rifle man. This is a simple way.

Another method is using a timer in addition and take this anim into account there.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
or you know, just use damage detection system, or if you want to code it, use the techniques they use, which is "Unit event - Unit deals damage" essentially
DDS? So naive -_-
WE WANT MORE POWAH!!!

I just think it's about time that someone created a system, that detects when an attack is launched.
Detect launch? So naive -_-
WE WANT MORE POWAH!!!

I created a resource named BasicAttack (which can be found in the lab) that has many things that you could copy just for simple usage.
It is not completely finished as it doesnt properly work with attack move... sort of.
But you can still take a look at the duration calculations in it.
There are three variables that you need:
Backswing point,
Damage Point,
Bonus attack speed.

Anyway, you should definately check out the ODE (Object Data Extractor).
In its current state, it is simply said a list of natives to load in Object Editor data for units and items. (Dunno about the progress on it but Abilities would be really useful for it.)

Also, it is kind of nice if your stuff works well with WC3... but lets be real, that is not going to happen at all.
You are not going to keep track of a unit's bonus attack speed, actual attack damage and more stuff like that. If you want systems that do more than they are supposed to do, then you have to code more things yourself.

For example, in my BasicAttack, you need values for basic attack damage and for the bonus attack speed... so you need a stat system that knows the exact values of the two that you will then use.
However, this means that abilities like Trueshot Aura, Berserk, Item Attack Speed Bonus, etc will not be allowed to use any more.
On the other hand, with BasicAttack, you are able to set the attack speed of a unit by simply editting a real variable so you dont need those abilities at all.
 
Status
Not open for further replies.
Top