From c803c56bef7e7973811b46c715805530e82d40d2 Mon Sep 17 00:00:00 2001
From: "Dr. Jaska" <drjaska83@gmail.com>
Date: Mon, 12 Jun 2023 17:35:53 +0000
Subject: [PATCH] Simpler implementation of !1200 and fixes to !1195

---
 qcsrc/client/main.qc                          |  5 +++-
 .../gamemode/survival/cl_survival.qc          | 26 ++++++++++++-------
 .../gamemode/survival/sv_survival.qc          | 26 +++++--------------
 3 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc
index ce7f51e1d9..68b21f46cf 100644
--- a/qcsrc/client/main.qc
+++ b/qcsrc/client/main.qc
@@ -541,7 +541,7 @@ float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary)
 
 // --------------------------------------------------------------------------
 // BEGIN OPTIONAL CSQC FUNCTIONS
-
+.int survival_status;
 void Ent_RemovePlayerScore(entity this)
 {
 	if(this.owner) {
@@ -550,6 +550,9 @@ void Ent_RemovePlayerScore(entity this)
 		FOREACH(Scores, true, {
 			this.owner.(scores(it)) = 0; // clear all scores
 		});
+		this.owner.colormap = 0;
+		// TODO add a hook to reset this Survival field
+		this.owner.survival_status = 0;
 	}
 }
 
diff --git a/qcsrc/common/gamemodes/gamemode/survival/cl_survival.qc b/qcsrc/common/gamemodes/gamemode/survival/cl_survival.qc
index 01e6a60068..0f57de6811 100644
--- a/qcsrc/common/gamemodes/gamemode/survival/cl_survival.qc
+++ b/qcsrc/common/gamemodes/gamemode/survival/cl_survival.qc
@@ -8,13 +8,13 @@ NET_HANDLE(ENT_CLIENT_SURVIVALSTATUSES, bool isnew)
 	make_pure(this);
 	int sf = 0;
 	serialize(byte, 0, sf);
-	if (sf & BIT(1)) // make all players survivors
+	if (sf & BIT(0)) // make all players survivors
 	{
 		for (int j = 0; j < maxclients; ++j)
 			if (playerslots[j])
 				playerslots[j].survival_status = SURV_STATUS_PREY;
 	}
-	if (sf & BIT(0)) // reveal hunters (to hunters)
+	if (sf & BIT(1)) // receive hunter statuses
 	{
 		for (int i = 1; i <= maxclients; i += 8)
 		{
@@ -30,18 +30,14 @@ NET_HANDLE(ENT_CLIENT_SURVIVALSTATUSES, bool isnew)
 		}
 	}
 
-	// we could check STAT(GAME_STOPPED) instead of this dedicated flag,
-	// unfortunately STAT(GAME_STOPPED) is still false right when we receive this
-	bool reveal_hunters_to_survivors = (sf & BIT(2)); // when a round ends
-
-	int mystatus = playerslots[player_localnum].survival_status;
+	// color all players
 	for (int i = 1; i <= maxclients; ++i)
 	{
 		entity e = playerslots[i - 1];
 		if (!e) continue;
 
-		int plcolor = SURV_COLOR_PREY;
-		if(e.survival_status == SURV_STATUS_HUNTER && (mystatus == SURV_STATUS_HUNTER || reveal_hunters_to_survivors))
+		int plcolor = SURV_COLOR_PREY; // default color
+		if(e.survival_status == SURV_STATUS_HUNTER) // if client knows this hunter
 			plcolor = SURV_COLOR_HUNTER;
 
 		e.colormap = 1024 + plcolor; // override scoreboard and player model colors
@@ -94,6 +90,18 @@ MUTATOR_HOOKFUNCTION(cl_surv, ForcePlayercolors_Skip, CBC_ORDER_LAST)
 	return true;
 }
 
+MUTATOR_HOOKFUNCTION(cl_surv, DrawScoreboard)
+{
+	if(!ISGAMETYPE(SURVIVAL))
+		return false;
+
+	// initialize colors of new players
+	for(entity pl = players.sort_next; pl; pl = pl.sort_next)
+		if(pl.gotscores && pl.colormap == 0)
+			pl.colormap = 1024 + SURV_COLOR_PREY;
+	return false;
+}
+
 MUTATOR_HOOKFUNCTION(cl_surv, DrawScoreboard_Force)
 {
 	// show the scoreboard when the round ends, so players can see who the hunter was
diff --git a/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc b/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc
index dea924772d..cfdc948c04 100644
--- a/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc
+++ b/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc
@@ -14,14 +14,8 @@ void SurvivalStatuses_Init();
 void SurvivalStatuses_Send()
 {
 	// SendFlags can be set to anything != 0, SurvivalStatuses_SendEntity won't use its value
+	// Dr. Jaska: this was a lie, the flags were not reset until now
 	survivalStatuses.SendFlags = 1;
-	survivalStatuses.nextthink = 0; // clear delayed send
-}
-
-void SurvivalStatuses_Send_Delayed()
-{
-	survivalStatuses.think = SurvivalStatuses_Send;
-	survivalStatuses.nextthink = time + 0.2;
 }
 
 bool SurvivalStatuses_SendEntity(entity this, entity dest, float sendflags)
@@ -29,16 +23,14 @@ bool SurvivalStatuses_SendEntity(entity this, entity dest, float sendflags)
 	Stream out = MSG_ENTITY;
 	WriteHeader(out, ENT_CLIENT_SURVIVALSTATUSES);
 
-	sendflags |= BIT(1); // make all players survivors
-
-	if (dest.survival_status == SURV_STATUS_HUNTER);
-		sendflags |= BIT(0); // send hunter statuses
+	// TODO: optimize this instead of always setting it on
+	sendflags = BIT(0); // reset all flags and make all players survivors
 
-	if (round_handler_AwaitingNextRound())
-		sendflags |= (BIT(0) | BIT(2)); // send hunter statuses and reveal hunters to survivors
+	if ((dest.survival_status == SURV_STATUS_HUNTER) || round_handler_AwaitingNextRound())
+		sendflags |= BIT(1); // send hunter statuses
 
 	serialize(byte, out, sendflags);
-	if (sendflags & BIT(0)) {
+	if (sendflags & BIT(1)) {
 		for (int i = 1; i <= maxclients; i += 8) {
 			int f = 0;
 			entity e = edict_num(i);
@@ -50,6 +42,7 @@ bool SurvivalStatuses_SendEntity(entity this, entity dest, float sendflags)
 			serialize(byte, out, f);
 		}
 	}
+	//print(sprintf("sent flags %f to %s\n", sendflags, dest.netname));
 	return true;
 }
 
@@ -305,10 +298,6 @@ MUTATOR_HOOKFUNCTION(surv, PutClientInServer)
 
 	if (!warmup_stage)
 		eliminatedPlayers.SendFlags |= 1;
-	// send statuses with a small delay to make sure a playerslot exists, otherwise
-	// personal colors for this player won't be overriden
-	// it also reduces network traffic when multiple clients join the server at once (at map start)
-	SurvivalStatuses_Send_Delayed();
 }
 
 MUTATOR_HOOKFUNCTION(surv, reset_map_players)
@@ -324,7 +313,6 @@ MUTATOR_HOOKFUNCTION(surv, reset_map_players)
 		}
 	});
 	bot_relinkplayerlist();
-	// this will also clear scheduled SurvivalStatuses_Send set by PutClientInServer
 	SurvivalStatuses_Send();
 	return true;
 }
-- 
2.39.5