pmodel command support for Nehahra multiplayer (select skins/models by one number...
[divverent/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 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<svs.maxclients ; j++, client++)
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<svs.maxclients ; i++, client++)
227         {
228                 if (!client->active)
229                         continue;
230                 total = 0;
231                 for (j=0 ; j<NUM_PING_TIMES ; 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 <servername>
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<Cmd_Argc() ; 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         SV_SpawnServer (name);
283         if (!sv.active)
284                 return;
285         
286         if (cls.state != ca_dedicated)
287         {
288                 strcpy (cls.spawnparms, "");
289
290                 for (i=2 ; i<Cmd_Argc() ; i++)
291                 {
292                         strcat (cls.spawnparms, Cmd_Argv(i));
293                         strcat (cls.spawnparms, " ");
294                 }
295                 
296                 Cmd_ExecuteString ("connect local", src_command);
297         }       
298 }
299
300 /*
301 ==================
302 Host_Changelevel_f
303
304 Goes to a new map, taking all clients along
305 ==================
306 */
307 void Host_Changelevel_f (void)
308 {
309         char    level[MAX_QPATH];
310
311         if (Cmd_Argc() != 2)
312         {
313                 Con_Printf ("changelevel <levelname> : continue game on a new level\n");
314                 return;
315         }
316         if (!sv.active || cls.demoplayback)
317         {
318                 Con_Printf ("Only the server may changelevel\n");
319                 return;
320         }
321         SV_SaveSpawnparms ();
322         strcpy (level, Cmd_Argv(1));
323         SV_SpawnServer (level);
324 }
325
326 /*
327 ==================
328 Host_Restart_f
329
330 Restarts the current server for a dead player
331 ==================
332 */
333 void Host_Restart_f (void)
334 {
335         char    mapname[MAX_QPATH];
336
337         if (cls.demoplayback || !sv.active)
338                 return;
339
340         if (cmd_source != src_command)
341                 return;
342         strcpy (mapname, sv.name);      // must copy out, because it gets cleared
343                                                                 // in sv_spawnserver
344         SV_SpawnServer (mapname);
345 }
346
347 /*
348 ==================
349 Host_Reconnect_f
350
351 This command causes the client to wait for the signon messages again.
352 This is sent just before a server changes levels
353 ==================
354 */
355 void Host_Reconnect_f (void)
356 {
357         SCR_BeginLoadingPlaque ();
358         cls.signon = 0;         // need new connection messages
359 }
360
361 /*
362 =====================
363 Host_Connect_f
364
365 User command to connect to server
366 =====================
367 */
368 void Host_Connect_f (void)
369 {
370         char    name[MAX_QPATH];
371         
372         cls.demonum = -1;               // stop demo loop in case this fails
373         if (cls.demoplayback)
374         {
375                 CL_StopPlayback ();
376                 CL_Disconnect ();
377         }
378         strcpy (name, Cmd_Argv(1));
379         CL_EstablishConnection (name);
380         Host_Reconnect_f ();
381 }
382
383
384 /*
385 ===============================================================================
386
387 LOAD / SAVE GAME
388
389 ===============================================================================
390 */
391
392 #define SAVEGAME_VERSION        5
393
394 /*
395 ===============
396 Host_SavegameComment
397
398 Writes a SAVEGAME_COMMENT_LENGTH character comment describing the current 
399 ===============
400 */
401 void Host_SavegameComment (char *text)
402 {
403         int             i;
404         char    kills[20];
405
406         for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
407                 text[i] = ' ';
408         memcpy (text, cl.levelname, strlen(cl.levelname));
409         sprintf (kills,"kills:%3i/%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
410         memcpy (text+22, kills, strlen(kills));
411 // convert space to _ to make stdio happy
412         for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
413                 if (text[i] == ' ')
414                         text[i] = '_';
415         text[SAVEGAME_COMMENT_LENGTH] = '\0';
416 }
417
418
419 /*
420 ===============
421 Host_Savegame_f
422 ===============
423 */
424 void Host_Savegame_f (void)
425 {
426         char    name[256];
427         FILE    *f;
428         int             i;
429         char    comment[SAVEGAME_COMMENT_LENGTH+1];
430
431         if (cmd_source != src_command)
432                 return;
433
434         if (!sv.active)
435         {
436                 Con_Printf ("Not playing a local game.\n");
437                 return;
438         }
439
440         if (cl.intermission)
441         {
442                 Con_Printf ("Can't save in intermission.\n");
443                 return;
444         }
445
446         if (svs.maxclients != 1)
447         {
448                 Con_Printf ("Can't save multiplayer games.\n");
449                 return;
450         }
451
452         if (Cmd_Argc() != 2)
453         {
454                 Con_Printf ("save <savename> : save a game\n");
455                 return;
456         }
457
458         if (strstr(Cmd_Argv(1), ".."))
459         {
460                 Con_Printf ("Relative pathnames are not allowed.\n");
461                 return;
462         }
463                 
464         for (i=0 ; i<svs.maxclients ; i++)
465         {
466                 if (svs.clients[i].active && (svs.clients[i].edict->v.health <= 0) )
467                 {
468                         Con_Printf ("Can't savegame with a dead player\n");
469                         return;
470                 }
471         }
472
473         sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
474         COM_DefaultExtension (name, ".sav");
475         
476         Con_Printf ("Saving game to %s...\n", name);
477         f = fopen (name, "w");
478         if (!f)
479         {
480                 Con_Printf ("ERROR: couldn't open.\n");
481                 return;
482         }
483         
484         fprintf (f, "%i\n", SAVEGAME_VERSION);
485         Host_SavegameComment (comment);
486         fprintf (f, "%s\n", comment);
487         for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
488                 fprintf (f, "%f\n", svs.clients->spawn_parms[i]);
489         fprintf (f, "%d\n", current_skill);
490         fprintf (f, "%s\n", sv.name);
491         fprintf (f, "%f\n",sv.time);
492
493 // write the light styles
494
495         for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
496         {
497                 if (sv.lightstyles[i])
498                         fprintf (f, "%s\n", sv.lightstyles[i]);
499                 else
500                         fprintf (f,"m\n");
501         }
502
503
504         ED_WriteGlobals (f);
505         for (i=0 ; i<sv.num_edicts ; i++)
506         {
507                 ED_Write (f, EDICT_NUM(i));
508                 fflush (f);
509         }
510         fclose (f);
511         Con_Printf ("done.\n");
512 }
513
514
515 /*
516 ===============
517 Host_Loadgame_f
518 ===============
519 */
520 void Host_Loadgame_f (void)
521 {
522         char    name[MAX_OSPATH];
523         FILE    *f;
524         char    mapname[MAX_QPATH];
525         float   time, tfloat;
526         char    str[32768], *start;
527         int             i, r;
528         edict_t *ent;
529         int             entnum;
530         int             version;
531         float                   spawn_parms[NUM_SPAWN_PARMS];
532
533         if (cmd_source != src_command)
534                 return;
535
536         if (Cmd_Argc() != 2)
537         {
538                 Con_Printf ("load <savename> : load a game\n");
539                 return;
540         }
541
542         cls.demonum = -1;               // stop demo loop in case this fails
543
544         sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
545         COM_DefaultExtension (name, ".sav");
546         
547 // we can't call SCR_BeginLoadingPlaque, because too much stack space has
548 // been used.  The menu calls it before stuffing loadgame command
549 //      SCR_BeginLoadingPlaque ();
550
551         Con_Printf ("Loading game from %s...\n", name);
552         f = fopen (name, "r");
553         if (!f)
554         {
555                 Con_Printf ("ERROR: couldn't open.\n");
556                 return;
557         }
558
559         fscanf (f, "%i\n", &version);
560         if (version != SAVEGAME_VERSION)
561         {
562                 fclose (f);
563                 Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
564                 return;
565         }
566         fscanf (f, "%s\n", str);
567         for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
568                 fscanf (f, "%f\n", &spawn_parms[i]);
569 // this silliness is so we can load 1.06 save files, which have float skill values
570         fscanf (f, "%f\n", &tfloat);
571         current_skill = (int)(tfloat + 0.1);
572         Cvar_SetValue ("skill", (float)current_skill);
573
574         fscanf (f, "%s\n",mapname);
575         fscanf (f, "%f\n",&time);
576
577         CL_Disconnect_f ();
578         
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                 fscanf (f, "%s\n", str);
593                 sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
594                 strcpy (sv.lightstyles[i], str);
595         }
596
597 // load the edicts out of the savegame file
598         entnum = -1;            // -1 is the globals
599         while (!feof(f))
600         {
601                 for (i=0 ; i<sizeof(str)-1 ; i++)
602                 {
603                         r = fgetc (f);
604                         if (r == EOF || !r)
605                                 break;
606                         str[i] = r;
607                         if (r == '}')
608                         {
609                                 i++;
610                                 break;
611                         }
612                 }
613                 if (i == sizeof(str)-1)
614                         Sys_Error ("Loadgame buffer overflow");
615                 str[i] = 0;
616                 start = str;
617                 start = COM_Parse(str);
618                 if (!com_token[0])
619                         break;          // end of file
620                 if (strcmp(com_token,"{"))
621                         Sys_Error ("First token isn't a brace");
622                         
623                 if (entnum == -1)
624                 {       // parse the global vars
625                         ED_ParseGlobals (start);
626                 }
627                 else
628                 {       // parse an edict
629
630                         ent = EDICT_NUM(entnum);
631                         memset (&ent->v, 0, progs->entityfields * 4);
632                         ent->free = false;
633                         ED_ParseEdict (start, ent);
634         
635                 // link it into the bsp tree
636                         if (!ent->free)
637                                 SV_LinkEdict (ent, false);
638                 }
639
640                 entnum++;
641         }
642         
643         sv.num_edicts = entnum;
644         sv.time = time;
645
646         fclose (f);
647
648         for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
649                 svs.clients->spawn_parms[i] = spawn_parms[i];
650
651         if (cls.state != ca_dedicated)
652         {
653                 CL_EstablishConnection ("local");
654                 Host_Reconnect_f ();
655         }
656 }
657
658 //============================================================================
659
660 /*
661 ======================
662 Host_Name_f
663 ======================
664 */
665 void Host_Name_f (void)
666 {
667         char    *newName;
668
669         if (Cmd_Argc () == 1)
670         {
671                 Con_Printf ("\"name\" is \"%s\"\n", cl_name.string);
672                 return;
673         }
674         if (Cmd_Argc () == 2)
675                 newName = Cmd_Argv(1);  
676         else
677                 newName = Cmd_Args();
678         newName[15] = 0;
679
680         if (cmd_source == src_command)
681         {
682                 if (strcmp(cl_name.string, newName) == 0)
683                         return;
684                 Cvar_Set ("_cl_name", newName);
685                 if (cls.state == ca_connected)
686                         Cmd_ForwardToServer ();
687                 return;
688         }
689
690         if (host_client->name[0] && strcmp(host_client->name, "unconnected") )
691                 if (strcmp(host_client->name, newName) != 0)
692                         Con_Printf ("%s renamed to %s\n", host_client->name, newName);
693         strcpy (host_client->name, newName);
694         host_client->edict->v.netname = host_client->name - pr_strings;
695         
696 // send notification to all clients
697         
698         MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
699         MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
700         MSG_WriteString (&sv.reliable_datagram, host_client->name);
701 }
702
703         
704 void Host_Version_f (void)
705 {
706         Con_Printf ("Version %4.2f\n", VERSION);
707         Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
708 }
709
710 #ifdef IDGODS
711 void Host_Please_f (void)
712 {
713         client_t *cl;
714         int                     j;
715         
716         if (cmd_source != src_command)
717                 return;
718
719         if ((Cmd_Argc () == 3) && strcmp(Cmd_Argv(1), "#") == 0)
720         {
721                 j = atof(Cmd_Argv(2)) - 1;
722                 if (j < 0 || j >= svs.maxclients)
723                         return;
724                 if (!svs.clients[j].active)
725                         return;
726                 cl = &svs.clients[j];
727                 if (cl->privileged)
728                 {
729                         cl->privileged = false;
730                         cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
731                         cl->edict->v.movetype = MOVETYPE_WALK;
732                         noclip_anglehack = false;
733                 }
734                 else
735                         cl->privileged = true;
736         }
737
738         if (Cmd_Argc () != 2)
739                 return;
740
741         for (j=0, cl = svs.clients ; j<svs.maxclients ; j++, cl++)
742         {
743                 if (!cl->active)
744                         continue;
745                 if (strcasecmp(cl->name, Cmd_Argv(1)) == 0)
746                 {
747                         if (cl->privileged)
748                         {
749                                 cl->privileged = false;
750                                 cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
751                                 cl->edict->v.movetype = MOVETYPE_WALK;
752                                 noclip_anglehack = false;
753                         }
754                         else
755                                 cl->privileged = true;
756                         break;
757                 }
758         }
759 }
760 #endif
761
762
763 void Host_Say(qboolean teamonly)
764 {
765         client_t *client;
766         client_t *save;
767         int             j;
768         char    *p;
769         // LordHavoc: 256 char say messages
770         unsigned char   text[256];
771         qboolean        fromServer = false;
772
773         if (cmd_source == src_command)
774         {
775                 if (cls.state == ca_dedicated)
776                 {
777                         fromServer = true;
778                         teamonly = false;
779                 }
780                 else
781                 {
782                         Cmd_ForwardToServer ();
783                         return;
784                 }
785         }
786
787         if (Cmd_Argc () < 2)
788                 return;
789
790         save = host_client;
791
792         p = Cmd_Args();
793 // remove quotes if present
794         if (*p == '"')
795         {
796                 p++;
797                 p[strlen(p)-1] = 0;
798         }
799
800 // turn on color set 1
801         if (!fromServer)
802                 sprintf (text, "%c%s: ", 1, save->name);
803         else
804                 sprintf (text, "%c<%s> ", 1, hostname.string);
805
806         j = sizeof(text) - 2 - strlen(text);  // -2 for /n and null terminator
807         if (strlen(p) > j)
808                 p[j] = 0;
809
810         strcat (text, p);
811         strcat (text, "\n");
812
813         for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
814         {
815                 if (!client || !client->active || !client->spawned)
816                         continue;
817                 if (teamplay.value && teamonly && client->edict->v.team != save->edict->v.team)
818                         continue;
819                 host_client = client;
820                 SV_ClientPrintf("%s", text);
821         }
822         host_client = save;
823
824         Sys_Printf("%s", &text[1]);
825 }
826
827
828 void Host_Say_f(void)
829 {
830         Host_Say(false);
831 }
832
833
834 void Host_Say_Team_f(void)
835 {
836         Host_Say(true);
837 }
838
839
840 void Host_Tell_f(void)
841 {
842         client_t *client;
843         client_t *save;
844         int             j;
845         char    *p;
846         char    text[64];
847
848         if (cmd_source == src_command)
849         {
850                 Cmd_ForwardToServer ();
851                 return;
852         }
853
854         if (Cmd_Argc () < 3)
855                 return;
856
857         strcpy(text, host_client->name);
858         strcat(text, ": ");
859
860         p = Cmd_Args();
861
862 // remove quotes if present
863         if (*p == '"')
864         {
865                 p++;
866                 p[strlen(p)-1] = 0;
867         }
868
869 // check length & truncate if necessary
870         j = sizeof(text) - 2 - strlen(text);  // -2 for /n and null terminator
871         if (strlen(p) > j)
872                 p[j] = 0;
873
874         strcat (text, p);
875         strcat (text, "\n");
876
877         save = host_client;
878         for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
879         {
880                 if (!client->active || !client->spawned)
881                         continue;
882                 if (Q_strcasecmp(client->name, Cmd_Argv(1)))
883                         continue;
884                 host_client = client;
885                 SV_ClientPrintf("%s", text);
886                 break;
887         }
888         host_client = save;
889 }
890
891
892 /*
893 ==================
894 Host_Color_f
895 ==================
896 */
897 void Host_Color_f(void)
898 {
899         int             top, bottom;
900         int             playercolor;
901         
902         if (Cmd_Argc() == 1)
903         {
904                 Con_Printf ("\"color\" is \"%i %i\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f);
905                 Con_Printf ("color <0-13> [0-13]\n");
906                 return;
907         }
908
909         if (Cmd_Argc() == 2)
910                 top = bottom = atoi(Cmd_Argv(1));
911         else
912         {
913                 top = atoi(Cmd_Argv(1));
914                 bottom = atoi(Cmd_Argv(2));
915         }
916         
917         top &= 15;
918         // LordHavoc: allow skin colormaps 14 and 15 (was 13)
919         if (top > 15)
920                 top = 15;
921         bottom &= 15;
922         // LordHavoc: allow skin colormaps 14 and 15 (was 13)
923         if (bottom > 15)
924                 bottom = 15;
925         
926         playercolor = top*16 + bottom;
927
928         if (cmd_source == src_command)
929         {
930                 Cvar_SetValue ("_cl_color", playercolor);
931                 if (cls.state == ca_connected)
932                         Cmd_ForwardToServer ();
933                 return;
934         }
935
936         host_client->colors = playercolor;
937         host_client->edict->v.team = bottom + 1;
938
939 // send notification to all clients
940         MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
941         MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
942         MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
943 }
944
945 /*
946 ==================
947 Host_Kill_f
948 ==================
949 */
950 void Host_Kill_f (void)
951 {
952         if (cmd_source == src_command)
953         {
954                 Cmd_ForwardToServer ();
955                 return;
956         }
957
958         if (sv_player->v.health <= 0)
959         {
960                 SV_ClientPrintf ("Can't suicide -- allready dead!\n");
961                 return;
962         }
963         
964         pr_global_struct->time = sv.time;
965         pr_global_struct->self = EDICT_TO_PROG(sv_player);
966         PR_ExecuteProgram (pr_global_struct->ClientKill);
967 }
968
969
970 /*
971 ==================
972 Host_Pause_f
973 ==================
974 */
975 void Host_Pause_f (void)
976 {
977         
978         if (cmd_source == src_command)
979         {
980                 Cmd_ForwardToServer ();
981                 return;
982         }
983         if (!pausable.value)
984                 SV_ClientPrintf ("Pause not allowed.\n");
985         else
986         {
987                 sv.paused ^= 1;
988
989                 if (sv.paused)
990                 {
991                         SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->v.netname);
992                 }
993                 else
994                 {
995                         SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->v.netname);
996                 }
997
998         // send notification to all clients
999                 MSG_WriteByte (&sv.reliable_datagram, svc_setpause);
1000                 MSG_WriteByte (&sv.reliable_datagram, sv.paused);
1001         }
1002 }
1003
1004 //===========================================================================
1005
1006
1007 /*
1008 ==================
1009 Host_PreSpawn_f
1010 ==================
1011 */
1012 void Host_PreSpawn_f (void)
1013 {
1014         if (cmd_source == src_command)
1015         {
1016                 Con_Printf ("prespawn is not valid from the console\n");
1017                 return;
1018         }
1019
1020         if (host_client->spawned)
1021         {
1022                 Con_Printf ("prespawn not valid -- allready spawned\n");
1023                 return;
1024         }
1025         
1026         SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize);
1027         MSG_WriteByte (&host_client->message, svc_signonnum);
1028         MSG_WriteByte (&host_client->message, 2);
1029         host_client->sendsignon = true;
1030 }
1031
1032 dfunction_t *ED_FindFunction (char *name);
1033
1034 /*
1035 ==================
1036 Host_Spawn_f
1037 ==================
1038 */
1039 void Host_Spawn_f (void)
1040 {
1041         int             i;
1042         client_t        *client;
1043         edict_t *ent;
1044         func_t RestoreGame;
1045         dfunction_t *f;
1046
1047         if (cmd_source == src_command)
1048         {
1049                 Con_Printf ("spawn is not valid from the console\n");
1050                 return;
1051         }
1052
1053         if (host_client->spawned)
1054         {
1055                 Con_Printf ("Spawn not valid -- allready spawned\n");
1056                 return;
1057         }
1058
1059 // run the entrance script
1060         if (sv.loadgame)
1061         {       // loaded games are fully inited allready
1062                 // if this is the last client to be connected, unpause
1063                 sv.paused = false;
1064
1065                 if (f = ED_FindFunction ("RestoreGame"))
1066                 if (RestoreGame = (func_t)(f - pr_functions))
1067                 {
1068                         Con_DPrintf("Calling RestoreGame\n");
1069                         pr_global_struct->time = sv.time;
1070                         pr_global_struct->self = EDICT_TO_PROG(sv_player);
1071                         PR_ExecuteProgram (RestoreGame);
1072                 }
1073         }
1074         else
1075         {
1076                 // set up the edict
1077                 ent = host_client->edict;
1078
1079                 memset (&ent->v, 0, progs->entityfields * 4);
1080                 ent->v.colormap = NUM_FOR_EDICT(ent);
1081                 ent->v.team = (host_client->colors & 15) + 1;
1082                 ent->v.netname = host_client->name - pr_strings;
1083
1084                 // copy spawn parms out of the client_t
1085
1086                 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1087                         (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
1088
1089                 // call the spawn function
1090
1091                 pr_global_struct->time = sv.time;
1092                 pr_global_struct->self = EDICT_TO_PROG(sv_player);
1093                 PR_ExecuteProgram (pr_global_struct->ClientConnect);
1094
1095                 if ((Sys_FloatTime() - host_client->netconnection->connecttime) <= sv.time)
1096                         Sys_Printf ("%s entered the game\n", host_client->name);
1097
1098                 PR_ExecuteProgram (pr_global_struct->PutClientInServer);        
1099         }
1100
1101
1102 // send all current names, colors, and frag counts
1103         SZ_Clear (&host_client->message);
1104
1105 // send time of update
1106         MSG_WriteByte (&host_client->message, svc_time);
1107         MSG_WriteFloat (&host_client->message, sv.time);
1108
1109         for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
1110         {
1111                 MSG_WriteByte (&host_client->message, svc_updatename);
1112                 MSG_WriteByte (&host_client->message, i);
1113                 MSG_WriteString (&host_client->message, client->name);
1114                 MSG_WriteByte (&host_client->message, svc_updatefrags);
1115                 MSG_WriteByte (&host_client->message, i);
1116                 MSG_WriteShort (&host_client->message, client->old_frags);
1117                 MSG_WriteByte (&host_client->message, svc_updatecolors);
1118                 MSG_WriteByte (&host_client->message, i);
1119                 MSG_WriteByte (&host_client->message, client->colors);
1120         }
1121         
1122 // send all current light styles
1123         for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
1124         {
1125                 MSG_WriteByte (&host_client->message, svc_lightstyle);
1126                 MSG_WriteByte (&host_client->message, (char)i);
1127                 MSG_WriteString (&host_client->message, sv.lightstyles[i]);
1128         }
1129
1130 //
1131 // send some stats
1132 //
1133         MSG_WriteByte (&host_client->message, svc_updatestat);
1134         MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
1135         MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets);
1136
1137         MSG_WriteByte (&host_client->message, svc_updatestat);
1138         MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
1139         MSG_WriteLong (&host_client->message, pr_global_struct->total_monsters);
1140
1141         MSG_WriteByte (&host_client->message, svc_updatestat);
1142         MSG_WriteByte (&host_client->message, STAT_SECRETS);
1143         MSG_WriteLong (&host_client->message, pr_global_struct->found_secrets);
1144
1145         MSG_WriteByte (&host_client->message, svc_updatestat);
1146         MSG_WriteByte (&host_client->message, STAT_MONSTERS);
1147         MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters);
1148
1149 //
1150 // send a fixangle
1151 // Never send a roll angle, because savegames can catch the server
1152 // in a state where it is expecting the client to correct the angle
1153 // and it won't happen if the game was just loaded, so you wind up
1154 // with a permanent head tilt
1155         ent = EDICT_NUM( 1 + (host_client - svs.clients) );
1156         MSG_WriteByte (&host_client->message, svc_setangle);
1157         for (i=0 ; i < 2 ; i++)
1158                 MSG_WriteAngle (&host_client->message, ent->v.angles[i] );
1159         MSG_WriteAngle (&host_client->message, 0 );
1160
1161         SV_WriteClientdataToMessage (sv_player, &host_client->message);
1162
1163         MSG_WriteByte (&host_client->message, svc_signonnum);
1164         MSG_WriteByte (&host_client->message, 3);
1165         host_client->sendsignon = true;
1166 }
1167
1168 /*
1169 ==================
1170 Host_Begin_f
1171 ==================
1172 */
1173 void Host_Begin_f (void)
1174 {
1175         if (cmd_source == src_command)
1176         {
1177                 Con_Printf ("begin is not valid from the console\n");
1178                 return;
1179         }
1180
1181         host_client->spawned = true;
1182 }
1183
1184 //===========================================================================
1185
1186
1187 /*
1188 ==================
1189 Host_Kick_f
1190
1191 Kicks a user off of the server
1192 ==================
1193 */
1194 void Host_Kick_f (void)
1195 {
1196         char            *who;
1197         char            *message = NULL;
1198         client_t        *save;
1199         int                     i;
1200         qboolean        byNumber = false;
1201
1202         if (cmd_source == src_command)
1203         {
1204                 if (!sv.active)
1205                 {
1206                         Cmd_ForwardToServer ();
1207                         return;
1208                 }
1209         }
1210         else if (pr_global_struct->deathmatch && !host_client->privileged)
1211                 return;
1212
1213         save = host_client;
1214
1215         if (Cmd_Argc() > 2 && strcmp(Cmd_Argv(1), "#") == 0)
1216         {
1217                 i = atof(Cmd_Argv(2)) - 1;
1218                 if (i < 0 || i >= svs.maxclients)
1219                         return;
1220                 if (!svs.clients[i].active)
1221                         return;
1222                 host_client = &svs.clients[i];
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 (Q_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                         if (cls.state == ca_dedicated)
1240                                 who = "Console";
1241                         else
1242                                 who = cl_name.string;
1243                 else
1244                         who = save->name;
1245
1246                 // can't kick yourself!
1247                 if (host_client == save)
1248                         return;
1249
1250                 if (Cmd_Argc() > 2)
1251                 {
1252                         message = COM_Parse(Cmd_Args());
1253                         if (byNumber)
1254                         {
1255                                 message++;                                                      // skip the #
1256                                 while (*message == ' ')                         // skip white space
1257                                         message++;
1258                                 message += strlen(Cmd_Argv(2)); // skip the number
1259                         }
1260                         while (*message && *message == ' ')
1261                                 message++;
1262                 }
1263                 if (message)
1264                         SV_ClientPrintf ("Kicked by %s: %s\n", who, message);
1265                 else
1266                         SV_ClientPrintf ("Kicked by %s\n", who);
1267                 SV_DropClient (false);
1268         }
1269
1270         host_client = save;
1271 }
1272
1273 /*
1274 ===============================================================================
1275
1276 DEBUGGING TOOLS
1277
1278 ===============================================================================
1279 */
1280
1281 /*
1282 ==================
1283 Host_Give_f
1284 ==================
1285 */
1286 void Host_Give_f (void)
1287 {
1288         char    *t;
1289         int             v;
1290         eval_t  *val;
1291
1292         if (cmd_source == src_command)
1293         {
1294                 Cmd_ForwardToServer ();
1295                 return;
1296         }
1297
1298         if (pr_global_struct->deathmatch && !host_client->privileged)
1299                 return;
1300
1301         t = Cmd_Argv(1);
1302         v = atoi (Cmd_Argv(2));
1303         
1304         switch (t[0])
1305         {
1306    case '0':
1307    case '1':
1308    case '2':
1309    case '3':
1310    case '4':
1311    case '5':
1312    case '6':
1313    case '7':
1314    case '8':
1315    case '9':
1316       // MED 01/04/97 added hipnotic give stuff
1317       if (hipnotic)
1318       {
1319          if (t[0] == '6')
1320          {
1321             if (t[1] == 'a')
1322                sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
1323             else
1324                sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
1325          }
1326          else if (t[0] == '9')
1327             sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
1328          else if (t[0] == '0')
1329             sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
1330          else if (t[0] >= '2')
1331             sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
1332       }
1333       else
1334       {
1335          if (t[0] >= '2')
1336             sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
1337       }
1338                 break;
1339         
1340     case 's':
1341                 if (rogue)
1342                 {
1343                     if (val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1))
1344                             val->_float = v;
1345                 }
1346
1347         sv_player->v.ammo_shells = v;
1348         break;          
1349     case 'n':
1350                 if (rogue)
1351                 {
1352                     if (val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1))
1353                         {
1354                             val->_float = v;
1355                                 if (sv_player->v.weapon <= IT_LIGHTNING)
1356                                         sv_player->v.ammo_nails = v;
1357                         }
1358                 }
1359                 else
1360                 {
1361                         sv_player->v.ammo_nails = v;
1362                 }
1363         break;          
1364     case 'l':
1365                 if (rogue)
1366                 {
1367                         val = GETEDICTFIELDVALUE(sv_player, eval_ammo_lava_nails);
1368                         if (val)
1369                         {
1370                                 val->_float = v;
1371                                 if (sv_player->v.weapon > IT_LIGHTNING)
1372                                         sv_player->v.ammo_nails = v;
1373                         }
1374                 }
1375         break;
1376     case 'r':
1377                 if (rogue)
1378                 {
1379                         val = GETEDICTFIELDVALUE(sv_player, eval_ammo_rockets1);
1380                         if (val)
1381                         {
1382                                 val->_float = v;
1383                                 if (sv_player->v.weapon <= IT_LIGHTNING)
1384                                         sv_player->v.ammo_rockets = v;
1385                         }
1386                 }
1387                 else
1388                 {
1389                         sv_player->v.ammo_rockets = v;
1390                 }
1391         break;          
1392     case 'm':
1393                 if (rogue)
1394                 {
1395                         val = GETEDICTFIELDVALUE(sv_player, eval_ammo_multi_rockets);
1396                         if (val)
1397                         {
1398                                 val->_float = v;
1399                                 if (sv_player->v.weapon > IT_LIGHTNING)
1400                                         sv_player->v.ammo_rockets = v;
1401                         }
1402                 }
1403         break;          
1404     case 'h':
1405         sv_player->v.health = v;
1406         break;          
1407     case 'c':
1408                 if (rogue)
1409                 {
1410                         val = GETEDICTFIELDVALUE(sv_player, eval_ammo_cells1);
1411                         if (val)
1412                         {
1413                                 val->_float = v;
1414                                 if (sv_player->v.weapon <= IT_LIGHTNING)
1415                                         sv_player->v.ammo_cells = v;
1416                         }
1417                 }
1418                 else
1419                 {
1420                         sv_player->v.ammo_cells = v;
1421                 }
1422         break;          
1423     case 'p':
1424                 if (rogue)
1425                 {
1426                         val = GETEDICTFIELDVALUE(sv_player, eval_ammo_plasma);
1427                         if (val)
1428                         {
1429                                 val->_float = v;
1430                                 if (sv_player->v.weapon > IT_LIGHTNING)
1431                                         sv_player->v.ammo_cells = v;
1432                         }
1433                 }
1434         break;          
1435     }
1436 }
1437
1438 edict_t *FindViewthing (void)
1439 {
1440         int             i;
1441         edict_t *e;
1442         
1443         for (i=0 ; i<sv.num_edicts ; i++)
1444         {
1445                 e = EDICT_NUM(i);
1446                 if ( !strcmp (pr_strings + e->v.classname, "viewthing") )
1447                         return e;
1448         }
1449         Con_Printf ("No viewthing on map\n");
1450         return NULL;
1451 }
1452
1453 /*
1454 ==================
1455 Host_Viewmodel_f
1456 ==================
1457 */
1458 void Host_Viewmodel_f (void)
1459 {
1460         edict_t *e;
1461         model_t *m;
1462
1463         e = FindViewthing ();
1464         if (!e)
1465                 return;
1466
1467         m = Mod_ForName (Cmd_Argv(1), false);
1468         if (!m)
1469         {
1470                 Con_Printf ("Can't load %s\n", Cmd_Argv(1));
1471                 return;
1472         }
1473         
1474         e->v.frame = 0;
1475         cl.model_precache[(int)e->v.modelindex] = m;
1476 }
1477
1478 /*
1479 ==================
1480 Host_Viewframe_f
1481 ==================
1482 */
1483 void Host_Viewframe_f (void)
1484 {
1485         edict_t *e;
1486         int             f;
1487         model_t *m;
1488
1489         e = FindViewthing ();
1490         if (!e)
1491                 return;
1492         m = cl.model_precache[(int)e->v.modelindex];
1493
1494         f = atoi(Cmd_Argv(1));
1495         if (f >= m->numframes)
1496                 f = m->numframes-1;
1497
1498         e->v.frame = f;         
1499 }
1500
1501
1502 void PrintFrameName (model_t *m, int frame)
1503 {
1504         aliashdr_t                      *hdr;
1505         maliasframedesc_t       *pframedesc;
1506
1507         hdr = (aliashdr_t *)Mod_Extradata (m);
1508         if (!hdr)
1509                 return;
1510         pframedesc = &hdr->frames[frame];
1511         
1512         Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
1513 }
1514
1515 /*
1516 ==================
1517 Host_Viewnext_f
1518 ==================
1519 */
1520 void Host_Viewnext_f (void)
1521 {
1522         edict_t *e;
1523         model_t *m;
1524         
1525         e = FindViewthing ();
1526         if (!e)
1527                 return;
1528         m = cl.model_precache[(int)e->v.modelindex];
1529
1530         e->v.frame = e->v.frame + 1;
1531         if (e->v.frame >= m->numframes)
1532                 e->v.frame = m->numframes - 1;
1533
1534         PrintFrameName (m, e->v.frame);         
1535 }
1536
1537 /*
1538 ==================
1539 Host_Viewprev_f
1540 ==================
1541 */
1542 void Host_Viewprev_f (void)
1543 {
1544         edict_t *e;
1545         model_t *m;
1546
1547         e = FindViewthing ();
1548         if (!e)
1549                 return;
1550
1551         m = cl.model_precache[(int)e->v.modelindex];
1552
1553         e->v.frame = e->v.frame - 1;
1554         if (e->v.frame < 0)
1555                 e->v.frame = 0;
1556
1557         PrintFrameName (m, e->v.frame);         
1558 }
1559
1560 /*
1561 ===============================================================================
1562
1563 DEMO LOOP CONTROL
1564
1565 ===============================================================================
1566 */
1567
1568
1569 /*
1570 ==================
1571 Host_Startdemos_f
1572 ==================
1573 */
1574 void Host_Startdemos_f (void)
1575 {
1576         int             i, c;
1577
1578         if (cls.state == ca_dedicated)
1579         {
1580                 if (!sv.active)
1581                         Cbuf_AddText ("map start\n");
1582                 return;
1583         }
1584
1585         c = Cmd_Argc() - 1;
1586         if (c > MAX_DEMOS)
1587         {
1588                 Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS);
1589                 c = MAX_DEMOS;
1590         }
1591         Con_Printf ("%i demo(s) in loop\n", c);
1592
1593         for (i=1 ; i<c+1 ; i++)
1594                 strncpy (cls.demos[i-1], Cmd_Argv(i), sizeof(cls.demos[0])-1);
1595
1596         if (!sv.active && cls.demonum != -1 && !cls.demoplayback)
1597         {
1598                 cls.demonum = 0;
1599                 CL_NextDemo ();
1600         }
1601         else
1602                 cls.demonum = -1;
1603 }
1604
1605
1606 /*
1607 ==================
1608 Host_Demos_f
1609
1610 Return to looping demos
1611 ==================
1612 */
1613 void Host_Demos_f (void)
1614 {
1615         if (cls.state == ca_dedicated)
1616                 return;
1617         if (cls.demonum == -1)
1618                 cls.demonum = 1;
1619         CL_Disconnect_f ();
1620         CL_NextDemo ();
1621 }
1622
1623 /*
1624 ==================
1625 Host_Stopdemo_f
1626
1627 Return to looping demos
1628 ==================
1629 */
1630 void Host_Stopdemo_f (void)
1631 {
1632         if (cls.state == ca_dedicated)
1633                 return;
1634         if (!cls.demoplayback)
1635                 return;
1636         CL_StopPlayback ();
1637         CL_Disconnect ();
1638 }
1639
1640 /*
1641 ======================
1642 Host_PModel_f
1643 LordHavoc: Intended for Nehahra, I personally think this is dumb, but Mindcrime won't listen.
1644 ======================
1645 */
1646 void Host_PModel_f (void)
1647 {
1648         int i;
1649         eval_t *val;
1650
1651         if (Cmd_Argc () == 1)
1652         {
1653                 Con_Printf ("usage: pmodel modelnumber\n");
1654                 return;
1655         }
1656         i = atoi(Cmd_Argv(1));
1657
1658         if (cmd_source == src_command)
1659         {
1660                 if (cls.state == ca_connected)
1661                         Cmd_ForwardToServer ();
1662                 return;
1663         }
1664
1665         if (val = GETEDICTFIELDVALUE(host_client->edict, eval_pmodel))
1666                 val->_float = i;
1667 }
1668
1669 //=============================================================================
1670
1671 /*
1672 ==================
1673 Host_InitCommands
1674 ==================
1675 */
1676 void Host_InitCommands (void)
1677 {
1678         Cmd_AddCommand ("status", Host_Status_f);
1679         Cmd_AddCommand ("quit", Host_Quit_f);
1680         if (nehahra)
1681         {
1682                 Cmd_AddCommand ("max", Host_God_f);
1683                 Cmd_AddCommand ("monster", Host_Notarget_f);
1684                 Cmd_AddCommand ("scrag", Host_Fly_f);
1685                 Cmd_AddCommand ("wraith", Host_Noclip_f);
1686                 Cmd_AddCommand ("gimme", Host_Give_f);
1687         }
1688         else
1689         {
1690                 Cmd_AddCommand ("god", Host_God_f);
1691                 Cmd_AddCommand ("notarget", Host_Notarget_f);
1692                 Cmd_AddCommand ("fly", Host_Fly_f);
1693                 Cmd_AddCommand ("noclip", Host_Noclip_f);
1694                 Cmd_AddCommand ("give", Host_Give_f);
1695         }
1696         Cmd_AddCommand ("map", Host_Map_f);
1697         Cmd_AddCommand ("restart", Host_Restart_f);
1698         Cmd_AddCommand ("changelevel", Host_Changelevel_f);
1699         Cmd_AddCommand ("connect", Host_Connect_f);
1700         Cmd_AddCommand ("reconnect", Host_Reconnect_f);
1701         Cmd_AddCommand ("name", Host_Name_f);
1702         Cmd_AddCommand ("version", Host_Version_f);
1703 #ifdef IDGODS
1704         Cmd_AddCommand ("please", Host_Please_f);
1705 #endif
1706         Cmd_AddCommand ("say", Host_Say_f);
1707         Cmd_AddCommand ("say_team", Host_Say_Team_f);
1708         Cmd_AddCommand ("tell", Host_Tell_f);
1709         Cmd_AddCommand ("color", Host_Color_f);
1710         Cmd_AddCommand ("kill", Host_Kill_f);
1711         Cmd_AddCommand ("pause", Host_Pause_f);
1712         Cmd_AddCommand ("spawn", Host_Spawn_f);
1713         Cmd_AddCommand ("begin", Host_Begin_f);
1714         Cmd_AddCommand ("prespawn", Host_PreSpawn_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         Cmd_AddCommand ("pmodel", Host_PModel_f);
1720
1721         Cmd_AddCommand ("startdemos", Host_Startdemos_f);
1722         Cmd_AddCommand ("demos", Host_Demos_f);
1723         Cmd_AddCommand ("stopdemo", Host_Stopdemo_f);
1724
1725         Cmd_AddCommand ("viewmodel", Host_Viewmodel_f);
1726         Cmd_AddCommand ("viewframe", Host_Viewframe_f);
1727         Cmd_AddCommand ("viewnext", Host_Viewnext_f);
1728         Cmd_AddCommand ("viewprev", Host_Viewprev_f);
1729
1730         Cmd_AddCommand ("mcache", Mod_Print);
1731 }