From 3b5e884b5e67ad05b088c0f0d6af589a6c39be3a Mon Sep 17 00:00:00 2001
From: bones_was_here <bones_was_here@xonotic.au>
Date: Fri, 21 Oct 2022 01:29:14 +1000
Subject: [PATCH] Improve end of warmup countdown abort (when player count
 drops too low)

Respects g_warmup_allguns 1.
Previously players were left with only shotgun and blaster in the
resumed warmup when sv_ready_restart_after_countdown 0.

Fixes incomplete countdown abort when sv_ready_restart_after_countdown 1.

Allows bots to start playing again immediately when countdown is aborted.
---
 qcsrc/server/bot/default/bot.qc |  1 -
 qcsrc/server/client.qc          | 28 +++++++++++++++++-----------
 qcsrc/server/client.qh          |  2 ++
 qcsrc/server/command/vote.qc    |  5 ++++-
 4 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/qcsrc/server/bot/default/bot.qc b/qcsrc/server/bot/default/bot.qc
index b81507890..d7cf429d7 100644
--- a/qcsrc/server/bot/default/bot.qc
+++ b/qcsrc/server/bot/default/bot.qc
@@ -118,7 +118,6 @@ void bot_think(entity this)
 			W_NextWeapon(this, 0, weaponentity);
 		// block the bot during the countdown to game start
 		CS(this).movement = '0 0 0';
-		this.bot_nextthink = game_starttime;
 		return;
 	}
 
diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc
index 6d8ef921b..5b7509e48 100644
--- a/qcsrc/server/client.qc
+++ b/qcsrc/server/client.qc
@@ -536,6 +536,19 @@ void FixPlayermodel(entity player)
 				setcolor(player, stof(autocvar_sv_defaultplayercolors));
 }
 
+void GiveWarmupResources(entity this)
+{
+	SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
+	SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
+	SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
+	SetResource(this, RES_CELLS, warmup_start_ammo_cells);
+	SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
+	SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
+	SetResource(this, RES_HEALTH, warmup_start_health);
+	SetResource(this, RES_ARMOR, warmup_start_armorvalue);
+	STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
+}
+
 void PutPlayerInServer(entity this)
 {
 	if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
@@ -578,17 +591,10 @@ void PutPlayerInServer(entity this)
 	this.takedamage = DAMAGE_AIM;
 	this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
 
-	if (warmup_stage) {
-		SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
-		SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
-		SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
-		SetResource(this, RES_CELLS, warmup_start_ammo_cells);
-		SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
-		SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
-		SetResource(this, RES_HEALTH, warmup_start_health);
-		SetResource(this, RES_ARMOR, warmup_start_armorvalue);
-		STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
-	} else {
+	if (warmup_stage)
+		GiveWarmupResources(this);
+	else
+	{
 		SetResource(this, RES_SHELLS, start_ammo_shells);
 		SetResource(this, RES_BULLETS, start_ammo_nails);
 		SetResource(this, RES_ROCKETS, start_ammo_rockets);
diff --git a/qcsrc/server/client.qh b/qcsrc/server/client.qh
index 56cce52a9..eebf016f7 100644
--- a/qcsrc/server/client.qh
+++ b/qcsrc/server/client.qh
@@ -393,6 +393,8 @@ void SetSpectatee_status(entity this, int spectatee_num);
 
 void FixPlayermodel(entity player);
 
+void GiveWarmupResources(entity this);
+
 void ClientInit_misc(entity this);
 
 int GetPlayerLimit();
diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc
index c4aec35b6..795ea09e5 100644
--- a/qcsrc/server/command/vote.qc
+++ b/qcsrc/server/command/vote.qc
@@ -419,7 +419,8 @@ void reset_map(bool dorespawn, bool is_fake_round_start)
 // Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown is set)
 void ReadyRestart_think(entity this)
 {
-	reset_map(true, false);
+	if (!warmup_stage) // if the countdown was not aborted
+		reset_map(true, false);
 	delete(this);
 }
 
@@ -536,6 +537,8 @@ void ReadyCount()
 			warmup_stage = autocvar_g_warmup; // CAN change it AFTER calling Nagger_ReadyCounted() this frame
 			game_starttime = time;
 			Send_Notification(NOTIF_ALL, NULL, MSG_MULTI, COUNTDOWN_STOP, minplayers);
+			if (!sv_ready_restart_after_countdown) // if we ran reset_map() at start of countdown
+				FOREACH_CLIENT(IS_PLAYER(it), { GiveWarmupResources(it); });
 		}
 		if (warmup_limit > 0)
 			warmup_limit = -1;
-- 
2.39.5