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