• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Host_Quit_f(void)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 
Host_Quit()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 */
Host_Status_f(void)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 */
Host_God_f(void)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 
Host_Notarget_f(void)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 
Host_Noclip_f(void)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 */
Host_Fly_f(void)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 */
Host_Ping_f(void)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 */
Host_Map_f(void)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 */
Host_Changelevel_f(void)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 */
Host_Restart_f(void)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 */
Host_Reconnect_f(void)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 */
Host_Connect_f(void)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 */
Host_SavegameComment(char * text)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 */
Host_Savegame_f(void)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 */
Host_Loadgame_f(void)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
SaveGamestate()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 
LoadGamestate(char * level,char * startspot)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
Host_Changelevel2_f(void)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 */
Host_Name_f(void)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 
Host_Version_f(void)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
Host_Please_f(void)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 
Host_Say(qboolean teamonly)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 
Host_Say_f(void)1079 void Host_Say_f(void)
1080 {
1081 	Host_Say(false);
1082 }
1083 
1084 
Host_Say_Team_f(void)1085 void Host_Say_Team_f(void)
1086 {
1087 	Host_Say(true);
1088 }
1089 
1090 
Host_Tell_f(void)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 */
Host_Color_f(void)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 */
Host_Kill_f(void)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 */
Host_Pause_f(void)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 */
Host_PreSpawn_f(void)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 */
Host_Spawn_f(void)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 */
Host_Begin_f(void)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 */
Host_Kick_f(void)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 */
Host_Give_f(void)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 
FindViewthing(void)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 */
Host_Viewmodel_f(void)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 */
Host_Viewframe_f(void)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 
PrintFrameName(model_t * m,int frame)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 */
Host_Viewnext_f(void)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 */
Host_Viewprev_f(void)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 */
Host_Startdemos_f(void)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 */
Host_Demos_f(void)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 */
Host_Stopdemo_f(void)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 */
Host_InitCommands(void)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