Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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