home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / glquake_src / host_cmd.c < prev    next >
C/C++ Source or Header  |  1999-12-28  |  40KB  |  1,926 lines

  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.