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