Bug Tracker – Attachment #539: initial patch based on r4823 for bug #1189

View | Details | Raw Unified | Return to bug 1189
Collapse All | Expand All

(-)a/client/src/cl_stubs.cpp (+1 lines)
Lines 61-66 void CTF_RememberFlagPos(mapthing2_t *mthing) {} Link Here
61
void CTF_SpawnFlag(flag_t f) {}
61
void CTF_SpawnFlag(flag_t f) {}
62
bool SV_AwarenessUpdate(player_t &pl, AActor* mo) { return true; }
62
bool SV_AwarenessUpdate(player_t &pl, AActor* mo) { return true; }
63
void SV_SendPackets(void) {}
63
void SV_SendPackets(void) {}
64
void SV_SetPlayerSpec(player_t &player, bool setting, bool silent) {}
64
65
65
VERSION_CONTROL (cl_stubs_cpp, "$Id: cl_stubs.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
66
VERSION_CONTROL (cl_stubs_cpp, "$Id: cl_stubs.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
66
67
(-)a/client/src/hu_elements.cpp (-5 / +23 lines)
Lines 46-51 extern fixed_t FocalLengthX; Link Here
46
46
47
EXTERN_CVAR (sv_fraglimit)
47
EXTERN_CVAR (sv_fraglimit)
48
EXTERN_CVAR (sv_gametype)
48
EXTERN_CVAR (sv_gametype)
49
EXTERN_CVAR (sv_maxlives)
49
EXTERN_CVAR (sv_maxclients)
50
EXTERN_CVAR (sv_maxclients)
50
EXTERN_CVAR (sv_maxplayers)
51
EXTERN_CVAR (sv_maxplayers)
51
EXTERN_CVAR (sv_maxplayersperteam)
52
EXTERN_CVAR (sv_maxplayersperteam)
Lines 200-205 std::string HelpText() { Link Here
200
		}
201
		}
201
	}
202
	}
202
203
204
	if (sv_maxlives > 0 && warmup.get_status () == ::Warmup::INGAME)
205
		return "Game has already started";
206
203
	return "Press USE to join";
207
	return "Press USE to join";
204
}
208
}
205
209
Lines 220-253 std::string SpyPlayerName(int& color) { Link Here
220
	return plyr->userinfo.netname;
224
	return plyr->userinfo.netname;
221
}
225
}
222
226
227
223
// Returns a string that contains the current warmup state.
228
// Returns a string that contains the current warmup state.
224
std::string Warmup(int& color)
229
std::string Warmup(int& color)
225
{
230
{
226
	color = CR_GREY;
231
	color = CR_GREY;
227
	player_t *dp = &displayplayer();
232
	player_t *dp = &displayplayer();
228
	player_t *cp = &consoleplayer();
233
	player_t *cp = &consoleplayer();
234
	std::string type = "";
235
236
	if (sv_maxlives > 0)
237
	{
238
		if (sv_gametype == GM_COOP)
239
			type = "Survival: ";
240
		if (sv_gametype == GM_DM)
241
			type = "Last Man Standing: ";
242
		if (sv_gametype == GM_TEAMDM)
243
			type = "Team LMS: ";
244
	}
245
	else
246
		type = "Warmup: ";
229
247
230
	::Warmup::status_t wstatus = warmup.get_status();
248
	::Warmup::status_t wstatus = warmup.get_status();
231
249
232
	if (wstatus == ::Warmup::WARMUP)
250
	if (wstatus == ::Warmup::WARMUP)
233
	{
251
	{
234
		if (dp->spectator)
252
		if (dp->spectator)
235
			return "Warmup: You are spectating";
253
			return type + "You are spectating";
236
		else if (dp->ready)
254
		else if (dp->ready)
237
		{
255
		{
238
			color = CR_GREEN;
256
			color = CR_GREEN;
239
			if (dp == cp)
257
			if (dp == cp)
240
				return "Warmup: You are ready";
258
				return type + "You are ready";
241
			else
259
			else
242
				return "Warmup: This player is ready";
260
				return type + "This player is ready";
243
		}
261
		}
244
		else
262
		else
245
		{
263
		{
246
			color = CR_RED;
264
			color = CR_RED;
247
			if (dp == cp)
265
			if (dp == cp)
248
				return "Warmup: You are not ready";
266
				return type + "You are not ready";
249
			else
267
			else
250
				return "Warmup: This player is not ready";
268
				return type + "This player is not ready";
251
		}
269
		}
252
	}
270
	}
253
	else if (wstatus == ::Warmup::COUNTDOWN || wstatus == ::Warmup::FORCE_COUNTDOWN)
271
	else if (wstatus == ::Warmup::COUNTDOWN || wstatus == ::Warmup::FORCE_COUNTDOWN)
(-)a/client/src/hu_stuff.cpp (-2 / +15 lines)
Lines 240-245 BOOL HU_Responder (event_t *ev) Link Here
240
240
241
EXTERN_CVAR(hud_targetcount)
241
EXTERN_CVAR(hud_targetcount)
242
EXTERN_CVAR (sv_maxplayers)
242
EXTERN_CVAR (sv_maxplayers)
243
EXTERN_CVAR (sv_maxlives)
243
244
244
//
245
//
245
// HU_Drawer
246
// HU_Drawer
Lines 446-457 void drawHeader(player_t *player, int y) { Link Here
446
	std::string str;
447
	std::string str;
447
448
448
	// Center
449
	// Center
449
	if (sv_gametype == GM_COOP) {
450
	if (sv_gametype == GM_COOP && sv_maxlives > 0) {
451
		str = "SURVIVAL";
452
	} else if (sv_gametype == GM_COOP) {
450
		str = "COOPERATIVE";
453
		str = "COOPERATIVE";
451
	} else if (sv_gametype == GM_DM && sv_maxplayers == 2) {
454
	} else if (sv_gametype == GM_DM && sv_maxplayers == 2) {
452
		str = "DUEL";
455
		str = "DUEL";
456
	} else if (sv_gametype == GM_DM && sv_maxlives > 0) {
457
		str = "LAST MAN STANDING";
453
	} else if (sv_gametype == GM_DM) {
458
	} else if (sv_gametype == GM_DM) {
454
		str = "DEATHMATCH";
459
		str = "DEATHMATCH";
460
	} else if (sv_gametype == GM_TEAMDM && sv_maxlives > 0) {
461
		str = "TEAM LAST MAN STANDING";
455
	} else if (sv_gametype == GM_TEAMDM) {
462
	} else if (sv_gametype == GM_TEAMDM) {
456
		str = "TEAM DEATHMATCH";
463
		str = "TEAM DEATHMATCH";
457
	} else if (sv_gametype == GM_CTF) {
464
	} else if (sv_gametype == GM_CTF) {
Lines 919-930 void drawLowHeader(player_t *player, int y) { Link Here
919
	std::string str;
926
	std::string str;
920
927
921
	// Center
928
	// Center
922
	if (sv_gametype == GM_COOP) {
929
	if (sv_gametype == GM_COOP && sv_maxlives > 0) {
930
		str = "SURVIVAL";
931
	} else if (sv_gametype == GM_COOP) {
923
		str = "COOPERATIVE";
932
		str = "COOPERATIVE";
924
	} else if (sv_gametype == GM_DM && sv_maxplayers == 2) {
933
	} else if (sv_gametype == GM_DM && sv_maxplayers == 2) {
925
		str = "DUEL";
934
		str = "DUEL";
935
	} else if (sv_gametype == GM_DM && sv_maxlives > 0) {
936
		str = "LAST MAN STANDING";
926
	} else if (sv_gametype == GM_DM) {
937
	} else if (sv_gametype == GM_DM) {
927
		str = "DEATHMATCH";
938
		str = "DEATHMATCH";
939
	} else if (sv_gametype == GM_TEAMDM && sv_maxlives > 0) {
940
		str = "TEAM LAST MAN STANDING";
928
	} else if (sv_gametype == GM_TEAMDM) {
941
	} else if (sv_gametype == GM_TEAMDM) {
929
		str = "TEAM DEATHMATCH";
942
		str = "TEAM DEATHMATCH";
930
	} else if (sv_gametype == GM_CTF) {
943
	} else if (sv_gametype == GM_CTF) {
(-)a/common/p_interaction.cpp (-1 / +57 lines)
Lines 97-102 void P_GiveKills(player_t* player, int num) Link Here
97
	player->killcount += num;
97
	player->killcount += num;
98
}
98
}
99
99
100
EXTERN_CVAR (sv_maxlives)
101
void SV_SetPlayerSpec(player_t &player, bool setting, bool silent);
102
100
// Give coop kills to a player
103
// Give coop kills to a player
101
void P_GiveDeaths(player_t* player, int num)
104
void P_GiveDeaths(player_t* player, int num)
102
{
105
{
Lines 1024-1029 void SexMessage (const char *from, char *to, int gender, const char *victim, con Link Here
1024
}
1027
}
1025
1028
1026
extern player_t *last_winner;
1029
extern player_t *last_winner;
1030
size_t P_NumPlayersInGame();
1027
1031
1028
//
1032
//
1029
// P_KillMobj
1033
// P_KillMobj
Lines 1229-1237 void P_KillMobj(AActor *source, AActor *target, AActor *inflictor, bool joinkill Link Here
1229
	{
1233
	{
1230
		ClientObituary(target, inflictor, source);
1234
		ClientObituary(target, inflictor, source);
1231
	}
1235
	}
1236
1237
	if (serverside && sv_maxlives > 0 && tplayer && tplayer->deathcount >= sv_maxlives)
1238
	{
1239
		SV_SetPlayerSpec (*tplayer, true, true);
1240
		SV_BroadcastPrintf(PRINT_HIGH, "%s ran out of lives.\n", tplayer->userinfo.netname.c_str ());
1241
	}
1242
1232
	// Check sv_fraglimit.
1243
	// Check sv_fraglimit.
1233
	if (source && source->player && target->player && level.time)
1244
	if (source && splayer && tplayer && level.time)
1234
	{
1245
	{
1246
		// [tm512 2014/04/16] Check for last man standing
1247
		if (sv_gametype != GM_COOP && sv_maxlives > 0)
1248
		{
1249
			if (sv_gametype == GM_DM && P_NumPlayersInGame () == 1)
1250
			{
1251
				player_t *lastplayer = NULL;
1252
				// find last player in the game, since it isn't always splayer
1253
				for (Players::iterator pit = players.begin();pit != players.end();++pit)
1254
				{
1255
					if (!pit->spectator && pit->ingame ())
1256
					{
1257
						lastplayer = &*pit;
1258
						break;
1259
					}
1260
				}
1261
1262
				SV_BroadcastPrintf (PRINT_HIGH, "Game won by %s!\n", lastplayer->userinfo.netname.c_str ());
1263
				shotclock = TICRATE * 2;
1264
			}
1265
			else if (sv_gametype == GM_TEAMDM)
1266
			{
1267
				int players_left [NUMTEAMS] = { 0 };
1268
1269
				// count the number of players for each team
1270
				for (Players::iterator pit = players.begin();pit != players.end();++pit)
1271
				{
1272
					if (!pit->spectator && pit->ingame ())
1273
						players_left [pit->userinfo.team] ++;
1274
				}
1275
1276
				// if more than two teams are added, this will need to be changed to something less simple
1277
				bool redwins = (players_left [0] == 0);
1278
				bool bluewins = (players_left [1] == 0);
1279
1280
				if (redwins || bluewins)
1281
				{
1282
					int winteam = bluewins ? 0 : 1;
1283
1284
					SV_BroadcastPrintf (PRINT_HIGH, "%s team wins!\n", team_names [winteam]);
1285
					shotclock = TICRATE * 2;
1286
				}
1287
			}
1288
1289
		}
1290
1235
		// [Toke] Better sv_fraglimit
1291
		// [Toke] Better sv_fraglimit
1236
		if (sv_gametype == GM_DM && sv_fraglimit &&
1292
		if (sv_gametype == GM_DM && sv_fraglimit &&
1237
            splayer->fragcount >= sv_fraglimit && !shotclock)
1293
            splayer->fragcount >= sv_fraglimit && !shotclock)
(-)a/server/src/g_level.cpp (-1 / +2 lines)
Lines 84-89 EXTERN_CVAR (sv_loopepisode) Link Here
84
EXTERN_CVAR (sv_intermissionlimit)
84
EXTERN_CVAR (sv_intermissionlimit)
85
EXTERN_CVAR (sv_warmup)
85
EXTERN_CVAR (sv_warmup)
86
EXTERN_CVAR (sv_timelimit)
86
EXTERN_CVAR (sv_timelimit)
87
EXTERN_CVAR (sv_maxlives)
87
88
88
extern int mapchange;
89
extern int mapchange;
89
extern int shotclock;
90
extern int shotclock;
Lines 376-382 void G_InitNew (const char *mapname) Link Here
376
	}
377
	}
377
378
378
	// [tm512 2014/04/10] For survival/duel, put waiting players in the game now
379
	// [tm512 2014/04/10] For survival/duel, put waiting players in the game now
379
	if (sv_maxplayers == 2 && last_winner)
380
	if ((sv_maxlives > 0 && sv_gametype == GM_COOP) || (sv_maxplayers == 2 && last_winner))
380
	{
381
	{
381
		if (sv_maxplayers == 2) // respawn the winner of the previous duel
382
		if (sv_maxplayers == 2) // respawn the winner of the previous duel
382
		{
383
		{
(-)a/server/src/g_warmup.cpp (-256 / +287 lines)
Lines 1-256 Link Here
1
// Emacs style mode select   -*- C++ -*-
1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
2
//-----------------------------------------------------------------------------
3
//
3
//
4
// $Id$
4
// $Id$
5
//
5
//
6
// Copyright (C) 2012 by The Odamex Team.
6
// Copyright (C) 2012 by The Odamex Team.
7
//
7
//
8
// This program is free software; you can redistribute it and/or
8
// This program is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU General Public License
9
// modify it under the terms of the GNU General Public License
10
// as published by the Free Software Foundation; either version 2
10
// as published by the Free Software Foundation; either version 2
11
// of the License, or (at your option) any later version.
11
// of the License, or (at your option) any later version.
12
//
12
//
13
// This program is distributed in the hope that it will be useful,
13
// This program is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
// GNU General Public License for more details.
16
// GNU General Public License for more details.
17
//
17
//
18
// DESCRIPTION:
18
// DESCRIPTION:
19
//   Implements warmup mode.
19
//   Implements warmup mode.
20
//
20
//
21
//-----------------------------------------------------------------------------
21
//-----------------------------------------------------------------------------
22
22
23
#include "g_warmup.h"
23
#include "g_warmup.h"
24
24
25
#include <cmath>
25
#include <cmath>
26
26
27
#include "c_cvars.h"
27
#include "c_cvars.h"
28
#include "c_dispatch.h"
28
#include "c_dispatch.h"
29
#include "d_player.h"
29
#include "d_player.h"
30
#include "g_level.h"
30
#include "g_level.h"
31
#include "i_net.h"
31
#include "i_net.h"
32
#include "sv_main.h"
32
#include "sv_main.h"
33
33
34
EXTERN_CVAR(sv_gametype)
34
EXTERN_CVAR(sv_gametype)
35
EXTERN_CVAR(sv_warmup)
35
EXTERN_CVAR(sv_warmup)
36
EXTERN_CVAR(sv_warmup_autostart)
36
EXTERN_CVAR(sv_warmup_autostart)
37
EXTERN_CVAR(sv_countdown)
37
EXTERN_CVAR(sv_countdown)
38
EXTERN_CVAR(sv_timelimit)
38
EXTERN_CVAR(sv_timelimit)
39
39
EXTERN_CVAR(sv_maxlives)
40
extern int mapchange;
40
41
41
extern int mapchange;
42
// Store Warmup state.
42
43
Warmup warmup;
43
// Store Warmup state.
44
44
Warmup warmup;
45
// Broadcast warmup state to client.
45
46
void SV_SendWarmupState(player_t &player, Warmup::status_t status, short count = 0)
46
// Broadcast warmup state to client.
47
{
47
void SV_SendWarmupState(player_t &player, Warmup::status_t status, short count = 0)
48
	client_t* cl = &player.client;
48
{
49
	MSG_WriteMarker(&cl->reliablebuf, svc_warmupstate);
49
	client_t* cl = &player.client;
50
	MSG_WriteByte(&cl->reliablebuf, static_cast<byte>(status));
50
	MSG_WriteMarker(&cl->reliablebuf, svc_warmupstate);
51
	if (status == Warmup::COUNTDOWN || status == Warmup::FORCE_COUNTDOWN)
51
	MSG_WriteByte(&cl->reliablebuf, static_cast<byte>(status));
52
		MSG_WriteShort(&cl->reliablebuf, count);
52
	if (status == Warmup::COUNTDOWN || status == Warmup::FORCE_COUNTDOWN)
53
}
53
		MSG_WriteShort(&cl->reliablebuf, count);
54
54
}
55
// Broadcast warmup state to all clients.
55
56
void SV_BroadcastWarmupState(Warmup::status_t status, short count = 0)
56
// Broadcast warmup state to all clients.
57
{
57
void SV_BroadcastWarmupState(Warmup::status_t status, short count = 0)
58
	for (Players::iterator it = players.begin(); it != players.end(); ++it)
58
{
59
	{
59
	for (Players::iterator it = players.begin(); it != players.end(); ++it)
60
		if (!it->ingame())
60
	{
61
			continue;
61
		if (!it->ingame())
62
		SV_SendWarmupState(*it, status, count);
62
			continue;
63
	}
63
		SV_SendWarmupState(*it, status, count);
64
}
64
	}
65
65
}
66
// Set warmup status and send clients warmup information.
66
67
void Warmup::set_status(Warmup::status_t new_status)
67
// Set warmup status and send clients warmup information.
68
{
68
void Warmup::set_status(Warmup::status_t new_status)
69
	this->status = new_status;
69
{
70
70
	this->status = new_status;
71
	// [AM] If we switch to countdown, set the correct time.
71
72
	if (this->status == Warmup::COUNTDOWN || this->status == Warmup::FORCE_COUNTDOWN)
72
	// [AM] If we switch to countdown, set the correct time.
73
	{
73
	if (this->status == Warmup::COUNTDOWN || this->status == Warmup::FORCE_COUNTDOWN)
74
		this->time_begin = level.time + (sv_countdown.asInt() * TICRATE);
74
	{
75
		SV_BroadcastWarmupState(new_status, (short)sv_countdown.asInt());
75
		this->time_begin = level.time + (sv_countdown.asInt() * TICRATE);
76
	}
76
		SV_BroadcastWarmupState(new_status, (short)sv_countdown.asInt());
77
	else
77
	}
78
		SV_BroadcastWarmupState(new_status);
78
	else
79
}
79
		SV_BroadcastWarmupState(new_status);
80
80
}
81
// Status getter
81
82
Warmup::status_t Warmup::get_status()
82
// Status getter
83
{
83
Warmup::status_t Warmup::get_status()
84
	return this->status;
84
{
85
}
85
	return this->status;
86
86
}
87
// Warmup countdown getter
87
88
short Warmup::get_countdown()
88
// Warmup countdown getter
89
{
89
short Warmup::get_countdown()
90
	return ceil((this->time_begin - level.time) / (float)TICRATE);
90
{
91
}
91
	return ceil((this->time_begin - level.time) / (float)TICRATE);
92
92
}
93
// Reset warmup to "factory defaults".
93
94
void Warmup::reset()
94
// Reset warmup to "factory defaults".
95
{
95
void Warmup::reset()
96
	if (sv_warmup && sv_gametype != GM_COOP)
96
{
97
		this->set_status(Warmup::WARMUP);
97
	if (sv_warmup && sv_gametype != GM_COOP)
98
	else
98
		this->set_status(Warmup::WARMUP);
99
		this->set_status(Warmup::DISABLED);
99
	else if (sv_maxlives > 0)
100
	this->time_begin = 0;
100
		this->set_status(Warmup::WARMUP);
101
}
101
	else
102
102
		this->set_status(Warmup::DISABLED);
103
// Don't allow a players score to change if the server is in the middle of warmup.
103
	this->time_begin = 0;
104
bool Warmup::checkscorechange()
104
}
105
{
105
106
	if (this->status == Warmup::WARMUP || this->status == Warmup::COUNTDOWN ||
106
// Don't allow a players score to change if the server is in the middle of warmup.
107
	    this->status == Warmup::FORCE_COUNTDOWN)
107
bool Warmup::checkscorechange()
108
		return false;
108
{
109
	return true;
109
	if (this->status == Warmup::WARMUP || this->status == Warmup::COUNTDOWN ||
110
}
110
	    this->status == Warmup::FORCE_COUNTDOWN)
111
111
		return false;
112
// Don't allow the timeleft to advance if the server is in the middle of warmup.
112
	return true;
113
bool Warmup::checktimeleftadvance()
113
}
114
{
114
115
	if (this->status == Warmup::WARMUP || this->status == Warmup::COUNTDOWN ||
115
// Don't allow the timeleft to advance if the server is in the middle of warmup.
116
	    this->status == Warmup::FORCE_COUNTDOWN)
116
bool Warmup::checktimeleftadvance()
117
		return false;
117
{
118
	return true;
118
	if (this->status == Warmup::WARMUP || this->status == Warmup::COUNTDOWN ||
119
}
119
	    this->status == Warmup::FORCE_COUNTDOWN)
120
120
		return false;
121
// Don't allow players to fire their weapon if the server is in the middle
121
	return true;
122
// of a countdown.
122
}
123
bool Warmup::checkfireweapon()
123
124
{
124
// Don't allow players to fire their weapon if the server is in the middle
125
	if (this->status == Warmup::COUNTDOWN || this->status == Warmup::FORCE_COUNTDOWN)
125
// of a countdown.
126
		return false;
126
bool Warmup::checkfireweapon()
127
	return true;
127
{
128
}
128
	if (this->status == Warmup::COUNTDOWN || this->status == Warmup::FORCE_COUNTDOWN)
129
129
		return false;
130
// Check to see if we should allow players to toggle their ready state.
130
	return true;
131
bool Warmup::checkreadytoggle()
131
}
132
{
132
133
	if (this->status == Warmup::INGAME || this->status == Warmup::FORCE_COUNTDOWN)
133
// Check to see if we should allow players to toggle their ready state.
134
		return false;
134
bool Warmup::checkreadytoggle()
135
	return true;
135
{
136
}
136
	if (this->status == Warmup::INGAME || this->status == Warmup::FORCE_COUNTDOWN)
137
137
		return false;
138
extern size_t P_NumPlayersInGame();
138
	return true;
139
extern size_t P_NumReadyPlayersInGame();
139
}
140
140
141
// Start or stop the countdown based on if players are ready or not.
141
extern size_t P_NumPlayersInGame();
142
void Warmup::readytoggle()
142
extern size_t P_NumReadyPlayersInGame();
143
{
143
144
	// If warmup mode is disabled, don't bother.
144
// Start or stop the countdown based on if players are ready or not.
145
	if (this->status == Warmup::DISABLED)
145
void Warmup::readytoggle()
146
		return;
146
{
147
147
	// If warmup mode is disabled, don't bother.
148
	// If we're not actually in a countdown we can control, don't bother.
148
	if (this->status == Warmup::DISABLED)
149
	if (this->status == Warmup::FORCE_COUNTDOWN)
149
		return;
150
		return;
150
151
151
	// If we're not actually in a countdown we can control, don't bother.
152
	// Rerun our checks to make sure we didn't skip them earlier.
152
	if (this->status == Warmup::FORCE_COUNTDOWN)
153
	if (!this->checkreadytoggle())
153
		return;
154
		return;
154
155
155
	// Rerun our checks to make sure we didn't skip them earlier.
156
	// Check to see if we satisfy our autostart setting.
156
	if (!this->checkreadytoggle())
157
	size_t ready = P_NumReadyPlayersInGame();
157
		return;
158
	size_t total = P_NumPlayersInGame();
158
159
	size_t needed;
159
	// Check to see if we satisfy our autostart setting.
160
160
	size_t ready = P_NumReadyPlayersInGame();
161
	// We want at least one ingame ready player to start the game.  Servers
161
	size_t total = P_NumPlayersInGame();
162
	// that start automatically with no ready players are handled by
162
	size_t needed;
163
	// Warmup::tic().
163
164
	if (ready == 0 || total == 0)
164
	// We want at least one ingame ready player to start the game.  Servers
165
		return;
165
	// that start automatically with no ready players are handled by
166
166
	// Warmup::tic().
167
	float f_calc = total * sv_warmup_autostart;
167
	if (ready == 0 || total == 0)
168
	size_t i_calc = (int)floor(f_calc + 0.5f);
168
		return;
169
	if (f_calc > i_calc - MPEPSILON && f_calc < i_calc + MPEPSILON) {
169
170
		needed = i_calc + 1;
170
	float f_calc = total * sv_warmup_autostart;
171
	}
171
	size_t i_calc = (int)floor(f_calc + 0.5f);
172
	needed = (int)ceil(f_calc);
172
	if (f_calc > i_calc - MPEPSILON && f_calc < i_calc + MPEPSILON) {
173
173
		needed = i_calc + 1;
174
	if (ready >= needed)
174
	}
175
	{
175
	needed = (int)ceil(f_calc);
176
		if (this->status == Warmup::WARMUP)
176
177
			this->set_status(Warmup::COUNTDOWN);
177
	if (ready >= needed)
178
	}
178
	{
179
	else
179
		if (this->status == Warmup::WARMUP)
180
	{
180
			this->set_status(Warmup::COUNTDOWN);
181
		if (this->status == Warmup::COUNTDOWN)
181
	}
182
		{
182
	else
183
			this->set_status(Warmup::WARMUP);
183
	{
184
			SV_BroadcastPrintf(PRINT_HIGH, "Countdown aborted: Player unreadied.\n");
184
		if (this->status == Warmup::COUNTDOWN)
185
		}
185
		{
186
	}
186
			this->set_status(Warmup::WARMUP);
187
	return;
187
			SV_BroadcastPrintf(PRINT_HIGH, "Countdown aborted: Player unreadied.\n");
188
}
188
		}
189
189
	}
190
// We want to restart the map, so initialize a countdown that we
190
	return;
191
// can't bail out of.
191
}
192
void Warmup::restart()
192
193
{
193
// We want to restart the map, so initialize a countdown that we
194
	this->set_status(Warmup::FORCE_COUNTDOWN);
194
// can't bail out of.
195
}
195
void Warmup::restart()
196
196
{
197
// Force the start of the game.
197
	this->set_status(Warmup::FORCE_COUNTDOWN);
198
void Warmup::forcestart()
198
}
199
{
199
200
	// Useless outside of warmup.
200
// Force the start of the game.
201
	if (this->status != Warmup::WARMUP)
201
void Warmup::forcestart()
202
		return;
202
{
203
203
	// Useless outside of warmup.
204
	this->set_status(Warmup::COUNTDOWN);
204
	if (this->status != Warmup::WARMUP)
205
}
205
		return;
206
206
207
// Handle tic-by-tic maintenance of the warmup.
207
	this->set_status(Warmup::COUNTDOWN);
208
void Warmup::tic()
208
}
209
{
209
210
	// If warmup isn't enabled, return
210
player_t *SV_PopFromQueue (void);
211
	if (this->status == Warmup::DISABLED)
211
void SV_SetPlayerSpec(player_t &player, bool setting, bool silent);
212
		return;
212
213
213
// Handle tic-by-tic maintenance of the warmup.
214
	// If autostart is zeroed out, start immediately.
214
void Warmup::tic()
215
	if (this->status == Warmup::WARMUP && sv_warmup_autostart == 0.0f)
215
{
216
		this->set_status(Warmup::COUNTDOWN);
216
	// If warmup isn't enabled, return
217
217
	if (this->status == Warmup::DISABLED)
218
	// If there aren't any more active players, go back to warm up mode [tm512 2014/04/08]
218
		return;
219
	if (this->status != Warmup::WARMUP && P_NumPlayersInGame () == 0)
219
220
		this->set_status (Warmup::WARMUP);
220
	// If autostart is zeroed out, start immediately.
221
221
	if (this->status == Warmup::WARMUP && sv_warmup_autostart == 0.0f)
222
	// If we're not advancing the countdown, we don't care.
222
		this->set_status(Warmup::COUNTDOWN);
223
	if (!(this->status == Warmup::COUNTDOWN || this->status == Warmup::FORCE_COUNTDOWN))
223
224
		return;
224
	// If there aren't any more active players, go back to warm up mode [tm512 2014/04/08]
225
225
	if (this->status != Warmup::WARMUP && P_NumPlayersInGame () == 0)
226
	// If we haven't reached the level tic that we begin the map on,
226
	{
227
	// we don't care.
227
		this->set_status (Warmup::WARMUP);
228
	if (this->time_begin > level.time)
228
		if (sv_gametype == GM_COOP) // in survival we want to join some people now
229
	{
229
		{
230
		// Broadcast a countdown (this should be handled clientside)
230
			player_t *pl;
231
		if ((this->time_begin - level.time) % TICRATE == 0)
231
			while (pl = SV_PopFromQueue ())
232
		{
232
				SV_SetPlayerSpec (*pl, false, true);
233
			SV_BroadcastWarmupState(this->status, this->get_countdown());
233
		}
234
		}
234
	}
235
		return;
235
236
	}
236
	// If we're in survival/LMS mode and someone joins the game, activate the countdown
237
237
	if (sv_maxlives > 0 && P_NumPlayersInGame () > 0)
238
	if (sv_warmup)
238
	{
239
		this->set_status(Warmup::INGAME);
239
		// we're on a brand new level, so don't initiate the countdown, just carry on with the game
240
	else
240
		if (level.time == 1)
241
		this->set_status(Warmup::DISABLED);
241
		{
242
242
			this->set_status(Warmup::INGAME);
243
	// [SL] always reset the time (for now at least)
243
			return;
244
	level.time = 0;
244
		}
245
	level.timeleft = sv_timelimit * TICRATE * 60;
245
246
	level.inttimeleft = mapchange / TICRATE;
246
		if (this->status == Warmup::WARMUP)
247
247
			this->set_status(Warmup::FORCE_COUNTDOWN);
248
	G_DeferedFullReset();
248
	}
249
	SV_BroadcastPrintf(PRINT_HIGH, "The match has started.\n");
249
250
}
250
	// If we're not advancing the countdown, we don't care.
251
251
	if (!(this->status == Warmup::COUNTDOWN || this->status == Warmup::FORCE_COUNTDOWN))
252
BEGIN_COMMAND (forcestart)
252
		return;
253
{
253
254
	warmup.forcestart();
254
	// If we haven't reached the level tic that we begin the map on,
255
}
255
	// we don't care.
256
END_COMMAND (forcestart)
256
	if (this->time_begin > level.time)
257
	{
258
		// Broadcast a countdown (this should be handled clientside)
259
		if ((this->time_begin - level.time) % TICRATE == 0)
260
		{
261
			SV_BroadcastWarmupState(this->status, this->get_countdown());
262
		}
263
		return;
264
	}
265
266
	if (sv_warmup || sv_maxlives > 0)
267
		this->set_status(Warmup::INGAME);
268
	else
269
		this->set_status(Warmup::DISABLED);
270
271
	// [SL] always reset the time (for now at least)
272
	level.time = 0;
273
	level.timeleft = sv_timelimit * TICRATE * 60;
274
	level.inttimeleft = mapchange / TICRATE;
275
276
	if (sv_maxlives > 0)
277
		G_DeferedReset ();
278
	else
279
		G_DeferedFullReset();
280
	SV_BroadcastPrintf(PRINT_HIGH, "The match has started.\n");
281
}
282
283
BEGIN_COMMAND (forcestart)
284
{
285
	warmup.forcestart();
286
}
287
END_COMMAND (forcestart)
(-)a/server/src/sv_main.cpp (-1 / +14 lines)
Lines 3683-3688 void SV_Spectate (player_t &player) { Link Here
3683
// param to spec or unspec the player without a broadcasted message.
3683
// param to spec or unspec the player without a broadcasted message.
3684
void P_SetSpectatorFlags(player_t &player);
3684
void P_SetSpectatorFlags(player_t &player);
3685
3685
3686
EXTERN_CVAR (sv_maxlives)
3687
3686
void SV_SetPlayerSpec(player_t &player, bool setting, bool silent) {
3688
void SV_SetPlayerSpec(player_t &player, bool setting, bool silent) {
3687
	// We don't care about spectators during intermission
3689
	// We don't care about spectators during intermission
3688
	if (gamestate == GS_INTERMISSION) {
3690
	if (gamestate == GS_INTERMISSION) {
Lines 3690-3695 void SV_SetPlayerSpec(player_t &player, bool setting, bool silent) { Link Here
3690
	}
3692
	}
3691
3693
3692
	if (!setting && player.spectator) {
3694
	if (!setting && player.spectator) {
3695
3696
		// Make sure a survival/LMS game isn't active
3697
		if (sv_maxlives > 0 && warmup.get_status () == Warmup::INGAME)
3698
		{
3699
			// Queue join if this is a survival game
3700
			if (sv_gametype == GM_COOP)
3701
				SV_QueueJoin (&player);
3702
3703
			return;
3704
		}
3705
3693
		// We want to unspectate the player.
3706
		// We want to unspectate the player.
3694
		if ((level.time > player.joinafterspectatortime + TICRATE * 3) ||
3707
		if ((level.time > player.joinafterspectatortime + TICRATE * 3) ||
3695
			level.time > player.joinafterspectatortime + TICRATE * 5) {
3708
			level.time > player.joinafterspectatortime + TICRATE * 5) {
Lines 3796-3802 void SV_SetPlayerSpec(player_t &player, bool setting, bool silent) { Link Here
3796
			SV_BroadcastPrintf(PRINT_HIGH, "%s became a spectator.\n", player.userinfo.netname.c_str());
3809
			SV_BroadcastPrintf(PRINT_HIGH, "%s became a spectator.\n", player.userinfo.netname.c_str());
3797
		}
3810
		}
3798
3811
3799
		// In a duel, try to fill empty spots
3812
		// In a duel, try to fill the empty spot
3800
		if (sv_maxplayers == 2)
3813
		if (sv_maxplayers == 2)
3801
		{
3814
		{
3802
			player_t *pl = SV_PopFromQueue ();
3815
			player_t *pl = SV_PopFromQueue ();

Return to bug 1189