Because this function is crap, like the lot of vanilla âlibraryâ functions.

To calculate a planar angle you need 2 *vectors*: start (`v1`

) and end (`v2`

) or 3 *points*: `v1`

, `v2`

and `o`

, which is typically the origin (`[0, 0, 0]`

). `v1`

and `v2`

grow from `o`

, forming a triangle. If `o`

is not at the origin, you need to do some shifting. The angle is then returned as an unsigned real number between 0 and 180, which means that you get the same value if you switch `v1`

and `v2`

. The function you posted returns angle between `v1`

and `x`

axis, with tip of the angle located at `v2`

. It is not generic. And it is why you only get values between 0 and 90.

##
See image for comparison (correct on the left).

In my scripts I use a function that returns *signed* angle between vectors (-180 to 180) so you also get the direction, i.e. to determine whether the target is to the left or right of source. When working with creatures, `v1`

is often the facing vector of the source (i.e. PC) and `v2`

is difference between location of source and target (facing vector towards the target from source).

In short: dot product to get the angle, cross product to get the sign.

Script below does the calculation and runs a short demo. This code is robust.

```
//::////////////////////////////////////////////////////////////////////////////
//:: By NWShacker, 2022-01-11, licence: CC BY-SA 4.0
//::////////////////////////////////////////////////////////////////////////////
// By NWShacker, 2022-01-11, licence: CC BY-SA 4.0
// =============================================================================
// Calculates signed angle (-180 to 180) between vSource and vTarget within XY
// plane (ignoring Z components). This can be interpreted as by how many degrees
// vSource must be rotated around origin ([0, 0, 0]) and in which direction:
// negative - clockwise, positive - counter-clockwise to obtain vTarget (right
// hand rule). 0.0 is returned if either of the vectors has length 0.
// =============================================================================
// Parameters:
// * vSource: start vector
// * vTarget: end vector
// =============================================================================
// Return value:
// * 0.0 - vTarget points exactly in the same direction as vSource
// * 180.0 - vTarget points exactly in the opposite direction to vSource
// * between 0.0 and +180.0 - vTarget points somewhere to the left of vSource
// * between 0.0 and -180.0 - vTarget points somewhere to the right of vSource
float NWSH_GetSignedAngleBetweenVectors(vector vSource, vector vTarget);
float NWSH_GetSignedAngleBetweenVectors(vector vSource, vector vTarget)
{
float fAngle;
// normalize vSource
vSource = VectorNormalize(vSource);
// normalize vTarget
vTarget = VectorNormalize(vTarget);
// return 0 if vSource or vTarget has zero length
if(VectorMagnitude(vSource) == 0.0 || VectorMagnitude(vTarget) == 0.0)
{
return 0.0;
}
// calculate vector dot product to determine the angle
fAngle = acos(vTarget.x * vSource.x + vTarget.y * vSource.y);
// calculate vector cross product to determine the sign
if(vTarget.x * vSource.y - vTarget.y * vSource.x > 0.0)
{
return -fAngle;
}
else
{
return fAngle;
}
}
// By NWShacker, 2022-01-11, licence: CC BY-SA 4.0
// =============================================================================
// Uses NWSH_GetSignedAngleBetweenVectors() to obtain signed angle (-180 to 180)
// describing position of lTarget within XY plane in respect to lSource. If
// lTarget and lSource are in different areas this function returns 0.0.
// =============================================================================
// Parameters:
// * lSource: start location
// * lTarget: end location
// * iUseFacing:
// * TRUE: calculate angle between facing vector of lSource and vector from
// lSource to lTarget (both vectors starting from lSource)
// * FALSE: calculate angle between vectors pointing to lSource and lTarget
// (both vectors starting from origin, [0, 0, 0])
// =============================================================================
// Return value:
// +135 +90 +45
// \ | /
// \ | /
// +/-180 -- lSource == facing of lSource => 0
// / | \
// / | \
// -135 -90 -45
float NWSH_GetSignedAngleBetweenLocations(location lSource, location lTarget, int iUseFacing=FALSE);
float NWSH_GetSignedAngleBetweenLocations(location lSource, location lTarget, int iUseFacing=FALSE)
{
vector vSource;
vector vTarget;
float fAngle;
// check if lTarget and lSource are valid and in the same area
if(GetAreaFromLocation(lTarget) != GetAreaFromLocation(lSource) ||
!GetIsObjectValid(GetAreaFromLocation(lTarget)))
{
return 0.0;
}
if(iUseFacing)
{
// if iUseFacing is TRUE, calculate angle relative to lSource,
// between vector of its facing and vector towards lTarget
vSource = AngleToVector(GetFacingFromLocation(lSource));
vTarget = GetPositionFromLocation(lTarget) - GetPositionFromLocation(lSource);
}
else
{
// otherwise calculate angle between vectors of positions
// of lSource and lTarget attached at the origin
vSource = GetPositionFromLocation(lSource);
vTarget = GetPositionFromLocation(lTarget);
}
return NWSH_GetSignedAngleBetweenVectors(vSource, vTarget);
}
// =============================================================================
// DEMO: iterates all objects in the area of the caller and makes them speak
// their relative angle in respect to the caller.
// =============================================================================
void main()
{
object oObject;
float fAngle;
oObject = GetFirstObjectInArea();
while(GetIsObjectValid(oObject))
{
fAngle = NWSH_GetSignedAngleBetweenLocations(
GetLocation(OBJECT_SELF),
GetLocation(oObject),
TRUE);
AssignCommand(oObject, SpeakString(FloatToString(fAngle, 0, 1)));
oObject = GetNextObjectInArea();
}
}
```

Your case: `vPC`

is PCâs position (`o`

), `vTrgt`

is position of primary target (`v1`

), `vHit`

is position of the secondary target (`v2`

). So you simply check if:

```
fabs(NWSH_GetSignedAngleBetweenVectors(vTrgt-vPC, vHit-vPC)) <= 10.0
```