From b0e4ebf4cf698adc8d6322fb366d0e6045d555e6 Mon Sep 17 00:00:00 2001
From: terencehill <piuntn@gmail.com>
Date: Sun, 14 Apr 2013 12:19:47 +0200
Subject: [PATCH] Implement a function to spectate previous player and add
 possibility to spectate next/previous player with next/previous weapon binds
 (primary fire still changes to the next player)

---
 qcsrc/client/hud.qc       |  2 +-
 qcsrc/server/cl_client.qc | 50 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc
index bf72c2f46..90dac2e09 100644
--- a/qcsrc/client/hud.qc
+++ b/qcsrc/client/hud.qc
@@ -3656,7 +3656,7 @@ void HUD_InfoMessages(void)
 			if(spectatee_status == -1)
 				s = sprintf(_("^1Press ^3%s^1 to spectate"), getcommandkey("primary fire", "+fire"));
 			else
-				s = sprintf(_("^1Press ^3%s^1 for another player"), getcommandkey("primary fire", "+fire"));
+				s = sprintf(_("^1Press ^3%s^1 or ^3%s^1 for next or previous player"), getcommandkey("next weapon", "weapnext"), getcommandkey("previous weapon", "weapprev"));
 			drawInfoMessage(s)
 
 			if(spectatee_status == -1)
diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc
index 8d84988b4..3f6006838 100644
--- a/qcsrc/server/cl_client.qc
+++ b/qcsrc/server/cl_client.qc
@@ -2274,6 +2274,44 @@ float SpectateNext()
 	return setSpectator();
 }
 
+float SpectatePrev()
+{
+	// NOTE: chain order is from the highest to the lower entnum (unlike find)
+	other = findchain(classname, "player");
+	if not(other) // no player
+		return FALSE;
+
+	entity first = other;
+	// skip players until current spectated player
+	if(self.enemy)
+	while(other && other != self.enemy)
+		other = other.chain;
+
+	if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
+	{
+		do { other = other.chain; }
+		while(other && other.team != self.team);
+
+		if not(other)
+		{
+			other = first;
+			while(other.team != self.team)
+				other = other.chain;
+			if(other == self.enemy)
+				return TRUE;
+		}
+	}
+	else
+	{
+		if(other.chain)
+			other = other.chain;
+		else
+			other = first;
+	}
+	self.enemy = other;
+	return setSpectator();
+}
+
 /*
 =============
 ShowRespawnCountdown()
@@ -2458,7 +2496,7 @@ void SpectatorThink()
 		if (self.BUTTON_JUMP && !self.version_mismatch) {
 			self.flags &~= FL_JUMPRELEASED;
 			self.flags |= FL_SPAWNING;
-		} else if(self.BUTTON_ATCK) {
+		} else if(self.BUTTON_ATCK || self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || self.impulse >= 200 && self.impulse <= 209) {
 			self.flags &~= FL_JUMPRELEASED;
 			if(SpectateNext()) {
 				self.classname = "spectator";
@@ -2466,6 +2504,16 @@ void SpectatorThink()
 				self.classname = "observer";
 				PutClientInServer();
 			}
+			self.impulse = 0;
+		} else if(self.impulse == 12 || self.impulse == 16  || self.impulse == 19 || self.impulse >= 220 && self.impulse <= 229) {
+			self.flags &~= FL_JUMPRELEASED;
+			if(SpectatePrev()) {
+				self.classname = "spectator";
+			} else {
+				self.classname = "observer";
+				PutClientInServer();
+			}
+			self.impulse = 0;
 		} else if (self.BUTTON_ATCK2) {
 			self.flags &~= FL_JUMPRELEASED;
 			self.classname = "observer";
-- 
2.39.5