home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / winquake / host_cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  37.3 KB  |  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.