1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: m_cheat.cpp 4472 2014-01-06 00:32:09Z dr_sean $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Copyright (C) 2006-2014 by The Odamex Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 // Cheat code checking.
21 //
22 //-----------------------------------------------------------------------------
23
24
25 #include <stdlib.h>
26 #include <math.h>
27
28 #include "m_cheat.h"
29 #include "d_player.h"
30 #include "doomstat.h"
31 #include "gstrings.h"
32 #include "p_inter.h"
33 #include "d_items.h"
34 #include "p_local.h"
35
36 //
37 // CHEAT SEQUENCE PACKAGE
38 //
39
40 static int firsttime = 1;
41 static unsigned char cheat_xlate_table[256];
42
43
44 //
45 // Called in st_stuff module, which handles the input.
46 // Returns a 1 if the cheat was successful, 0 if failed.
47 //
cht_CheckCheat(cheatseq_t * cht,char key)48 int cht_CheckCheat (cheatseq_t *cht, char key)
49 {
50 int i;
51 int rc = 0;
52
53 if (firsttime)
54 {
55 firsttime = 0;
56 for (i = 0; i < 256; i++)
57 cheat_xlate_table[i] = (unsigned char)SCRAMBLE(i);
58 }
59
60 if (!cht->p)
61 cht->p = cht->sequence; // initialize if first time
62
63 if (*cht->p == 0)
64 *(cht->p++) = key;
65 else if (cheat_xlate_table[(unsigned char)tolower(key)] == *cht->p)
66 cht->p++;
67 else
68 cht->p = cht->sequence;
69
70 if (*cht->p == 1)
71 cht->p++;
72 else if (*cht->p == 0xff) // end of sequence character
73 {
74 cht->p = cht->sequence;
75 rc = 1;
76 }
77
78 return rc;
79 }
80
cht_GetParam(cheatseq_t * cht,char * buffer)81 void cht_GetParam (cheatseq_t *cht, char *buffer)
82 {
83
84 unsigned char *p, c;
85
86 p = cht->sequence;
87 while (*(p++) != 1);
88
89 do
90 {
91 c = *p;
92 *(buffer++) = c;
93 *(p++) = 0;
94 }
95 while (c && *p!=0xff );
96
97 if (*p==0xff)
98 *buffer = 0;
99
100 }
101
102 extern void A_PainDie(AActor *);
103
104 // [RH] Actually handle the cheat. The cheat code in st_stuff.c now just
105 // writes some bytes to the network data stream, and the network code
106 // later calls us.
107
cht_DoCheat(player_t * player,int cheat)108 void cht_DoCheat (player_t *player, int cheat)
109 {
110 const char *msg = "";
111 char msgbuild[32];
112
113 switch (cheat) {
114 case CHT_IDDQD:
115 if (!(player->cheats & CF_GODMODE)) {
116 if (player->mo)
117 player->mo->health = deh.GodHealth;
118
119 player->health = deh.GodHealth;
120 }
121 case CHT_GOD:
122 player->cheats ^= CF_GODMODE;
123 if (player->cheats & CF_GODMODE)
124 msg = GStrings(STSTR_DQDON);
125 else
126 msg = GStrings(STSTR_DQDOFF);
127 break;
128
129 case CHT_NOCLIP:
130 player->cheats ^= CF_NOCLIP;
131 if (player->cheats & CF_NOCLIP)
132 msg = GStrings(STSTR_NCON);
133 else
134 msg = GStrings(STSTR_NCOFF);
135 break;
136
137 case CHT_FLY:
138 player->cheats ^= CF_FLY;
139 if (player->cheats & CF_FLY)
140 msg = "You feel lighter";
141 else
142 msg = "Gravity weighs you down";
143 break;
144
145 case CHT_NOTARGET:
146 if (!multiplayer)
147 {
148 player->cheats ^= CF_NOTARGET;
149 if (player->cheats & CF_NOTARGET)
150 msg = "notarget ON";
151 else
152 msg = "notarget OFF";
153 }
154 break;
155
156 case CHT_CHASECAM:
157 player->cheats ^= CF_CHASECAM;
158 if (player->cheats & CF_CHASECAM)
159 msg = "chasecam ON";
160 else
161 msg = "chasecam OFF";
162 break;
163
164 case CHT_CHAINSAW:
165 player->weaponowned[wp_chainsaw] = true;
166 player->powers[pw_invulnerability] = true;
167 msg = GStrings(STSTR_CHOPPERS);
168 break;
169
170 case CHT_IDKFA:
171 cht_Give (player, "backpack");
172 cht_Give (player, "weapons");
173 cht_Give (player, "ammo");
174 cht_Give (player, "keys");
175 player->armorpoints = deh.KFAArmor;
176 player->armortype = deh.KFAAC;
177 msg = GStrings(STSTR_KFAADDED);
178 break;
179
180 case CHT_IDFA:
181 cht_Give (player, "backpack");
182 cht_Give (player, "weapons");
183 cht_Give (player, "ammo");
184 player->armorpoints = deh.FAArmor;
185 player->armortype = deh.FAAC;
186 msg = GStrings(STSTR_FAADDED);
187 break;
188
189 case CHT_BEHOLDV:
190 case CHT_BEHOLDS:
191 case CHT_BEHOLDI:
192 case CHT_BEHOLDR:
193 case CHT_BEHOLDA:
194 case CHT_BEHOLDL:
195 {
196 int i = cheat - CHT_BEHOLDV;
197
198 if (!player->powers[i])
199 P_GivePower (player, i);
200 else if (i!=pw_strength)
201 player->powers[i] = 1;
202 else
203 player->powers[i] = 0;
204 }
205 msg = GStrings(STSTR_BEHOLDX);
206 break;
207
208 case CHT_MASSACRE:
209 {
210 // jff 02/01/98 'em' cheat - kill all monsters
211 // partially taken from Chi's .46 port
212 //
213 // killough 2/7/98: cleaned up code and changed to use dprintf;
214 // fixed lost soul bug (LSs left behind when PEs are killed)
215
216 int killcount = 0;
217 AActor *actor;
218 TThinkerIterator<AActor> iterator;
219
220 while ( (actor = iterator.Next ()) )
221 {
222 if (actor->flags & MF_COUNTKILL || actor->type == MT_SKULL)
223 {
224 // killough 3/6/98: kill even if PE is dead
225 if (actor->health > 0)
226 {
227 killcount++;
228 P_DamageMobj (actor, NULL, NULL, 10000, MOD_UNKNOWN);
229 }
230 if (actor->type == MT_PAIN)
231 {
232 A_PainDie (actor); // killough 2/8/98
233 P_SetMobjState (actor, S_PAIN_DIE6);
234 }
235 }
236 }
237 // killough 3/22/98: make more intelligent about plural
238 // Ty 03/27/98 - string(s) *not* externalized
239 sprintf (msgbuild, "%d Monster%s Killed", killcount, killcount==1 ? "" : "s");
240 msg = msgbuild;
241 }
242 break;
243 }
244 if (player == &consoleplayer())
245 Printf (PRINT_HIGH, "%s\n", msg);
246 else
247 Printf (PRINT_HIGH, "%s is a cheater: %s\n", player->userinfo.netname.c_str(), msg);
248 }
249
cht_Give(player_t * player,const char * name)250 void cht_Give (player_t *player, const char *name)
251 {
252 BOOL giveall;
253 int i;
254 gitem_t *it;
255
256 if (player != &consoleplayer())
257 Printf (PRINT_HIGH, "%s is a cheater: give %s\n", player->userinfo.netname.c_str(), name);
258
259 if (stricmp (name, "all") == 0)
260 giveall = true;
261 else
262 giveall = false;
263
264 if (giveall || strnicmp (name, "health", 6) == 0) {
265 int h;
266
267 if (0 < (h = atoi (name + 6))) {
268 if (player->mo) {
269 player->mo->health += h;
270 player->health = player->mo->health;
271 } else {
272 player->health += h;
273 }
274 } else {
275 if (player->mo)
276 player->mo->health = deh.GodHealth;
277
278 player->health = deh.GodHealth;
279 }
280
281 if (!giveall)
282 return;
283 }
284
285 if (giveall || stricmp (name, "backpack") == 0) {
286 if (!player->backpack) {
287 for (i=0 ; i<NUMAMMO ; i++)
288 player->maxammo[i] *= 2;
289 player->backpack = true;
290 }
291 for (i=0 ; i<NUMAMMO ; i++)
292 P_GiveAmmo (player, (ammotype_t)i, 1);
293
294 if (!giveall)
295 return;
296 }
297
298 if (giveall || stricmp (name, "weapons") == 0) {
299 weapontype_t pendweap = player->pendingweapon;
300 for (i = 0; i<NUMWEAPONS; i++)
301 P_GiveWeapon (player, (weapontype_t)i, false);
302 player->pendingweapon = pendweap;
303
304 if (!giveall)
305 return;
306 }
307
308 if (giveall || stricmp (name, "ammo") == 0) {
309 for (i=0;i<NUMAMMO;i++)
310 player->ammo[i] = player->maxammo[i];
311
312 if (!giveall)
313 return;
314 }
315
316 if (giveall || stricmp (name, "armor") == 0) {
317 player->armorpoints = 200;
318 player->armortype = 2;
319
320 if (!giveall)
321 return;
322 }
323
324 if (giveall || stricmp (name, "keys") == 0) {
325 for (i=0;i<NUMCARDS;i++)
326 player->cards[i] = true;
327
328 if (!giveall)
329 return;
330 }
331
332 if (giveall)
333 return;
334
335 it = FindItem (name);
336 if (!it) {
337 it = FindItemByClassname (name);
338 if (!it) {
339 if (player == &consoleplayer())
340 Printf (PRINT_HIGH, "Unknown item\n");
341 return;
342 }
343 }
344
345 if (it->flags & IT_AMMO) {
346 int howmuch;
347
348 /* if (argc == 3)
349 howmuch = atoi (argv[2]);
350 else */
351 howmuch = it->quantity;
352
353 P_GiveAmmo (player, (ammotype_t)it->offset, howmuch);
354 } else if (it->flags & IT_WEAPON) {
355 P_GiveWeapon (player, (weapontype_t)it->offset, 0);
356 } else if (it->flags & IT_KEY) {
357 P_GiveCard (player, (card_t)it->offset);
358 } else if (it->flags & IT_POWERUP) {
359 P_GivePower (player, it->offset);
360 } else if (it->flags & IT_ARMOR) {
361 P_GiveArmor (player, it->offset);
362 }
363 }
364
cht_Suicide(player_t * plyr)365 void cht_Suicide (player_t *plyr)
366 {
367 plyr->mo->flags |= MF_SHOOTABLE;
368 while (plyr->health > 0)
369 P_DamageMobj (plyr->mo, plyr->mo, plyr->mo, 10000, MOD_SUICIDE);
370 plyr->mo->flags &= ~MF_SHOOTABLE;
371 }
372
373 VERSION_CONTROL (m_cheat_cpp, "$Id: m_cheat.cpp 4472 2014-01-06 00:32:09Z dr_sean $")
374
375