Checking for angle using no angles

This tutorial helper you?

  • Yes

    Votes: 1 14.3%
  • I still have some questions.

    Votes: 2 28.6%
  • No

    Votes: 4 57.1%

  • Total voters
    7

mapguy

New Member
Reaction score
46
This tutorial is about dodging the WC3 bug when we want to detect an interval between 2 angles. If you already know how to do this don't read this tutorial.

This tutorial teaches a way you can use to check angles without using angles, only distances.
The reason for this is because WC3 has problems with it's angles, the angle between point goes from -180 to +180, which means you have a lot of problems when you want to detect if damage comes from behind, if units are inside a cone, if a unit is looking to the other, etc.


the problem:
If you have a simple spell that you want to get unit in a cone, which means:
Angle between (caster) and (enemy) is a value between ((angle between (caster) and (target point of ability beeing cast)) + or - 10).

if the angle between (caster) and (target point of ability beeing cast) is 175, the angle between (caster) and (target) must be between +185 and +165. But there is no +185 angle on warcraft!.
Usually you will create a very complicated trigger to dodge this problems, this tutorial will show an easier way to do this using mathematical logic.

I need any mathematical knoledge to do this?
No, you don't. I will only show and explain how the method works, and then, you just have to putthe values inside a formula.


TUTORIAL

First of all, I must say that I'm going to use a backstab detection as example.

Imagine this spell:
Backstab (passive)
Everytime you hit an enemy from behind you deal 25 bonus damage.
Note: angle between target's back and damage source must be +or- 30 degrees.

THIS IS THE FORMULA! YOU CAN JUST USE IT IF YOU UNDERSTAND, IF NOT, READ THE REST OF THE TUTORIAL
this is the formula, you just have to change the value 30 to the limit angle you would like to use.
Code:
set A = position of (damage source)
set B = position of (triggering unit)
set C = B offset by (distance between A and B) and (fancing of (triggering unit)) degrees.
If (Cos(30/2)) < ((Distance between C and A) / ((Distance between C and B)x2) then do your action

No need for mathematical Knoledge, just use the formula above!


Code:
set A = position of (damage source)
set B = position of (triggering unit)
set C = B offset by (distance between A and B) and (fancing of (triggering unit)) degrees.
set cb = (distance between C and B) x 2
if cb = 0 then (set cb = 0.01)
If (Cos(30/2)) < ((Distance between C and A) / (cb) then do your actions
this is to prevent divisions by zero, but, I think it is almost impossible to have a distance between target and sorce equal to zero...so, use it just if you think your map could lead to a value like 0, if not, just use the first formula)

you can download the demo map in the bottom of this post and just Copy and Paste the trigger inside your map


---------------------------------------IF YOU DON'T UNDERSTOOD THE FORMULA READ THIS----------------
1 - First of all you have to use a damage detection system (but this is not a tutorial about damage systems, so, I'll not explain how to use them or create them).

2 - when a unit takes damage and this is a damage that results from an attack you have to pick a lot of points:
A = the position of the damage source.
B = the position of the target.
-ab- = the distance between A and B.
C = B offset by -ab- and (facing of target)
after you pick all the 3 points listed above you will have a mathematical circle with:
B as its center.
A as a point in the border of the circle.
C as another point in the border.
-ab- as the radius of the circle.

Using mathematical logic I can say that the the distance between B and A is equal to the radius, also, the distance between B and C is equal to the radius and equal to -ab-.

TO detect the angles we have to transform out circle into a rectangle triangle, for this, we just have to pick 2 distance values:
Hip = 2x(Distance between C and B)
Cat = Distance between A and C.
Then we detect a Cosine:
Cosine = Cat / Hip
The only thing we will use now is this Cosine.
Do you remember that the angle between the source and the back of the target must be +or- 30 degrees?
So, just do this:
set Limit_Cosine = Cosine of (30/2) degrees
check if Cosine > Limit_Cosine

--------------end----------------------

This tutorial helped you?
Is this tutorial too abstract?
Is it to complicated?
Did you find any bug when using this?
Do you want help with other types of spells like cone detection, see if unit is looking to another, etc?
I'll check this tutorial for comments, and I can update it if someone is having troubles to use this mathematical content.

I Hope at least one person find help here.:thup:

Here is the demo map, it works PERFECTLY!
 

Attachments

  • Backstab demo.w3x
    17.2 KB · Views: 264

Moridin

Snow Leopard
Reaction score
144
There are loads of grammatical and spelling errors in this. Either proof-read it yourself or get someone to do that for you.

I personally didn't really understand this.

1) Why are Hip and Cat called "Hip" and "Cat" ? :S

2) I think the cone you've given here is 45 degrees, how would I go about changing that? How would I detect a cone behind a unit?

3) I really didn't get how you used Cosine and Limit Cosine.

4) I've done a backstab mechanic before. Wouldn't it be easier just to check the absolute difference between facing angles of the two units?
 

13lade619

is now a game developer :)
Reaction score
398
it's been done before.. you should've just asked.

IsUnitBehind
JASS:
function IsUnitBehindUnit takes unit u2, unit u1, real def returns boolean
    local real face = GetUnitFacing(u1)
    local real rangle = bj_RADTODEG*Atan2(GetUnitY(u2)-GetUnitY(u1),GetUnitX(u2)-GetUnitX(u1))
    set def = def / 2
    return not (RAbsBJ(face-rangle) &lt; def or RAbsBJ(face-rangle-360) &lt; def)
endfunction


Units in Sector
http://www.thehelper.net/forums/showthread.php?t=103445&highlight=Units+sector

Plus.

your methods are complicated and cumbersome.
you dont really need 3 points and you dont even need the Cosine function.

you only need some rather simple arithmetic on angles.
 

Nherwyziant

Be better than you were yesterday :D
Reaction score
96
I made a test and it doesn't work, maybe I just misunderstood. Can you make a test map or somethin

Anyway, spelling errors.
 

mapguy

New Member
Reaction score
46
There are loads of grammatical and spelling errors in this. Either proof-read it yourself or get someone to do that for you.

I personally didn't really understand this.

1) Why are Hip and Cat called "Hip" and "Cat" ? :S
Hip = Hipotenuse
Cat = Catet

2) I think the cone you've given here is 45 degrees, how would I go about changing that? How would I detect a cone behind a unit?
The cone pick units in an angle of +or- 15degrees from C and +or- 30 degrees from B.

3) I really didn't get how you used Cosine and Limit Cosine.

4) I've done a backstab mechanic before. Wouldn't it be easier just to check the absolute difference between facing angles of the two units?
THe WC3 as I said has bugged angles. it goes from -180 to +180, which means you find some bugs when you use absolute angles.
because 170 +or- 20 = 150 and 190 (there is no angle 190 on WC3, the equivalent angle is -170)

I made a test and it doesn't work, maybe I just misunderstood. Can you make a test map or somethin

Anyway, spelling errors.
maybe you misunderstood, I'll post a demo map.
the spelling errors is because my english is not native, I am still lerning it.

it's been done before.. you should've just asked.

IsUnitBehind
Jass:

function IsUnitBehindUnit takes unit u2, unit u1, real def returns boolean
local real face = GetUnitFacing(u1)
local real rangle = bj_RADTODEG*Atan2(GetUnitY(u2)-GetUnitY(u1),GetUnitX(u2)-GetUnitX(u1))
set def = def / 2
return not (RAbsBJ(face-rangle) < def or RAbsBJ(face-rangle-360) < def)
endfunction


Units in Sector
http://www.thehelper.net/forums/show...t=Units+sector

Plus.

your methods are complicated and cumbersome.
you dont really need 3 points and you dont even need the Cosine function.

you only need some rather simple arithmetic on angles.
are you sure this works for angles that are very close to +180 and -180?
this code can be translate do GUI? I dont understand JASS.
 

Moridin

Snow Leopard
Reaction score
144
Here's my backstab trigger. The actual condition you need for it is much smaller because of all the actions meant for my map.

Trigger:
  • Ninja Backstab
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • ((Triggering unit) is A structure) Equal to False
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Attacking unit)) Equal to Ninja
        • Then - Actions
          • Set Unit_A_Angle = (Facing of (Triggering unit))
          • Set Unit_B_Angle = (Facing of (Attacking unit))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Abs(((Integer(Unit_A_Angle)) - (Integer(Unit_B_Angle))))) Less than or equal to 45
                  • (Abs(((Integer(Unit_A_Angle)) - (Integer(Unit_B_Angle))))) Greater than or equal to 315
            • Then - Actions
              • Game - Display to (Player group((Owner of (Attacking unit)))) the text: Backstab! Ninajs do...
              • Floating Text - Create floating text that reads Backstab! above (Triggering unit) with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Change the lifespan of (Last created floating text) to 1.00 seconds
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Triggering unit) is alive) Equal to True
                • Then - Actions
                  • Unit - Cause (Attacking unit) to damage (Triggering unit), dealing 500.00 damage of attack type Spells and damage type Normal
                • Else - Actions
            • Else - Actions
        • Else - Actions
 

roXplosive

New Member
Reaction score
15
I've taken a look at aceheart's solution and i agree it's elegant because we all know the tangent function is monotonous and growing he used this property to get the units in a cone by making it verify the inequality

tan(minangle)<=tan(unit_angle)<=tan(maxangle)

he neglected division by zero and eliminated the fractions obtaining (this removes the domain limitation of tan function from -pi/2 to pi/2 domain) :

sin(minangle)*cos(unitangle)<=sin(unitangle)*cos(minangle) and similar for the max angle . Also cos(unitangle) and sin(unitangle) are divided by the distance between the unit and the caster which is constant and thus eliminated from calculations . He notes sin(minangle)=y1 and cos(minangle)=x1 ,y=yunit-ycaster and x=xunit-xcaster and it all becomes :

y1*x<=y*x1 and the other inequality . Quite nice and fast to compute since there are no divisions and trigonometry involved .
 

mapguy

New Member
Reaction score
46
Here's my backstab trigger. The actual condition you need for it is much smaller because of all the actions meant for my map.

Trigger:
  • Ninja Backstab
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • ((Triggering unit) is A structure) Equal to False
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Attacking unit)) Equal to Ninja
        • Then - Actions
          • Set Unit_A_Angle = (Facing of (Triggering unit))
          • Set Unit_B_Angle = (Facing of (Attacking unit))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Abs(((Integer(Unit_A_Angle)) - (Integer(Unit_B_Angle))))) Less than or equal to 45
                  • (Abs(((Integer(Unit_A_Angle)) - (Integer(Unit_B_Angle))))) Greater than or equal to 315
            • Then - Actions
              • Game - Display to (Player group((Owner of (Attacking unit)))) the text: Backstab! Ninajs do...
              • Floating Text - Create floating text that reads Backstab! above (Triggering unit) with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Change the lifespan of (Last created floating text) to 1.00 seconds
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Triggering unit) is alive) Equal to True
                • Then - Actions
                  • Unit - Cause (Attacking unit) to damage (Triggering unit), dealing 500.00 damage of attack type Spells and damage type Normal
                • Else - Actions
            • Else - Actions
        • Else - Actions

I am pretty sure it dont works when one unit is facing like -175 and the other +170
 

Moridin

Snow Leopard
Reaction score
144
I am pretty sure it dont works when one unit is facing like -175 and the other +170

170 - (- 175) = 170 + 175 = 345

(Abs(((Integer(Unit_A_Angle)) - (Integer(Unit_B_Angle))))) Greater than or equal to 315

Or:

-175 - 170 = -345 -> Absolute = 345. Implies the same result.

It works.

----------------

Also for a cone you can use this:
Angle A = Angle from (Position of (Triggering unit)) to (Position of (Target point of ability being cast))
Angle B = Angle from (Position of (Triggering unit)) to (Position of (<The unit you are checking to see if it's in the cone or not>))

Again,

If
Abs(Angle A - Angle B) < 45
OR
Abs(Angle A - Angle B) > 315

Then the unit is inside a cone of 90 degrees.

Edit: You should know that facing angle is from -180 to 180 while angle from point A to point B is from 0 to 360. Also, the function absolute simply ignores any "-" minus sine.
 

roXplosive

New Member
Reaction score
15
I don't say this won't work . It's pretty obvious but i think the solution using angles isn't as good as using differences and multiplication as Aceheart suggested and leads to excessive calculation . I expect the trigonometric functions and their inverses to have some tabeled values and those are used for calculation but getting the angle requires using arctangent (most common) function . This returns values from -90 to 90 degrees and you have to check yourself if the y_unit-y_caster<0 and if so add 180 degrees to the angle to get the real one . I'm saying that computation time wise there are better alternatives than using engine's angle functions .
 

Moridin

Snow Leopard
Reaction score
144
No doubt Acehart's method is more efficient than mine. I only use angles because I understand what's going on :p lol. Unfortunately, even though I have learned trig for the past 4 years, I still don't really understand it in a practical sense.
 

mapguy

New Member
Reaction score
46
Moridin:

your method has a problem.

sometimes a unit deals damage before turning, which means you hit the target on the back but it DONT CONT!
also, if the target is in your back and you turn on to hit him, your first strike count as backstab, even if it is not.

(you created the same bug as rikimaru in dota)

my method uses the facing angle of the target and the angle between 2 points (target - agressor), which returns better results and never bugs.
 

Moridin

Snow Leopard
Reaction score
144
sometimes a unit deals damage before turning, which means you hit the target on the back but it DONT CONT!
I'm pretty sure this is a bug in itself. A unit isn't supposed to be able to hit something without turning around to face it unless it has no facing angle in the first place (towers).

also, if the target is in your back and you turn on to hit him, your first strike count as backstab, even if it is not.
I didn't get what you mean by this.
 

mapguy

New Member
Reaction score
46
I'm pretty sure this is a bug in itself. A unit isn't supposed to be able to hit something without turning around to face it unless it has no facing angle in the first place (towers).


I didn't get what you mean by this.

play dota...the bug is there.
sometimes a unit deals the damage before turning if it's attack animation is too fast or if it`s turn speed is low.

check my demo map and check the part of the tutorial, I placed a global formula that can be used almost everytime and never bugs.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top