From 66f8908b03b68cc0d350b1556f49af3d6eb39ab6 Mon Sep 17 00:00:00 2001
From: SMS Alfredo <65426124+SMS-Alfredo@users.noreply.github.com>
Date: Sat, 22 Jul 2023 20:44:22 -0500
Subject: [PATCH] Reset Camera only if a new camera is set / Fix Lua jank with
 setting awayviewmobj or awayviewtics solo

---
 src/lua_playerlib.c | 27 ++++++++++++++++++++-------
 src/p_spec.c        |  8 ++++----
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 1c3b4f46c2..4b4c9d30f3 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -1278,17 +1278,30 @@ static int player_set(lua_State *L)
 		mobj_t *mo = NULL;
 		if (!lua_isnil(L, 3))
 			mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
-		P_SetTarget(&plr->awayviewmobj, mo);
-		if (plr == &players[displayplayer])
-			P_ResetCamera(plr, &camera); // reset p1 camera on p1 getting an awayviewmobj
-		else if (splitscreen && plr == &players[secondarydisplayplayer])
-			P_ResetCamera(plr, &camera2);  // reset p2 camera on p2 getting an awayviewmobj
+		if (plr->awayviewmobj != mo) {
+			P_SetTarget(&plr->awayviewmobj, mo);
+			if (plr->awayviewtics) {
+				if (!plr->awayviewmobj)
+					plr->awayviewtics = 0; // can't have a NULL awayviewmobj with awayviewtics!
+				if (plr == &players[displayplayer])
+					P_ResetCamera(plr, &camera); // reset p1 camera on p1 getting an awayviewmobj
+				else if (splitscreen && plr == &players[secondarydisplayplayer])
+					P_ResetCamera(plr, &camera2);  // reset p2 camera on p2 getting an awayviewmobj
+			}
+		}
 		break;
 	}
 	case player_awayviewtics:
-		plr->awayviewtics = (INT32)luaL_checkinteger(L, 3);
-		if (plr->awayviewtics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!!
+		INT32 tics = (INT32)luaL_checkinteger(L, 3);
+		if (tics && !plr->awayviewmobj) // awayviewtics must ALWAYS have an awayviewmobj set!!
 			P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now.
+		if ((tics && !plr->awayviewtics) || (!tics && plr->awayviewtics)) {
+			if (plr == &players[displayplayer])
+				P_ResetCamera(plr, &camera); // reset p1 camera on p1 transitioning to/from zero awayviewtics
+			else if (splitscreen && plr == &players[secondarydisplayplayer])
+				P_ResetCamera(plr, &camera2);  // reset p2 camera on p2 transitioning to/from zero awayviewtics
+		}
+		plr->awayviewtics = tics;
 		break;
 	case player_awayviewaiming:
 		plr->awayviewaiming = luaL_checkangle(L, 3);
diff --git a/src/p_spec.c b/src/p_spec.c
index 877b9c7bc3..33253e5219 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2661,10 +2661,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				// This is not revoked until overwritten; awayviewtics is ignored
 				if (titlemapinaction)
 					titlemapcameraref = altview;
-				else
-				{
+				else if (!mo->player->awayviewtics || mo->player->awayviewmobj != altview) {
 					P_SetTarget(&mo->player->awayviewmobj, altview);
-					mo->player->awayviewtics = line->args[1];
 					
 					if (mo->player == &players[displayplayer])
 						P_ResetCamera(mo->player, &camera); // reset p1 camera on p1 getting an awayviewmobj
@@ -2679,8 +2677,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				aim <<= 8;
 				if (titlemapinaction)
 					titlemapcameraref->cusval = (angle_t)aim;
-				else
+				else {
 					mo->player->awayviewaiming = (angle_t)aim;
+					mo->player->awayviewtics = line->args[1];
+				}
 			}
 			break;
 
-- 
GitLab