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