From 1d930b45cf595bcff2d3c8115df803e4977c19bc Mon Sep 17 00:00:00 2001
From: argv-minus-one <argv-minus-one@users.noreply.github.com>
Date: Mon, 20 Aug 2018 16:31:52 -0700
Subject: [PATCH] Add ZScript method `LevelLocals.SphericalCoords`.

It computes spherical coordinates from one point in the world to another. Useful for checking whether one actor is inside another actor's view cone.
---
 src/g_level.cpp                | 24 ++++++++++++++++++++++++
 wadsrc/static/zscript/base.txt |  1 +
 2 files changed, 25 insertions(+)

diff --git a/src/g_level.cpp b/src/g_level.cpp
index 207a3682ab..86567ea847 100644
--- a/src/g_level.cpp
+++ b/src/g_level.cpp
@@ -2043,6 +2043,30 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, Vec3Diff)
 	ACTION_RETURN_VEC3(VecDiff(DVector3(x1, y1, z1), DVector3(x2, y2, z2)));
 }
 
+DEFINE_ACTION_FUNCTION(FLevelLocals, SphericalCoords)
+{
+	PARAM_PROLOGUE;
+	PARAM_FLOAT(viewpointX);
+	PARAM_FLOAT(viewpointY);
+	PARAM_FLOAT(viewpointZ);
+	PARAM_FLOAT(targetX);
+	PARAM_FLOAT(targetY);
+	PARAM_FLOAT(targetZ);
+	PARAM_ANGLE_DEF(viewYaw);
+	PARAM_ANGLE_DEF(viewPitch);
+	PARAM_BOOL_DEF(absolute);
+
+	DVector3 viewpoint(viewpointX, viewpointY, viewpointZ);
+	DVector3 target(targetX, targetY, targetZ);
+	auto vecTo = absolute ? target - viewpoint : VecDiff(viewpoint, target);
+
+	ACTION_RETURN_VEC3(DVector3(
+		deltaangle(vecTo.Angle(), viewYaw).Degrees,
+		deltaangle(-vecTo.Pitch(), viewPitch).Degrees,
+		vecTo.Length()
+	));
+}
+
 DEFINE_ACTION_FUNCTION(FLevelLocals, Vec2Offset)
 {
 	PARAM_PROLOGUE;
diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt
index dbf71a9424..498f6ae717 100644
--- a/wadsrc/static/zscript/base.txt
+++ b/wadsrc/static/zscript/base.txt
@@ -668,6 +668,7 @@ struct LevelLocals native
 
 	native static clearscope vector2 Vec2Diff(vector2 v1, vector2 v2);
 	native static clearscope vector3 Vec3Diff(vector3 v1, vector3 v2);
+	native static clearscope vector3 SphericalCoords(vector3 viewpoint, vector3 targetPos, vector2 viewAngles = (0, 0), bool absolute = false);	
 	
 	native static clearscope vector2 Vec2Offset(vector2 pos, vector2 dir, bool absolute = false);
 	native static clearscope vector3 Vec2OffsetZ(vector2 pos, vector2 dir, double atz, bool absolute = false);