Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 
     21 #include "quakedef.h"
     22 
     23 extern cvar_t	pausable;
     24 
     25 int	current_skill;
     26 
     27 void Mod_Print (void);
     28 
     29 /*
     30 ==================
     31 Host_Quit_f
     32 ==================
     33 */
     34 
     35 extern void M_Menu_Quit_f (void);
     36 
     37 void Host_Quit();
     38 
     39 void Host_Quit_f (void)
     40 {
     41 	if (key_dest != key_console && cls.state != ca_dedicated)
     42 	{
     43 		M_Menu_Quit_f ();
     44 		return;
     45 	}
     46 	Host_Quit();
     47 }
     48 
     49 void Host_Quit()
     50 {
     51 	CL_Disconnect ();
     52 	Host_ShutdownServer(false);
     53 
     54 	Sys_Quit ();
     55 }
     56 
     57 
     58 /*
     59 ==================
     60 Host_Status_f
     61 ==================
     62 */
     63 void Host_Status_f (void)
     64 {
     65 	client_t	*client;
     66 	int			seconds;
     67 	int			minutes;
     68 	int			hours = 0;
     69 	int			j;
     70 	void		(*print) (const char *fmt, ...);
     71 
     72 	if (cmd_source == src_command)
     73 	{
     74 		if (!sv.active)
     75 		{
     76 			Cmd_ForwardToServer ();
     77 			return;
     78 		}
     79 		print = Con_Printf;
     80 	}
     81 	else
     82 		print = SV_ClientPrintf;
     83 
     84 	print ("host:    %s\n", Cvar_VariableString ("hostname"));
     85 	print ("version: %4.2f\n", VERSION);
     86 	if (tcpipAvailable)
     87 		print ("tcp/ip:  %s\n", my_tcpip_address);
     88 	if (ipxAvailable)
     89 		print ("ipx:     %s\n", my_ipx_address);
     90 	print ("map:     %s\n", sv.name);
     91 	print ("players: %i active (%i max)\n\n", net_activeconnections, svs.maxclients);
     92 	for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
     93 	{
     94 		if (!client->active)
     95 			continue;
     96 		seconds = (int)(net_time - client->netconnection->connecttime);
     97 		minutes = seconds / 60;
     98 		if (minutes)
     99 		{
    100 			seconds -= (minutes * 60);
    101 			hours = minutes / 60;
    102 			if (hours)
    103 				minutes -= (hours * 60);
    104 		}
    105 		else
    106 			hours = 0;
    107 		print ("#%-2u %-16.16s  %3i  %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->u.v.frags, hours, minutes, seconds);
    108 		print ("   %s\n", client->netconnection->address);
    109 	}
    110 }
    111 
    112 
    113 /*
    114 ==================
    115 Host_God_f
    116 
    117 Sets client to godmode
    118 ==================
    119 */
    120 void Host_God_f (void)
    121 {
    122 	if (cmd_source == src_command)
    123 	{
    124 		Cmd_ForwardToServer ();
    125 		return;
    126 	}
    127 
    128 	if (pr_global_struct->deathmatch && !host_client->privileged)
    129 		return;
    130 
    131 	sv_player->u.v.flags = (int)sv_player->u.v.flags ^ FL_GODMODE;
    132 	if (!((int)sv_player->u.v.flags & FL_GODMODE) )
    133 		SV_ClientPrintf ("godmode OFF\n");
    134 	else
    135 		SV_ClientPrintf ("godmode ON\n");
    136 }
    137 
    138 void Host_Notarget_f (void)
    139 {
    140 	if (cmd_source == src_command)
    141 	{
    142 		Cmd_ForwardToServer ();
    143 		return;
    144 	}
    145 
    146 	if (pr_global_struct->deathmatch && !host_client->privileged)
    147 		return;
    148 
    149 	sv_player->u.v.flags = (int)sv_player->u.v.flags ^ FL_NOTARGET;
    150 	if (!((int)sv_player->u.v.flags & FL_NOTARGET) )
    151 		SV_ClientPrintf ("notarget OFF\n");
    152 	else
    153 		SV_ClientPrintf ("notarget ON\n");
    154 }
    155 
    156 qboolean noclip_anglehack;
    157 
    158 void Host_Noclip_f (void)
    159 {
    160 	if (cmd_source == src_command)
    161 	{
    162 		Cmd_ForwardToServer ();
    163 		return;
    164 	}
    165 
    166 	if (pr_global_struct->deathmatch && !host_client->privileged)
    167 		return;
    168 
    169 	if (sv_player->u.v.movetype != MOVETYPE_NOCLIP)
    170 	{
    171 		noclip_anglehack = true;
    172 		sv_player->u.v.movetype = MOVETYPE_NOCLIP;
    173 		SV_ClientPrintf ("noclip ON\n");
    174 	}
    175 	else
    176 	{
    177 		noclip_anglehack = false;
    178 		sv_player->u.v.movetype = MOVETYPE_WALK;
    179 		SV_ClientPrintf ("noclip OFF\n");
    180 	}
    181 }
    182 
    183 /*
    184 ==================
    185 Host_Fly_f
    186 
    187 Sets client to flymode
    188 ==================
    189 */
    190 void Host_Fly_f (void)
    191 {
    192 	if (cmd_source == src_command)
    193 	{
    194 		Cmd_ForwardToServer ();
    195 		return;
    196 	}
    197 
    198 	if (pr_global_struct->deathmatch && !host_client->privileged)
    199 		return;
    200 
    201 	if (sv_player->u.v.movetype != MOVETYPE_FLY)
    202 	{
    203 		sv_player->u.v.movetype = MOVETYPE_FLY;
    204 		SV_ClientPrintf ("flymode ON\n");
    205 	}
    206 	else
    207 	{
    208 		sv_player->u.v.movetype = MOVETYPE_WALK;
    209 		SV_ClientPrintf ("flymode OFF\n");
    210 	}
    211 }
    212 
    213 
    214 /*
    215 ==================
    216 Host_Ping_f
    217 
    218 ==================
    219 */
    220 void Host_Ping_f (void)
    221 {
    222 	int		i, j;
    223 	float	total;
    224 	client_t	*client;
    225 
    226 	if (cmd_source == src_command)
    227 	{
    228 		Cmd_ForwardToServer ();
    229 		return;
    230 	}
    231 
    232 	SV_ClientPrintf ("Client ping times:\n");
    233 	for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
    234 	{
    235 		if (!client->active)
    236 			continue;
    237 		total = 0;
    238 		for (j=0 ; j<NUM_PING_TIMES ; j++)
    239 			total+=client->ping_times[j];
    240 		total /= NUM_PING_TIMES;
    241 		SV_ClientPrintf ("%4i %s\n", (int)(total*1000), client->name);
    242 	}
    243 }
    244 
    245 /*
    246 ===============================================================================
    247 
    248 SERVER TRANSITIONS
    249 
    250 ===============================================================================
    251 */
    252 
    253 
    254 /*
    255 ======================
    256 Host_Map_f
    257 
    258 handle a
    259 map <servername>
    260 command from the console.  Active clients are kicked off.
    261 ======================
    262 */
    263 void Host_Map_f (void)
    264 {
    265 	int		i;
    266 	char	name[MAX_QPATH];
    267 
    268 	if (cmd_source != src_command)
    269 		return;
    270 
    271 	cls.demonum = -1;		// stop demo loop in case this fails
    272 
    273 	CL_Disconnect ();
    274 	Host_ShutdownServer(false);
    275 
    276 	key_dest = key_game;			// remove console or menu
    277 	SCR_BeginLoadingPlaque ();
    278 
    279 	cls.mapstring[0] = 0;
    280 	for (i=0 ; i<Cmd_Argc() ; i++)
    281 	{
    282 		strcat (cls.mapstring, Cmd_Argv(i));
    283 		strcat (cls.mapstring, " ");
    284 	}
    285 	strcat (cls.mapstring, "\n");
    286 
    287 	svs.serverflags = 0;			// haven't completed an episode yet
    288 	strcpy (name, Cmd_Argv(1));
    289 #ifdef QUAKE2
    290 	SV_SpawnServer (name, NULL);
    291 #else
    292 	SV_SpawnServer (name);
    293 #endif
    294 	if (!sv.active)
    295 		return;
    296 
    297 	if (cls.state != ca_dedicated)
    298 	{
    299 		strcpy (cls.spawnparms, "");
    300 
    301 		for (i=2 ; i<Cmd_Argc() ; i++)
    302 		{
    303 			strcat (cls.spawnparms, Cmd_Argv(i));
    304 			strcat (cls.spawnparms, " ");
    305 		}
    306 
    307 		Cmd_ExecuteString2 ("connect local", src_command);
    308 	}
    309 }
    310 
    311 /*
    312 ==================
    313 Host_Changelevel_f
    314 
    315 Goes to a new map, taking all clients along
    316 ==================
    317 */
    318 void Host_Changelevel_f (void)
    319 {
    320 #ifdef QUAKE2
    321 	char	level[MAX_QPATH];
    322 	char	_startspot[MAX_QPATH];
    323 	char	*startspot;
    324 
    325 	if (Cmd_Argc() < 2)
    326 	{
    327 		Con_Printf ("changelevel <levelname> : continue game on a new level\n");
    328 		return;
    329 	}
    330 	if (!sv.active || cls.demoplayback)
    331 	{
    332 		Con_Printf ("Only the server may changelevel\n");
    333 		return;
    334 	}
    335 
    336 	strcpy (level, Cmd_Argv(1));
    337 	if (Cmd_Argc() == 2)
    338 		startspot = NULL;
    339 	else
    340 	{
    341 		strcpy (_startspot, Cmd_Argv(2));
    342 		startspot = _startspot;
    343 	}
    344 
    345 	SV_SaveSpawnparms ();
    346 	SV_SpawnServer (level, startspot);
    347 #else
    348 	char	level[MAX_QPATH];
    349 
    350 	if (Cmd_Argc() != 2)
    351 	{
    352 		Con_Printf ("changelevel <levelname> : continue game on a new level\n");
    353 		return;
    354 	}
    355 	if (!sv.active || cls.demoplayback)
    356 	{
    357 		Con_Printf ("Only the server may changelevel\n");
    358 		return;
    359 	}
    360 	SV_SaveSpawnparms ();
    361 	strcpy (level, Cmd_Argv(1));
    362 	SV_SpawnServer (level);
    363 #endif
    364 }
    365 
    366 /*
    367 ==================
    368 Host_Restart_f
    369 
    370 Restarts the current server for a dead player
    371 ==================
    372 */
    373 void Host_Restart_f (void)
    374 {
    375 	char	mapname[MAX_QPATH];
    376 #ifdef QUAKE2
    377 	char	startspot[MAX_QPATH];
    378 #endif
    379 
    380 	if (cls.demoplayback || !sv.active)
    381 		return;
    382 
    383 	if (cmd_source != src_command)
    384 		return;
    385 	strcpy (mapname, sv.name);	// must copy out, because it gets cleared
    386 								// in sv_spawnserver
    387 #ifdef QUAKE2
    388 	strcpy(startspot, sv.startspot);
    389 	SV_SpawnServer (mapname, startspot);
    390 #else
    391 	SV_SpawnServer (mapname);
    392 #endif
    393 }
    394 
    395 /*
    396 ==================
    397 Host_Reconnect_f
    398 
    399 This command causes the client to wait for the signon messages again.
    400 This is sent just before a server changes levels
    401 ==================
    402 */
    403 void Host_Reconnect_f (void)
    404 {
    405 	SCR_BeginLoadingPlaque ();
    406 	cls.signon = 0;		// need new connection messages
    407 }
    408 
    409 /*
    410 =====================
    411 Host_Connect_f
    412 
    413 User command to connect to server
    414 =====================
    415 */
    416 void Host_Connect_f (void)
    417 {
    418 	char	name[MAX_QPATH];
    419 
    420 	cls.demonum = -1;		// stop demo loop in case this fails
    421 	if (cls.demoplayback)
    422 	{
    423 		CL_StopPlayback ();
    424 		CL_Disconnect ();
    425 	}
    426 	strcpy (name, Cmd_Argv(1));
    427 	CL_EstablishConnection (name);
    428 	Host_Reconnect_f ();
    429 }
    430 
    431 
    432 /*
    433 ===============================================================================
    434 
    435 LOAD / SAVE GAME
    436 
    437 ===============================================================================
    438 */
    439 
    440 #define	SAVEGAME_VERSION	5
    441 
    442 /*
    443 ===============
    444 Host_SavegameComment
    445 
    446 Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current
    447 ===============
    448 */
    449 void Host_SavegameComment (char *text)
    450 {
    451 	int		i;
    452 	char	kills[20];
    453 
    454 	for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
    455 		text[i] = ' ';
    456 	memcpy (text, cl.levelname, strlen(cl.levelname));
    457 	sprintf (kills,"kills:%3i/%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
    458 	memcpy (text+22, kills, strlen(kills));
    459 // convert space to _ to make stdio happy
    460 	for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
    461 		if (text[i] == ' ')
    462 			text[i] = '_';
    463 	text[SAVEGAME_COMMENT_LENGTH] = '\0';
    464 }
    465 
    466 
    467 /*
    468 ===============
    469 Host_Savegame_f
    470 ===============
    471 */
    472 void Host_Savegame_f (void)
    473 {
    474 	char	name[256];
    475 	FILE	*f;
    476 	int		i;
    477 	char	comment[SAVEGAME_COMMENT_LENGTH+1];
    478 
    479 	if (cmd_source != src_command)
    480 		return;
    481 
    482 	if (!sv.active)
    483 	{
    484 		Con_Printf ("Not playing a local game.\n");
    485 		return;
    486 	}
    487 
    488 	if (cl.intermission)
    489 	{
    490 		Con_Printf ("Can't save in intermission.\n");
    491 		return;
    492 	}
    493 
    494 	if (svs.maxclients != 1)
    495 	{
    496 		Con_Printf ("Can't save multiplayer games.\n");
    497 		return;
    498 	}
    499 
    500 	if (Cmd_Argc() != 2)
    501 	{
    502 		Con_Printf ("save <savename> : save a game\n");
    503 		return;
    504 	}
    505 
    506 	if (strstr(Cmd_Argv(1), ".."))
    507 	{
    508 		Con_Printf ("Relative pathnames are not allowed.\n");
    509 		return;
    510 	}
    511 
    512 	for (i=0 ; i<svs.maxclients ; i++)
    513 	{
    514 		if (svs.clients[i].active && (svs.clients[i].edict->u.v.health <= 0) )
    515 		{
    516 			Con_Printf ("Can't savegame with a dead player\n");
    517 			return;
    518 		}
    519 	}
    520 
    521 	sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
    522 	COM_DefaultExtension (name, ".sav");
    523 
    524 	Con_Printf ("Saving game to %s...\n", name);
    525 	f = fopen (name, "w");
    526 	if (!f)
    527 	{
    528 		Con_Printf ("ERROR: couldn't open.\n");
    529 		return;
    530 	}
    531 
    532 	fprintf (f, "%i\n", SAVEGAME_VERSION);
    533 	Host_SavegameComment (comment);
    534 	fprintf (f, "%s\n", comment);
    535 	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
    536 		fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
    537 	fprintf (f, "%d\n", current_skill);
    538 	fprintf (f, "%s\n", sv.name);
    539 	fprintf (f, "%f\n",sv.time);
    540 
    541 // write the light styles
    542 
    543 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
    544 	{
    545 		if (sv.lightstyles[i])
    546 			fprintf (f, "%s\n", sv.lightstyles[i]);
    547 		else
    548 			fprintf (f,"m\n");
    549 	}
    550 
    551 
    552 	ED_WriteGlobals (f);
    553 	for (i=0 ; i<sv.num_edicts ; i++)
    554 	{
    555 		ED_Write (f, EDICT_NUM(i));
    556 		fflush (f);
    557 	}
    558 	fclose (f);
    559 	Con_Printf ("done.\n");
    560 }
    561 
    562 
    563 /*
    564 ===============
    565 Host_Loadgame_f
    566 ===============
    567 */
    568 void Host_Loadgame_f (void)
    569 {
    570 	char	name[MAX_OSPATH];
    571 	FILE	*f;
    572 	char	mapname[MAX_QPATH];
    573 	float	time, tfloat;
    574 	char	str[32768], *start;
    575 	int		i, r;
    576 	edict_t	*ent;
    577 	int		entnum;
    578 	int		version;
    579 	float			spawn_parms[NUM_SPAWN_PARMS];
    580 
    581 	if (cmd_source != src_command)
    582 		return;
    583 
    584 	if (Cmd_Argc() != 2)
    585 	{
    586 		Con_Printf ("load <savename> : load a game\n");
    587 		return;
    588 	}
    589 
    590 	cls.demonum = -1;		// stop demo loop in case this fails
    591 
    592 	sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
    593 	COM_DefaultExtension (name, ".sav");
    594 
    595 // we can't call SCR_BeginLoadingPlaque, because too much stack space has
    596 // been used.  The menu calls it before stuffing loadgame command
    597 //	SCR_BeginLoadingPlaque ();
    598 
    599 	Con_Printf ("Loading game from %s...\n", name);
    600 	f = fopen (name, "r");
    601 	if (!f)
    602 	{
    603 		Con_Printf ("ERROR: couldn't open.\n");
    604 		return;
    605 	}
    606 
    607 	fscanf (f, "%i\n", &version);
    608 	if (version != SAVEGAME_VERSION)
    609 	{
    610 		fclose (f);
    611 		Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
    612 		return;
    613 	}
    614 	fscanf (f, "%s\n", str);
    615 	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
    616 		fscanf (f, "%f\n", &spawn_parms[i]);
    617 // this silliness is so we can load 1.06 save files, which have float skill values
    618 	fscanf (f, "%f\n", &tfloat);
    619 	current_skill = (int)(tfloat + 0.1);
    620 	Cvar_SetValue ("skill", (float)current_skill);
    621 
    622 #ifdef QUAKE2
    623 	Cvar_SetValue ("deathmatch", 0);
    624 	Cvar_SetValue ("coop", 0);
    625 	Cvar_SetValue ("teamplay", 0);
    626 #endif
    627 
    628 	fscanf (f, "%s\n",mapname);
    629 	fscanf (f, "%f\n",&time);
    630 
    631 	CL_Disconnect_f ();
    632 
    633 #ifdef QUAKE2
    634 	SV_SpawnServer (mapname, NULL);
    635 #else
    636 	SV_SpawnServer (mapname);
    637 #endif
    638 	if (!sv.active)
    639 	{
    640 		Con_Printf ("Couldn't load map\n");
    641 		return;
    642 	}
    643 	sv.paused = true;		// pause until all clients connect
    644 	sv.loadgame = true;
    645 
    646 // load the light styles
    647 
    648 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
    649 	{
    650 		fscanf (f, "%s\n", str);
    651 		sv.lightstyles[i] = (char*) Hunk_Alloc (strlen(str)+1);
    652 		strcpy (sv.lightstyles[i], str);
    653 	}
    654 
    655 // load the edicts out of the savegame file
    656 	entnum = -1;		// -1 is the globals
    657 	while (!feof(f))
    658 	{
    659 		for (i=0 ; i< (int) (sizeof(str)-1) ; i++)
    660 		{
    661 			r = fgetc (f);
    662 			if (r == EOF || !r)
    663 				break;
    664 			str[i] = r;
    665 			if (r == '}')
    666 			{
    667 				i++;
    668 				break;
    669 			}
    670 		}
    671 		if (i == sizeof(str)-1)
    672 			Sys_Error ("Loadgame buffer overflow");
    673 		str[i] = 0;
    674 		start = str;
    675 		start = COM_Parse(str);
    676 		if (!com_token[0])
    677 			break;		// end of file
    678 		if (strcmp(com_token,"{"))
    679 			Sys_Error ("First token isn't a brace");
    680 
    681 		if (entnum == -1)
    682 		{	// parse the global vars
    683 			ED_ParseGlobals (start);
    684 		}
    685 		else
    686 		{	// parse an edict
    687 
    688 			ent = EDICT_NUM(entnum);
    689 			memset (&ent->u.v, 0, progs->entityfields * 4);
    690 			ent->free = false;
    691 			ED_ParseEdict (start, ent);
    692 
    693 		// link it into the bsp tree
    694 			if (!ent->free)
    695 				SV_LinkEdict (ent, false);
    696 		}
    697 
    698 		entnum++;
    699 	}
    700 
    701 	sv.num_edicts = entnum;
    702 	sv.time = time;
    703 
    704 	fclose (f);
    705 
    706 	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
    707 		svs.clients->spawn_parms[i] = spawn_parms[i];
    708 
    709 	if (cls.state != ca_dedicated)
    710 	{
    711 		CL_EstablishConnection ("local");
    712 		Host_Reconnect_f ();
    713 	}
    714 }
    715 
    716 #ifdef QUAKE2
    717 void SaveGamestate()
    718 {
    719 	char	name[256];
    720 	FILE	*f;
    721 	int		i;
    722 	char	comment[SAVEGAME_COMMENT_LENGTH+1];
    723 	edict_t	*ent;
    724 
    725 	sprintf (name, "%s/%s.gip", com_gamedir, sv.name);
    726 
    727 	Con_Printf ("Saving game to %s...\n", name);
    728 	f = fopen (name, "w");
    729 	if (!f)
    730 	{
    731 		Con_Printf ("ERROR: couldn't open.\n");
    732 		return;
    733 	}
    734 
    735 	fprintf (f, "%i\n", SAVEGAME_VERSION);
    736 	Host_SavegameComment (comment);
    737 	fprintf (f, "%s\n", comment);
    738 //	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
    739 //		fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
    740 	fprintf (f, "%f\n", skill.value);
    741 	fprintf (f, "%s\n", sv.name);
    742 	fprintf (f, "%f\n", sv.time);
    743 
    744 // write the light styles
    745 
    746 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
    747 	{
    748 		if (sv.lightstyles[i])
    749 			fprintf (f, "%s\n", sv.lightstyles[i]);
    750 		else
    751 			fprintf (f,"m\n");
    752 	}
    753 
    754 
    755 	for (i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
    756 	{
    757 		ent = EDICT_NUM(i);
    758 		if ((int)ent->u.v.flags & FL_ARCHIVE_OVERRIDE)
    759 			continue;
    760 		fprintf (f, "%i\n",i);
    761 		ED_Write (f, ent);
    762 		fflush (f);
    763 	}
    764 	fclose (f);
    765 	Con_Printf ("done.\n");
    766 }
    767 
    768 int LoadGamestate(char *level, char *startspot)
    769 {
    770 	char	name[MAX_OSPATH];
    771 	FILE	*f;
    772 	char	mapname[MAX_QPATH];
    773 	float	time, sk;
    774 	char	str[32768], *start;
    775 	int		i, r;
    776 	edict_t	*ent;
    777 	int		entnum;
    778 	int		version;
    779 //	float	spawn_parms[NUM_SPAWN_PARMS];
    780 
    781 	sprintf (name, "%s/%s.gip", com_gamedir, level);
    782 
    783 	Con_Printf ("Loading game from %s...\n", name);
    784 	f = fopen (name, "r");
    785 	if (!f)
    786 	{
    787 		Con_Printf ("ERROR: couldn't open.\n");
    788 		return -1;
    789 	}
    790 
    791 	fscanf (f, "%i\n", &version);
    792 	if (version != SAVEGAME_VERSION)
    793 	{
    794 		fclose (f);
    795 		Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
    796 		return -1;
    797 	}
    798 	fscanf (f, "%s\n", str);
    799 //	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
    800 //		fscanf (f, "%f\n", &spawn_parms[i]);
    801 	fscanf (f, "%f\n", &sk);
    802 	Cvar_SetValue ("skill", sk);
    803 
    804 	fscanf (f, "%s\n",mapname);
    805 	fscanf (f, "%f\n",&time);
    806 
    807 	SV_SpawnServer (mapname, startspot);
    808 
    809 	if (!sv.active)
    810 	{
    811 		Con_Printf ("Couldn't load map\n");
    812 		return -1;
    813 	}
    814 
    815 // load the light styles
    816 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
    817 	{
    818 		fscanf (f, "%s\n", str);
    819 		sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
    820 		strcpy (sv.lightstyles[i], str);
    821 	}
    822 
    823 // load the edicts out of the savegame file
    824 	while (!feof(f))
    825 	{
    826 		fscanf (f, "%i\n",&entnum);
    827 		for (i=0 ; i<sizeof(str)-1 ; i++)
    828 		{
    829 			r = fgetc (f);
    830 			if (r == EOF || !r)
    831 				break;
    832 			str[i] = r;
    833 			if (r == '}')
    834 			{
    835 				i++;
    836 				break;
    837 			}
    838 		}
    839 		if (i == sizeof(str)-1)
    840 			Sys_Error ("Loadgame buffer overflow");
    841 		str[i] = 0;
    842 		start = str;
    843 		start = COM_Parse(str);
    844 		if (!com_token[0])
    845 			break;		// end of file
    846 		if (strcmp(com_token,"{"))
    847 			Sys_Error ("First token isn't a brace");
    848 
    849 		// parse an edict
    850 
    851 		ent = EDICT_NUM(entnum);
    852 		memset (&ent->v, 0, progs->entityfields * 4);
    853 		ent->free = false;
    854 		ED_ParseEdict (start, ent);
    855 
    856 		// link it into the bsp tree
    857 		if (!ent->free)
    858 			SV_LinkEdict (ent, false);
    859 	}
    860 
    861 //	sv.num_edicts = entnum;
    862 	sv.time = time;
    863 	fclose (f);
    864 
    865 //	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
    866 //		svs.clients->spawn_parms[i] = spawn_parms[i];
    867 
    868 	return 0;
    869 }
    870 
    871 // changing levels within a unit
    872 void Host_Changelevel2_f (void)
    873 {
    874 	char	level[MAX_QPATH];
    875 	char	_startspot[MAX_QPATH];
    876 	char	*startspot;
    877 
    878 	if (Cmd_Argc() < 2)
    879 	{
    880 		Con_Printf ("changelevel2 <levelname> : continue game on a new level in the unit\n");
    881 		return;
    882 	}
    883 	if (!sv.active || cls.demoplayback)
    884 	{
    885 		Con_Printf ("Only the server may changelevel\n");
    886 		return;
    887 	}
    888 
    889 	strcpy (level, Cmd_Argv(1));
    890 	if (Cmd_Argc() == 2)
    891 		startspot = NULL;
    892 	else
    893 	{
    894 		strcpy (_startspot, Cmd_Argv(2));
    895 		startspot = _startspot;
    896 	}
    897 
    898 	SV_SaveSpawnparms ();
    899 
    900 	// save the current level's state
    901 	SaveGamestate ();
    902 
    903 	// try to restore the new level
    904 	if (LoadGamestate (level, startspot))
    905 		SV_SpawnServer (level, startspot);
    906 }
    907 #endif
    908 
    909 
    910 //============================================================================
    911 
    912 /*
    913 ======================
    914 Host_Name_f
    915 ======================
    916 */
    917 void Host_Name_f (void)
    918 {
    919 	char	*newName;
    920 
    921 	if (Cmd_Argc () == 1)
    922 	{
    923 		Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
    924 		return;
    925 	}
    926 	if (Cmd_Argc () == 2)
    927 		newName = Cmd_Argv(1);
    928 	else
    929 		newName = Cmd_Args();
    930 	newName[15] = 0;
    931 
    932 	if (cmd_source == src_command)
    933 	{
    934 		if (Q_strcmp(cl_name.string, newName) == 0)
    935 			return;
    936 		Cvar_Set ("_cl_name", newName);
    937 		if (cls.state == ca_connected)
    938 			Cmd_ForwardToServer ();
    939 		return;
    940 	}
    941 
    942 	if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
    943 		if (Q_strcmp(host_client->name, newName) != 0)
    944 			Con_Printf ("%s renamed to %s\n", host_client->name, newName);
    945 	Q_strcpy (host_client->name, newName);
    946 	host_client->edict->u.v.netname = host_client->name - pr_strings;
    947 
    948 // send notification to all clients
    949 
    950 	MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
    951 	MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
    952 	MSG_WriteString (&sv.reliable_datagram, host_client->name);
    953 }
    954 
    955 
    956 void Host_Version_f (void)
    957 {
    958 	Con_Printf ("Version %4.2f\n", VERSION);
    959 	Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
    960 }
    961 
    962 #ifdef IDGODS
    963 void Host_Please_f (void)
    964 {
    965 	client_t *cl;
    966 	int			j;
    967 
    968 	if (cmd_source != src_command)
    969 		return;
    970 
    971 	if ((Cmd_Argc () == 3) && Q_strcmp(Cmd_Argv(1), "#") == 0)
    972 	{
    973 		j = Q_atof(Cmd_Argv(2)) - 1;
    974 		if (j < 0 || j >= svs.maxclients)
    975 			return;
    976 		if (!svs.clients[j].active)
    977 			return;
    978 		cl = &svs.clients[j];
    979 		if (cl->privileged)
    980 		{
    981 			cl->privileged = false;
    982 			cl->edict->u.v.flags = (int)cl->edict->u.v.flags & ~(FL_GODMODE|FL_NOTARGET);
    983 			cl->edict->u.v.movetype = MOVETYPE_WALK;
    984 			noclip_anglehack = false;
    985 		}
    986 		else
    987 			cl->privileged = true;
    988 	}
    989 
    990 	if (Cmd_Argc () != 2)
    991 		return;
    992 
    993 	for (j=0, cl = svs.clients ; j<svs.maxclients ; j++, cl++)
    994 	{
    995 		if (!cl->active)
    996 			continue;
    997 		if (Q_strcasecmp(cl->name, Cmd_Argv(1)) == 0)
    998 		{
    999 			if (cl->privileged)
   1000 			{
   1001 				cl->privileged = false;
   1002 				cl->edict->u.v.flags = (int)cl->edict->u.v.flags & ~(FL_GODMODE|FL_NOTARGET);
   1003 				cl->edict->u.v.movetype = MOVETYPE_WALK;
   1004 				noclip_anglehack = false;
   1005 			}
   1006 			else
   1007 				cl->privileged = true;
   1008 			break;
   1009 		}
   1010 	}
   1011 }
   1012 #endif
   1013 
   1014 
   1015 void Host_Say(qboolean teamonly)
   1016 {
   1017 	client_t *client;
   1018 	client_t *save;
   1019 	int		j;
   1020 	char	*p;
   1021 	unsigned char	text[64];
   1022 	qboolean	fromServer = false;
   1023 
   1024 	if (cmd_source == src_command)
   1025 	{
   1026 		if (cls.state == ca_dedicated)
   1027 		{
   1028 			fromServer = true;
   1029 			teamonly = false;
   1030 		}
   1031 		else
   1032 		{
   1033 			Cmd_ForwardToServer ();
   1034 			return;
   1035 		}
   1036 	}
   1037 
   1038 	if (Cmd_Argc () < 2)
   1039 		return;
   1040 
   1041 	save = host_client;
   1042 
   1043 	p = Cmd_Args();
   1044 // remove quotes if present
   1045 	if (*p == '"')
   1046 	{
   1047 		p++;
   1048 		p[Q_strlen(p)-1] = 0;
   1049 	}
   1050 
   1051 // turn on color set 1
   1052 	if (!fromServer)
   1053 		sprintf ((char*) text, "%c%s: ", 1, save->name);
   1054 	else
   1055 		sprintf ((char*) text, "%c<%s> ", 1, hostname.string);
   1056 
   1057 	j = sizeof(text) - 2 - Q_strlen((char*) text);  // -2 for /n and null terminator
   1058 	if (Q_strlen((char*) p) > j)
   1059 		p[j] = 0;
   1060 
   1061 	strcat ((char*) text, p);
   1062 	strcat ((char*) text, "\n");
   1063 
   1064 	for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
   1065 	{
   1066 		if (!client || !client->active || !client->spawned)
   1067 			continue;
   1068 		if (teamplay.value && teamonly && client->edict->u.v.team != save->edict->u.v.team)
   1069 			continue;
   1070 		host_client = client;
   1071 		SV_ClientPrintf("%s", text);
   1072 	}
   1073 	host_client = save;
   1074 
   1075 	Sys_Printf("%s", &text[1]);
   1076 }
   1077 
   1078 
   1079 void Host_Say_f(void)
   1080 {
   1081 	Host_Say(false);
   1082 }
   1083 
   1084 
   1085 void Host_Say_Team_f(void)
   1086 {
   1087 	Host_Say(true);
   1088 }
   1089 
   1090 
   1091 void Host_Tell_f(void)
   1092 {
   1093 	client_t *client;
   1094 	client_t *save;
   1095 	int		j;
   1096 	char	*p;
   1097 	char	text[64];
   1098 
   1099 	if (cmd_source == src_command)
   1100 	{
   1101 		Cmd_ForwardToServer ();
   1102 		return;
   1103 	}
   1104 
   1105 	if (Cmd_Argc () < 3)
   1106 		return;
   1107 
   1108 	Q_strcpy(text, host_client->name);
   1109 	Q_strcat(text, ": ");
   1110 
   1111 	p = Cmd_Args();
   1112 
   1113 // remove quotes if present
   1114 	if (*p == '"')
   1115 	{
   1116 		p++;
   1117 		p[Q_strlen(p)-1] = 0;
   1118 	}
   1119 
   1120 // check length & truncate if necessary
   1121 	j = sizeof(text) - 2 - Q_strlen(text);  // -2 for /n and null terminator
   1122 	if (Q_strlen(p) > j)
   1123 		p[j] = 0;
   1124 
   1125 	strcat (text, p);
   1126 	strcat (text, "\n");
   1127 
   1128 	save = host_client;
   1129 	for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
   1130 	{
   1131 		if (!client->active || !client->spawned)
   1132 			continue;
   1133 		if (Q_strcasecmp(client->name, Cmd_Argv(1)))
   1134 			continue;
   1135 		host_client = client;
   1136 		SV_ClientPrintf("%s", text);
   1137 		break;
   1138 	}
   1139 	host_client = save;
   1140 }
   1141 
   1142 
   1143 /*
   1144 ==================
   1145 Host_Color_f
   1146 ==================
   1147 */
   1148 void Host_Color_f(void)
   1149 {
   1150 	int		top, bottom;
   1151 	int		playercolor;
   1152 
   1153 	if (Cmd_Argc() == 1)
   1154 	{
   1155 		Con_Printf ("\"color\" is \"%i %i\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f);
   1156 		Con_Printf ("color <0-13> [0-13]\n");
   1157 		return;
   1158 	}
   1159 
   1160 	if (Cmd_Argc() == 2)
   1161 		top = bottom = atoi(Cmd_Argv(1));
   1162 	else
   1163 	{
   1164 		top = atoi(Cmd_Argv(1));
   1165 		bottom = atoi(Cmd_Argv(2));
   1166 	}
   1167 
   1168 	top &= 15;
   1169 	if (top > 13)
   1170 		top = 13;
   1171 	bottom &= 15;
   1172 	if (bottom > 13)
   1173 		bottom = 13;
   1174 
   1175 	playercolor = top*16 + bottom;
   1176 
   1177 	if (cmd_source == src_command)
   1178 	{
   1179 		Cvar_SetValue ("_cl_color", playercolor);
   1180 		if (cls.state == ca_connected)
   1181 			Cmd_ForwardToServer ();
   1182 		return;
   1183 	}
   1184 
   1185 	host_client->colors = playercolor;
   1186 	host_client->edict->u.v.team = bottom + 1;
   1187 
   1188 // send notification to all clients
   1189 	MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
   1190 	MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
   1191 	MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
   1192 }
   1193 
   1194 /*
   1195 ==================
   1196 Host_Kill_f
   1197 ==================
   1198 */
   1199 void Host_Kill_f (void)
   1200 {
   1201 	if (cmd_source == src_command)
   1202 	{
   1203 		Cmd_ForwardToServer ();
   1204 		return;
   1205 	}
   1206 
   1207 	if (sv_player->u.v.health <= 0)
   1208 	{
   1209 		SV_ClientPrintf ("Can't suicide -- allready dead!\n");
   1210 		return;
   1211 	}
   1212 
   1213 	pr_global_struct->time = sv.time;
   1214 	pr_global_struct->self = EDICT_TO_PROG(sv_player);
   1215 	PR_ExecuteProgram (pr_global_struct->ClientKill);
   1216 }
   1217 
   1218 
   1219 /*
   1220 ==================
   1221 Host_Pause_f
   1222 ==================
   1223 */
   1224 void Host_Pause_f (void)
   1225 {
   1226 
   1227 	if (cmd_source == src_command)
   1228 	{
   1229 		Cmd_ForwardToServer ();
   1230 		return;
   1231 	}
   1232 	if (!pausable.value)
   1233 		SV_ClientPrintf ("Pause not allowed.\n");
   1234 	else
   1235 	{
   1236 		sv.paused ^= 1;
   1237 
   1238 		if (sv.paused)
   1239 		{
   1240 			SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->u.v.netname);
   1241 		}
   1242 		else
   1243 		{
   1244 			SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->u.v.netname);
   1245 		}
   1246 
   1247 	// send notification to all clients
   1248 		MSG_WriteByte (&sv.reliable_datagram, svc_setpause);
   1249 		MSG_WriteByte (&sv.reliable_datagram, sv.paused);
   1250 	}
   1251 }
   1252 
   1253 //===========================================================================
   1254 
   1255 
   1256 /*
   1257 ==================
   1258 Host_PreSpawn_f
   1259 ==================
   1260 */
   1261 void Host_PreSpawn_f (void)
   1262 {
   1263 	if (cmd_source == src_command)
   1264 	{
   1265 		Con_Printf ("prespawn is not valid from the console\n");
   1266 		return;
   1267 	}
   1268 
   1269 	if (host_client->spawned)
   1270 	{
   1271 		Con_Printf ("prespawn not valid -- allready spawned\n");
   1272 		return;
   1273 	}
   1274 
   1275 	SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize);
   1276 	MSG_WriteByte (&host_client->message, svc_signonnum);
   1277 	MSG_WriteByte (&host_client->message, 2);
   1278 	host_client->sendsignon = true;
   1279 }
   1280 
   1281 /*
   1282 ==================
   1283 Host_Spawn_f
   1284 ==================
   1285 */
   1286 void Host_Spawn_f (void)
   1287 {
   1288 	int		i;
   1289 	client_t	*client;
   1290 	edict_t	*ent;
   1291 
   1292 	if (cmd_source == src_command)
   1293 	{
   1294 		Con_Printf ("spawn is not valid from the console\n");
   1295 		return;
   1296 	}
   1297 
   1298 	if (host_client->spawned)
   1299 	{
   1300 		Con_Printf ("Spawn not valid -- allready spawned\n");
   1301 		return;
   1302 	}
   1303 
   1304 // run the entrance script
   1305 	if (sv.loadgame)
   1306 	{	// loaded games are fully inited allready
   1307 		// if this is the last client to be connected, unpause
   1308 		sv.paused = false;
   1309 	}
   1310 	else
   1311 	{
   1312 		// set up the edict
   1313 		ent = host_client->edict;
   1314 
   1315 		memset (&ent->u.v, 0, progs->entityfields * 4);
   1316 		ent->u.v.colormap = NUM_FOR_EDICT(ent);
   1317 		ent->u.v.team = (host_client->colors & 15) + 1;
   1318 		ent->u.v.netname = host_client->name - pr_strings;
   1319 
   1320 		// copy spawn parms out of the client_t
   1321 
   1322 		for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
   1323 			(&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
   1324 
   1325 		// call the spawn function
   1326 
   1327 		pr_global_struct->time = sv.time;
   1328 		pr_global_struct->self = EDICT_TO_PROG(sv_player);
   1329 		PR_ExecuteProgram (pr_global_struct->ClientConnect);
   1330 
   1331 		if ((Sys_FloatTime() - host_client->netconnection->connecttime) <= sv.time)
   1332 			Sys_Printf ("%s entered the game\n", host_client->name);
   1333 
   1334 		PR_ExecuteProgram (pr_global_struct->PutClientInServer);
   1335 	}
   1336 
   1337 
   1338 // send all current names, colors, and frag counts
   1339 	SZ_Clear (&host_client->message);
   1340 
   1341 // send time of update
   1342 	MSG_WriteByte (&host_client->message, svc_time);
   1343 	MSG_WriteFloat (&host_client->message, sv.time);
   1344 
   1345 	for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
   1346 	{
   1347 		MSG_WriteByte (&host_client->message, svc_updatename);
   1348 		MSG_WriteByte (&host_client->message, i);
   1349 		MSG_WriteString (&host_client->message, client->name);
   1350 		MSG_WriteByte (&host_client->message, svc_updatefrags);
   1351 		MSG_WriteByte (&host_client->message, i);
   1352 		MSG_WriteShort (&host_client->message, client->old_frags);
   1353 		MSG_WriteByte (&host_client->message, svc_updatecolors);
   1354 		MSG_WriteByte (&host_client->message, i);
   1355 		MSG_WriteByte (&host_client->message, client->colors);
   1356 	}
   1357 
   1358 // send all current light styles
   1359 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
   1360 	{
   1361 		MSG_WriteByte (&host_client->message, svc_lightstyle);
   1362 		MSG_WriteByte (&host_client->message, (char)i);
   1363 		MSG_WriteString (&host_client->message, sv.lightstyles[i]);
   1364 	}
   1365 
   1366 //
   1367 // send some stats
   1368 //
   1369 	MSG_WriteByte (&host_client->message, svc_updatestat);
   1370 	MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
   1371 	MSG_WriteLong (&host_client->message, (int) pr_global_struct->total_secrets);
   1372 
   1373 	MSG_WriteByte (&host_client->message, svc_updatestat);
   1374 	MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
   1375 	MSG_WriteLong (&host_client->message, (int) pr_global_struct->total_monsters);
   1376 
   1377 	MSG_WriteByte (&host_client->message, svc_updatestat);
   1378 	MSG_WriteByte (&host_client->message, STAT_SECRETS);
   1379 	MSG_WriteLong (&host_client->message, (int) pr_global_struct->found_secrets);
   1380 
   1381 	MSG_WriteByte (&host_client->message, svc_updatestat);
   1382 	MSG_WriteByte (&host_client->message, STAT_MONSTERS);
   1383 	MSG_WriteLong (&host_client->message, (int) pr_global_struct->killed_monsters);
   1384 
   1385 
   1386 //
   1387 // send a fixangle
   1388 // Never send a roll angle, because savegames can catch the server
   1389 // in a state where it is expecting the client to correct the angle
   1390 // and it won't happen if the game was just loaded, so you wind up
   1391 // with a permanent head tilt
   1392 	ent = EDICT_NUM( 1 + (host_client - svs.clients) );
   1393 	MSG_WriteByte (&host_client->message, svc_setangle);
   1394 	for (i=0 ; i < 2 ; i++)
   1395 		MSG_WriteAngle (&host_client->message, ent->u.v.angles[i] );
   1396 	MSG_WriteAngle (&host_client->message, 0 );
   1397 
   1398 	SV_WriteClientdataToMessage (sv_player, &host_client->message);
   1399 
   1400 	MSG_WriteByte (&host_client->message, svc_signonnum);
   1401 	MSG_WriteByte (&host_client->message, 3);
   1402 	host_client->sendsignon = true;
   1403 }
   1404 
   1405 /*
   1406 ==================
   1407 Host_Begin_f
   1408 ==================
   1409 */
   1410 void Host_Begin_f (void)
   1411 {
   1412 	if (cmd_source == src_command)
   1413 	{
   1414 		Con_Printf ("begin is not valid from the console\n");
   1415 		return;
   1416 	}
   1417 
   1418 	host_client->spawned = true;
   1419 }
   1420 
   1421 //===========================================================================
   1422 
   1423 
   1424 /*
   1425 ==================
   1426 Host_Kick_f
   1427 
   1428 Kicks a user off of the server
   1429 ==================
   1430 */
   1431 void Host_Kick_f (void)
   1432 {
   1433 	const char		*who;
   1434 	const char		*message = NULL;
   1435 	client_t	*save;
   1436 	int			i;
   1437 	qboolean	byNumber = false;
   1438 
   1439 	if (cmd_source == src_command)
   1440 	{
   1441 		if (!sv.active)
   1442 		{
   1443 			Cmd_ForwardToServer ();
   1444 			return;
   1445 		}
   1446 	}
   1447 	else if (pr_global_struct->deathmatch && !host_client->privileged)
   1448 		return;
   1449 
   1450 	save = host_client;
   1451 
   1452 	if (Cmd_Argc() > 2 && Q_strcmp(Cmd_Argv(1), "#") == 0)
   1453 	{
   1454 		i = (int) Q_atof(Cmd_Argv(2)) - 1;
   1455 		if (i < 0 || i >= svs.maxclients)
   1456 			return;
   1457 		if (!svs.clients[i].active)
   1458 			return;
   1459 		host_client = &svs.clients[i];
   1460 		byNumber = true;
   1461 	}
   1462 	else
   1463 	{
   1464 		for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
   1465 		{
   1466 			if (!host_client->active)
   1467 				continue;
   1468 			if (Q_strcasecmp(host_client->name, Cmd_Argv(1)) == 0)
   1469 				break;
   1470 		}
   1471 	}
   1472 
   1473 	if (i < svs.maxclients)
   1474 	{
   1475 		if (cmd_source == src_command)
   1476 			if (cls.state == ca_dedicated)
   1477 				who = "Console";
   1478 			else
   1479 				who = cl_name.string;
   1480 		else
   1481 			who = save->name;
   1482 
   1483 		// can't kick yourself!
   1484 		if (host_client == save)
   1485 			return;
   1486 
   1487 		if (Cmd_Argc() > 2)
   1488 		{
   1489 			message = COM_Parse(Cmd_Args());
   1490 			if (byNumber)
   1491 			{
   1492 				message++;							// skip the #
   1493 				while (*message == ' ')				// skip white space
   1494 					message++;
   1495 				message += Q_strlen(Cmd_Argv(2));	// skip the number
   1496 			}
   1497 			while (*message && *message == ' ')
   1498 				message++;
   1499 		}
   1500 		if (message)
   1501 			SV_ClientPrintf ("Kicked by %s: %s\n", who, message);
   1502 		else
   1503 			SV_ClientPrintf ("Kicked by %s\n", who);
   1504 		SV_DropClient (false);
   1505 	}
   1506 
   1507 	host_client = save;
   1508 }
   1509 
   1510 /*
   1511 ===============================================================================
   1512 
   1513 DEBUGGING TOOLS
   1514 
   1515 ===============================================================================
   1516 */
   1517 
   1518 /*
   1519 ==================
   1520 Host_Give_f
   1521 ==================
   1522 */
   1523 void Host_Give_f (void)
   1524 {
   1525 	char	*t;
   1526 	int		v, w;
   1527 	eval_t	*val;
   1528 
   1529 	if (cmd_source == src_command)
   1530 	{
   1531 		Cmd_ForwardToServer ();
   1532 		return;
   1533 	}
   1534 
   1535 	if (pr_global_struct->deathmatch && !host_client->privileged)
   1536 		return;
   1537 
   1538 	t = Cmd_Argv(1);
   1539 	v = atoi (Cmd_Argv(2));
   1540 
   1541 	switch (t[0])
   1542 	{
   1543    case '0':
   1544    case '1':
   1545    case '2':
   1546    case '3':
   1547    case '4':
   1548    case '5':
   1549    case '6':
   1550    case '7':
   1551    case '8':
   1552    case '9':
   1553       // MED 01/04/97 added hipnotic give stuff
   1554       if (hipnotic)
   1555       {
   1556          if (t[0] == '6')
   1557          {
   1558             if (t[1] == 'a')
   1559                sv_player->u.v.items = (int)sv_player->u.v.items | HIT_PROXIMITY_GUN;
   1560             else
   1561                sv_player->u.v.items = (int)sv_player->u.v.items | IT_GRENADE_LAUNCHER;
   1562          }
   1563          else if (t[0] == '9')
   1564             sv_player->u.v.items = (int)sv_player->u.v.items | HIT_LASER_CANNON;
   1565          else if (t[0] == '0')
   1566             sv_player->u.v.items = (int)sv_player->u.v.items | HIT_MJOLNIR;
   1567          else if (t[0] >= '2')
   1568             sv_player->u.v.items = (int)sv_player->u.v.items | (IT_SHOTGUN << (t[0] - '2'));
   1569       }
   1570       else
   1571       {
   1572          if (t[0] >= '2')
   1573             sv_player->u.v.items = (int)sv_player->u.v.items | (IT_SHOTGUN << (t[0] - '2'));
   1574       }
   1575 		break;
   1576 
   1577     case 's':
   1578 		if (rogue)
   1579 		{
   1580 	        val = GetEdictFieldValue(sv_player, "ammo_shells1");
   1581 		    if (val)
   1582 			    val->_float = v;
   1583 		}
   1584 
   1585         sv_player->u.v.ammo_shells = v;
   1586         break;
   1587     case 'n':
   1588 		if (rogue)
   1589 		{
   1590 			val = GetEdictFieldValue(sv_player, "ammo_nails1");
   1591 			if (val)
   1592 			{
   1593 				val->_float = v;
   1594 				if (sv_player->u.v.weapon <= IT_LIGHTNING)
   1595 					sv_player->u.v.ammo_nails = v;
   1596 			}
   1597 		}
   1598 		else
   1599 		{
   1600 			sv_player->u.v.ammo_nails = v;
   1601 		}
   1602         break;
   1603     case 'l':
   1604 		if (rogue)
   1605 		{
   1606 			val = GetEdictFieldValue(sv_player, "ammo_lava_nails");
   1607 			if (val)
   1608 			{
   1609 				val->_float = v;
   1610 				if (sv_player->u.v.weapon > IT_LIGHTNING)
   1611 					sv_player->u.v.ammo_nails = v;
   1612 			}
   1613 		}
   1614         break;
   1615     case 'r':
   1616 		if (rogue)
   1617 		{
   1618 			val = GetEdictFieldValue(sv_player, "ammo_rockets1");
   1619 			if (val)
   1620 			{
   1621 				val->_float = v;
   1622 				if (sv_player->u.v.weapon <= IT_LIGHTNING)
   1623 					sv_player->u.v.ammo_rockets = v;
   1624 			}
   1625 		}
   1626 		else
   1627 		{
   1628 			sv_player->u.v.ammo_rockets = v;
   1629 		}
   1630         break;
   1631     case 'm':
   1632 		if (rogue)
   1633 		{
   1634 			val = GetEdictFieldValue(sv_player, "ammo_multi_rockets");
   1635 			if (val)
   1636 			{
   1637 				val->_float = v;
   1638 				if (sv_player->u.v.weapon > IT_LIGHTNING)
   1639 					sv_player->u.v.ammo_rockets = v;
   1640 			}
   1641 		}
   1642         break;
   1643     case 'h':
   1644         sv_player->u.v.health = v;
   1645         break;
   1646     case 'c':
   1647 		if (rogue)
   1648 		{
   1649 			val = GetEdictFieldValue(sv_player, "ammo_cells1");
   1650 			if (val)
   1651 			{
   1652 				val->_float = v;
   1653 				if (sv_player->u.v.weapon <= IT_LIGHTNING)
   1654 					sv_player->u.v.ammo_cells = v;
   1655 			}
   1656 		}
   1657 		else
   1658 		{
   1659 			sv_player->u.v.ammo_cells = v;
   1660 		}
   1661         break;
   1662     case 'p':
   1663 		if (rogue)
   1664 		{
   1665 			val = GetEdictFieldValue(sv_player, "ammo_plasma");
   1666 			if (val)
   1667 			{
   1668 				val->_float = v;
   1669 				if (sv_player->u.v.weapon > IT_LIGHTNING)
   1670 					sv_player->u.v.ammo_cells = v;
   1671 			}
   1672 		}
   1673         break;
   1674     }
   1675 }
   1676 
   1677 edict_t	*FindViewthing (void)
   1678 {
   1679 	int		i;
   1680 	edict_t	*e;
   1681 
   1682 	for (i=0 ; i<sv.num_edicts ; i++)
   1683 	{
   1684 		e = EDICT_NUM(i);
   1685 		if ( !strcmp (pr_strings + e->u.v.classname, "viewthing") )
   1686 			return e;
   1687 	}
   1688 	Con_Printf ("No viewthing on map\n");
   1689 	return NULL;
   1690 }
   1691 
   1692 /*
   1693 ==================
   1694 Host_Viewmodel_f
   1695 ==================
   1696 */
   1697 void Host_Viewmodel_f (void)
   1698 {
   1699 	edict_t	*e;
   1700 	model_t	*m;
   1701 
   1702 	e = FindViewthing ();
   1703 	if (!e)
   1704 		return;
   1705 
   1706 	m = Mod_ForName (Cmd_Argv(1), false);
   1707 	if (!m)
   1708 	{
   1709 		Con_Printf ("Can't load %s\n", Cmd_Argv(1));
   1710 		return;
   1711 	}
   1712 
   1713 	e->u.v.frame = 0;
   1714 	cl.model_precache[(int)e->u.v.modelindex] = m;
   1715 }
   1716 
   1717 /*
   1718 ==================
   1719 Host_Viewframe_f
   1720 ==================
   1721 */
   1722 void Host_Viewframe_f (void)
   1723 {
   1724 	edict_t	*e;
   1725 	int		f;
   1726 	model_t	*m;
   1727 
   1728 	e = FindViewthing ();
   1729 	if (!e)
   1730 		return;
   1731 	m = cl.model_precache[(int)e->u.v.modelindex];
   1732 
   1733 	f = atoi(Cmd_Argv(1));
   1734 	if (f >= m->numframes)
   1735 		f = m->numframes-1;
   1736 
   1737 	e->u.v.frame = f;
   1738 }
   1739 
   1740 
   1741 void PrintFrameName (model_t *m, int frame)
   1742 {
   1743 	aliashdr_t 			*hdr;
   1744 	maliasframedesc_t	*pframedesc;
   1745 
   1746 	hdr = (aliashdr_t *)Mod_Extradata (m);
   1747 	if (!hdr)
   1748 		return;
   1749 	pframedesc = &hdr->frames[frame];
   1750 
   1751 	Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
   1752 }
   1753 
   1754 /*
   1755 ==================
   1756 Host_Viewnext_f
   1757 ==================
   1758 */
   1759 void Host_Viewnext_f (void)
   1760 {
   1761 	edict_t	*e;
   1762 	model_t	*m;
   1763 
   1764 	e = FindViewthing ();
   1765 	if (!e)
   1766 		return;
   1767 	m = cl.model_precache[(int)e->u.v.modelindex];
   1768 
   1769 	e->u.v.frame = e->u.v.frame + 1;
   1770 	if (e->u.v.frame >= m->numframes)
   1771 		e->u.v.frame = m->numframes - 1;
   1772 
   1773 	PrintFrameName (m, (int) e->u.v.frame);
   1774 }
   1775 
   1776 /*
   1777 ==================
   1778 Host_Viewprev_f
   1779 ==================
   1780 */
   1781 void Host_Viewprev_f (void)
   1782 {
   1783 	edict_t	*e;
   1784 	model_t	*m;
   1785 
   1786 	e = FindViewthing ();
   1787 	if (!e)
   1788 		return;
   1789 
   1790 	m = cl.model_precache[(int)e->u.v.modelindex];
   1791 
   1792 	e->u.v.frame = e->u.v.frame - 1;
   1793 	if (e->u.v.frame < 0)
   1794 		e->u.v.frame = 0;
   1795 
   1796 	PrintFrameName (m, (int) e->u.v.frame);
   1797 }
   1798 
   1799 /*
   1800 ===============================================================================
   1801 
   1802 DEMO LOOP CONTROL
   1803 
   1804 ===============================================================================
   1805 */
   1806 
   1807 
   1808 /*
   1809 ==================
   1810 Host_Startdemos_f
   1811 ==================
   1812 */
   1813 void Host_Startdemos_f (void)
   1814 {
   1815 	int		i, c;
   1816 
   1817 	if (cls.state == ca_dedicated)
   1818 	{
   1819 		if (!sv.active)
   1820 			Cbuf_AddText ("map start\n");
   1821 		return;
   1822 	}
   1823 
   1824 	c = Cmd_Argc() - 1;
   1825 	if (c > MAX_DEMOS)
   1826 	{
   1827 		Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS);
   1828 		c = MAX_DEMOS;
   1829 	}
   1830 	Con_Printf ("%i demo(s) in loop\n", c);
   1831 
   1832 	for (i=1 ; i<c+1 ; i++)
   1833 		strncpy (cls.demos[i-1], Cmd_Argv(i), sizeof(cls.demos[0])-1);
   1834 
   1835 	if (!sv.active && cls.demonum != -1 && !cls.demoplayback)
   1836 	{
   1837 		cls.demonum = 0;
   1838 		CL_NextDemo ();
   1839 	}
   1840 	else
   1841 		cls.demonum = -1;
   1842 }
   1843 
   1844 
   1845 /*
   1846 ==================
   1847 Host_Demos_f
   1848 
   1849 Return to looping demos
   1850 ==================
   1851 */
   1852 void Host_Demos_f (void)
   1853 {
   1854 	if (cls.state == ca_dedicated)
   1855 		return;
   1856 	if (cls.demonum == -1)
   1857 		cls.demonum = 1;
   1858 	CL_Disconnect_f ();
   1859 	CL_NextDemo ();
   1860 }
   1861 
   1862 /*
   1863 ==================
   1864 Host_Stopdemo_f
   1865 
   1866 Return to looping demos
   1867 ==================
   1868 */
   1869 void Host_Stopdemo_f (void)
   1870 {
   1871 	if (cls.state == ca_dedicated)
   1872 		return;
   1873 	if (!cls.demoplayback)
   1874 		return;
   1875 	CL_StopPlayback ();
   1876 	CL_Disconnect ();
   1877 }
   1878 
   1879 //=============================================================================
   1880 
   1881 /*
   1882 ==================
   1883 Host_InitCommands
   1884 ==================
   1885 */
   1886 void Host_InitCommands (void)
   1887 {
   1888 	Cmd_AddCommand ("status", Host_Status_f);
   1889 	Cmd_AddCommand ("quit", Host_Quit_f);
   1890 	Cmd_AddCommand ("god", Host_God_f);
   1891 	Cmd_AddCommand ("notarget", Host_Notarget_f);
   1892 	Cmd_AddCommand ("fly", Host_Fly_f);
   1893 	Cmd_AddCommand ("map", Host_Map_f);
   1894 	Cmd_AddCommand ("restart", Host_Restart_f);
   1895 	Cmd_AddCommand ("changelevel", Host_Changelevel_f);
   1896 #ifdef QUAKE2
   1897 	Cmd_AddCommand ("changelevel2", Host_Changelevel2_f);
   1898 #endif
   1899 	Cmd_AddCommand ("connect", Host_Connect_f);
   1900 	Cmd_AddCommand ("reconnect", Host_Reconnect_f);
   1901 	Cmd_AddCommand ("name", Host_Name_f);
   1902 	Cmd_AddCommand ("noclip", Host_Noclip_f);
   1903 	Cmd_AddCommand ("version", Host_Version_f);
   1904 #ifdef IDGODS
   1905 	Cmd_AddCommand ("please", Host_Please_f);
   1906 #endif
   1907 	Cmd_AddCommand ("say", Host_Say_f);
   1908 	Cmd_AddCommand ("say_team", Host_Say_Team_f);
   1909 	Cmd_AddCommand ("tell", Host_Tell_f);
   1910 	Cmd_AddCommand ("color", Host_Color_f);
   1911 	Cmd_AddCommand ("kill", Host_Kill_f);
   1912 	Cmd_AddCommand ("pause", Host_Pause_f);
   1913 	Cmd_AddCommand ("spawn", Host_Spawn_f);
   1914 	Cmd_AddCommand ("begin", Host_Begin_f);
   1915 	Cmd_AddCommand ("prespawn", Host_PreSpawn_f);
   1916 	Cmd_AddCommand ("kick", Host_Kick_f);
   1917 	Cmd_AddCommand ("ping", Host_Ping_f);
   1918 	Cmd_AddCommand ("load", Host_Loadgame_f);
   1919 	Cmd_AddCommand ("save", Host_Savegame_f);
   1920 	Cmd_AddCommand ("give", Host_Give_f);
   1921 
   1922 	Cmd_AddCommand ("startdemos", Host_Startdemos_f);
   1923 	Cmd_AddCommand ("demos", Host_Demos_f);
   1924 	Cmd_AddCommand ("stopdemo", Host_Stopdemo_f);
   1925 
   1926 	Cmd_AddCommand ("viewmodel", Host_Viewmodel_f);
   1927 	Cmd_AddCommand ("viewframe", Host_Viewframe_f);
   1928 	Cmd_AddCommand ("viewnext", Host_Viewnext_f);
   1929 	Cmd_AddCommand ("viewprev", Host_Viewprev_f);
   1930 
   1931 	Cmd_AddCommand ("mcache", Mod_Print);
   1932 }
   1933