1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: g_level.cpp 4556 2014-02-10 02:48:10Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 1998-2006 by Randy Heit (ZDoom).
8 // Copyright (C) 2006-2014 by The Odamex Team.
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // DESCRIPTION:
21 //	G_LEVEL
22 //
23 //-----------------------------------------------------------------------------
24 
25 
26 #include <sstream>
27 #include <string>
28 #include <algorithm>
29 #include <vector>
30 #include <set>
31 
32 #include "c_console.h"
33 #include "c_dispatch.h"
34 #include "c_level.h"
35 #include "d_event.h"
36 #include "d_main.h"
37 #include "doomstat.h"
38 #include "g_level.h"
39 #include "g_game.h"
40 #include "gstrings.h"
41 #include "gi.h"
42 
43 #include "i_system.h"
44 #include "m_alloc.h"
45 #include "m_fileio.h"
46 #include "m_misc.h"
47 #include "minilzo.h"
48 #include "m_random.h"
49 #include "p_acs.h"
50 #include "p_ctf.h"
51 #include "p_local.h"
52 #include "p_mobj.h"
53 #include "p_saveg.h"
54 #include "p_setup.h"
55 #include "p_unlag.h"
56 #include "r_data.h"
57 #include "r_sky.h"
58 #include "s_sound.h"
59 #include "s_sndseq.h"
60 #include "sc_man.h"
61 #include "sv_main.h"
62 #include "sv_maplist.h"
63 #include "sv_vote.h"
64 #include "v_video.h"
65 #include "w_wad.h"
66 #include "z_zone.h"
67 #include "g_warmup.h"
68 
69 
70 // FIXME: Remove this as soon as the JoinString is gone from G_ChangeMap()
71 #include "cmdlib.h"
72 
73 #define lioffset(x)		myoffsetof(level_pwad_info_t,x)
74 #define cioffset(x)		myoffsetof(cluster_info_t,x)
75 
76 extern int nextupdate;
77 
78 
79 EXTERN_CVAR (sv_endmapscript)
80 EXTERN_CVAR (sv_startmapscript)
81 EXTERN_CVAR (sv_curmap)
82 EXTERN_CVAR (sv_nextmap)
83 EXTERN_CVAR (sv_loopepisode)
84 EXTERN_CVAR (sv_intermissionlimit)
85 EXTERN_CVAR (sv_warmup)
86 EXTERN_CVAR (sv_timelimit)
87 
88 extern int mapchange;
89 extern int shotclock;
90 
91 // Start time for timing demos
92 dtime_t starttime;
93 
94 // ACS variables with world scope
95 int ACS_WorldVars[NUM_WORLDVARS];
96 
97 // ACS variables with global scope
98 int ACS_GlobalVars[NUM_GLOBALVARS];
99 
100 // [AM] Stores the reset snapshot
101 FLZOMemFile	*reset_snapshot = NULL;
102 
103 BOOL firstmapinit = true; // Nes - Avoid drawing same init text during every rebirth in single-player servers.
104 
105 extern BOOL netdemo;
106 BOOL savegamerestore;
107 
108 extern int mousex, mousey, joyxmove, joyymove, Impulse;
109 extern BOOL sendpause, sendsave, sendcenterview;
110 
111 
112 bool isFast = false;
113 
114 //
115 // G_InitNew
116 // Can be called by the startup code or the menu task,
117 // consoleplayer, displayplayer, should be set.
118 //
119 static char d_mapname[9];
120 
G_DeferedInitNew(char * mapname)121 void G_DeferedInitNew (char *mapname)
122 {
123 	strncpy (d_mapname, mapname, 8);
124 	gameaction = ga_newgame;
125 
126 	// sv_nextmap cvar may be overridden by a script
127 	sv_nextmap.ForceSet(d_mapname);
128 }
129 
G_DeferedFullReset()130 void G_DeferedFullReset()
131 {
132 	gameaction = ga_fullresetlevel;
133 }
134 
G_DeferedReset()135 void G_DeferedReset()
136 {
137 	gameaction = ga_resetlevel;
138 }
139 
GetBase(const char * in)140 const char* GetBase(const char* in)
141 {
142 	const char* out = &in[strlen(in) - 1];
143 
144 	while (out > in && *(out-1) != PATHSEPCHAR)
145 		out--;
146 
147 	return out;
148 }
149 
BEGIN_COMMAND(wad)150 BEGIN_COMMAND (wad) // denis - changes wads
151 {
152 	// [Russell] print out some useful info
153 	if (argc == 1)
154 	{
155 	    Printf(PRINT_HIGH, "Usage: wad pwad [...] [deh/bex [...]]\n");
156 	    Printf(PRINT_HIGH, "       wad iwad [pwad [...]] [deh/bex [...]]\n");
157 	    Printf(PRINT_HIGH, "\n");
158 	    Printf(PRINT_HIGH, "Load a wad file on the fly, pwads/dehs/bexs require extension\n");
159 	    Printf(PRINT_HIGH, "eg: wad doom\n");
160 
161 	    return;
162 	}
163 
164 	std::string str = JoinStrings(VectorArgs(argc, argv), " ");
165 	G_LoadWad(str);
166 }
167 END_COMMAND (wad)
168 
169 BOOL 			secretexit;
170 
EXTERN_CVAR(sv_shufflemaplist)171 EXTERN_CVAR(sv_shufflemaplist)
172 
173 // Returns the next map, assuming there is no maplist.
174 std::string G_NextMap(void) {
175 	std::string next = level.nextmap;
176 
177 	if (gamestate == GS_STARTUP || sv_gametype != GM_COOP || !strlen(next.c_str())) {
178 		// if not coop, stay on same level
179 		// [ML] 1/25/10: OR if next is empty
180 		next = level.mapname;
181 	} else if (secretexit && W_CheckNumForName(level.secretmap) != -1) {
182 		// if we hit a secret exit switch, go there instead.
183 		next = level.secretmap;
184 	}
185 
186 	// NES - exiting a Doom 1 episode moves to the next episode,
187 	// rather than always going back to E1M1
188 	if (!strncmp(next.c_str(), "EndGame", 7) ||
189 		(gamemode == retail_chex && !strncmp (level.nextmap, "E1M6", 4))) {
190 		if (gameinfo.flags & GI_MAPxx || gamemode == shareware ||
191 			(!sv_loopepisode && ((gamemode == registered && level.cluster == 3) || ((gameinfo.flags & GI_MENUHACK_RETAIL) && level.cluster == 4)))) {
192 			next = CalcMapName(1, 1);
193 		} else if (sv_loopepisode) {
194 			next = CalcMapName(level.cluster, 1);
195 		} else {
196 			next = CalcMapName(level.cluster + 1, 1);
197 		}
198 	}
199 	return next;
200 }
201 
202 // Determine the "next map" and change to it.
G_ChangeMap()203 void G_ChangeMap() {
204 	unnatural_level_progression = false;
205 
206 	size_t next_index;
207 	if (!Maplist::instance().get_next_index(next_index)) {
208 		// We don't have a maplist, so grab the next 'natural' map lump.
209 		std::string next = G_NextMap();
210 		G_DeferedInitNew((char *)next.c_str());
211 	} else {
212 		maplist_entry_t maplist_entry;
213 		Maplist::instance().get_map_by_index(next_index, maplist_entry);
214 
215 		G_LoadWad(JoinStrings(maplist_entry.wads, " "), maplist_entry.map);
216 
217 		// Set the new map as the current map
218 		Maplist::instance().set_index(next_index);
219 	}
220 
221 	// run script at the end of each map
222 	// [ML] 8/22/2010: There are examples in the wiki that outright don't work
223 	// when onlcvars (addcommandstring's second param) is true.  Is there a
224 	// reason why the mapscripts ahve to be safe mode?
225 	if(strlen(sv_endmapscript.cstring()))
226 		AddCommandString(sv_endmapscript.cstring()/*, true*/);
227 }
228 
229 // Change to a map based on a maplist index.
G_ChangeMap(size_t index)230 void G_ChangeMap(size_t index) {
231 	maplist_entry_t maplist_entry;
232 	if (!Maplist::instance().get_map_by_index(index, maplist_entry)) {
233 		// That maplist index doesn't actually exist
234 		Printf(PRINT_HIGH, "%s\n", Maplist::instance().get_error().c_str());
235 		return;
236 	}
237 
238 	G_LoadWad(JoinStrings(maplist_entry.wads, " "), maplist_entry.map);
239 
240 	// Set the new map as the current map
241 	Maplist::instance().set_index(index);
242 
243 	// run script at the end of each map
244 	// [ML] 8/22/2010: There are examples in the wiki that outright don't work
245 	// when onlcvars (addcommandstring's second param) is true.  Is there a
246 	// reason why the mapscripts ahve to be safe mode?
247 	if(strlen(sv_endmapscript.cstring()))
248 		AddCommandString(sv_endmapscript.cstring()/*, true*/);
249 }
250 
251 // Restart the current map.
G_RestartMap()252 void G_RestartMap() {
253 	// Restart the current map.
254 	G_DeferedInitNew(level.mapname);
255 
256 	// run script at the end of each map
257 	// [ML] 8/22/2010: There are examples in the wiki that outright don't work
258 	// when onlcvars (addcommandstring's second param) is true.  Is there a
259 	// reason why the mapscripts ahve to be safe mode?
260 	if(strlen(sv_endmapscript.cstring()))
261 		AddCommandString(sv_endmapscript.cstring()/*, true*/);
262 }
263 
BEGIN_COMMAND(nextmap)264 BEGIN_COMMAND (nextmap) {
265 	G_ExitLevel(0, 1);
266 } END_COMMAND (nextmap)
267 
BEGIN_COMMAND(forcenextmap)268 BEGIN_COMMAND (forcenextmap) {
269 	G_ChangeMap();
270 } END_COMMAND (forcenextmap)
271 
BEGIN_COMMAND(restart)272 BEGIN_COMMAND (restart) {
273 	warmup.restart();
274 } END_COMMAND (restart)
275 
276 void SV_ClientFullUpdate(player_t &pl);
277 void SV_CheckTeam(player_t &pl);
278 
279 //
280 // G_DoNewGame
281 //
282 // denis - rewritten so that it does not force client reconnects
283 //
G_DoNewGame(void)284 void G_DoNewGame (void)
285 {
286 	for (Players::iterator it = players.begin();it != players.end();++it)
287 	{
288 		if(!(it->ingame()))
289 			continue;
290 
291 		SV_SendLoadMap(wadfiles, patchfiles, d_mapname, &*it);
292 	}
293 
294 	sv_curmap.ForceSet(d_mapname);
295 
296 	G_InitNew (d_mapname);
297 	gameaction = ga_nothing;
298 
299 	// run script at the start of each map
300 	// [ML] 8/22/2010: There are examples in the wiki that outright don't work
301 	// when onlcvars (addcommandstring's second param) is true.  Is there a
302 	// reason why the mapscripts ahve to be safe mode?
303 	if (strlen(sv_startmapscript.cstring()))
304 		AddCommandString(sv_startmapscript.cstring()/*,true*/);
305 
306 	for (Players::iterator it = players.begin();it != players.end();++it)
307 	{
308 		if (!(it->ingame()))
309 			continue;
310 
311 		if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF)
312 			SV_CheckTeam(*it);
313 		else
314 			it->userinfo.color = it->prefcolor;
315 
316 		SV_ClientFullUpdate(*it);
317 	}
318 }
319 
320 EXTERN_CVAR (sv_skill)
321 EXTERN_CVAR (sv_monstersrespawn)
322 EXTERN_CVAR (sv_fastmonsters)
323 EXTERN_CVAR (sv_maxplayers)
324 
325 void G_PlayerReborn (player_t &player);
326 void SV_ServerSettingChange();
327 
G_InitNew(const char * mapname)328 void G_InitNew (const char *mapname)
329 {
330 	size_t i;
331 
332 	if (!savegamerestore)
333 		G_ClearSnapshots ();
334 
335 	// [RH] Mark all levels as not visited
336 	if (!savegamerestore)
337 	{
338 		for (i = 0; i < wadlevelinfos.size(); i++)
339 			wadlevelinfos[i].flags &= ~LEVEL_VISITED;
340 
341 		for (i = 0; LevelInfos[i].mapname[0]; i++)
342 			LevelInfos[i].flags &= ~LEVEL_VISITED;
343 	}
344 
345 	int old_gametype = sv_gametype.asInt();
346 
347 	cvar_t::UnlatchCVars ();
348 
349 	if (old_gametype != sv_gametype || sv_gametype != GM_COOP) {
350 		unnatural_level_progression = true;
351 
352 		// Nes - Force all players to be spectators when the sv_gametype is not now or previously co-op.
353 		for (Players::iterator it = players.begin();it != players.end();++it)
354 		{
355 			// [SL] 2011-07-30 - Don't force downloading players to become spectators
356 			// it stops their downloading
357 			if (!(it->ingame()))
358 				continue;
359 
360 			for (Players::iterator pit = players.begin();pit != players.end();++pit)
361 			{
362 				if (!(pit->ingame()))
363 					continue;
364 				MSG_WriteMarker (&(pit->client.reliablebuf), svc_spectate);
365 				MSG_WriteByte (&(pit->client.reliablebuf), it->id);
366 				MSG_WriteByte (&(pit->client.reliablebuf), true);
367 			}
368 			it->spectator = true;
369 			it->playerstate = PST_LIVE;
370 			it->joinafterspectatortime = -(TICRATE * 5);
371 		}
372 	}
373 
374 	// [SL] 2011-09-01 - Change gamestate here so SV_ServerSettingChange will
375 	// send changed cvars
376 	gamestate = GS_LEVEL;
377 	SV_ServerSettingChange();
378 
379 	if (paused)
380 	{
381 		paused = false;
382 	}
383 
384 	// [RH] If this map doesn't exist, bomb out
385 	if (W_CheckNumForName (mapname) == -1)
386 	{
387 		I_Error ("Could not find map %s\n", mapname);
388 	}
389 
390 	if (sv_skill == sk_nightmare || sv_monstersrespawn)
391 		respawnmonsters = true;
392 	else
393 		respawnmonsters = false;
394 
395 	bool wantFast = sv_fastmonsters || (sv_skill == sk_nightmare);
396 	if (wantFast != isFast)
397 	{
398 		if (wantFast)
399 		{
400 			for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
401 				states[i].tics >>= 1;
402 			mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT;
403 			mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT;
404 			mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT;
405 		}
406 		else
407 		{
408 			for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
409 				states[i].tics <<= 1;
410 			mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT;
411 			mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT;
412 			mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT;
413 		}
414 		isFast = wantFast;
415 	}
416 
417 	// [SL] 2011-05-11 - Reset all reconciliation system data for unlagging
418 	Unlag::getInstance().reset();
419 
420 	if (!savegamerestore)
421 	{
422 		M_ClearRandom ();
423 		memset (ACS_WorldVars, 0, sizeof(ACS_WorldVars));
424 		memset (ACS_GlobalVars, 0, sizeof(ACS_GlobalVars));
425 		level.time = 0;
426 		level.timeleft = 0;
427 		level.inttimeleft = 0;
428 
429 		// force players to be initialized upon first level load
430 		for (Players::iterator it = players.begin();it != players.end();++it)
431 		{
432 			// [SL] 2011-05-11 - Register the players in the reconciliation
433 			// system for unlagging
434 			Unlag::getInstance().registerPlayer(it->id);
435 
436 			if(!(it->ingame()))
437 				continue;
438 
439 			// denis - dead players should have their stuff looted, otherwise they'd take their ammo into their afterlife!
440 			if (it->playerstate == PST_DEAD)
441 				G_PlayerReborn(*it);
442 
443 			it->playerstate = PST_ENTER; // [BC]
444 
445 			it->joinafterspectatortime = -(TICRATE * 5);
446 		}
447 	}
448 
449 	// [SL] 2012-12-08 - Multiplayer is always true for servers
450 	multiplayer = true;
451 
452 	usergame = true;				// will be set false if a demo
453 	paused = false;
454 	demoplayback = false;
455 	viewactive = true;
456 	shotclock = 0;
457 
458 	strncpy (level.mapname, mapname, 8);
459 	G_DoLoadLevel (0);
460 
461 	// denis - hack to fix ctfmode, as it is only known after the map is processed!
462 	//if(old_ctfmode != ctfmode)
463 	//	SV_ServerSettingChange();
464 }
465 
466 //
467 // G_DoCompleted
468 //
469 
G_ExitLevel(int position,int drawscores)470 void G_ExitLevel (int position, int drawscores)
471 {
472 	SV_ExitLevel();
473 
474 	if (drawscores)
475         SV_DrawScores();
476 
477 	int intlimit = (sv_intermissionlimit < 1 || sv_gametype == GM_COOP ? DEFINTSECS : sv_intermissionlimit);
478 
479 	gamestate = GS_INTERMISSION;
480 	shotclock = 0;
481 	mapchange = TICRATE*intlimit;  // wait n seconds, default 10
482 
483     secretexit = false;
484 
485     gameaction = ga_completed;
486 
487 	// denis - this will skip wi_stuff and allow some time for finale text
488 	//G_WorldDone();
489 }
490 
491 // Here's for the german edition.
G_SecretExitLevel(int position,int drawscores)492 void G_SecretExitLevel (int position, int drawscores)
493 {
494 	SV_ExitLevel();
495 
496     if (drawscores)
497         SV_DrawScores();
498 
499 	int intlimit = (sv_intermissionlimit < 1 || sv_gametype == GM_COOP ? DEFINTSECS : sv_intermissionlimit);
500 
501 	gamestate = GS_INTERMISSION;
502 	shotclock = 0;
503 	mapchange = TICRATE*intlimit;  // wait n seconds, defaults to 10
504 
505 	// IF NO WOLF3D LEVELS, NO SECRET EXIT!
506 	if ( (gameinfo.flags & GI_MAPxx)
507 		 && (W_CheckNumForName("map31")<0))
508 		secretexit = false;
509 	else
510 		secretexit = true;
511 
512     gameaction = ga_completed;
513 
514 	// denis - this will skip wi_stuff and allow some time for finale text
515 	//G_WorldDone();
516 }
517 
G_DoCompleted()518 void G_DoCompleted()
519 {
520 	gameaction = ga_nothing;
521 
522 	for (Players::iterator it = players.begin();it != players.end();++it)
523 		if (it->ingame())
524 			G_PlayerFinishLevel(*it);
525 }
526 
527 extern void G_SerializeLevel(FArchive &arc, bool hubLoad, bool noStorePlayers);
528 
529 // [AM] - Save the state of the level that can be reset to
G_DoSaveResetState()530 void G_DoSaveResetState()
531 {
532 	if (reset_snapshot != NULL)
533 	{
534 		// An existing reset snapshot exists.  Kill it and replace it with
535 		// a new one.
536 		delete reset_snapshot;
537 	}
538 	reset_snapshot = new FLZOMemFile;
539 	reset_snapshot->Open();
540 	FArchive arc(*reset_snapshot);
541 	G_SerializeLevel(arc, false, true);
542 	arc << level.time;
543 }
544 
545 // [AM] - Reset the state of the level.  Second parameter is true if you want
546 //        to zero-out gamestate as well (i.e. resetting scores, RNG, etc.).
G_DoResetLevel(bool full_reset)547 void G_DoResetLevel(bool full_reset)
548 {
549 	gameaction = ga_nothing;
550 	if (reset_snapshot == NULL)
551 	{
552 		// No saved state to reload to
553 		DPrintf("G_DoResetLevel: No saved state to reload.");
554 		return;
555 	}
556 
557 	// Clear CTF state.
558 	Players::iterator it;
559 	if (sv_gametype == GM_CTF)
560 	{
561 		for (size_t i = 0;i < NUMFLAGS;i++)
562 		{
563 			for (it = players.begin();it != players.end();++it)
564 			{
565 				it->flags[i] = false;
566 			}
567 			CTFdata[i].flagger = 0;
568 			CTFdata[i].state = flag_home;
569 		}
570 	}
571 
572 	// Clear netids of every non-player actor so we don't spam the
573 	// destruction message of actors to clients.
574 	{
575 		AActor* mo;
576 		TThinkerIterator<AActor> iterator;
577 		while ((mo = iterator.Next()))
578 		{
579 			if (mo->netid && mo->type != MT_PLAYER)
580 			{
581 				ServerNetID.ReleaseNetID(mo->netid);
582 				mo->netid = 0;
583 			}
584 		}
585 	}
586 
587 	// Tell clients that a map reset is incoming.
588 	for (it = players.begin();it != players.end();++it)
589 	{
590 		if (!(it->ingame()))
591 			continue;
592 
593 		client_t *cl = &(it->client);
594 		MSG_WriteMarker(&cl->reliablebuf, svc_resetmap);
595 	}
596 
597 	// Unserialize saved snapshot
598 	reset_snapshot->Reopen();
599 	FArchive arc(*reset_snapshot);
600 	G_SerializeLevel(arc, false, true);
601 	int level_time;
602 	arc >> level_time;
603 	reset_snapshot->Seek(0, FFile::ESeekSet);
604 
605 	// Assign new netids to every non-player actor to make sure we don't have
606 	// any weird destruction of any items post-reset.
607 	{
608 		AActor* mo;
609 		TThinkerIterator<AActor> iterator;
610 		while ((mo = iterator.Next()))
611 		{
612 			if (mo->netid && mo->type != MT_PLAYER)
613 			{
614 				mo->netid = ServerNetID.ObtainNetID();
615 			}
616 		}
617 	}
618 
619 	// Clear the item respawn queue, otherwise all those actors we just
620 	// destroyed and replaced with the serialized items will start respawning.
621 	iquehead = iquetail = 0;
622 	// Potentially clear out gamestate as well.
623 	if (full_reset)
624 	{
625 		// Set time to the initial tic
626 		level.time = level_time;
627 		// Clear global goals.
628 		for (size_t i = 0; i < NUMTEAMS; i++)
629 			TEAMpoints[i] = 0;
630 		// Clear player information.
631 		for (it = players.begin();it != players.end();++it)
632 		{
633 			it->fragcount = 0;
634 			it->itemcount = 0;
635 			it->secretcount = 0;
636 			it->deathcount = 0;
637 			it->killcount = 0;
638 			it->points = 0;
639 			it->joinafterspectatortime = level.time;
640 
641 			// [AM] Only touch ready state if warmup mode is enabled.
642 			if (sv_warmup)
643 				it->ready = false;
644 		}
645 		// For predictable first spawns.
646 		M_ClearRandom();
647 	}
648 
649 	// [SL] always reset the time (for now at least)
650 	level.time = 0;
651 	level.timeleft = sv_timelimit * TICRATE * 60;
652 	level.inttimeleft = mapchange / TICRATE;
653 
654 	// Send information about the newly reset map.
655 	for (it = players.begin();it != players.end();++it)
656 	{
657 		// Player needs to actually be ingame
658 		if (!it->ingame())
659 			continue;
660 
661 		SV_ClientFullUpdate(*it);
662 	}
663 	// Force every ingame player to be reborn.
664 	for (it = players.begin();it != players.end();++it)
665 	{
666 		// Spectators aren't reborn.
667 		if (!it->ingame() || it->spectator)
668 			continue;
669 
670 		// Destroy the attached mobj, otherwise we leave a ghost.
671 		it->mo->Destroy();
672 
673 		// Set the respawning machinery in motion
674 		it->playerstate = full_reset ? PST_ENTER : PST_REBORN;
675 
676 		// Do this here, otherwise players won't be reborn until next tic.
677 		// [AM] Also, forgetting to do this will result in ticcmds that rely on
678 		//      a players subsector to be valid (like use) to crash the server.
679 		G_DoReborn(*it);
680 	}
681 }
682 
683 //
684 // G_DoLoadLevel
685 //
686 extern gamestate_t 	wipegamestate;
687 extern float BaseBlendA;
688 
G_DoLoadLevel(int position)689 void G_DoLoadLevel (int position)
690 {
691 	static int lastposition = 0;
692 	size_t i;
693 
694 	if (position != -1)
695 		firstmapinit = true;
696 
697 	if (position == -1)
698 		position = lastposition;
699 	else
700 		lastposition = position;
701 
702 	G_InitLevelLocals ();
703 
704 	if (firstmapinit) {
705 		Printf (PRINT_HIGH, "--- %s: \"%s\" ---\n", level.mapname, level.level_name);
706 		firstmapinit = false;
707 	}
708 
709 	if (wipegamestate == GS_LEVEL)
710 		wipegamestate = GS_FORCEWIPE;
711 
712 	gamestate = GS_LEVEL;
713 
714 //	if (demoplayback || oldgs == GS_STARTUP)
715 //		C_HideConsole ();
716 
717 	// Set the sky map.
718 	// First thing, we have a dummy sky texture name,
719 	//	a flat. The data is in the WAD only because
720 	//	we look for an actual index, instead of simply
721 	//	setting one.
722 	skyflatnum = R_FlatNumForName ( SKYFLATNAME );
723 
724 	// DOOM determines the sky texture to be used
725 	// depending on the current episode, and the game version.
726 	// [RH] Fetch sky parameters from level_locals_t.
727 	// [ML] 5/11/06 - remove sky2 remenants
728 	// [SL] 2012-03-19 - Add sky2 back
729 	sky1texture = R_TextureNumForName (level.skypic);
730 	if (strlen(level.skypic2))
731 		sky2texture = R_TextureNumForName (level.skypic2);
732 	else
733 		sky2texture = 0;
734 
735 	for (Players::iterator it = players.begin();it != players.end();++it)
736 	{
737 		if (it->ingame() && it->playerstate == PST_DEAD)
738 			it->playerstate = PST_REBORN;
739 
740 		// [AM] If sv_keepkeys is on, players might still be carrying keys, so
741 		//      make sure they're gone.
742 		for (size_t j = 0; j < NUMCARDS; j++)
743 			it->cards[j] = false;
744 
745 		it->fragcount = 0;
746 		it->itemcount = 0;
747 		it->secretcount = 0;
748 		it->deathcount = 0; // [Toke - Scores - deaths]
749 		it->killcount = 0; // [deathz0r] Coop kills
750 		it->points = 0;
751 
752 		// [AM] Only touch ready state if warmup mode is enabled.
753 		if (sv_warmup)
754 		{
755 			it->ready = false;
756 			it->timeout_ready = 0;
757 
758 			// [AM] Make sure the clients are updated on the new ready state
759 			for (Players::iterator pit = players.begin();pit != players.end();++pit)
760 			{
761 				MSG_WriteMarker(&(pit->client.reliablebuf), svc_readystate);
762 				MSG_WriteByte(&(pit->client.reliablebuf), it->id);
763 				MSG_WriteBool(&(pit->client.reliablebuf), false);
764 			}
765 		}
766 	}
767 
768 	// [deathz0r] It's a smart idea to reset the team points
769 	if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF)
770 	{
771 		for (size_t i = 0; i < NUMTEAMS; i++)
772 			TEAMpoints[i] = 0;
773 	}
774 
775 	// initialize the msecnode_t freelist.					phares 3/25/98
776 	// any nodes in the freelist are gone by now, cleared
777 	// by Z_FreeTags() when the previous level ended or player
778 	// died.
779 
780 	{
781 		extern msecnode_t *headsecnode; // phares 3/25/98
782 		headsecnode = NULL;
783 
784 		// denis - todo - wtf is this crap?
785 		// [RH] Need to prevent the AActor destructor from trying to
786 		//		free the nodes
787 		AActor *actor;
788 		TThinkerIterator<AActor> iterator;
789 
790 		while ( (actor = iterator.Next ()) )
791 		{
792 			actor->touching_sectorlist = NULL;
793 
794 			// denis - clear every actor netid so that they don't announce their destruction to clients
795 			ServerNetID.ReleaseNetID(actor->netid);
796 			actor->netid = 0;
797 		}
798 	}
799 
800 	// For single-player servers.
801 	for (Players::iterator it = players.begin();it != players.end();++it)
802 		it->joinafterspectatortime -= level.time;
803 
804 	flagdata *tempflag;
805 
806 	// Nes - CTF Pre flag setup
807 	if (sv_gametype == GM_CTF) {
808 		tempflag = &CTFdata[it_blueflag];
809 		tempflag->flaglocated = false;
810 
811 		tempflag = &CTFdata[it_redflag];
812 		tempflag->flaglocated = false;
813 	}
814 
815 	P_SetupLevel (level.mapname, position);
816 
817 	// Nes - CTF Post flag setup
818 	if (sv_gametype == GM_CTF) {
819 		tempflag = &CTFdata[it_blueflag];
820 		if (!tempflag->flaglocated)
821 			SV_BroadcastPrintf(PRINT_HIGH, "WARNING: Blue flag pedestal not found! No blue flags in game.\n");
822 
823 		tempflag = &CTFdata[it_redflag];
824 		if (!tempflag->flaglocated)
825 			SV_BroadcastPrintf(PRINT_HIGH, "WARNING: Red flag pedestal not found! No red flags in game.\n");
826 	}
827 
828 	displayplayer_id = consoleplayer_id;				// view the guy you are playing
829 
830 	gameaction = ga_nothing;
831 	Z_CheckHeap ();
832 
833 	// clear cmd building stuff // denis - todo - could we get rid of this?
834 	Impulse = 0;
835 	for (i = 0; i < NUM_ACTIONS; i++)
836 		if (i != ACTION_MLOOK && i != ACTION_KLOOK)
837 			Actions[i] = 0;
838 
839 	joyxmove = joyymove = 0;
840 	mousex = mousey = 0;
841 	sendpause = sendsave = paused = sendcenterview = false;
842 
843 	if (timingdemo)
844 	{
845 		static BOOL firstTime = true;
846 
847 		if (firstTime)
848 		{
849 			starttime = I_MSTime();
850 			firstTime = false;
851 		}
852 	}
853 
854 	level.starttime = I_MSTime() * TICRATE / 1000;
855 	// [RH] Restore the state of the level.
856 	G_UnSnapshotLevel (!savegamerestore);
857 	// [RH] Do script actions that were triggered on another map.
858 	P_DoDeferedScripts ();
859 	// [AM] Save the state of the level on the first tic.
860 	G_DoSaveResetState();
861 	// [AM] Handle warmup init.
862 	warmup.reset();
863 	//	C_FlushDisplay ();
864 }
865 
866 //
867 // G_WorldDone
868 //
G_WorldDone(void)869 void G_WorldDone (void)
870 {
871 	cluster_info_t *nextcluster;
872 	cluster_info_t *thiscluster;
873 
874 	//gameaction = ga_worlddone;
875 
876 	if (level.flags & LEVEL_CHANGEMAPCHEAT)
877 		return;
878 
879 	const char *finaletext = NULL;
880 	thiscluster = FindClusterInfo (level.cluster);
881 	if (!strncmp (level.nextmap, "EndGame", 7) || (gamemode == retail_chex && !strncmp (level.nextmap, "E1M6", 4))) {
882 //		F_StartFinale (thiscluster->messagemusic, thiscluster->finaleflat, thiscluster->exittext); // denis - fixme - what should happen on the server?
883 		finaletext = thiscluster->exittext;
884 	} else {
885 		if (!secretexit)
886 			nextcluster = FindClusterInfo (FindLevelInfo (level.nextmap)->cluster);
887 		else
888 			nextcluster = FindClusterInfo (FindLevelInfo (level.secretmap)->cluster);
889 
890 		if (nextcluster->cluster != level.cluster && sv_gametype == GM_COOP) {
891 			// Only start the finale if the next level's cluster is different
892 			// than the current one and we're not in deathmatch.
893 			if (nextcluster->entertext) {
894 //				F_StartFinale (nextcluster->messagemusic, nextcluster->finaleflat, nextcluster->entertext); // denis - fixme
895 				finaletext = nextcluster->entertext;
896 			} else if (thiscluster->exittext) {
897 //				F_StartFinale (thiscluster->messagemusic, thiscluster->finaleflat, thiscluster->exittext); // denis - fixme
898 				finaletext = thiscluster->exittext;
899 			}
900 		}
901 	}
902 
903 	if(finaletext)
904 		mapchange += strlen(finaletext)*2;
905 }
906 
907 
908 VERSION_CONTROL (g_level_cpp, "$Id: g_level.cpp 4556 2014-02-10 02:48:10Z dr_sean $")
909