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

[Trigger] Damage reduction on unit side

Status
Not open for further replies.
Level 11
Joined
Oct 16, 2013
Messages
246
Hi, I'm trying to make a unit that takes less damage if hit on the left side, in a similar way that Rigwarl's Bristleback works in Dota. That's all what I've got:

  • Events
    • Unit - 'My unit' Is attacked
  • Conditions
  • Actions
    • Set MyUnit = 'My unit'
    • Set Attacker = (Attacking unit)
    • Set MyUnitFacingAngle = (Facing of 'My unit')
    • Set AttackerFacingAngle = (Facing of (Attacking unit))
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If: Conditions
        • MyUnitFacingAngle Greater than or Equal to (AttackerFacingAngle + 45.00)
        • MyUnitFacingAngle Less than or Equal to (AttackerFacingAngle + 135.00)
      • Then: Actions
      • Else: Actions
The issue is that this doesn't seem to work when 'My unit' is facing the east. I'm pretty sure it's because of the 0º-360º and I was thinking about adding a number to the FacingAngle Variables but I don't know how many or when. Forget about the rest of the trigger, I just need the angle check fixed. Thanks in advance.
 
This won't work since you are using the "is Attacked" event. This event only detects when an attack order is issued, that is, the damage haven't been done and the attack order is only beginning. Use Damage Detection Systems instead.

For the angle, It's wrong. You need nested if's. Detect first whether or not an attack is received within the (facing angle + 180)+67.5 and (facing angle + 180)-67.5. Then check if the attack is within (Facing angle +180)+22.5 and (Facing angle +180)-22.5. If both of which are true, reduce it to the number corresponding 45 degrees, if the first one is true then reduce it to it's corresponding damage.

And yes, I know Bristleback and that's how it's "Back" works :D
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
For the angle detection you utilize the power of the cosine (or sine, depending which is optimal).

Get the angle the damaged unit is facing. Let us call this angleface.
Get the angle the damage source is from the perspective of the damaged unit. Let us call this anglesource.
Work out the angle which where damage should be blocked from. This is done by getting angleface and adding 90 degrees to it. Let us call this angleblock. angleblock = (angleface + 90)
Work out the angle difference from angleblock to anglesource. This is done by getting anglesource and subtracting angleblock. Let us call this anglediff. anglediff = (anglesource - angleblock)
Utilize cosine to convert anglediff into a comparable facing deviant. Simply put anglediff through cosine. Let us call the result anglecomp. anglecomp = (Cos(anglediff))
Compute a threshold value for the angle based on the maximum deviation you want to permit from the block angle. This is done by putting the amount through the cosine function as well. In this case the threshold value is 45 degrees. Let us call this compthresh. compthresh = (Cos(45))
Finally you can test if a hit should be blocked or not by checking if anglecomp is above the threshold. In this case it would be (anglecomp greater than or equal to compthresh).

If you inline the mathematics you get...
(Cos(anglesource - (angleface + 90)) >= Cos(45))
(Cos(anglesource - angleface - 90) >= Cos(45))

As we know from mathematics, the Cosine and Sine functions are related to each other by an input offset of 90 degrees. As such we can optimize this by replacing the cosine with a sine function.

(Sin(anglesource - angleface) >= Cos(45))

Due to the circular nature of Sin and Cos functions any intermediate angles <0 or >360 does not matter.
 
Level 11
Joined
Oct 16, 2013
Messages
246
I already explained that part.

Yeah, I know. I was just doing something wrong.

For the angle detection you utilize the power of the cosine (or sine, depending which is optimal).

Get the angle the damaged unit is facing. Let us call this angleface.
Get the angle the damage source is from the perspective of the damaged unit. Let us call this anglesource.
Work out the angle which where damage should be blocked from. This is done by getting angleface and adding 90 degrees to it. Let us call this angleblock. angleblock = (angleface + 90)
Work out the angle difference from angleblock to anglesource. This is done by getting anglesource and subtracting angleblock. Let us call this anglediff. anglediff = (anglesource - angleblock)
Utilize cosine to convert anglediff into a comparable facing deviant. Simply put anglediff through cosine. Let us call the result anglecomp. anglecomp = (Cos(anglediff))
Compute a threshold value for the angle based on the maximum deviation you want to permit from the block angle. This is done by putting the amount through the cosine function as well. In this case the threshold value is 45 degrees. Let us call this compthresh. compthresh = (Cos(45))
Finally you can test if a hit should be blocked or not by checking if anglecomp is above the threshold. In this case it would be (anglecomp greater than or equal to compthresh).

If you inline the mathematics you get...
(Cos(anglesource - (angleface + 90)) >= Cos(45))
(Cos(anglesource - angleface - 90) >= Cos(45))

As we know from mathematics, the Cosine and Sine functions are related to each other by an input offset of 90 degrees. As such we can optimize this by replacing the cosine with a sine function.

(Sin(anglesource - angleface) >= Cos(45))

Due to the circular nature of Sin and Cos functions any intermediate angles <0 or >360 does not matter.

Thanks for this clear explanation, Doc. This finally helped me to solve my problem.


+rep and a sexy tuskarr good-night kiss for both of you.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
It should be noted that this approach best applies to heavy scripting languages like JASS. Computing a Cosine or Sine is not much more expensive than a few basic operators so its overhead makes little difference and can even end up being faster (saves on a lot of operations).

In languages like C++ this might not be the case. Simple comparisons are usually considerably faster than computing sine or cosine values. As such it might be better to do angular comparisons factoring in the circular nature rather than computing a sine/cosine value, especially if angle is in integer form.
 
Status
Not open for further replies.
Top