m_cheat.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2002 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * Cheat sequence checking.
  31. *
  32. *-----------------------------------------------------------------------------*/
  33. #include "doomstat.h"
  34. #include "g_game.h"
  35. #include "r_data.h"
  36. #include "p_inter.h"
  37. #include "p_tick.h"
  38. #include "m_cheat.h"
  39. #include "m_argv.h"
  40. #include "s_sound.h"
  41. #include "sounds.h"
  42. #include "dstrings.h"
  43. #include "r_main.h"
  44. #include "p_map.h"
  45. #include "d_deh.h" // Ty 03/27/98 - externalized strings
  46. /* cph 2006/07/23 - needs direct access to thinkercap */
  47. #include "p_tick.h"
  48. #define plyr (players+consoleplayer) /* the console player */
  49. //e6y: for speedup
  50. static int boom_cheat_route[MAX_COMPATIBILITY_LEVEL];
  51. //-----------------------------------------------------------------------------
  52. //
  53. // CHEAT SEQUENCE PACKAGE
  54. //
  55. //-----------------------------------------------------------------------------
  56. static void cheat_mus();
  57. static void cheat_choppers();
  58. static void cheat_god();
  59. static void cheat_fa();
  60. static void cheat_k();
  61. static void cheat_kfa();
  62. static void cheat_noclip();
  63. static void cheat_pw();
  64. static void cheat_behold();
  65. static void cheat_clev();
  66. static void cheat_mypos();
  67. static void cheat_rate();
  68. static void cheat_comp();
  69. static void cheat_friction();
  70. static void cheat_pushers();
  71. static void cheat_tnttran();
  72. static void cheat_massacre();
  73. static void cheat_ddt();
  74. static void cheat_hom();
  75. static void cheat_fast();
  76. static void cheat_tntkey();
  77. static void cheat_tntkeyx();
  78. static void cheat_tntkeyxx();
  79. static void cheat_tntweap();
  80. static void cheat_tntweapx();
  81. static void cheat_tntammo();
  82. static void cheat_tntammox();
  83. static void cheat_smart();
  84. static void cheat_pitch();
  85. static void cheat_megaarmour();
  86. static void cheat_health();
  87. static void cheat_notarget();
  88. static void cheat_fly();
  89. //-----------------------------------------------------------------------------
  90. //
  91. // List of cheat codes, functions, and special argument indicators.
  92. //
  93. // The first argument is the cheat code.
  94. //
  95. // The second argument is its DEH name, or NULL if it's not supported by -deh.
  96. //
  97. // The third argument is a combination of the bitmasks:
  98. // {always, not_dm, not_coop, not_net, not_menu, not_demo, not_deh},
  99. // which excludes the cheat during certain modes of play.
  100. //
  101. // The fourth argument is the handler function.
  102. //
  103. // The fifth argument is passed to the handler function if it's non-negative;
  104. // if negative, then its negative indicates the number of extra characters
  105. // expected after the cheat code, which are passed to the handler function
  106. // via a pointer to a buffer (after folding any letters to lowercase).
  107. //
  108. //-----------------------------------------------------------------------------
  109. cheatseq_t cheat[] = {
  110. CHEAT("idmus", "Change music", always, cheat_mus, -2),
  111. CHEAT("idchoppers", "Chainsaw", cht_never, cheat_choppers, 0),
  112. CHEAT("iddqd", "God mode", cht_never, cheat_god, 0),
  113. CHEAT("idkfa", "Ammo & Keys", cht_never, cheat_kfa, 0),
  114. CHEAT("idfa", "Ammo", cht_never, cheat_fa, 0),
  115. CHEAT("idspispopd", "No Clipping 1", cht_never, cheat_noclip, 0),
  116. CHEAT("idclip", "No Clipping 2", cht_never, cheat_noclip, 0),
  117. CHEAT("idbeholdh", "Invincibility", cht_never, cheat_health, 0),
  118. CHEAT("idbeholdm", "Invincibility", cht_never, cheat_megaarmour, 0),
  119. CHEAT("idbeholdv", "Invincibility", cht_never, cheat_pw, pw_invulnerability),
  120. CHEAT("idbeholds", "Berserk", cht_never, cheat_pw, pw_strength),
  121. CHEAT("idbeholdi", "Invisibility", cht_never, cheat_pw, pw_invisibility),
  122. CHEAT("idbeholdr", "Radiation Suit", cht_never, cheat_pw, pw_ironfeet),
  123. CHEAT("idbeholda", "Auto-map", not_dm, cheat_pw, pw_allmap),
  124. CHEAT("idbeholdl", "Lite-Amp Goggles", not_dm, cheat_pw, pw_infrared),
  125. CHEAT("idbehold", "BEHOLD menu", not_dm, cheat_behold, 0),
  126. CHEAT("idclev", "Level Warp", cht_never | not_menu, cheat_clev, -2),
  127. CHEAT("idmypos", "Player Position", not_dm, cheat_mypos, 0),
  128. CHEAT("idrate", "Frame rate", always, cheat_rate, 0),
  129. // phares
  130. CHEAT("tntcomp", NULL, cht_never, cheat_comp, 0),
  131. // jff 2/01/98 kill all monsters
  132. CHEAT("tntem", NULL, cht_never, cheat_massacre, 0),
  133. // killough 2/07/98: moved from am_map.c
  134. CHEAT("iddt", "Map cheat", not_dm, cheat_ddt, 0),
  135. // killough 2/07/98: HOM autodetector
  136. CHEAT("tnthom", NULL, always, cheat_hom, 0),
  137. // killough 2/16/98: generalized key cheats
  138. CHEAT("tntkey", NULL, cht_never, cheat_tntkey, 0),
  139. CHEAT("tntkeyr", NULL, cht_never, cheat_tntkeyx, 0),
  140. CHEAT("tntkeyy", NULL, cht_never, cheat_tntkeyx, 0),
  141. CHEAT("tntkeyb", NULL, cht_never, cheat_tntkeyx, 0),
  142. CHEAT("tntkeyrc", NULL, cht_never, cheat_tntkeyxx, it_redcard),
  143. CHEAT("tntkeyyc", NULL, cht_never, cheat_tntkeyxx, it_yellowcard),
  144. CHEAT("tntkeybc", NULL, cht_never, cheat_tntkeyxx, it_bluecard),
  145. CHEAT("tntkeyrs", NULL, cht_never, cheat_tntkeyxx, it_redskull),
  146. CHEAT("tntkeyys", NULL, cht_never, cheat_tntkeyxx, it_yellowskull),
  147. // killough 2/16/98: end generalized keys
  148. CHEAT("tntkeybs", NULL, cht_never, cheat_tntkeyxx, it_blueskull),
  149. // Ty 04/11/98 - Added TNTKA
  150. CHEAT("tntka", NULL, cht_never, cheat_k, 0),
  151. // killough 2/16/98: generalized weapon cheats
  152. CHEAT("tntweap", NULL, cht_never, cheat_tntweap, 0),
  153. CHEAT("tntweap", NULL, cht_never, cheat_tntweapx, -1),
  154. CHEAT("tntammo", NULL, cht_never, cheat_tntammo, 0),
  155. // killough 2/16/98: end generalized weapons
  156. CHEAT("tntammo", NULL, cht_never, cheat_tntammox, -1),
  157. // invoke translucency // phares
  158. CHEAT("tnttran", NULL, always, cheat_tnttran, 0),
  159. // killough 2/21/98: smart monster toggle
  160. CHEAT("tntsmart", NULL, cht_never, cheat_smart, 0),
  161. // killough 2/21/98: pitched sound toggle
  162. CHEAT("tntpitch", NULL, always, cheat_pitch, 0),
  163. // killough 2/21/98: reduce RSI injury by adding simpler alias sequences:
  164. // killough 2/21/98: same as tnttran
  165. CHEAT("tntran", NULL, always, cheat_tnttran, 0),
  166. // killough 2/21/98: same as tntammo
  167. CHEAT("tntamo", NULL, cht_never, cheat_tntammo, 0),
  168. // killough 2/21/98: same as tntammo
  169. CHEAT("tntamo", NULL, cht_never, cheat_tntammox, -1),
  170. // killough 3/6/98: -fast toggle
  171. CHEAT("tntfast", NULL, cht_never, cheat_fast, 0),
  172. // phares 3/10/98: toggle variable friction effects
  173. CHEAT("tntice", NULL, cht_never, cheat_friction, 0),
  174. // phares 3/10/98: toggle pushers
  175. CHEAT("tntpush", NULL, cht_never, cheat_pushers, 0),
  176. // [RH] Monsters don't target
  177. CHEAT("notarget", NULL, cht_never, cheat_notarget, 0),
  178. // fly mode is active
  179. CHEAT("fly", NULL, cht_never, cheat_fly, 0),
  180. // end-of-list marker
  181. {NULL}
  182. };
  183. //-----------------------------------------------------------------------------
  184. static void cheat_mus(buf)
  185. char buf[3];
  186. {
  187. int musnum;
  188. //jff 3/20/98 note: this cheat allowed in netgame/demorecord
  189. //jff 3/17/98 avoid musnum being negative and crashing
  190. if (!isdigit(buf[0]) || !isdigit(buf[1]))
  191. return;
  192. plyr->message = s_STSTR_MUS; // Ty 03/27/98 - externalized
  193. if (gamemode == commercial)
  194. {
  195. musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1;
  196. //jff 4/11/98 prevent IDMUS00 in DOOMII and IDMUS36 or greater
  197. if (musnum < mus_runnin || ((buf[0]-'0')*10 + buf[1]-'0') > 35)
  198. plyr->message = s_STSTR_NOMUS; // Ty 03/27/98 - externalized
  199. else
  200. {
  201. S_ChangeMusic(musnum, 1);
  202. idmusnum = musnum; //jff 3/17/98 remember idmus number for restore
  203. }
  204. }
  205. else
  206. {
  207. musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1');
  208. //jff 4/11/98 prevent IDMUS0x IDMUSx0 in DOOMI and greater than introa
  209. if (buf[0] < '1' || buf[1] < '1' || ((buf[0]-'1')*9 + buf[1]-'1') > 31)
  210. plyr->message = s_STSTR_NOMUS; // Ty 03/27/98 - externalized
  211. else
  212. {
  213. S_ChangeMusic(musnum, 1);
  214. idmusnum = musnum; //jff 3/17/98 remember idmus number for restore
  215. }
  216. }
  217. }
  218. // 'choppers' invulnerability & chainsaw
  219. static void cheat_choppers()
  220. {
  221. plyr->weaponowned[wp_chainsaw] = true;
  222. plyr->powers[pw_invulnerability] = true;
  223. plyr->message = s_STSTR_CHOPPERS; // Ty 03/27/98 - externalized
  224. }
  225. static void cheat_god()
  226. { // 'dqd' cheat for toggleable god mode
  227. plyr->cheats ^= CF_GODMODE;
  228. if (plyr->cheats & CF_GODMODE)
  229. {
  230. if (plyr->mo)
  231. plyr->mo->health = god_health; // Ty 03/09/98 - deh
  232. plyr->health = god_health;
  233. plyr->message = s_STSTR_DQDON; // Ty 03/27/98 - externalized
  234. }
  235. else
  236. plyr->message = s_STSTR_DQDOFF; // Ty 03/27/98 - externalized
  237. }
  238. // CPhipps - new health and armour cheat codes
  239. static void cheat_health()
  240. {
  241. if (!(plyr->cheats & CF_GODMODE)) {
  242. if (plyr->mo)
  243. plyr->mo->health = mega_health;
  244. plyr->health = mega_health;
  245. plyr->message = s_STSTR_BEHOLDX; // Ty 03/27/98 - externalized
  246. }
  247. }
  248. static void cheat_megaarmour()
  249. {
  250. plyr->armorpoints = idfa_armor; // Ty 03/09/98 - deh
  251. plyr->armortype = idfa_armor_class; // Ty 03/09/98 - deh
  252. plyr->message = s_STSTR_BEHOLDX; // Ty 03/27/98 - externalized
  253. }
  254. static void cheat_fa()
  255. {
  256. int i;
  257. if (!plyr->backpack)
  258. {
  259. for (i=0 ; i<NUMAMMO ; i++)
  260. plyr->maxammo[i] *= 2;
  261. plyr->backpack = true;
  262. }
  263. plyr->armorpoints = idfa_armor; // Ty 03/09/98 - deh
  264. plyr->armortype = idfa_armor_class; // Ty 03/09/98 - deh
  265. // You can't own weapons that aren't in the game // phares 02/27/98
  266. for (i=0;i<NUMWEAPONS;i++)
  267. if (!(((i == wp_plasma || i == wp_bfg) && gamemode == shareware) ||
  268. (i == wp_supershotgun && gamemode != commercial)))
  269. plyr->weaponowned[i] = true;
  270. for (i=0;i<NUMAMMO;i++)
  271. if (i!=am_cell || gamemode!=shareware)
  272. plyr->ammo[i] = plyr->maxammo[i];
  273. plyr->message = s_STSTR_FAADDED;
  274. }
  275. static void cheat_k()
  276. {
  277. int i;
  278. for (i=0;i<NUMCARDS;i++)
  279. if (!plyr->cards[i]) // only print message if at least one key added
  280. { // however, caller may overwrite message anyway
  281. plyr->cards[i] = true;
  282. plyr->message = "Keys Added";
  283. }
  284. }
  285. static void cheat_kfa()
  286. {
  287. cheat_k();
  288. cheat_fa();
  289. plyr->message = STSTR_KFAADDED;
  290. }
  291. static void cheat_noclip()
  292. {
  293. // Simplified, accepting both "noclip" and "idspispopd".
  294. // no clipping mode cheat
  295. plyr->message = (plyr->cheats ^= CF_NOCLIP) & CF_NOCLIP ?
  296. s_STSTR_NCON : s_STSTR_NCOFF; // Ty 03/27/98 - externalized
  297. }
  298. // 'behold?' power-up cheats (modified for infinite duration -- killough)
  299. static void cheat_pw(int pw)
  300. {
  301. if (plyr->powers[pw])
  302. plyr->powers[pw] = pw!=pw_strength && pw!=pw_allmap; // killough
  303. else
  304. {
  305. P_GivePower(plyr, pw);
  306. if (pw != pw_strength)
  307. plyr->powers[pw] = -1; // infinite duration -- killough
  308. }
  309. plyr->message = s_STSTR_BEHOLDX; // Ty 03/27/98 - externalized
  310. }
  311. // 'behold' power-up menu
  312. static void cheat_behold()
  313. {
  314. plyr->message = s_STSTR_BEHOLD; // Ty 03/27/98 - externalized
  315. }
  316. // 'clev' change-level cheat
  317. static void cheat_clev(char buf[3])
  318. {
  319. int epsd, map;
  320. if (gamemode == commercial)
  321. {
  322. epsd = 1; //jff was 0, but espd is 1-based
  323. map = (buf[0] - '0')*10 + buf[1] - '0';
  324. }
  325. else
  326. {
  327. epsd = buf[0] - '0';
  328. map = buf[1] - '0';
  329. }
  330. // Catch invalid maps.
  331. if (epsd < 1 || map < 1 || // Ohmygod - this is not going to work.
  332. //e6y: The fourth episode for pre-ultimate complevels is not allowed.
  333. (compatibility_level < ultdoom_compatibility && (epsd > 3)) ||
  334. (gamemode == retail && (epsd > 4 || map > 9 )) ||
  335. (gamemode == registered && (epsd > 3 || map > 9 )) ||
  336. (gamemode == shareware && (epsd > 1 || map > 9 )) ||
  337. (gamemode == commercial && (epsd > 1 || map > 33 )) ) //jff no 33 and 34
  338. return; //8/14/98 allowed
  339. if (!bfgedition && map == 33)
  340. return;
  341. if (gamemission == pack_nerve && map > 9)
  342. return;
  343. // Chex.exe always warps to episode 1.
  344. if (gamemission == chex)
  345. {
  346. epsd = 1;
  347. }
  348. // So be it.
  349. plyr->message = s_STSTR_CLEV; // Ty 03/27/98 - externalized
  350. G_DeferedInitNew(gameskill, epsd, map);
  351. }
  352. // 'mypos' for player position
  353. // killough 2/7/98: simplified using dprintf and made output more user-friendly
  354. static void cheat_mypos()
  355. {
  356. doom_printf("Position (%d,%d,%d)\tAngle %-.0f",
  357. players[consoleplayer].mo->x >> FRACBITS,
  358. players[consoleplayer].mo->y >> FRACBITS,
  359. players[consoleplayer].mo->z >> FRACBITS,
  360. players[consoleplayer].mo->angle * (90.0/ANG90));
  361. }
  362. // cph - cheat to toggle frame rate/rendering stats display
  363. static void cheat_rate()
  364. {
  365. rendering_stats ^= 1;
  366. }
  367. // compatibility cheat
  368. static void cheat_comp()
  369. {
  370. // CPhipps - modified for new compatibility system
  371. compatibility_level++; compatibility_level %= MAX_COMPATIBILITY_LEVEL;
  372. // must call G_Compatibility after changing compatibility_level
  373. // (fixes sf bug number 1558738)
  374. G_Compatibility();
  375. doom_printf("New compatibility level:\n%s",
  376. comp_lev_str[compatibility_level]);
  377. }
  378. // variable friction cheat
  379. static void cheat_friction()
  380. {
  381. plyr->message = // Ty 03/27/98 - *not* externalized
  382. (variable_friction = !variable_friction) ? "Variable Friction enabled" :
  383. "Variable Friction disabled";
  384. }
  385. // Pusher cheat
  386. // phares 3/10/98
  387. static void cheat_pushers()
  388. {
  389. plyr->message = // Ty 03/27/98 - *not* externalized
  390. (allow_pushers = !allow_pushers) ? "Pushers enabled" : "Pushers disabled";
  391. }
  392. // translucency cheat
  393. static void cheat_tnttran()
  394. {
  395. plyr->message = // Ty 03/27/98 - *not* externalized
  396. (general_translucency = !general_translucency) ? "Translucency enabled" :
  397. "Translucency disabled";
  398. // killough 3/1/98, 4/11/98: cache translucency map on a demand basis
  399. if (general_translucency && !main_tranmap)
  400. R_InitTranMap(0);
  401. }
  402. static void cheat_massacre() // jff 2/01/98 kill all monsters
  403. {
  404. // jff 02/01/98 'em' cheat - kill all monsters
  405. // partially taken from Chi's .46 port
  406. //
  407. // killough 2/7/98: cleaned up code and changed to use dprintf;
  408. // fixed lost soul bug (LSs left behind when PEs are killed)
  409. int killcount=0;
  410. thinker_t *currentthinker = NULL;
  411. extern void A_PainDie(mobj_t *);
  412. // killough 7/20/98: kill friendly monsters only if no others to kill
  413. uint_64_t mask = MF_FRIEND;
  414. P_MapStart();
  415. do
  416. while ((currentthinker = P_NextThinker(currentthinker,th_all)) != NULL)
  417. if (currentthinker->function == P_MobjThinker &&
  418. !(((mobj_t *) currentthinker)->flags & mask) && // killough 7/20/98
  419. (((mobj_t *) currentthinker)->flags & MF_COUNTKILL ||
  420. ((mobj_t *) currentthinker)->type == MT_SKULL))
  421. { // killough 3/6/98: kill even if PE is dead
  422. if (((mobj_t *) currentthinker)->health > 0)
  423. {
  424. killcount++;
  425. P_DamageMobj((mobj_t *)currentthinker, NULL, NULL, 10000);
  426. }
  427. if (((mobj_t *) currentthinker)->type == MT_PAIN)
  428. {
  429. A_PainDie((mobj_t *) currentthinker); // killough 2/8/98
  430. P_SetMobjState ((mobj_t *) currentthinker, S_PAIN_DIE6);
  431. }
  432. }
  433. while (!killcount && mask ? mask=0, 1 : 0); // killough 7/20/98
  434. P_MapEnd();
  435. // killough 3/22/98: make more intelligent about plural
  436. // Ty 03/27/98 - string(s) *not* externalized
  437. doom_printf("%d Monster%s Killed", killcount, killcount==1 ? "" : "s");
  438. }
  439. // killough 2/7/98: move iddt cheat from am_map.c to here
  440. // killough 3/26/98: emulate Doom better
  441. static void cheat_ddt()
  442. {
  443. extern int ddt_cheating;
  444. if (automapmode & am_active)
  445. ddt_cheating = (ddt_cheating+1) % 3;
  446. }
  447. // killough 2/7/98: HOM autodetection
  448. static void cheat_hom()
  449. {
  450. plyr->message = (flashing_hom = !flashing_hom) ? "HOM Detection On" :
  451. "HOM Detection Off";
  452. }
  453. // killough 3/6/98: -fast parameter toggle
  454. static void cheat_fast()
  455. {
  456. plyr->message = (fastparm = !fastparm) ? "Fast Monsters On" :
  457. "Fast Monsters Off"; // Ty 03/27/98 - *not* externalized
  458. G_SetFastParms(fastparm); // killough 4/10/98: set -fast parameter correctly
  459. }
  460. // killough 2/16/98: keycard/skullkey cheat functions
  461. static void cheat_tntkey()
  462. {
  463. plyr->message = "Red, Yellow, Blue"; // Ty 03/27/98 - *not* externalized
  464. }
  465. static void cheat_tntkeyx()
  466. {
  467. plyr->message = "Card, Skull"; // Ty 03/27/98 - *not* externalized
  468. }
  469. static void cheat_tntkeyxx(int key)
  470. {
  471. plyr->message = (plyr->cards[key] = !plyr->cards[key]) ?
  472. "Key Added" : "Key Removed"; // Ty 03/27/98 - *not* externalized
  473. }
  474. // killough 2/16/98: generalized weapon cheats
  475. static void cheat_tntweap()
  476. { // Ty 03/27/98 - *not* externalized
  477. plyr->message = gamemode==commercial ? // killough 2/28/98
  478. "Weapon number 1-9" : "Weapon number 1-8";
  479. }
  480. static void cheat_tntweapx(buf)
  481. char buf[3];
  482. {
  483. int w = *buf - '1';
  484. if ((w==wp_supershotgun && gamemode!=commercial) || // killough 2/28/98
  485. ((w==wp_bfg || w==wp_plasma) && gamemode==shareware))
  486. return;
  487. if (w==wp_fist) // make '1' apply beserker strength toggle
  488. cheat_pw(pw_strength);
  489. else
  490. if (w >= 0 && w < NUMWEAPONS) {
  491. if ((plyr->weaponowned[w] = !plyr->weaponowned[w]))
  492. plyr->message = "Weapon Added"; // Ty 03/27/98 - *not* externalized
  493. else
  494. {
  495. plyr->message = "Weapon Removed"; // Ty 03/27/98 - *not* externalized
  496. if (w==plyr->readyweapon) // maybe switch if weapon removed
  497. plyr->pendingweapon = P_SwitchWeapon(plyr);
  498. }
  499. }
  500. }
  501. // killough 2/16/98: generalized ammo cheats
  502. static void cheat_tntammo()
  503. {
  504. plyr->message = "Ammo 1-4, Backpack"; // Ty 03/27/98 - *not* externalized
  505. }
  506. static void cheat_tntammox(buf)
  507. char buf[1];
  508. {
  509. int a = *buf - '1';
  510. if (*buf == 'b') // Ty 03/27/98 - strings *not* externalized
  511. if ((plyr->backpack = !plyr->backpack))
  512. for (plyr->message = "Backpack Added", a=0 ; a<NUMAMMO ; a++)
  513. plyr->maxammo[a] <<= 1;
  514. else
  515. for (plyr->message = "Backpack Removed", a=0 ; a<NUMAMMO ; a++)
  516. {
  517. if (plyr->ammo[a] > (plyr->maxammo[a] >>= 1))
  518. plyr->ammo[a] = plyr->maxammo[a];
  519. }
  520. else
  521. if (a>=0 && a<NUMAMMO) // Ty 03/27/98 - *not* externalized
  522. { // killough 5/5/98: switch plasma and rockets for now -- KLUDGE
  523. a = a==am_cell ? am_misl : a==am_misl ? am_cell : a; // HACK
  524. plyr->message = (plyr->ammo[a] = !plyr->ammo[a]) ?
  525. plyr->ammo[a] = plyr->maxammo[a], "Ammo Added" : "Ammo Removed";
  526. }
  527. }
  528. static void cheat_smart()
  529. {
  530. plyr->message = (monsters_remember = !monsters_remember) ?
  531. "Smart Monsters Enabled" : "Smart Monsters Disabled";
  532. }
  533. static void cheat_pitch()
  534. {
  535. plyr->message=(pitched_sounds = !pitched_sounds) ? "Pitch Effects Enabled" :
  536. "Pitch Effects Disabled";
  537. }
  538. static void cheat_notarget()
  539. {
  540. plyr->cheats ^= CF_NOTARGET;
  541. if (plyr->cheats & CF_NOTARGET)
  542. plyr->message = "Notarget Mode ON";
  543. else
  544. plyr->message = "Notarget Mode OFF";
  545. }
  546. static void cheat_fly()
  547. {
  548. if (plyr->mo != NULL)
  549. {
  550. plyr->cheats ^= CF_FLY;
  551. if (plyr->cheats & CF_FLY)
  552. {
  553. plyr->mo->flags |= MF_NOGRAVITY;
  554. plyr->mo->flags |= MF_FLY;
  555. plyr->message = "Fly mode ON";
  556. }
  557. else
  558. {
  559. plyr->mo->flags &= ~MF_NOGRAVITY;
  560. plyr->mo->flags &= ~MF_FLY;
  561. plyr->message = "Fly mode OFF";
  562. }
  563. }
  564. }
  565. //-----------------------------------------------------------------------------
  566. // 2/7/98: Cheat detection rewritten by Lee Killough, to avoid
  567. // scrambling and to use a more general table-driven approach.
  568. //-----------------------------------------------------------------------------
  569. static int M_FindCheats_Boom(int key)
  570. {
  571. static uint_64_t sr;
  572. static char argbuf[CHEAT_ARGS_MAX+1], *arg;
  573. static int init, argsleft, cht;
  574. int i, ret, matchedbefore;
  575. // If we are expecting arguments to a cheat
  576. // (e.g. idclev), put them in the arg buffer
  577. if (argsleft)
  578. {
  579. *arg++ = tolower(key); // store key in arg buffer
  580. if (!--argsleft) // if last key in arg list,
  581. cheat[cht].func(argbuf); // process the arg buffer
  582. return 1; // affirmative response
  583. }
  584. key = tolower(key) - 'a';
  585. if (key < 0 || key >= 32) // ignore most non-alpha cheat letters
  586. {
  587. sr = 0; // clear shift register
  588. return 0;
  589. }
  590. if (!init) // initialize aux entries of table
  591. {
  592. init = 1;
  593. for (i=0;cheat[i].cheat;i++)
  594. {
  595. uint_64_t c=0, m=0;
  596. const char *p;
  597. for (p=cheat[i].cheat; *p; p++)
  598. {
  599. unsigned key = tolower(*p)-'a'; // convert to 0-31
  600. if (key >= 32) // ignore most non-alpha cheat letters
  601. continue;
  602. c = (c<<5) + key; // shift key into code
  603. m = (m<<5) + 31; // shift 1's into mask
  604. }
  605. cheat[i].code = c; // code for this cheat key
  606. cheat[i].mask = m; // mask for this cheat key
  607. }
  608. }
  609. sr = (sr<<5) + key; // shift this key into shift register
  610. for (matchedbefore = ret = i = 0; cheat[i].cheat; i++)
  611. if ((sr & cheat[i].mask) == cheat[i].code && // if match found
  612. !(cheat[i].when & not_dm && deathmatch) && // and if cheat allowed
  613. !(cheat[i].when & not_coop && netgame && !deathmatch) &&
  614. !(cheat[i].when & not_demo && (demorecording || demoplayback)) &&
  615. !(cheat[i].when & not_menu && menuactive) &&
  616. !(cheat[i].when & not_deh && M_CheckParm("-deh"))) {
  617. if (cheat[i].arg < 0) // if additional args are required
  618. {
  619. cht = i; // remember this cheat code
  620. arg = argbuf; // point to start of arg buffer
  621. argsleft = -cheat[i].arg; // number of args expected
  622. ret = 1; // responder has eaten key
  623. }
  624. else
  625. if (!matchedbefore) // allow only one cheat at a time
  626. {
  627. matchedbefore = ret = 1; // responder has eaten key
  628. cheat[i].func(cheat[i].arg); // call cheat handler
  629. }
  630. }
  631. return ret;
  632. }
  633. //
  634. // CHEAT SEQUENCE PACKAGE
  635. //
  636. //
  637. // Called in st_stuff module, which handles the input.
  638. // Returns a 1 if the cheat was successful, 0 if failed.
  639. //
  640. static int M_FindCheats_Doom(int key)
  641. {
  642. int rc = 0;
  643. cheatseq_t* cht;
  644. char char_key;
  645. char_key = (char)key;
  646. for (cht = cheat; cht->cheat; cht++)
  647. {
  648. if (!(cht->when & not_dm && deathmatch) && // and if cheat allowed
  649. !(cht->when & not_coop && netgame && !deathmatch) &&
  650. !(cht->when & not_demo && (demorecording || demoplayback)) &&
  651. !(cht->when & not_menu && menuactive) &&
  652. !(cht->when & not_deh && M_CheckParm("-deh")))
  653. {
  654. // if we make a short sequence on a cheat with parameters, this
  655. // will not work in vanilla doom. behave the same.
  656. if (demo_compatibility || compatibility_level == lxdoom_1_compatibility)
  657. {
  658. if (cht->arg < 0 && cht->deh_sequence_len < cht->sequence_len)
  659. continue;
  660. }
  661. if (cht->chars_read < cht->deh_sequence_len)
  662. {
  663. // still reading characters from the cheat code
  664. // and verifying. reset back to the beginning
  665. // if a key is wrong
  666. if (char_key == cht->cheat[cht->chars_read])
  667. ++cht->chars_read;
  668. else
  669. cht->chars_read = 0;
  670. cht->param_chars_read = 0;
  671. }
  672. else if (cht->param_chars_read < -cht->arg)
  673. {
  674. // we have passed the end of the cheat sequence and are
  675. // entering parameters now
  676. cht->parameter_buf[cht->param_chars_read] = char_key;
  677. ++cht->param_chars_read;
  678. // affirmative response
  679. rc = 1;
  680. }
  681. if (cht->chars_read >= cht->deh_sequence_len &&
  682. cht->param_chars_read >= -cht->arg)
  683. {
  684. if (cht->param_chars_read)
  685. {
  686. static char argbuf[CHEAT_ARGS_MAX + 1];
  687. // process the arg buffer
  688. memcpy(argbuf, cht->parameter_buf, -cht->arg);
  689. cht->func(argbuf);
  690. }
  691. else
  692. {
  693. // call cheat handler
  694. cht->func(cht->arg);
  695. }
  696. cht->chars_read = cht->param_chars_read = 0;
  697. rc = 1;
  698. }
  699. }
  700. }
  701. return rc;
  702. }
  703. static void cht_InitCheats(void)
  704. {
  705. static int init = false;
  706. if (!init)
  707. {
  708. cheatseq_t* cht;
  709. init = true;
  710. memset(boom_cheat_route, 0, sizeof(boom_cheat_route));
  711. boom_cheat_route[boom_compatibility_compatibility] = 1;
  712. boom_cheat_route[boom_201_compatibility] = 1;
  713. boom_cheat_route[boom_202_compatibility] = 1;
  714. boom_cheat_route[mbf_compatibility] = 1;
  715. for (cht = cheat; cht->cheat; cht++)
  716. {
  717. cht->deh_sequence_len = strlen(cht->cheat);
  718. }
  719. }
  720. }
  721. dboolean M_FindCheats(int key)
  722. {
  723. cht_InitCheats();
  724. if (boom_cheat_route[compatibility_level])
  725. return M_FindCheats_Boom(key);
  726. else
  727. return M_FindCheats_Doom(key);
  728. }