• 🏆 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!
  • ✅ The POLL for Hive's Texturing Contest #33 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!

[Spell] Determining "left" and "right" from 2 points not working correctly

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi guys,

The following trigger (not from me) is supposed to determine the angle from caster to target, select bystanding units on the "left" and "right" (from caster's view) and then push those bystanders to the respective side.

However, the trigger bugs in some instances, namely when the caster is in the "east" and the target in the "west". The bug is that units who are supposed to be pushed to the "left", get pushed to the "right" instead. Attached some pictures for visibility.

I try to understand why this happens but I don't find anything wrong with the trigger.

Can anyone please help here please to make the behaviour more consistent?

  • Primal Roar Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Primal Roar
    • Actions
      • Set VariableSet Primal_Roar_Caster = (Casting unit)
      • Set VariableSet Primal_Roar_Target = (Target unit of ability being cast)
      • Set VariableSet Primal_Roar_Level = (Level of (Ability being cast) for Primal_Roar_Caster)
      • Unit - Cause Primal_Roar_Caster to damage Primal_Roar_Target, dealing (150.00 + (50.00 x (Real(Primal_Roar_Level)))) damage of attack type Spells and damage type Normal
      • Set VariableSet Primal_Roar_Point = (Position of Primal_Roar_Caster)
      • Set VariableSet Primal_Roar_Point2 = (Position of Primal_Roar_Target)
      • Set VariableSet Primal_Roar_Facing = (Angle from Primal_Roar_Point to Primal_Roar_Point2)
      • Custom script: call RemoveLocation(udg_Primal_Roar_Point2)
      • For each (Integer Primal_Roar_Loop) from 1 to 6, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • Primal_Roar_Loop Equal to 1
                  • Primal_Roar_Loop Equal to 3
                  • Primal_Roar_Loop Equal to 5
            • Then - Actions
              • Set VariableSet Primal_Roar_Point2 = (Primal_Roar_Point offset by (100.00 x (Real(Primal_Roar_Loop))) towards Primal_Roar_Facing degrees.)
              • Unit - Create 1 Primal Roar for (Owner of Primal_Roar_Caster) at Primal_Roar_Point2 facing Primal_Roar_Facing degrees
              • Unit - Add a 0.50 second Generic expiration timer to (Last created unit)
              • Custom script: call RemoveLocation(udg_Primal_Roar_Point2)
            • Else - Actions
          • Set VariableSet Primal_Roar_Point2 = (Primal_Roar_Point offset by (100.00 x (Real(Primal_Roar_Loop))) towards Primal_Roar_Facing degrees.)
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in (Units within 250.00 of Primal_Roar_Point2.) and do (Actions)
            • Loop - Actions
              • Set VariableSet Primal_Roar_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Primal_Roar_TempUnit is A structure) Equal to False
                  • (Primal_Roar_TempUnit is alive) Equal to True
                  • (Primal_Roar_TempUnit belongs to an enemy of (Owner of Primal_Roar_Caster).) Equal to True
                  • (Primal_Roar_TempUnit is invulnerable) Equal to False
                  • Primal_Roar_TempUnit Not equal to Primal_Roar_Target
                  • (Primal_Roar_TempUnit is in Primal_Roar_Group.) Equal to False
                • Then - Actions
                  • Unit - Cause Primal_Roar_Caster to damage Primal_Roar_TempUnit, dealing (150.00 + (50.00 x (Real(Primal_Roar_Level)))) damage of attack type Spells and damage type Normal
                  • Set VariableSet Primal_Roar_Index = (Primal_Roar_Index + 1)
                  • Set VariableSet Primal_Roar_MUI = (Primal_Roar_MUI + 1)
                  • Set VariableSet Primal_Roar_Instance[Primal_Roar_Loop] = 0
                  • Set VariableSet Primal_Roar_Unit[Primal_Roar_MUI] = Primal_Roar_TempUnit
                  • If (Primal_Roar_Index Equal to 1) then do (Set VariableSet Primal_Roar_Group = (Units of type No unit-type)) else do (Do nothing)
                  • Unit Group - Add Primal_Roar_Unit[Primal_Roar_MUI] to Primal_Roar_Group
                  • Set VariableSet Primal_Roar_Point3 = (Position of (Picked unit))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Angle from Primal_Roar_Point to Primal_Roar_Point3) Greater than Primal_Roar_Facing
                    • Then - Actions
                      • Set VariableSet Primal_Roar_Angle[Primal_Roar_MUI] = (Primal_Roar_Facing + 90.00)
                    • Else - Actions
                      • Set VariableSet Primal_Roar_Angle[Primal_Roar_MUI] = (Primal_Roar_Facing - 90.00)
                  • Custom script: call RemoveLocation(udg_Primal_Roar_Point3)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Primal_Roar_Index Equal to 1
                    • Then - Actions
                      • Trigger - Turn on Primal Roar Loop <gen>
                    • Else - Actions
                • Else - Actions
          • Unit - Create 1 Dummy for (Owner of Primal_Roar_Caster) at Primal_Roar_Point2 facing Default building facing degrees
          • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
          • Unit - Add Primal Roar Slow to (Last created unit)
          • Unit - Set level of Primal Roar Slow for (Last created unit) to Primal_Roar_Level
          • Unit - Order (Last created unit) to Human Mountain King - Thunder Clap.
          • Custom script: call RemoveLocation(udg_Primal_Roar_Point2)
      • Unit - Create 1 Dummy for (Owner of Primal_Roar_Caster) at Primal_Roar_Point facing Default building facing degrees
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Unit - Add Primal Roar Stun (Spell Immunity Pierce) to (Last created unit)
      • Unit - Set level of Primal Roar Stun (Spell Immunity Pierce) for (Last created unit) to Primal_Roar_Level
      • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt Primal_Roar_Target
      • Custom script: call RemoveLocation(udg_Primal_Roar_Point)
      • Sound - Play BattleRoar <gen> at 100.00% volume, attached to Primal_Roar_Caster
  • Primal Roar Loop
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • For each (Integer Primal_Roar_Loop) from 1 to Primal_Roar_MUI, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Primal_Roar_Unit[Primal_Roar_Loop] Not equal to No unit
            • Then - Actions
              • Set VariableSet Primal_Roar_Point = (Position of Primal_Roar_Unit[Primal_Roar_Loop])
              • Set VariableSet Primal_Roar_Point2 = (Primal_Roar_Point offset by 25.00 towards Primal_Roar_Angle[Primal_Roar_Loop] degrees.)
              • Unit - Move Primal_Roar_Unit[Primal_Roar_Loop] instantly to Primal_Roar_Point2, facing Primal_Roar_Angle[Primal_Roar_Loop] degrees
              • Custom script: call RemoveLocation(udg_Primal_Roar_Point2)
              • Custom script: call RemoveLocation(udg_Primal_Roar_Point)
              • Special Effect - Create a special effect attached to the origin of Primal_Roar_Unit[Primal_Roar_Loop] using Abilities\Weapons\AncientProtectorMissile\AncientProtectorMissile.mdl
              • Special Effect - Destroy (Last created special effect)
              • Set VariableSet Primal_Roar_Instance[Primal_Roar_Loop] = (Primal_Roar_Instance[Primal_Roar_Loop] + 1)
              • -------- Increase to 12 if you want range 300 (=25x12) --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Primal_Roar_Instance[Primal_Roar_Loop] Equal to 10
                • Then - Actions
                  • Unit Group - Remove Primal_Roar_Unit[Primal_Roar_Loop] from Primal_Roar_Group.
                  • Set VariableSet Primal_Roar_Unit[Primal_Roar_Loop] = No unit
                  • Set VariableSet Primal_Roar_Angle[Primal_Roar_Loop] = 0.00
                  • Set VariableSet Primal_Roar_Instance[Primal_Roar_Loop] = 0
                  • Set VariableSet Primal_Roar_Index = (Primal_Roar_Index - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Primal_Roar_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                      • Set VariableSet Primal_Roar_MUI = 0
                      • Custom script: call DestroyGroup(udg_Primal_Roar_Group)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
 

Attachments

  • WC3ScrnShot_061620_173706_001.png
    WC3ScrnShot_061620_173706_001.png
    6 MB · Views: 48
  • WC3ScrnShot_061620_173707_001.png
    WC3ScrnShot_061620_173707_001.png
    5.9 MB · Views: 27
  • WC3ScrnShot_061620_173708_001.png
    WC3ScrnShot_061620_173708_001.png
    6 MB · Views: 38

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,239
(Angle from Primal_Roar_Point to Primal_Roar_Point3) Greater than Primal_Roar_Facing
Does not factor in that angles wrap around. For example -360 = 0 = 360.

There are many solutions. One can modulo the angle difference and then compare that against 0. One can also pass the difference through the sine function and compare the output.
 
Level 12
Joined
May 16, 2020
Messages
660
Does not factor in that angles wrap around. For example -360 = 0 = 360.

There are many solutions. One can modulo the angle difference and then compare that against 0. One can also pass the difference through the sine function and compare the output.

Thanks for the answer, but... I have no idea how to apply what you just wrote. How would I change the code for that?
 
Level 12
Joined
May 16, 2020
Messages
660
Something like (this is typed, not checked in World Editor)...

(Sine((Angle from Primal_Roar_Point to Primal_Roar_Point3) - Primal_Roar_Facing)) Greater than 0.00

  • (Sin(((Angle from Primal_Roar_Point to Primal_Roar_Point3) - Primal_Roar_Facing))) Greater than 0.00
Wow that worked, thank you! Can you maybe in simple terms explain how this fixes the problem?

I notice btw a slight lag now when the ability starts (only the first time), is that because the game has to calculate more?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,239
Wow that worked, thank you! Can you maybe in simple terms explain how this fixes the problem?
The input to the sine function is valid for all angles. Sine works like sine does, the same function taught in high school mathematics. This property is used to deal with angle wrap around.

In case people have forgotten. Sine is positive for angles 0 to 180 and negative for angles 180 to 360. 180 to 360 can be considered an alias of angles -180 to 0, e.t.c.

An alternative would be some clever use of modulo to clamp the angle within a practical comparison range. However I am less confident using that due to how many different ways modulo could work.
I notice btw a slight lag now when the ability starts (only the first time), is that because the game has to calculate more?
The lag will have always been there. This is usually caused by assets and objects being loaded in for the first time.
 
Status
Not open for further replies.
Top