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