Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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