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