host_cmd.c 37 KB

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