1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_things.cpp 4469 2014-01-03 23:38:29Z dr_sean $
5 //
6 // Copyright (C) 2006-2014 by The Odamex Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // DESCRIPTION:
19 // [RH] new file to deal with general things
20 //
21 //-----------------------------------------------------------------------------
22 
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 #include "doomtype.h"
28 #include "i_system.h"
29 #include "p_local.h"
30 #include "c_effect.h"
31 #include "p_mobj.h"
32 #include "info.h"
33 #include "s_sound.h"
34 #include "tables.h"
35 #include "doomstat.h"
36 #include "m_random.h"
37 #include "c_console.h"
38 
39 EXTERN_CVAR (sv_nomonsters)
40 
41 // List of spawnable things for the Thing_Spawn and Thing_Projectile specials.
42 
43 int SpawnableThings[] = {
44 	0,
45 	MT_SHOTGUY,
46 	MT_CHAINGUY,
47 	MT_BRUISER,
48 	MT_POSSESSED,
49 	MT_TROOP,
50 	MT_BABY,
51 	MT_SPIDER,
52 	MT_SERGEANT,
53 	MT_SHADOWS,
54 	MT_TROOPSHOT,
55 	MT_CLIP,
56 	MT_MISC22,	// Shells
57 	0,
58 	0,
59 	0,
60 	0,
61 	0,
62 	0,
63 	MT_HEAD,
64 	MT_UNDEAD,
65 	MT_BRIDGE,
66 	MT_MISC3,	// Armor bonus
67 	MT_MISC10,	// Stim pack
68 	MT_MISC11,	// Medkit
69 	MT_MISC12,	// Soul sphere
70 	0,
71 	MT_SHOTGUN,
72 	MT_CHAINGUN,
73 	MT_MISC27,	// Rocket launcher
74 	MT_MISC28,	// Plasma gun
75 	MT_MISC25,	// BFG
76 	MT_MISC26,	// Chainsaw
77 	MT_SUPERSHOTGUN,
78 	0,
79 	0,
80 	0,
81 	0,
82 	0,
83 	0,
84 	0,
85 	0,	// T_MORPHBLAST
86 	0,	// T_ROCK1
87 	0,	// T_ROCK2
88 	0,	// T_ROCK3
89 	0,	// T_DIRT1
90 	0,	// T_DIRT2
91 	0,	// T_DIRT3
92 	0,	// T_DIRT4
93 	0,	// T_DIRT5
94 	0,	// T_DIRT6
95 	MT_PLASMA,
96 	0,	// T_POISONDART
97 	MT_TRACER,
98 	0,	// T_STAINEDGLASS1
99 	0,	// T_STAINEDGLASS2
100 	0,	// T_STAINEDGLASS3
101 	0,	// T_STAINEDGLASS4
102 	0,	// T_STAINEDGLASS5
103 	0,	// T_STAINEDGLASS6
104 	0,	// T_STAINEDGLASS7
105 	0,	// T_STAINEDGLASS8
106 	0,	// T_STAINEDGLASS9
107 	0,	// T_STAINEDGLASS0
108 	0,
109 	0,
110 	0,
111 	0,
112 	MT_MISC0,	// Green armor
113 	MT_MISC1,	// Blue armor
114 	0,
115 	0,
116 	0,
117 	0,
118 	0,
119 	MT_MISC20,	// Energy cell
120 	0,
121 	0,
122 	0,
123 	0,
124 	0,
125 	0,
126 	0,
127 	0,
128 	0,
129 	MT_MISC4,	// Blue key card
130 	MT_MISC5,	// Red key card
131 	MT_MISC6,	// Yellow key card
132 	MT_MISC7,	// Yellow skull key
133 	MT_MISC8,	// Red skull key
134 	MT_MISC9,	// Blue skull key
135 	0,
136 	0,
137 	0,
138 	0,
139 	0,
140 	0,
141 	0,
142 	MT_FIRE,
143 	0,
144 	0,
145 	0,
146 	0,
147 	0,
148 	0,
149 	0,
150 	0,
151 	0,
152 	0,
153 	0,
154 	MT_SKULL,
155 	MT_VILE,
156 	MT_FATSO,
157 	MT_KNIGHT,
158 	MT_CYBORG,
159 	MT_PAIN,
160 	MT_WOLFSS,
161 	0,
162 	0,
163 	0,
164 	0,
165 	0,
166 	0,
167 	0,
168 	0,
169 	MT_BARREL,
170 	MT_HEADSHOT,
171 	MT_ROCKET,
172 	MT_BFG,
173 	MT_ARACHPLAZ,
174 	MT_BLOOD,
175 	MT_PUFF,
176 	MT_MEGA,	// Mega sphere
177 	MT_INV,
178 	MT_MISC13,	// Berserk
179 	MT_INS,		// Blur sphere
180 	MT_MISC14,	// Rad suit
181 	MT_MISC15,	// Computer map
182 	MT_MISC16,	// Light amp
183 	MT_MISC17,	// Box of ammo
184 	MT_MISC18,	// Rocket
185 	MT_MISC19,	// Box of rockets
186 	MT_MISC21,	// Battery pack
187 	MT_MISC23,	// Box of shells
188 	MT_MISC24,	// Backpack
189 	MT_MISC68,	// Guts
190 	MT_MISC71,	// Blood pool
191 	MT_MISC84,	// Pool o' blood 1
192 	MT_MISC85,	// Pool o' blood 2
193 	MT_MISC77,	// Flaming barrel
194 	MT_MISC86	// Brains
195 };
196 
197 const int NumSpawnableThings = sizeof(SpawnableThings)/sizeof(*SpawnableThings);
198 
P_Thing_Spawn(int tid,int type,angle_t angle,BOOL fog)199 BOOL P_Thing_Spawn (int tid, int type, angle_t angle, BOOL fog)
200 {
201 	fixed_t z;
202 	int rtn = 0;
203 	int kind;
204 	AActor *spot = NULL, *mobj;
205 
206 	if (type >= NumSpawnableThings)
207 		return false;
208 
209 	if ( (kind = SpawnableThings[type]) == 0)
210 		return false;
211 
212 	if ((mobjinfo[kind].flags & MF_COUNTKILL) && sv_nomonsters == 1)
213 		return false;
214 
215 	while ( (spot = AActor::FindByTID (spot, tid)) )
216 	{
217 		if (mobjinfo[kind].flags2 & MF2_FLOATBOB)
218 			z = spot->z - spot->floorz;
219 		else
220 			z = spot->z;
221 
222 		mobj = new AActor (spot->x, spot->y, z, (mobjtype_t)kind);
223 
224 		if (mobj)
225 		{
226 			if (P_TestMobjLocation (mobj))
227 			{
228 				rtn++;
229 				mobj->angle = angle;
230 				if (fog)
231 					S_Sound (new AActor (spot->x, spot->y, spot->z, MT_TFOG),
232 							 CHAN_VOICE, "misc/teleport", 1, ATTN_NORM);
233 				mobj->flags |= MF_DROPPED;	// Don't respawn
234 				if (mobj->flags2 & MF2_FLOATBOB)
235 				{
236 					mobj->special1 = mobj->z - mobj->floorz;
237 				}
238 			}
239 			else
240 			{
241 				mobj->Destroy ();
242 				rtn = false;
243 			}
244 		}
245 	}
246 
247 	return rtn != 0;
248 }
249 
P_Thing_Projectile(int tid,int type,angle_t angle,fixed_t speed,fixed_t vspeed,BOOL gravity)250 BOOL P_Thing_Projectile (int tid, int type, angle_t angle,
251 						 fixed_t speed, fixed_t vspeed, BOOL gravity)
252 {
253 	int rtn = 0;
254 	int kind;
255 	AActor *spot = NULL, *mobj;
256 
257 	if (type >= NumSpawnableThings)
258 		return false;
259 
260 	if ( (kind = SpawnableThings[type]) == 0)
261 		return false;
262 
263 	if ((mobjinfo[kind].flags & MF_COUNTKILL) && sv_nomonsters)
264 		return false;
265 
266 	while ( (spot = AActor::FindByTID (spot, tid)) )
267 	{
268 		if (spot->type != MT_MAPSPOT && spot->type != MT_MAPSPOTGRAVITY)
269 			continue;
270 
271 		mobj = new AActor (spot->x, spot->y, spot->z, (mobjtype_t)kind);
272 
273 		if (mobj)
274 		{
275 			if (mobj->info->seesound)
276 				S_Sound (mobj, CHAN_VOICE, mobj->info->seesound, 1, ATTN_NORM);
277 			if (gravity)
278 			{
279 				mobj->flags &= ~MF_NOGRAVITY;
280 				if (!(mobj->flags & MF_COUNTKILL))
281 					mobj->flags2 |= MF2_LOGRAV;
282 			}
283 			else
284 				mobj->flags |= MF_NOGRAVITY;
285 			mobj->target = spot->ptr();
286 			mobj->angle = angle;
287 			mobj->momx = FixedMul (speed, finecosine[angle>>ANGLETOFINESHIFT]);
288 			mobj->momy = FixedMul (speed, finesine[angle>>ANGLETOFINESHIFT]);
289 			mobj->momz = vspeed;
290 			mobj->flags |= MF_DROPPED;
291 			if (mobj->flags & MF_MISSILE)
292 				rtn = P_CheckMissileSpawn (mobj);
293 			else if (!P_TestMobjLocation (mobj))
294 				mobj->Destroy ();
295 		}
296 	}
297 
298 	return rtn;
299 }
300 
P_ActivateMobj(AActor * mobj,AActor * activator)301 BOOL P_ActivateMobj (AActor *mobj, AActor *activator)
302 {
303 	if (mobj->flags & MF_COUNTKILL)
304 	{
305 		mobj->flags2 &= !(MF2_DORMANT | MF2_INVULNERABLE);
306 		return true;
307 	}
308 	else
309 	{
310 		switch (mobj->type)
311 		{
312 			case MT_SPARK:
313 			{
314 				int count = mobj->args[0];
315 				char sound[16];
316 
317 				if (count == 0)
318 					count = 32;
319 
320 				P_DrawSplash (count, mobj->x, mobj->y, mobj->z, mobj->angle, 1);
321 				sprintf (sound, "world/spark%d", 1+(M_Random() % 3));
322 				S_Sound (mobj, CHAN_AUTO, sound, 1, ATTN_STATIC);
323 				break;
324 			}
325 
326 			case MT_FOUNTAIN:
327 				mobj->effects &= ~FX_FOUNTAINMASK;
328 				mobj->effects |= mobj->args[0] << FX_FOUNTAINSHIFT;
329 				break;
330 
331 			case MT_SECRETTRIGGER:
332 				if (activator->player->mo == consoleplayer().camera)
333 				{
334 					if (mobj->args[0] <= 1)
335 					{
336 						C_MidPrint ("A secret is revealed!");
337 					}
338 					if (mobj->args[0] == 0 || mobj->args[0] == 2)
339 					{
340 						S_Sound (activator, CHAN_AUTO, "misc/secret", 1, ATTN_NORM);
341 					}
342 				}
343 				level.found_secrets++;
344 				mobj->Destroy ();
345 				break;
346 
347 			default:
348 				break;
349 		}
350 	}
351 	return false;
352 }
353 
P_DeactivateMobj(AActor * mobj)354 BOOL P_DeactivateMobj (AActor *mobj)
355 {
356 	if (mobj->flags & MF_COUNTKILL)
357 	{
358 		mobj->flags2 |= MF2_DORMANT | MF2_INVULNERABLE;
359 		return true;
360 	}
361 	else
362 	{
363 		switch (mobj->type)
364 		{
365 			case MT_FOUNTAIN:
366 				mobj->effects &= ~FX_FOUNTAINMASK;
367 				break;
368 			default:
369 				break;
370 		}
371 	}
372 	return false;
373 }
374 
375 VERSION_CONTROL (p_things_cpp, "$Id: p_things.cpp 4469 2014-01-03 23:38:29Z dr_sean $")
376