home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / host_cmd.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  40KB  |  1,939 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. #ifdef AMIGA
  954.   Con_Printf ("Quake%s V%4.2f\n",
  955. #ifdef __PPC__
  956. #ifdef WOS
  957.               "WOS",
  958. #else
  959.               "PPC",
  960. #endif
  961. #else
  962.               "68k",
  963. #endif
  964.               AMIGA_VERSION);
  965. #endif
  966. }
  967.  
  968. #ifdef IDGODS
  969. void Host_Please_f (void)
  970. {
  971.   client_t *cl;
  972.   int     j;
  973.   
  974.   if (cmd_source != src_command)
  975.     return;
  976.  
  977.   if ((Cmd_Argc () == 3) && Q_strcmp(Cmd_Argv(1), "#") == 0)
  978.   {
  979.     j = Q_atof(Cmd_Argv(2)) - 1;
  980.     if (j < 0 || j >= svs.maxclients)
  981.       return;
  982.     if (!svs.clients[j].active)
  983.       return;
  984.     cl = &svs.clients[j];
  985.     if (cl->privileged)
  986.     {
  987.       cl->privileged = false;
  988.       cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
  989.       cl->edict->v.movetype = MOVETYPE_WALK;
  990.       noclip_anglehack = false;
  991.     }
  992.     else
  993.       cl->privileged = true;
  994.   }
  995.  
  996.   if (Cmd_Argc () != 2)
  997.     return;
  998.  
  999.   for (j=0, cl = svs.clients ; j<svs.maxclients ; j++, cl++)
  1000.   {
  1001.     if (!cl->active)
  1002.       continue;
  1003.     if (Q_strcasecmp(cl->name, Cmd_Argv(1)) == 0)
  1004.     {
  1005.       if (cl->privileged)
  1006.       {
  1007.         cl->privileged = false;
  1008.         cl->edict->v.flags = (int)cl->edict->v.flags & ~(FL_GODMODE|FL_NOTARGET);
  1009.         cl->edict->v.movetype = MOVETYPE_WALK;
  1010.         noclip_anglehack = false;
  1011.       }
  1012.       else
  1013.         cl->privileged = true;
  1014.       break;
  1015.     }
  1016.   }
  1017. }
  1018. #endif
  1019.  
  1020.  
  1021. void Host_Say(qboolean teamonly)
  1022. {
  1023.   client_t *client;
  1024.   client_t *save;
  1025.   int   j;
  1026.   char  *p;
  1027.   unsigned char text[64];
  1028.   qboolean  fromServer = false;
  1029.  
  1030.   if (cmd_source == src_command)
  1031.   {
  1032.     if (cls.state == ca_dedicated)
  1033.     {
  1034.       fromServer = true;
  1035.       teamonly = false;
  1036.     }
  1037.     else
  1038.     {
  1039.       Cmd_ForwardToServer ();
  1040.       return;
  1041.     }
  1042.   }
  1043.  
  1044.   if (Cmd_Argc () < 2)
  1045.     return;
  1046.  
  1047.   save = host_client;
  1048.  
  1049.   p = Cmd_Args();
  1050. // remove quotes if present
  1051.   if (*p == '"')
  1052.   {
  1053.     p++;
  1054.     p[Q_strlen(p)-1] = 0;
  1055.   }
  1056.  
  1057. // turn on color set 1
  1058.   if (!fromServer)
  1059.     sprintf (text, "%c%s: ", 1, save->name);
  1060.   else
  1061.     sprintf (text, "%c<%s> ", 1, hostname.string);
  1062.  
  1063.   j = sizeof(text) - 2 - Q_strlen(text);  // -2 for /n and null terminator
  1064.   if (Q_strlen(p) > j)
  1065.     p[j] = 0;
  1066.  
  1067.   strcat (text, p);
  1068.   strcat (text, "\n");
  1069.  
  1070.   for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
  1071.   {
  1072.     if (!client || !client->active || !client->spawned)
  1073.       continue;
  1074.     if (teamplay.value && teamonly && client->edict->v.team != save->edict->v.team)
  1075.       continue;
  1076.     host_client = client;
  1077.     SV_ClientPrintf("%s", text);
  1078.   }
  1079.   host_client = save;
  1080.  
  1081.   Sys_Printf("%s", &text[1]);
  1082. }
  1083.  
  1084.  
  1085. void Host_Say_f(void)
  1086. {
  1087.   Host_Say(false);
  1088. }
  1089.  
  1090.  
  1091. void Host_Say_Team_f(void)
  1092. {
  1093.   Host_Say(true);
  1094. }
  1095.  
  1096.  
  1097. void Host_Tell_f(void)
  1098. {
  1099.   client_t *client;
  1100.   client_t *save;
  1101.   int   j;
  1102.   char  *p;
  1103.   char  text[64];
  1104.  
  1105.   if (cmd_source == src_command)
  1106.   {
  1107.     Cmd_ForwardToServer ();
  1108.     return;
  1109.   }
  1110.  
  1111.   if (Cmd_Argc () < 3)
  1112.     return;
  1113.  
  1114.   Q_strcpy(text, host_client->name);
  1115.   Q_strcat(text, ": ");
  1116.  
  1117.   p = Cmd_Args();
  1118.  
  1119. // remove quotes if present
  1120.   if (*p == '"')
  1121.   {
  1122.     p++;
  1123.     p[Q_strlen(p)-1] = 0;
  1124.   }
  1125.  
  1126. // check length & truncate if necessary
  1127.   j = sizeof(text) - 2 - Q_strlen(text);  // -2 for /n and null terminator
  1128.   if (Q_strlen(p) > j)
  1129.     p[j] = 0;
  1130.  
  1131.   strcat (text, p);
  1132.   strcat (text, "\n");
  1133.  
  1134.   save = host_client;
  1135.   for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++)
  1136.   {
  1137.     if (!client->active || !client->spawned)
  1138.       continue;
  1139.     if (Q_strcasecmp(client->name, Cmd_Argv(1)))
  1140.       continue;
  1141.     host_client = client;
  1142.     SV_ClientPrintf("%s", text);
  1143.     break;
  1144.   }
  1145.   host_client = save;
  1146. }
  1147.  
  1148.  
  1149. /*
  1150. ==================
  1151. Host_Color_f
  1152. ==================
  1153. */
  1154. void Host_Color_f(void)
  1155. {
  1156.   int   top, bottom;
  1157.   int   playercolor;
  1158.   
  1159.   if (Cmd_Argc() == 1)
  1160.   {
  1161.     Con_Printf ("\"color\" is \"%i %i\"\n", ((int)cl_color.value) >> 4, ((int)cl_color.value) & 0x0f);
  1162.     Con_Printf ("color <0-13> [0-13]\n");
  1163.     return;
  1164.   }
  1165.  
  1166.   if (Cmd_Argc() == 2)
  1167.     top = bottom = atoi(Cmd_Argv(1));
  1168.   else
  1169.   {
  1170.     top = atoi(Cmd_Argv(1));
  1171.     bottom = atoi(Cmd_Argv(2));
  1172.   }
  1173.   
  1174.   top &= 15;
  1175.   if (top > 13)
  1176.     top = 13;
  1177.   bottom &= 15;
  1178.   if (bottom > 13)
  1179.     bottom = 13;
  1180.   
  1181.   playercolor = top*16 + bottom;
  1182.  
  1183.   if (cmd_source == src_command)
  1184.   {
  1185.     Cvar_SetValue ("_cl_color", playercolor);
  1186.     if (cls.state == ca_connected)
  1187.       Cmd_ForwardToServer ();
  1188.     return;
  1189.   }
  1190.  
  1191.   host_client->colors = playercolor;
  1192.   host_client->edict->v.team = bottom + 1;
  1193.  
  1194. // send notification to all clients
  1195.   MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
  1196.   MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
  1197.   MSG_WriteByte (&sv.reliable_datagram, host_client->colors);
  1198. }
  1199.  
  1200. /*
  1201. ==================
  1202. Host_Kill_f
  1203. ==================
  1204. */
  1205. void Host_Kill_f (void)
  1206. {
  1207.   if (cmd_source == src_command)
  1208.   {
  1209.     Cmd_ForwardToServer ();
  1210.     return;
  1211.   }
  1212.  
  1213.   if (sv_player->v.health <= 0)
  1214.   {
  1215.     SV_ClientPrintf ("Can't suicide -- allready dead!\n");
  1216.     return;
  1217.   }
  1218.   
  1219.   pr_global_struct->time = sv.time;
  1220.   pr_global_struct->self = EDICT_TO_PROG(sv_player);
  1221.   PR_ExecuteProgram (pr_global_struct->ClientKill);
  1222. }
  1223.  
  1224.  
  1225. /*
  1226. ==================
  1227. Host_Pause_f
  1228. ==================
  1229. */
  1230. void Host_Pause_f (void)
  1231. {
  1232.   
  1233.   if (cmd_source == src_command)
  1234.   {
  1235.     Cmd_ForwardToServer ();
  1236.     return;
  1237.   }
  1238.   if (!pausable.value)
  1239.     SV_ClientPrintf ("Pause not allowed.\n");
  1240.   else
  1241.   {
  1242.     sv.paused ^= 1;
  1243.  
  1244.     if (sv.paused)
  1245.     {
  1246.       SV_BroadcastPrintf ("%s paused the game\n", pr_strings + sv_player->v.netname);
  1247.     }
  1248.     else
  1249.     {
  1250.       SV_BroadcastPrintf ("%s unpaused the game\n",pr_strings + sv_player->v.netname);
  1251.     }
  1252.  
  1253.   // send notification to all clients
  1254.     MSG_WriteByte (&sv.reliable_datagram, svc_setpause);
  1255.     MSG_WriteByte (&sv.reliable_datagram, sv.paused);
  1256.   }
  1257. }
  1258.  
  1259. //===========================================================================
  1260.  
  1261.  
  1262. /*
  1263. ==================
  1264. Host_PreSpawn_f
  1265. ==================
  1266. */
  1267. void Host_PreSpawn_f (void)
  1268. {
  1269.   if (cmd_source == src_command)
  1270.   {
  1271.     Con_Printf ("prespawn is not valid from the console\n");
  1272.     return;
  1273.   }
  1274.  
  1275.   if (host_client->spawned)
  1276.   {
  1277.     Con_Printf ("prespawn not valid -- allready spawned\n");
  1278.     return;
  1279.   }
  1280.   
  1281.   SZ_Write (&host_client->message, sv.signon.data, sv.signon.cursize);
  1282.   MSG_WriteByte (&host_client->message, svc_signonnum);
  1283.   MSG_WriteByte (&host_client->message, 2);
  1284.   host_client->sendsignon = true;
  1285. }
  1286.  
  1287. /*
  1288. ==================
  1289. Host_Spawn_f
  1290. ==================
  1291. */
  1292. void Host_Spawn_f (void)
  1293. {
  1294.   int   i;
  1295.   client_t  *client;
  1296.   edict_t *ent;
  1297.  
  1298.   if (cmd_source == src_command)
  1299.   {
  1300.     Con_Printf ("spawn is not valid from the console\n");
  1301.     return;
  1302.   }
  1303.  
  1304.   if (host_client->spawned)
  1305.   {
  1306.     Con_Printf ("Spawn not valid -- allready spawned\n");
  1307.     return;
  1308.   }
  1309.  
  1310. // run the entrance script
  1311.   if (sv.loadgame)
  1312.   { // loaded games are fully inited allready
  1313.     // if this is the last client to be connected, unpause
  1314.     sv.paused = false;
  1315.   }
  1316.   else
  1317.   {
  1318.     // set up the edict
  1319.     ent = host_client->edict;
  1320.  
  1321.     memset (&ent->v, 0, progs->entityfields * 4);
  1322.     ent->v.colormap = NUM_FOR_EDICT(ent);
  1323.     ent->v.team = (host_client->colors & 15) + 1;
  1324.     ent->v.netname = host_client->name - pr_strings;
  1325.  
  1326.     // copy spawn parms out of the client_t
  1327.  
  1328.     for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
  1329.       (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
  1330.  
  1331.     // call the spawn function
  1332.  
  1333.     pr_global_struct->time = sv.time;
  1334.     pr_global_struct->self = EDICT_TO_PROG(sv_player);
  1335.     PR_ExecuteProgram (pr_global_struct->ClientConnect);
  1336.  
  1337.     if ((Sys_FloatTime() - host_client->netconnection->connecttime) <= sv.time)
  1338.       Sys_Printf ("%s entered the game\n", host_client->name);
  1339.  
  1340.     PR_ExecuteProgram (pr_global_struct->PutClientInServer);  
  1341.   }
  1342.  
  1343.  
  1344. // send all current names, colors, and frag counts
  1345.   SZ_Clear (&host_client->message);
  1346.  
  1347. // send time of update
  1348.   MSG_WriteByte (&host_client->message, svc_time);
  1349.   MSG_WriteFloat (&host_client->message, sv.time);
  1350.  
  1351.   for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++)
  1352.   {
  1353.     MSG_WriteByte (&host_client->message, svc_updatename);
  1354.     MSG_WriteByte (&host_client->message, i);
  1355.     MSG_WriteString (&host_client->message, client->name);
  1356.     MSG_WriteByte (&host_client->message, svc_updatefrags);
  1357.     MSG_WriteByte (&host_client->message, i);
  1358.     MSG_WriteShort (&host_client->message, client->old_frags);
  1359.     MSG_WriteByte (&host_client->message, svc_updatecolors);
  1360.     MSG_WriteByte (&host_client->message, i);
  1361.     MSG_WriteByte (&host_client->message, client->colors);
  1362.   }
  1363.   
  1364. // send all current light styles
  1365.   for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
  1366.   {
  1367.     MSG_WriteByte (&host_client->message, svc_lightstyle);
  1368.     MSG_WriteByte (&host_client->message, (char)i);
  1369.     MSG_WriteString (&host_client->message, sv.lightstyles[i]);
  1370.   }
  1371.  
  1372. //
  1373. // send some stats
  1374. //
  1375.   MSG_WriteByte (&host_client->message, svc_updatestat);
  1376.   MSG_WriteByte (&host_client->message, STAT_TOTALSECRETS);
  1377.   MSG_WriteLong (&host_client->message, pr_global_struct->total_secrets);
  1378.  
  1379.   MSG_WriteByte (&host_client->message, svc_updatestat);
  1380.   MSG_WriteByte (&host_client->message, STAT_TOTALMONSTERS);
  1381.   MSG_WriteLong (&host_client->message, pr_global_struct->total_monsters);
  1382.  
  1383.   MSG_WriteByte (&host_client->message, svc_updatestat);
  1384.   MSG_WriteByte (&host_client->message, STAT_SECRETS);
  1385.   MSG_WriteLong (&host_client->message, pr_global_struct->found_secrets);
  1386.  
  1387.   MSG_WriteByte (&host_client->message, svc_updatestat);
  1388.   MSG_WriteByte (&host_client->message, STAT_MONSTERS);
  1389.   MSG_WriteLong (&host_client->message, pr_global_struct->killed_monsters);
  1390.  
  1391.   
  1392. //
  1393. // send a fixangle
  1394. // Never send a roll angle, because savegames can catch the server
  1395. // in a state where it is expecting the client to correct the angle
  1396. // and it won't happen if the game was just loaded, so you wind up
  1397. // with a permanent head tilt
  1398.   ent = EDICT_NUM( 1 + (host_client - svs.clients) );
  1399.   MSG_WriteByte (&host_client->message, svc_setangle);
  1400.   for (i=0 ; i < 2 ; i++)
  1401.     MSG_WriteAngle (&host_client->message, ent->v.angles[i] );
  1402.   MSG_WriteAngle (&host_client->message, 0 );
  1403.  
  1404.   SV_WriteClientdataToMessage (sv_player, &host_client->message);
  1405.  
  1406.   MSG_WriteByte (&host_client->message, svc_signonnum);
  1407.   MSG_WriteByte (&host_client->message, 3);
  1408.   host_client->sendsignon = true;
  1409. }
  1410.  
  1411. /*
  1412. ==================
  1413. Host_Begin_f
  1414. ==================
  1415. */
  1416. void Host_Begin_f (void)
  1417. {
  1418.   if (cmd_source == src_command)
  1419.   {
  1420.     Con_Printf ("begin is not valid from the console\n");
  1421.     return;
  1422.   }
  1423.  
  1424.   host_client->spawned = true;
  1425. }
  1426.  
  1427. //===========================================================================
  1428.  
  1429.  
  1430. /*
  1431. ==================
  1432. Host_Kick_f
  1433.  
  1434. Kicks a user off of the server
  1435. ==================
  1436. */
  1437. void Host_Kick_f (void)
  1438. {
  1439.   char    *who;
  1440.   char    *message = NULL;
  1441.   client_t  *save;
  1442.   int     i;
  1443.   qboolean  byNumber = false;
  1444.  
  1445.   if (cmd_source == src_command)
  1446.   {
  1447.     if (!sv.active)
  1448.     {
  1449.       Cmd_ForwardToServer ();
  1450.       return;
  1451.     }
  1452.   }
  1453.   else if (pr_global_struct->deathmatch && !host_client->privileged)
  1454.     return;
  1455.  
  1456.   save = host_client;
  1457.  
  1458.   if (Cmd_Argc() > 2 && Q_strcmp(Cmd_Argv(1), "#") == 0)
  1459.   {
  1460.     i = Q_atof(Cmd_Argv(2)) - 1;
  1461.     if (i < 0 || i >= svs.maxclients)
  1462.       return;
  1463.     if (!svs.clients[i].active)
  1464.       return;
  1465.     host_client = &svs.clients[i];
  1466.     byNumber = true;
  1467.   }
  1468.   else
  1469.   {
  1470.     for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
  1471.     {
  1472.       if (!host_client->active)
  1473.         continue;
  1474.       if (Q_strcasecmp(host_client->name, Cmd_Argv(1)) == 0)
  1475.         break;
  1476.     }
  1477.   }
  1478.  
  1479.   if (i < svs.maxclients)
  1480.   {
  1481.     if (cmd_source == src_command)
  1482.       if (cls.state == ca_dedicated)
  1483.         who = "Console";
  1484.       else
  1485.         who = cl_name.string;
  1486.     else
  1487.       who = save->name;
  1488.  
  1489.     // can't kick yourself!
  1490.     if (host_client == save)
  1491.       return;
  1492.  
  1493.     if (Cmd_Argc() > 2)
  1494.     {
  1495.       message = COM_Parse(Cmd_Args());
  1496.       if (byNumber)
  1497.       {
  1498.         message++;              // skip the #
  1499.         while (*message == ' ')       // skip white space
  1500.           message++;
  1501.         message += Q_strlen(Cmd_Argv(2)); // skip the number
  1502.       }
  1503.       while (*message && *message == ' ')
  1504.         message++;
  1505.     }
  1506.     if (message)
  1507.       SV_ClientPrintf ("Kicked by %s: %s\n", who, message);
  1508.     else
  1509.       SV_ClientPrintf ("Kicked by %s\n", who);
  1510.     SV_DropClient (false);
  1511.   }
  1512.  
  1513.   host_client = save;
  1514. }
  1515.  
  1516. /*
  1517. ===============================================================================
  1518.  
  1519. DEBUGGING TOOLS
  1520.  
  1521. ===============================================================================
  1522. */
  1523.  
  1524. /*
  1525. ==================
  1526. Host_Give_f
  1527. ==================
  1528. */
  1529. void Host_Give_f (void)
  1530. {
  1531.   char  *t;
  1532.   int   v, w;
  1533.   eval_t  *val;
  1534.  
  1535.   if (cmd_source == src_command)
  1536.   {
  1537.     Cmd_ForwardToServer ();
  1538.     return;
  1539.   }
  1540.  
  1541.   if (pr_global_struct->deathmatch && !host_client->privileged)
  1542.     return;
  1543.  
  1544.   t = Cmd_Argv(1);
  1545.   v = atoi (Cmd_Argv(2));
  1546.   
  1547.   switch (t[0])
  1548.   {
  1549.    case '0':
  1550.    case '1':
  1551.    case '2':
  1552.    case '3':
  1553.    case '4':
  1554.    case '5':
  1555.    case '6':
  1556.    case '7':
  1557.    case '8':
  1558.    case '9':
  1559.       // MED 01/04/97 added hipnotic give stuff
  1560.       if (hipnotic)
  1561.       {
  1562.          if (t[0] == '6')
  1563.          {
  1564.             if (t[1] == 'a')
  1565.                sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
  1566.             else
  1567.                sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
  1568.          }
  1569.          else if (t[0] == '9')
  1570.             sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
  1571.          else if (t[0] == '0')
  1572.             sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
  1573.          else if (t[0] >= '2')
  1574.             sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
  1575.       }
  1576.       else
  1577.       {
  1578.          if (t[0] >= '2')
  1579.             sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
  1580.       }
  1581.     break;
  1582.   
  1583.     case 's':
  1584.     if (rogue)
  1585.     {
  1586.           val = GetEdictFieldValue(sv_player, "ammo_shells1");
  1587.         if (val)
  1588.           val->_float = v;
  1589.     }
  1590.  
  1591.         sv_player->v.ammo_shells = v;
  1592.         break;    
  1593.     case 'n':
  1594.     if (rogue)
  1595.     {
  1596.       val = GetEdictFieldValue(sv_player, "ammo_nails1");
  1597.       if (val)
  1598.       {
  1599.         val->_float = v;
  1600.         if (sv_player->v.weapon <= IT_LIGHTNING)
  1601.           sv_player->v.ammo_nails = v;
  1602.       }
  1603.     }
  1604.     else
  1605.     {
  1606.       sv_player->v.ammo_nails = v;
  1607.     }
  1608.         break;    
  1609.     case 'l':
  1610.     if (rogue)
  1611.     {
  1612.       val = GetEdictFieldValue(sv_player, "ammo_lava_nails");
  1613.       if (val)
  1614.       {
  1615.         val->_float = v;
  1616.         if (sv_player->v.weapon > IT_LIGHTNING)
  1617.           sv_player->v.ammo_nails = v;
  1618.       }
  1619.     }
  1620.         break;
  1621.     case 'r':
  1622.     if (rogue)
  1623.     {
  1624.       val = GetEdictFieldValue(sv_player, "ammo_rockets1");
  1625.       if (val)
  1626.       {
  1627.         val->_float = v;
  1628.         if (sv_player->v.weapon <= IT_LIGHTNING)
  1629.           sv_player->v.ammo_rockets = v;
  1630.       }
  1631.     }
  1632.     else
  1633.     {
  1634.       sv_player->v.ammo_rockets = v;
  1635.     }
  1636.         break;    
  1637.     case 'm':
  1638.     if (rogue)
  1639.     {
  1640.       val = GetEdictFieldValue(sv_player, "ammo_multi_rockets");
  1641.       if (val)
  1642.       {
  1643.         val->_float = v;
  1644.         if (sv_player->v.weapon > IT_LIGHTNING)
  1645.           sv_player->v.ammo_rockets = v;
  1646.       }
  1647.     }
  1648.         break;    
  1649.     case 'h':
  1650.         sv_player->v.health = v;
  1651.         break;    
  1652.     case 'c':
  1653.     if (rogue)
  1654.     {
  1655.       val = GetEdictFieldValue(sv_player, "ammo_cells1");
  1656.       if (val)
  1657.       {
  1658.         val->_float = v;
  1659.         if (sv_player->v.weapon <= IT_LIGHTNING)
  1660.           sv_player->v.ammo_cells = v;
  1661.       }
  1662.     }
  1663.     else
  1664.     {
  1665.       sv_player->v.ammo_cells = v;
  1666.     }
  1667.         break;    
  1668.     case 'p':
  1669.     if (rogue)
  1670.     {
  1671.       val = GetEdictFieldValue(sv_player, "ammo_plasma");
  1672.       if (val)
  1673.       {
  1674.         val->_float = v;
  1675.         if (sv_player->v.weapon > IT_LIGHTNING)
  1676.           sv_player->v.ammo_cells = v;
  1677.       }
  1678.     }
  1679.         break;    
  1680.     }
  1681. }
  1682.  
  1683. edict_t *FindViewthing (void)
  1684. {
  1685.   int   i;
  1686.   edict_t *e;
  1687.   
  1688.   for (i=0 ; i<sv.num_edicts ; i++)
  1689.   {
  1690.     e = EDICT_NUM(i);
  1691.     if ( !strcmp (pr_strings + e->v.classname, "viewthing") )
  1692.       return e;
  1693.   }
  1694.   Con_Printf ("No viewthing on map\n");
  1695.   return NULL;
  1696. }
  1697.  
  1698. /*
  1699. ==================
  1700. Host_Viewmodel_f
  1701. ==================
  1702. */
  1703. void Host_Viewmodel_f (void)
  1704. {
  1705.   edict_t *e;
  1706.   model_t *m;
  1707.  
  1708.   e = FindViewthing ();
  1709.   if (!e)
  1710.     return;
  1711.  
  1712.   m = Mod_ForName (Cmd_Argv(1), false);
  1713.   if (!m)
  1714.   {
  1715.     Con_Printf ("Can't load %s\n", Cmd_Argv(1));
  1716.     return;
  1717.   }
  1718.   
  1719.   e->v.frame = 0;
  1720.   cl.model_precache[(int)e->v.modelindex] = m;
  1721. }
  1722.  
  1723. /*
  1724. ==================
  1725. Host_Viewframe_f
  1726. ==================
  1727. */
  1728. void Host_Viewframe_f (void)
  1729. {
  1730.   edict_t *e;
  1731.   int   f;
  1732.   model_t *m;
  1733.  
  1734.   e = FindViewthing ();
  1735.   if (!e)
  1736.     return;
  1737.   m = cl.model_precache[(int)e->v.modelindex];
  1738.  
  1739.   f = atoi(Cmd_Argv(1));
  1740.   if (f >= m->numframes)
  1741.     f = m->numframes-1;
  1742.  
  1743.   e->v.frame = f;   
  1744. }
  1745.  
  1746.  
  1747. void PrintFrameName (model_t *m, int frame)
  1748. {
  1749.   aliashdr_t      *hdr;
  1750.   maliasframedesc_t *pframedesc;
  1751.  
  1752.   hdr = (aliashdr_t *)Mod_Extradata (m);
  1753.   if (!hdr)
  1754.     return;
  1755.   pframedesc = &hdr->frames[frame];
  1756.   
  1757.   Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
  1758. }
  1759.  
  1760. /*
  1761. ==================
  1762. Host_Viewnext_f
  1763. ==================
  1764. */
  1765. void Host_Viewnext_f (void)
  1766. {
  1767.   edict_t *e;
  1768.   model_t *m;
  1769.   
  1770.   e = FindViewthing ();
  1771.   if (!e)
  1772.     return;
  1773.   m = cl.model_precache[(int)e->v.modelindex];
  1774.  
  1775.   e->v.frame = e->v.frame + 1;
  1776.   if (e->v.frame >= m->numframes)
  1777.     e->v.frame = m->numframes - 1;
  1778.  
  1779.   PrintFrameName (m, e->v.frame);   
  1780. }
  1781.  
  1782. /*
  1783. ==================
  1784. Host_Viewprev_f
  1785. ==================
  1786. */
  1787. void Host_Viewprev_f (void)
  1788. {
  1789.   edict_t *e;
  1790.   model_t *m;
  1791.  
  1792.   e = FindViewthing ();
  1793.   if (!e)
  1794.     return;
  1795.  
  1796.   m = cl.model_precache[(int)e->v.modelindex];
  1797.  
  1798.   e->v.frame = e->v.frame - 1;
  1799.   if (e->v.frame < 0)
  1800.     e->v.frame = 0;
  1801.  
  1802.   PrintFrameName (m, e->v.frame);   
  1803. }
  1804.  
  1805. /*
  1806. ===============================================================================
  1807.  
  1808. DEMO LOOP CONTROL
  1809.  
  1810. ===============================================================================
  1811. */
  1812.  
  1813.  
  1814. /*
  1815. ==================
  1816. Host_Startdemos_f
  1817. ==================
  1818. */
  1819. void Host_Startdemos_f (void)
  1820. {
  1821.   int   i, c;
  1822.  
  1823.   if (cls.state == ca_dedicated)
  1824.   {
  1825.     if (!sv.active)
  1826.       Cbuf_AddText ("map start\n");
  1827.     return;
  1828.   }
  1829.  
  1830.   c = Cmd_Argc() - 1;
  1831.   if (c > MAX_DEMOS)
  1832.   {
  1833.     Con_Printf ("Max %i demos in demoloop\n", MAX_DEMOS);
  1834.     c = MAX_DEMOS;
  1835.   }
  1836.   Con_Printf ("%i demo(s) in loop\n", c);
  1837.  
  1838.   for (i=1 ; i<c+1 ; i++)
  1839.     strncpy (cls.demos[i-1], Cmd_Argv(i), sizeof(cls.demos[0])-1);
  1840.  
  1841.   if (!sv.active && cls.demonum != -1 && !cls.demoplayback)
  1842.   {
  1843.     cls.demonum = 0;
  1844.     CL_NextDemo ();
  1845.   }
  1846.   else
  1847.     cls.demonum = -1;
  1848. }
  1849.  
  1850.  
  1851. /*
  1852. ==================
  1853. Host_Demos_f
  1854.  
  1855. Return to looping demos
  1856. ==================
  1857. */
  1858. void Host_Demos_f (void)
  1859. {
  1860.   if (cls.state == ca_dedicated)
  1861.     return;
  1862.   if (cls.demonum == -1)
  1863.     cls.demonum = 1;
  1864.   CL_Disconnect_f ();
  1865.   CL_NextDemo ();
  1866. }
  1867.  
  1868. /*
  1869. ==================
  1870. Host_Stopdemo_f
  1871.  
  1872. Return to looping demos
  1873. ==================
  1874. */
  1875. void Host_Stopdemo_f (void)
  1876. {
  1877.   if (cls.state == ca_dedicated)
  1878.     return;
  1879.   if (!cls.demoplayback)
  1880.     return;
  1881.   CL_StopPlayback ();
  1882.   CL_Disconnect ();
  1883. }
  1884.  
  1885. //=============================================================================
  1886.  
  1887. /*
  1888. ==================
  1889. Host_InitCommands
  1890. ==================
  1891. */
  1892. void Host_InitCommands (void)
  1893. {
  1894.   Cmd_AddCommand ("status", Host_Status_f);
  1895.   Cmd_AddCommand ("quit", Host_Quit_f);
  1896.   Cmd_AddCommand ("god", Host_God_f);
  1897.   Cmd_AddCommand ("notarget", Host_Notarget_f);
  1898.   Cmd_AddCommand ("fly", Host_Fly_f);
  1899.   Cmd_AddCommand ("map", Host_Map_f);
  1900.   Cmd_AddCommand ("restart", Host_Restart_f);
  1901.   Cmd_AddCommand ("changelevel", Host_Changelevel_f);
  1902. #ifdef QUAKE2
  1903.   Cmd_AddCommand ("changelevel2", Host_Changelevel2_f);
  1904. #endif
  1905.   Cmd_AddCommand ("connect", Host_Connect_f);
  1906.   Cmd_AddCommand ("reconnect", Host_Reconnect_f);
  1907.   Cmd_AddCommand ("name", Host_Name_f);
  1908.   Cmd_AddCommand ("noclip", Host_Noclip_f);
  1909.   Cmd_AddCommand ("version", Host_Version_f);
  1910. #ifdef IDGODS
  1911.   Cmd_AddCommand ("please", Host_Please_f);
  1912. #endif
  1913.   Cmd_AddCommand ("say", Host_Say_f);
  1914.   Cmd_AddCommand ("say_team", Host_Say_Team_f);
  1915.   Cmd_AddCommand ("tell", Host_Tell_f);
  1916.   Cmd_AddCommand ("color", Host_Color_f);
  1917.   Cmd_AddCommand ("kill", Host_Kill_f);
  1918.   Cmd_AddCommand ("pause", Host_Pause_f);
  1919.   Cmd_AddCommand ("spawn", Host_Spawn_f);
  1920.   Cmd_AddCommand ("begin", Host_Begin_f);
  1921.   Cmd_AddCommand ("prespawn", Host_PreSpawn_f);
  1922.   Cmd_AddCommand ("kick", Host_Kick_f);
  1923.   Cmd_AddCommand ("ping", Host_Ping_f);
  1924.   Cmd_AddCommand ("load", Host_Loadgame_f);
  1925.   Cmd_AddCommand ("save", Host_Savegame_f);
  1926.   Cmd_AddCommand ("give", Host_Give_f);
  1927.  
  1928.   Cmd_AddCommand ("startdemos", Host_Startdemos_f);
  1929.   Cmd_AddCommand ("demos", Host_Demos_f);
  1930.   Cmd_AddCommand ("stopdemo", Host_Stopdemo_f);
  1931.  
  1932.   Cmd_AddCommand ("viewmodel", Host_Viewmodel_f);
  1933.   Cmd_AddCommand ("viewframe", Host_Viewframe_f);
  1934.   Cmd_AddCommand ("viewnext", Host_Viewnext_f);
  1935.   Cmd_AddCommand ("viewprev", Host_Viewprev_f);
  1936.  
  1937.   Cmd_AddCommand ("mcache", Mod_Print);
  1938. }
  1939.