diff options
author | Dave Chapman <dave@dchapman.com> | 2006-03-28 15:44:01 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-03-28 15:44:01 +0000 |
commit | 47f4a458d636a889e955e68f896708f1276febc0 (patch) | |
tree | 99f770c02ef606f0abbdcd332ac39e69830d8007 /apps/plugins/doom/p_mobj.c | |
parent | fff7d6157d56f233cad5c2003475e47a5ff809a7 (diff) | |
download | rockbox-47f4a458d636a889e955e68f896708f1276febc0.tar.gz rockbox-47f4a458d636a889e955e68f896708f1276febc0.zip |
Patch #2969 - Doom! Currently only working on the H300.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9312 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/doom/p_mobj.c')
-rw-r--r-- | apps/plugins/doom/p_mobj.c | 1394 |
1 files changed, 1394 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_mobj.c b/apps/plugins/doom/p_mobj.c new file mode 100644 index 0000000000..3aaaf4510a --- /dev/null +++ b/apps/plugins/doom/p_mobj.c | |||
@@ -0,0 +1,1394 @@ | |||
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-2000 by | ||
10 | * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
25 | * 02111-1307, USA. | ||
26 | * | ||
27 | * DESCRIPTION: | ||
28 | * Moving object handling. Spawn functions. | ||
29 | * | ||
30 | *-----------------------------------------------------------------------------*/ | ||
31 | |||
32 | #include "doomdef.h" | ||
33 | #include "doomstat.h" | ||
34 | #include "m_random.h" | ||
35 | #include "r_main.h" | ||
36 | #include "p_maputl.h" | ||
37 | #include "p_map.h" | ||
38 | #include "p_tick.h" | ||
39 | #include "sounds.h" | ||
40 | #include "st_stuff.h" | ||
41 | #include "hu_stuff.h" | ||
42 | #include "s_sound.h" | ||
43 | #include "info.h" | ||
44 | #include "g_game.h" | ||
45 | #include "p_inter.h" | ||
46 | #include "rockmacros.h" | ||
47 | // | ||
48 | // P_SetMobjState | ||
49 | // Returns true if the mobj is still present. | ||
50 | // | ||
51 | |||
52 | statenum_t i IBSS_ATTR; // initial state | ||
53 | statenum_t seenstate_tab[NUMSTATES] IBSS_ATTR; // fast transition table | ||
54 | |||
55 | boolean P_SetMobjState(mobj_t* mobj,statenum_t state) | ||
56 | { | ||
57 | state_t* st; | ||
58 | // killough 4/9/98: remember states seen, to detect cycles: | ||
59 | statenum_t *seenstate = seenstate_tab; // pointer to table | ||
60 | static int recursion; // detects recursion | ||
61 | i = state; | ||
62 | boolean ret = true; // return value | ||
63 | |||
64 | if (recursion++) // if recursion detected, | ||
65 | memset(seenstate,0,sizeof(seenstate_tab)); // clear state table | ||
66 | |||
67 | do | ||
68 | { | ||
69 | if (state == S_NULL) | ||
70 | { | ||
71 | mobj->state = (state_t *) S_NULL; | ||
72 | P_RemoveMobj (mobj); | ||
73 | ret = false; | ||
74 | break; // killough 4/9/98 | ||
75 | } | ||
76 | |||
77 | st = &states[state]; | ||
78 | mobj->state = st; | ||
79 | mobj->tics = st->tics; | ||
80 | mobj->sprite = st->sprite; | ||
81 | mobj->frame = st->frame; | ||
82 | |||
83 | // Modified handling. | ||
84 | // Call action functions when the state is set | ||
85 | |||
86 | if (st->action) | ||
87 | st->action(mobj); | ||
88 | |||
89 | seenstate[state] = 1 + st->nextstate; // killough 4/9/98 | ||
90 | |||
91 | state = st->nextstate; | ||
92 | } while (!mobj->tics && !seenstate[state]); // killough 4/9/98 | ||
93 | |||
94 | if (ret && !mobj->tics) // killough 4/9/98: detect state cycles | ||
95 | doom_printf("Warning: State Cycle Detected"); | ||
96 | |||
97 | if (!--recursion) | ||
98 | for (;(state=seenstate[i]);i=state-1) | ||
99 | seenstate[i] = 0; // killough 4/9/98: erase memory of states | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | |||
105 | // | ||
106 | // P_ExplodeMissile | ||
107 | // | ||
108 | |||
109 | void P_ExplodeMissile (mobj_t* mo) | ||
110 | { | ||
111 | mo->momx = mo->momy = mo->momz = 0; | ||
112 | |||
113 | P_SetMobjState (mo, mobjinfo[mo->type].deathstate); | ||
114 | |||
115 | mo->tics -= P_Random(pr_explode)&3; | ||
116 | |||
117 | if (mo->tics < 1) | ||
118 | mo->tics = 1; | ||
119 | |||
120 | mo->flags &= ~MF_MISSILE; | ||
121 | |||
122 | if (mo->info->deathsound) | ||
123 | S_StartSound (mo, mo->info->deathsound); | ||
124 | } | ||
125 | |||
126 | |||
127 | // | ||
128 | // P_XYMovement | ||
129 | // | ||
130 | // Attempts to move something if it has momentum. | ||
131 | // | ||
132 | |||
133 | void P_XYMovement (mobj_t* mo) | ||
134 | { | ||
135 | player_t *player; | ||
136 | fixed_t xmove, ymove; | ||
137 | #if 0 | ||
138 | fixed_t ptryx; | ||
139 | fixed_t ptryy; | ||
140 | fixed_t xmove; | ||
141 | fixed_t ymove; | ||
142 | fixed_t oldx,oldy; // phares 9/10/98: reducing bobbing/momentum on ice | ||
143 | // when up against walls | ||
144 | #endif | ||
145 | if (!(mo->momx | mo->momy)) // Any momentum? | ||
146 | { | ||
147 | if (mo->flags & MF_SKULLFLY) | ||
148 | { | ||
149 | |||
150 | // the skull slammed into something | ||
151 | |||
152 | mo->flags &= ~MF_SKULLFLY; | ||
153 | mo->momz = 0; | ||
154 | |||
155 | P_SetMobjState (mo, mo->info->spawnstate); | ||
156 | } | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | player = mo->player; | ||
161 | |||
162 | if (mo->momx > MAXMOVE) | ||
163 | mo->momx = MAXMOVE; | ||
164 | else if (mo->momx < -MAXMOVE) | ||
165 | mo->momx = -MAXMOVE; | ||
166 | |||
167 | if (mo->momy > MAXMOVE) | ||
168 | mo->momy = MAXMOVE; | ||
169 | else if (mo->momy < -MAXMOVE) | ||
170 | mo->momy = -MAXMOVE; | ||
171 | |||
172 | xmove = mo->momx; | ||
173 | ymove = mo->momy; | ||
174 | |||
175 | #if 0 | ||
176 | oldx = mo->x; // phares 9/10/98: new code to reduce bobbing/momentum | ||
177 | oldy = mo->y; // when on ice & up against wall. These will be compared | ||
178 | // to your x,y values later to see if you were able to move | ||
179 | #endif | ||
180 | |||
181 | do | ||
182 | { | ||
183 | fixed_t ptryx, ptryy; | ||
184 | // killough 8/9/98: fix bug in original Doom source: | ||
185 | // Large negative displacements were never considered. | ||
186 | // This explains the tendency for Mancubus fireballs | ||
187 | // to pass through walls. | ||
188 | // CPhipps - compatibility optioned | ||
189 | |||
190 | if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2 || | ||
191 | (!comp[comp_moveblock] | ||
192 | && (xmove < -MAXMOVE/2 || ymove < -MAXMOVE/2))) | ||
193 | { | ||
194 | ptryx = mo->x + xmove/2; | ||
195 | ptryy = mo->y + ymove/2; | ||
196 | xmove >>= 1; | ||
197 | ymove >>= 1; | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | ptryx = mo->x + xmove; | ||
202 | ptryy = mo->y + ymove; | ||
203 | xmove = ymove = 0; | ||
204 | } | ||
205 | |||
206 | // killough 3/15/98: Allow objects to drop off | ||
207 | |||
208 | if (!P_TryMove (mo, ptryx, ptryy, true)) | ||
209 | { | ||
210 | // blocked move | ||
211 | |||
212 | // killough 8/11/98: bouncing off walls | ||
213 | // killough 10/98: | ||
214 | // Add ability for objects other than players to bounce on ice | ||
215 | |||
216 | if (!(mo->flags & MF_MISSILE) && | ||
217 | mbf_features && | ||
218 | (mo->flags & MF_BOUNCES || | ||
219 | (!player && blockline && | ||
220 | variable_friction && mo->z <= mo->floorz && | ||
221 | P_GetFriction(mo, NULL) > ORIG_FRICTION))) | ||
222 | { | ||
223 | if (blockline) | ||
224 | { | ||
225 | fixed_t r = ((blockline->dx >> FRACBITS) * mo->momx + | ||
226 | (blockline->dy >> FRACBITS) * mo->momy) / | ||
227 | ((blockline->dx >> FRACBITS)*(blockline->dx >> FRACBITS)+ | ||
228 | (blockline->dy >> FRACBITS)*(blockline->dy >> FRACBITS)); | ||
229 | fixed_t x = FixedMul(r, blockline->dx); | ||
230 | fixed_t y = FixedMul(r, blockline->dy); | ||
231 | |||
232 | // reflect momentum away from wall | ||
233 | |||
234 | mo->momx = x*2 - mo->momx; | ||
235 | mo->momy = y*2 - mo->momy; | ||
236 | |||
237 | // if under gravity, slow down in | ||
238 | // direction perpendicular to wall. | ||
239 | |||
240 | if (!(mo->flags & MF_NOGRAVITY)) | ||
241 | { | ||
242 | mo->momx = (mo->momx + x)/2; | ||
243 | mo->momy = (mo->momy + y)/2; | ||
244 | } | ||
245 | } | ||
246 | else | ||
247 | mo->momx = mo->momy = 0; | ||
248 | } | ||
249 | else | ||
250 | if (player) // try to slide along it | ||
251 | P_SlideMove (mo); | ||
252 | else | ||
253 | if (mo->flags & MF_MISSILE) | ||
254 | { | ||
255 | // explode a missile | ||
256 | |||
257 | if (ceilingline && | ||
258 | ceilingline->backsector && | ||
259 | ceilingline->backsector->ceilingpic == skyflatnum) | ||
260 | if (demo_compatibility || // killough | ||
261 | mo->z > ceilingline->backsector->ceilingheight) | ||
262 | { | ||
263 | // Hack to prevent missiles exploding | ||
264 | // against the sky. | ||
265 | // Does not handle sky floors. | ||
266 | |||
267 | P_RemoveMobj (mo); | ||
268 | return; | ||
269 | } | ||
270 | P_ExplodeMissile (mo); | ||
271 | } | ||
272 | else // whatever else it is, it is now standing still in (x,y) | ||
273 | mo->momx = mo->momy = 0; | ||
274 | } | ||
275 | } while (xmove || ymove); | ||
276 | |||
277 | // slow down | ||
278 | |||
279 | #if 0 /* killough 10/98: this is unused code (except maybe in .deh files?) */ | ||
280 | if (player && player->cheats & CF_NOMOMENTUM) | ||
281 | { | ||
282 | // debug option for no sliding at all | ||
283 | mo->momx = mo->momy = 0; | ||
284 | player->momx = player->momy = 0; /* killough 10/98 */ | ||
285 | return; | ||
286 | } | ||
287 | #endif | ||
288 | |||
289 | /* no friction for missiles or skulls ever, no friction when airborne */ | ||
290 | if (mo->flags & (MF_MISSILE | MF_SKULLFLY) || mo->z > mo->floorz) | ||
291 | return; | ||
292 | |||
293 | /* killough 8/11/98: add bouncers | ||
294 | * killough 9/15/98: add objects falling off ledges | ||
295 | * killough 11/98: only include bouncers hanging off ledges | ||
296 | */ | ||
297 | if (((mo->flags & MF_BOUNCES && mo->z > mo->dropoffz) || | ||
298 | mo->flags & MF_CORPSE || mo->intflags & MIF_FALLING) && | ||
299 | (mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4 || | ||
300 | mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4) && | ||
301 | mo->floorz != mo->subsector->sector->floorheight) | ||
302 | return; // do not stop sliding if halfway off a step with some momentum | ||
303 | |||
304 | // killough 11/98: | ||
305 | // Stop voodoo dolls that have come to rest, despite any | ||
306 | // moving corresponding player, except in old demos: | ||
307 | |||
308 | if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED && | ||
309 | mo->momy > -STOPSPEED && mo->momy < STOPSPEED && | ||
310 | (!player || !(player->cmd.forwardmove | player->cmd.sidemove) || | ||
311 | (player->mo != mo && compatibility_level >= lxdoom_1_compatibility))) | ||
312 | { | ||
313 | // if in a walking frame, stop moving | ||
314 | |||
315 | // killough 10/98: | ||
316 | // Don't affect main player when voodoo dolls stop, except in old demos: | ||
317 | |||
318 | if (player && (unsigned)(player->mo->state - states - S_PLAY_RUN1) < 4 | ||
319 | && (player->mo == mo || compatibility_level >= lxdoom_1_compatibility)) | ||
320 | P_SetMobjState(player->mo, S_PLAY); | ||
321 | |||
322 | mo->momx = mo->momy = 0; | ||
323 | |||
324 | /* killough 10/98: kill any bobbing momentum too (except in voodoo dolls) | ||
325 | * cph - DEMOSYNC - needs compatibility check? | ||
326 | */ | ||
327 | if (player && player->mo == mo) | ||
328 | player->momx = player->momy = 0; | ||
329 | } | ||
330 | else | ||
331 | { | ||
332 | /* phares 3/17/98 | ||
333 | * | ||
334 | * Friction will have been adjusted by friction thinkers for | ||
335 | * icy or muddy floors. Otherwise it was never touched and | ||
336 | * remained set at ORIG_FRICTION | ||
337 | * | ||
338 | * killough 8/28/98: removed inefficient thinker algorithm, | ||
339 | * instead using touching_sectorlist in P_GetFriction() to | ||
340 | * determine friction (and thus only when it is needed). | ||
341 | * | ||
342 | * killough 10/98: changed to work with new bobbing method. | ||
343 | * Reducing player momentum is no longer needed to reduce | ||
344 | * bobbing, so ice works much better now. | ||
345 | * | ||
346 | * cph - DEMOSYNC - need old code for Boom demos? | ||
347 | */ | ||
348 | |||
349 | fixed_t friction = P_GetFriction(mo, NULL); | ||
350 | |||
351 | mo->momx = FixedMul(mo->momx, friction); | ||
352 | mo->momy = FixedMul(mo->momy, friction); | ||
353 | |||
354 | /* killough 10/98: Always decrease player bobbing by ORIG_FRICTION. | ||
355 | * This prevents problems with bobbing on ice, where it was not being | ||
356 | * reduced fast enough, leading to all sorts of kludges being developed. | ||
357 | */ | ||
358 | |||
359 | if (player && player->mo == mo) /* Not voodoo dolls */ | ||
360 | { | ||
361 | player->momx = FixedMul(player->momx, ORIG_FRICTION); | ||
362 | player->momy = FixedMul(player->momy, ORIG_FRICTION); | ||
363 | } | ||
364 | |||
365 | } | ||
366 | } | ||
367 | |||
368 | |||
369 | // | ||
370 | // P_ZMovement | ||
371 | // | ||
372 | // Attempt vertical movement. | ||
373 | |||
374 | static void P_ZMovement (mobj_t* mo) | ||
375 | { | ||
376 | /* killough 7/11/98: | ||
377 | * BFG fireballs bounced on floors and ceilings in Pre-Beta Doom | ||
378 | * killough 8/9/98: added support for non-missile objects bouncing | ||
379 | * (e.g. grenade, mine, pipebomb) | ||
380 | */ | ||
381 | |||
382 | if (mo->flags & MF_BOUNCES && mo->momz) { | ||
383 | mo->z += mo->momz; | ||
384 | if (mo->z <= mo->floorz) { /* bounce off floors */ | ||
385 | mo->z = mo->floorz; | ||
386 | if (mo->momz < 0) { | ||
387 | mo->momz = -mo->momz; | ||
388 | if (!(mo->flags & MF_NOGRAVITY)) { /* bounce back with decay */ | ||
389 | mo->momz = mo->flags & MF_FLOAT ? // floaters fall slowly | ||
390 | mo->flags & MF_DROPOFF ? // DROPOFF indicates rate | ||
391 | FixedMul(mo->momz, (fixed_t)(FRACUNIT*.85)) : | ||
392 | FixedMul(mo->momz, (fixed_t)(FRACUNIT*.70)) : | ||
393 | FixedMul(mo->momz, (fixed_t)(FRACUNIT*.45)) ; | ||
394 | |||
395 | /* Bring it to rest below a certain speed */ | ||
396 | if (abs(mo->momz) <= mo->info->mass*(GRAVITY*4/256)) | ||
397 | mo->momz = 0; | ||
398 | } | ||
399 | |||
400 | /* killough 11/98: touchy objects explode on impact */ | ||
401 | if (mo->flags & MF_TOUCHY && mo->intflags & MIF_ARMED | ||
402 | && mo->health > 0) | ||
403 | P_DamageMobj(mo, NULL, NULL, mo->health); | ||
404 | else if (mo->flags & MF_FLOAT && sentient(mo)) | ||
405 | goto floater; | ||
406 | return; | ||
407 | } | ||
408 | } else if (mo->z >= mo->ceilingz - mo->height) { | ||
409 | /* bounce off ceilings */ | ||
410 | mo->z = mo->ceilingz - mo->height; | ||
411 | if (mo->momz > 0) { | ||
412 | if (mo->subsector->sector->ceilingpic != skyflatnum) | ||
413 | mo->momz = -mo->momz; /* always bounce off non-sky ceiling */ | ||
414 | else if (mo->flags & MF_MISSILE) | ||
415 | P_RemoveMobj(mo); /* missiles don't bounce off skies */ | ||
416 | else if (mo->flags & MF_NOGRAVITY) | ||
417 | mo->momz = -mo->momz; // bounce unless under gravity | ||
418 | |||
419 | if (mo->flags & MF_FLOAT && sentient(mo)) | ||
420 | goto floater; | ||
421 | |||
422 | return; | ||
423 | } | ||
424 | } else { | ||
425 | if (!(mo->flags & MF_NOGRAVITY)) /* free-fall under gravity */ | ||
426 | mo->momz -= mo->info->mass*(GRAVITY/256); | ||
427 | |||
428 | if (mo->flags & MF_FLOAT && sentient(mo)) goto floater; | ||
429 | return; | ||
430 | } | ||
431 | |||
432 | /* came to a stop */ | ||
433 | mo->momz = 0; | ||
434 | |||
435 | if (mo->flags & MF_MISSILE) { | ||
436 | if (ceilingline && | ||
437 | ceilingline->backsector && | ||
438 | ceilingline->backsector->ceilingpic == skyflatnum && | ||
439 | mo->z > ceilingline->backsector->ceilingheight) | ||
440 | P_RemoveMobj(mo); /* don't explode on skies */ | ||
441 | else | ||
442 | P_ExplodeMissile(mo); | ||
443 | } | ||
444 | |||
445 | if (mo->flags & MF_FLOAT && sentient(mo)) goto floater; | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | /* killough 8/9/98: end bouncing object code */ | ||
450 | |||
451 | // check for smooth step up | ||
452 | |||
453 | if (mo->player && | ||
454 | mo->player->mo == mo && // killough 5/12/98: exclude voodoo dolls | ||
455 | mo->z < mo->floorz) | ||
456 | { | ||
457 | mo->player->viewheight -= mo->floorz-mo->z; | ||
458 | mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3; | ||
459 | } | ||
460 | |||
461 | // adjust altitude | ||
462 | |||
463 | mo->z += mo->momz; | ||
464 | |||
465 | floater: | ||
466 | if ((mo->flags & MF_FLOAT) && mo->target) | ||
467 | |||
468 | // float down towards target if too close | ||
469 | |||
470 | if (!((mo->flags ^ MF_FLOAT) & (MF_FLOAT | MF_SKULLFLY | MF_INFLOAT)) && | ||
471 | mo->target) /* killough 11/98: simplify */ | ||
472 | { | ||
473 | fixed_t delta; | ||
474 | if (P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y) < | ||
475 | abs(delta = mo->target->z + (mo->height>>1) - mo->z)*3) | ||
476 | mo->z += delta < 0 ? -FLOATSPEED : FLOATSPEED; | ||
477 | } | ||
478 | |||
479 | // clip movement | ||
480 | |||
481 | if (mo->z <= mo->floorz) | ||
482 | { | ||
483 | // hit the floor | ||
484 | |||
485 | /* Note (id): | ||
486 | * somebody left this after the setting momz to 0, | ||
487 | * kinda useless there. | ||
488 | * cph - This was the a bug in the linuxdoom-1.10 source which | ||
489 | * caused it not to sync Doom 2 v1.9 demos. Someone | ||
490 | * added the above comment and moved up the following code. So | ||
491 | * demos would desync in close lost soul fights. | ||
492 | * Note that this only applies to original Doom 1 or Doom2 demos - | ||
493 | * Final Doom and Ultimate Doom. So we test demo_compatibility *and* | ||
494 | * gamemission. (Note we assume that Doom1 is always Ult Doom, which | ||
495 | * seems to hold for most published demos.) | ||
496 | */ | ||
497 | int correct_lost_soul_bounce = !demo_compatibility || (gamemission != doom2); | ||
498 | |||
499 | if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) | ||
500 | mo->momz = -mo->momz; // the skull slammed into something | ||
501 | |||
502 | if (mo->momz < 0) | ||
503 | { | ||
504 | /* killough 11/98: touchy objects explode on impact */ | ||
505 | if (mo->flags & MF_TOUCHY && mo->intflags & MIF_ARMED && mo->health > 0) | ||
506 | P_DamageMobj(mo, NULL, NULL, mo->health); | ||
507 | else | ||
508 | if (mo->player && /* killough 5/12/98: exclude voodoo dolls */ | ||
509 | mo->player->mo == mo && mo->momz < -GRAVITY*8) | ||
510 | { | ||
511 | // Squat down. | ||
512 | // Decrease viewheight for a moment | ||
513 | // after hitting the ground (hard), | ||
514 | // and utter appropriate sound. | ||
515 | |||
516 | mo->player->deltaviewheight = mo->momz>>3; | ||
517 | if (mo->health) /* cph - prevent "oof" when dead */ | ||
518 | S_StartSound (mo, sfx_oof); | ||
519 | } | ||
520 | mo->momz = 0; | ||
521 | } | ||
522 | mo->z = mo->floorz; | ||
523 | |||
524 | /* cph 2001/05/26 - | ||
525 | * See lost soul bouncing comment above. We need this here for bug | ||
526 | * compatibility with original Doom2 v1.9 - if a soul is charging and | ||
527 | * hit by a raising floor this incorrectly reverses its Y momentum. | ||
528 | */ | ||
529 | if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) | ||
530 | mo->momz = -mo->momz; // the skull slammed into something | ||
531 | |||
532 | if ( (mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP) ) | ||
533 | { | ||
534 | P_ExplodeMissile (mo); | ||
535 | return; | ||
536 | } | ||
537 | } | ||
538 | else // still above the floor // phares | ||
539 | if (!(mo->flags & MF_NOGRAVITY)) | ||
540 | { | ||
541 | if (!mo->momz) | ||
542 | mo->momz = -GRAVITY; | ||
543 | mo->momz -= GRAVITY; | ||
544 | } | ||
545 | |||
546 | if (mo->z + mo->height > mo->ceilingz) | ||
547 | { | ||
548 | |||
549 | // hit the ceiling | ||
550 | |||
551 | if (mo->momz > 0) | ||
552 | mo->momz = 0; | ||
553 | |||
554 | mo->z = mo->ceilingz - mo->height; | ||
555 | |||
556 | if (mo->flags & MF_SKULLFLY) | ||
557 | mo->momz = -mo->momz; // the skull slammed into something | ||
558 | |||
559 | if ( (mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP) ) | ||
560 | { | ||
561 | P_ExplodeMissile (mo); | ||
562 | return; | ||
563 | } | ||
564 | } | ||
565 | } | ||
566 | |||
567 | // | ||
568 | // P_NightmareRespawn | ||
569 | // | ||
570 | |||
571 | void P_NightmareRespawn(mobj_t* mobj) | ||
572 | { | ||
573 | fixed_t x; | ||
574 | fixed_t y; | ||
575 | fixed_t z; | ||
576 | subsector_t* ss; | ||
577 | mobj_t* mo; | ||
578 | mapthing_t* mthing; | ||
579 | |||
580 | x = mobj->spawnpoint.x << FRACBITS; | ||
581 | y = mobj->spawnpoint.y << FRACBITS; | ||
582 | |||
583 | /* haleyjd: stupid nightmare respawning bug fix | ||
584 | * | ||
585 | * 08/09/00: compatibility added, time to ramble :) | ||
586 | * This fixes the notorious nightmare respawning bug that causes monsters | ||
587 | * that didn't spawn at level startup to respawn at the point (0,0) | ||
588 | * regardless of that point's nature. SMMU and Eternity need this for | ||
589 | * script-spawned things like Halif Swordsmythe, as well. | ||
590 | * | ||
591 | * cph - copied from eternity, except comp_respawnfix becomes comp_respawn | ||
592 | * and the logic is reversed (i.e. like the rest of comp_ it *disables* | ||
593 | * the fix) | ||
594 | */ | ||
595 | if(!comp[comp_respawn] && !x && !y) | ||
596 | { | ||
597 | // spawnpoint was zeroed out, so use point of death instead | ||
598 | x = mobj->x; | ||
599 | y = mobj->y; | ||
600 | } | ||
601 | |||
602 | // something is occupying its position? | ||
603 | |||
604 | if (!P_CheckPosition (mobj, x, y) ) | ||
605 | return; // no respwan | ||
606 | |||
607 | // spawn a teleport fog at old spot | ||
608 | // because of removal of the body? | ||
609 | |||
610 | mo = P_SpawnMobj (mobj->x, | ||
611 | mobj->y, | ||
612 | mobj->subsector->sector->floorheight, | ||
613 | MT_TFOG); | ||
614 | |||
615 | // initiate teleport sound | ||
616 | |||
617 | S_StartSound (mo, sfx_telept); | ||
618 | |||
619 | // spawn a teleport fog at the new spot | ||
620 | |||
621 | ss = R_PointInSubsector (x,y); | ||
622 | |||
623 | mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG); | ||
624 | |||
625 | S_StartSound (mo, sfx_telept); | ||
626 | |||
627 | // spawn the new monster | ||
628 | |||
629 | mthing = &mobj->spawnpoint; | ||
630 | if (mobj->info->flags & MF_SPAWNCEILING) | ||
631 | z = ONCEILINGZ; | ||
632 | else | ||
633 | z = ONFLOORZ; | ||
634 | |||
635 | // inherit attributes from deceased one | ||
636 | |||
637 | mo = P_SpawnMobj (x,y,z, mobj->type); | ||
638 | mo->spawnpoint = mobj->spawnpoint; | ||
639 | mo->angle = ANG45 * (mthing->angle/45); | ||
640 | |||
641 | if (mthing->options & MTF_AMBUSH) | ||
642 | mo->flags |= MF_AMBUSH; | ||
643 | |||
644 | /* killough 11/98: transfer friendliness from deceased */ | ||
645 | mo->flags = (mo->flags & ~MF_FRIEND) | (mobj->flags & MF_FRIEND); | ||
646 | |||
647 | mo->reactiontime = 18; | ||
648 | |||
649 | // remove the old monster, | ||
650 | |||
651 | P_RemoveMobj (mobj); | ||
652 | } | ||
653 | |||
654 | |||
655 | // | ||
656 | // P_MobjThinker | ||
657 | // | ||
658 | |||
659 | void P_MobjThinker (mobj_t* mobj) | ||
660 | { | ||
661 | // killough 11/98: | ||
662 | // removed old code which looked at target references | ||
663 | // (we use pointer reference counting now) | ||
664 | |||
665 | // momentum movement | ||
666 | if (mobj->momx | mobj->momy || mobj->flags & MF_SKULLFLY) | ||
667 | { | ||
668 | P_XYMovement(mobj); | ||
669 | if (mobj->thinker.function != P_MobjThinker) // cph - Must've been removed | ||
670 | return; // killough - mobj was removed | ||
671 | } | ||
672 | |||
673 | if (mobj->z != mobj->floorz || mobj->momz) | ||
674 | { | ||
675 | P_ZMovement(mobj); | ||
676 | if (mobj->thinker.function != P_MobjThinker) // cph - Must've been removed | ||
677 | return; // killough - mobj was removed | ||
678 | } | ||
679 | else | ||
680 | if (!(mobj->momx | mobj->momy) && !sentient(mobj)) | ||
681 | { // non-sentient objects at rest | ||
682 | mobj->intflags |= MIF_ARMED; // arm a mine which has come to rest | ||
683 | |||
684 | // killough 9/12/98: objects fall off ledges if they are hanging off | ||
685 | // slightly push off of ledge if hanging more than halfway off | ||
686 | |||
687 | if (mobj->z > mobj->dropoffz && // Only objects contacting dropoff | ||
688 | !(mobj->flags & MF_NOGRAVITY) && // Only objects which fall | ||
689 | !comp[comp_falloff]) // Not in old demos | ||
690 | P_ApplyTorque(mobj); // Apply torque | ||
691 | else | ||
692 | mobj->intflags &= ~MIF_FALLING, mobj->gear = 0; // Reset torque | ||
693 | } | ||
694 | |||
695 | // cycle through states, | ||
696 | // calling action functions at transitions | ||
697 | |||
698 | if (mobj->tics != -1) | ||
699 | { | ||
700 | mobj->tics--; | ||
701 | |||
702 | // you can cycle through multiple states in a tic | ||
703 | |||
704 | if (!mobj->tics) | ||
705 | if (!P_SetMobjState (mobj, mobj->state->nextstate) ) | ||
706 | return; // freed itself | ||
707 | } | ||
708 | else | ||
709 | { | ||
710 | |||
711 | // check for nightmare respawn | ||
712 | |||
713 | if (! (mobj->flags & MF_COUNTKILL) ) | ||
714 | return; | ||
715 | |||
716 | if (!respawnmonsters) | ||
717 | return; | ||
718 | |||
719 | mobj->movecount++; | ||
720 | |||
721 | if (mobj->movecount < 12*35) | ||
722 | return; | ||
723 | |||
724 | if (leveltime & 31) | ||
725 | return; | ||
726 | |||
727 | if (P_Random (pr_respawn) > 4) | ||
728 | return; | ||
729 | |||
730 | P_NightmareRespawn (mobj); | ||
731 | } | ||
732 | |||
733 | } | ||
734 | |||
735 | |||
736 | // | ||
737 | // P_SpawnMobj | ||
738 | // | ||
739 | mobj_t* P_SpawnMobj(fixed_t x,fixed_t y,fixed_t z,mobjtype_t type) | ||
740 | { | ||
741 | mobj_t* mobj; | ||
742 | state_t* st; | ||
743 | mobjinfo_t* info; | ||
744 | |||
745 | mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); | ||
746 | memset (mobj, 0, sizeof (*mobj)); | ||
747 | info = &mobjinfo[type]; | ||
748 | mobj->type = type; | ||
749 | mobj->info = info; | ||
750 | mobj->x = x; | ||
751 | mobj->y = y; | ||
752 | mobj->radius = info->radius; | ||
753 | mobj->height = info->height; // phares | ||
754 | mobj->flags = info->flags; | ||
755 | |||
756 | /* killough 8/23/98: no friends, bouncers, or touchy things in old demos */ | ||
757 | if (!mbf_features) | ||
758 | mobj->flags &= ~(MF_BOUNCES | MF_FRIEND | MF_TOUCHY); | ||
759 | else | ||
760 | if (type == MT_PLAYER) // Except in old demos, players | ||
761 | mobj->flags |= MF_FRIEND; // are always friends. | ||
762 | |||
763 | mobj->health = info->spawnhealth; | ||
764 | |||
765 | if (gameskill != sk_nightmare) | ||
766 | mobj->reactiontime = info->reactiontime; | ||
767 | |||
768 | mobj->lastlook = P_Random (pr_lastlook) % MAXPLAYERS; | ||
769 | |||
770 | // do not set the state with P_SetMobjState, | ||
771 | // because action routines can not be called yet | ||
772 | |||
773 | st = &states[info->spawnstate]; | ||
774 | |||
775 | mobj->state = st; | ||
776 | mobj->tics = st->tics; | ||
777 | mobj->sprite = st->sprite; | ||
778 | mobj->frame = st->frame; | ||
779 | mobj->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98 | ||
780 | |||
781 | // set subsector and/or block links | ||
782 | |||
783 | P_SetThingPosition (mobj); | ||
784 | |||
785 | mobj->dropoffz = /* killough 11/98: for tracking dropoffs */ | ||
786 | mobj->floorz = mobj->subsector->sector->floorheight; | ||
787 | mobj->ceilingz = mobj->subsector->sector->ceilingheight; | ||
788 | |||
789 | mobj->z = z == ONFLOORZ ? mobj->floorz : z == ONCEILINGZ ? | ||
790 | mobj->ceilingz - mobj->height : z; | ||
791 | |||
792 | mobj->thinker.function = P_MobjThinker; | ||
793 | mobj->above_thing = 0; // phares | ||
794 | mobj->below_thing = 0; // phares | ||
795 | |||
796 | mobj->target = mobj->tracer = mobj->lastenemy = NULL; | ||
797 | P_AddThinker (&mobj->thinker); | ||
798 | if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL))) | ||
799 | totallive++; | ||
800 | return mobj; | ||
801 | } | ||
802 | |||
803 | |||
804 | mapthing_t itemrespawnque[ITEMQUESIZE]; | ||
805 | int itemrespawntime[ITEMQUESIZE]; | ||
806 | int iquehead; | ||
807 | int iquetail; | ||
808 | |||
809 | |||
810 | // | ||
811 | // P_RemoveMobj | ||
812 | // | ||
813 | |||
814 | void P_RemoveMobj (mobj_t* mobj) | ||
815 | { | ||
816 | if ((mobj->flags & MF_SPECIAL) | ||
817 | && !(mobj->flags & MF_DROPPED) | ||
818 | && (mobj->type != MT_INV) | ||
819 | && (mobj->type != MT_INS)) | ||
820 | { | ||
821 | itemrespawnque[iquehead] = mobj->spawnpoint; | ||
822 | itemrespawntime[iquehead] = leveltime; | ||
823 | iquehead = (iquehead+1)&(ITEMQUESIZE-1); | ||
824 | |||
825 | // lose one off the end? | ||
826 | |||
827 | if (iquehead == iquetail) | ||
828 | iquetail = (iquetail+1)&(ITEMQUESIZE-1); | ||
829 | } | ||
830 | |||
831 | // unlink from sector and block lists | ||
832 | |||
833 | P_UnsetThingPosition (mobj); | ||
834 | |||
835 | // Delete all nodes on the current sector_list phares 3/16/98 | ||
836 | |||
837 | if (sector_list) | ||
838 | { | ||
839 | P_DelSeclist(sector_list); | ||
840 | sector_list = NULL; | ||
841 | } | ||
842 | |||
843 | // stop any playing sound | ||
844 | |||
845 | S_StopSound (mobj); | ||
846 | |||
847 | // killough 11/98: | ||
848 | // | ||
849 | // Remove any references to other mobjs. | ||
850 | // | ||
851 | // Older demos might depend on the fields being left alone, however, | ||
852 | // if multiple thinkers reference each other indirectly before the | ||
853 | // end of the current tic. | ||
854 | // CPhipps - only leave dead references in old demos; I hope lxdoom_1 level | ||
855 | // demos are rare and don't rely on this. I hope. | ||
856 | |||
857 | if ((compatibility_level >= lxdoom_1_compatibility) || | ||
858 | (!demorecording && !demoplayback)) { | ||
859 | P_SetTarget(&mobj->target, NULL); | ||
860 | P_SetTarget(&mobj->tracer, NULL); | ||
861 | P_SetTarget(&mobj->lastenemy, NULL); | ||
862 | } | ||
863 | // free block | ||
864 | |||
865 | // P_RemoveThinker ((thinker_t*)mobj); | ||
866 | P_RemoveThinker (&mobj->thinker); | ||
867 | } | ||
868 | |||
869 | |||
870 | /* | ||
871 | * P_FindDoomedNum | ||
872 | * | ||
873 | * Finds a mobj type with a matching doomednum | ||
874 | * | ||
875 | * killough 8/24/98: rewrote to use hashing | ||
876 | */ | ||
877 | |||
878 | int P_FindDoomedNum(unsigned type) | ||
879 | { | ||
880 | static struct { int first, next; } *hash; | ||
881 | register int i; | ||
882 | |||
883 | if (!hash) | ||
884 | { | ||
885 | hash = Z_Malloc(sizeof (*hash) * NUMMOBJTYPES, PU_CACHE, (void*)(void*) &hash); | ||
886 | for (i=0; i<NUMMOBJTYPES; i++) | ||
887 | hash[i].first = NUMMOBJTYPES; | ||
888 | for (i=0; i<NUMMOBJTYPES; i++) | ||
889 | if (mobjinfo[i].doomednum != -1) | ||
890 | { | ||
891 | unsigned h = (unsigned) mobjinfo[i].doomednum % NUMMOBJTYPES; | ||
892 | hash[i].next = hash[h].first; | ||
893 | hash[h].first = i; | ||
894 | } | ||
895 | } | ||
896 | |||
897 | i = hash[type % NUMMOBJTYPES].first; | ||
898 | while ((i < NUMMOBJTYPES) && ((unsigned)mobjinfo[i].doomednum != type)) | ||
899 | i = hash[i].next; | ||
900 | return i; | ||
901 | } | ||
902 | |||
903 | // | ||
904 | // P_RespawnSpecials | ||
905 | // | ||
906 | |||
907 | void P_RespawnSpecials (void) | ||
908 | { | ||
909 | fixed_t x; | ||
910 | fixed_t y; | ||
911 | fixed_t z; | ||
912 | subsector_t* ss; | ||
913 | mobj_t* mo; | ||
914 | mapthing_t* mthing; | ||
915 | int i; | ||
916 | |||
917 | // only respawn items in deathmatch | ||
918 | |||
919 | if (deathmatch != 2) | ||
920 | return; | ||
921 | |||
922 | // nothing left to respawn? | ||
923 | |||
924 | if (iquehead == iquetail) | ||
925 | return; | ||
926 | |||
927 | // wait at least 30 seconds | ||
928 | |||
929 | if (leveltime - itemrespawntime[iquetail] < 30*35) | ||
930 | return; | ||
931 | |||
932 | mthing = &itemrespawnque[iquetail]; | ||
933 | |||
934 | x = mthing->x << FRACBITS; | ||
935 | y = mthing->y << FRACBITS; | ||
936 | |||
937 | // spawn a teleport fog at the new spot | ||
938 | |||
939 | ss = R_PointInSubsector (x,y); | ||
940 | mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); | ||
941 | S_StartSound (mo, sfx_itmbk); | ||
942 | |||
943 | // find which type to spawn | ||
944 | |||
945 | /* killough 8/23/98: use table for faster lookup */ | ||
946 | i = P_FindDoomedNum(mthing->type); | ||
947 | |||
948 | // spawn it | ||
949 | |||
950 | if (mobjinfo[i].flags & MF_SPAWNCEILING) | ||
951 | z = ONCEILINGZ; | ||
952 | else | ||
953 | z = ONFLOORZ; | ||
954 | |||
955 | mo = P_SpawnMobj (x,y,z, i); | ||
956 | mo->spawnpoint = *mthing; | ||
957 | mo->angle = ANG45 * (mthing->angle/45); | ||
958 | |||
959 | // pull it from the queue | ||
960 | |||
961 | iquetail = (iquetail+1)&(ITEMQUESIZE-1); | ||
962 | } | ||
963 | |||
964 | // | ||
965 | // P_SpawnPlayer | ||
966 | // Called when a player is spawned on the level. | ||
967 | // Most of the player structure stays unchanged | ||
968 | // between levels. | ||
969 | // | ||
970 | |||
971 | extern byte playernumtotrans[MAXPLAYERS]; | ||
972 | |||
973 | void P_SpawnPlayer (mapthing_t* mthing) | ||
974 | { | ||
975 | player_t* p; | ||
976 | fixed_t x; | ||
977 | fixed_t y; | ||
978 | fixed_t z; | ||
979 | mobj_t* mobj; | ||
980 | int i; | ||
981 | |||
982 | // not playing? | ||
983 | |||
984 | if (!playeringame[mthing->type-1]) | ||
985 | return; | ||
986 | |||
987 | p = &players[mthing->type-1]; | ||
988 | |||
989 | if (p->playerstate == PST_REBORN) | ||
990 | G_PlayerReborn (mthing->type-1); | ||
991 | |||
992 | x = mthing->x << FRACBITS; | ||
993 | y = mthing->y << FRACBITS; | ||
994 | z = ONFLOORZ; | ||
995 | mobj = P_SpawnMobj (x,y,z, MT_PLAYER); | ||
996 | |||
997 | // set color translations for player sprites | ||
998 | |||
999 | if (mthing->type > 0) | ||
1000 | mobj->flags |= playernumtotrans[mthing->type-1]<<MF_TRANSSHIFT; | ||
1001 | |||
1002 | mobj->angle = ANG45 * (mthing->angle/45); | ||
1003 | mobj->player = p; | ||
1004 | mobj->health = p->health; | ||
1005 | |||
1006 | p->mo = mobj; | ||
1007 | p->playerstate = PST_LIVE; | ||
1008 | p->refire = 0; | ||
1009 | p->message = NULL; | ||
1010 | p->damagecount = 0; | ||
1011 | p->bonuscount = 0; | ||
1012 | p->extralight = 0; | ||
1013 | p->fixedcolormap = 0; | ||
1014 | p->viewheight = VIEWHEIGHT; | ||
1015 | |||
1016 | p->momx = p->momy = 0; // killough 10/98: initialize bobbing to 0. | ||
1017 | |||
1018 | // setup gun psprite | ||
1019 | |||
1020 | P_SetupPsprites (p); | ||
1021 | |||
1022 | // give all cards in death match mode | ||
1023 | |||
1024 | if (deathmatch) | ||
1025 | for (i = 0 ; i < NUMCARDS ; i++) | ||
1026 | p->cards[i] = true; | ||
1027 | |||
1028 | if (mthing->type-1 == consoleplayer) | ||
1029 | { | ||
1030 | ST_Start(); // wake up the status bar | ||
1031 | HU_Start(); // wake up the heads up text | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | // | ||
1037 | // P_SpawnMapThing | ||
1038 | // The fields of the mapthing should | ||
1039 | // already be in host byte order. | ||
1040 | // | ||
1041 | |||
1042 | void P_SpawnMapThing (mapthing_t* mthing) | ||
1043 | { | ||
1044 | int i; | ||
1045 | //int bit; | ||
1046 | mobj_t* mobj; | ||
1047 | fixed_t x; | ||
1048 | fixed_t y; | ||
1049 | fixed_t z; | ||
1050 | |||
1051 | // killough 2/26/98: Ignore type-0 things as NOPs | ||
1052 | // phares 5/14/98: Ignore Player 5-8 starts (for now) | ||
1053 | |||
1054 | switch(mthing->type) | ||
1055 | { | ||
1056 | case 0: | ||
1057 | case DEN_PLAYER5: | ||
1058 | case DEN_PLAYER6: | ||
1059 | case DEN_PLAYER7: | ||
1060 | case DEN_PLAYER8: | ||
1061 | return; | ||
1062 | } | ||
1063 | |||
1064 | // killough 11/98: clear flags unused by Doom | ||
1065 | // | ||
1066 | // We clear the flags unused in Doom if we see flag mask 256 set, since | ||
1067 | // it is reserved to be 0 under the new scheme. A 1 in this reserved bit | ||
1068 | // indicates it's a Doom wad made by a Doom editor which puts 1's in | ||
1069 | // bits that weren't used in Doom (such as HellMaker wads). So we should | ||
1070 | // then simply ignore all upper bits. | ||
1071 | |||
1072 | if (demo_compatibility || | ||
1073 | (compatibility_level >= lxdoom_1_compatibility && | ||
1074 | mthing->options & MTF_RESERVED)) { | ||
1075 | if (!demo_compatibility) // cph - Add warning about bad thing flags | ||
1076 | printf("P_SpawnMapThing: correcting bad flags (%u) (thing type %d)\n", | ||
1077 | mthing->options, mthing->type); | ||
1078 | mthing->options &= MTF_EASY|MTF_NORMAL|MTF_HARD|MTF_AMBUSH|MTF_NOTSINGLE; | ||
1079 | } | ||
1080 | |||
1081 | // count deathmatch start positions | ||
1082 | |||
1083 | // doom2.exe has at most 10 deathmatch starts | ||
1084 | if (mthing->type == 11 && (!compatibility || deathmatch_p-deathmatchstarts < 10)) | ||
1085 | { | ||
1086 | // 1/11/98 killough -- new code removes limit on deathmatch starts: | ||
1087 | |||
1088 | size_t offset = deathmatch_p - deathmatchstarts; | ||
1089 | |||
1090 | if (offset >= num_deathmatchstarts) | ||
1091 | { | ||
1092 | num_deathmatchstarts = num_deathmatchstarts ? | ||
1093 | num_deathmatchstarts*2 : 16; | ||
1094 | deathmatchstarts = realloc(deathmatchstarts, | ||
1095 | num_deathmatchstarts * | ||
1096 | sizeof(*deathmatchstarts)); | ||
1097 | deathmatch_p = deathmatchstarts + offset; | ||
1098 | } | ||
1099 | memcpy(deathmatch_p++, mthing, sizeof(*mthing)); | ||
1100 | return; | ||
1101 | } | ||
1102 | |||
1103 | // check for players specially | ||
1104 | |||
1105 | if (mthing->type <= 4 && mthing->type > 0) // killough 2/26/98 -- fix crashes | ||
1106 | { | ||
1107 | #ifdef DOGS | ||
1108 | // killough 7/19/98: Marine's best friend :) | ||
1109 | if (!netgame && mthing->type > 1 && mthing->type <= dogs+1 && | ||
1110 | !players[mthing->type-1].secretcount) | ||
1111 | { // use secretcount to avoid multiple dogs in case of multiple starts | ||
1112 | players[mthing->type-1].secretcount = 1; | ||
1113 | |||
1114 | // killough 10/98: force it to be a friend | ||
1115 | mthing->options |= MTF_FRIEND; | ||
1116 | i = MT_DOGS; | ||
1117 | goto spawnit; | ||
1118 | } | ||
1119 | #endif | ||
1120 | |||
1121 | |||
1122 | // save spots for respawning in network games | ||
1123 | |||
1124 | playerstarts[mthing->type-1] = *mthing; | ||
1125 | if (!deathmatch) | ||
1126 | P_SpawnPlayer (mthing); | ||
1127 | return; | ||
1128 | } | ||
1129 | |||
1130 | // check for apropriate skill level | ||
1131 | |||
1132 | /* jff "not single" thing flag */ | ||
1133 | if (!netgame && mthing->options & MTF_NOTSINGLE) | ||
1134 | return; | ||
1135 | |||
1136 | //jff 3/30/98 implement "not deathmatch" thing flag | ||
1137 | |||
1138 | if (netgame && deathmatch && mthing->options & MTF_NOTDM) | ||
1139 | return; | ||
1140 | |||
1141 | //jff 3/30/98 implement "not cooperative" thing flag | ||
1142 | |||
1143 | if (netgame && !deathmatch && mthing->options & MTF_NOTCOOP) | ||
1144 | return; | ||
1145 | |||
1146 | // killough 11/98: simplify | ||
1147 | if (gameskill == sk_baby || gameskill == sk_easy ? | ||
1148 | !(mthing->options & MTF_EASY) : | ||
1149 | gameskill == sk_hard || gameskill == sk_nightmare ? | ||
1150 | !(mthing->options & MTF_HARD) : !(mthing->options & MTF_NORMAL)) | ||
1151 | return; | ||
1152 | |||
1153 | // find which type to spawn | ||
1154 | |||
1155 | // killough 8/23/98: use table for faster lookup | ||
1156 | i = P_FindDoomedNum(mthing->type); | ||
1157 | |||
1158 | // phares 5/16/98: | ||
1159 | // Do not abort because of an unknown thing. Ignore it, but post a | ||
1160 | // warning message for the player. | ||
1161 | |||
1162 | if (i == NUMMOBJTYPES) | ||
1163 | { | ||
1164 | doom_printf("Unknown Thing type %i at (%i, %i)",mthing->type,mthing->x,mthing->y); | ||
1165 | return; | ||
1166 | } | ||
1167 | |||
1168 | // don't spawn keycards and players in deathmatch | ||
1169 | |||
1170 | if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) | ||
1171 | return; | ||
1172 | |||
1173 | // don't spawn any monsters if -nomonsters | ||
1174 | |||
1175 | if (nomonsters && (i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL))) | ||
1176 | return; | ||
1177 | |||
1178 | // spawn it | ||
1179 | #ifdef DOGS | ||
1180 | spawnit: | ||
1181 | #endif | ||
1182 | |||
1183 | x = mthing->x << FRACBITS; | ||
1184 | y = mthing->y << FRACBITS; | ||
1185 | |||
1186 | if (mobjinfo[i].flags & MF_SPAWNCEILING) | ||
1187 | z = ONCEILINGZ; | ||
1188 | else | ||
1189 | z = ONFLOORZ; | ||
1190 | |||
1191 | mobj = P_SpawnMobj (x,y,z, i); | ||
1192 | mobj->spawnpoint = *mthing; | ||
1193 | |||
1194 | if (mobj->tics > 0) | ||
1195 | mobj->tics = 1 + (P_Random (pr_spawnthing) % mobj->tics); | ||
1196 | |||
1197 | if (!(mobj->flags & MF_FRIEND) && | ||
1198 | mthing->options & MTF_FRIEND && | ||
1199 | mbf_features) | ||
1200 | { | ||
1201 | mobj->flags |= MF_FRIEND; // killough 10/98: | ||
1202 | P_UpdateThinker(&mobj->thinker); // transfer friendliness flag | ||
1203 | } | ||
1204 | |||
1205 | /* killough 7/20/98: exclude friends */ | ||
1206 | if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL))) | ||
1207 | totalkills++; | ||
1208 | |||
1209 | if (mobj->flags & MF_COUNTITEM) | ||
1210 | totalitems++; | ||
1211 | |||
1212 | mobj->angle = ANG45 * (mthing->angle/45); | ||
1213 | if (mthing->options & MTF_AMBUSH) | ||
1214 | mobj->flags |= MF_AMBUSH; | ||
1215 | } | ||
1216 | |||
1217 | |||
1218 | // | ||
1219 | // GAME SPAWN FUNCTIONS | ||
1220 | // | ||
1221 | |||
1222 | // | ||
1223 | // P_SpawnPuff | ||
1224 | // | ||
1225 | |||
1226 | extern fixed_t attackrange; | ||
1227 | |||
1228 | void P_SpawnPuff(fixed_t x,fixed_t y,fixed_t z) | ||
1229 | { | ||
1230 | mobj_t* th; | ||
1231 | // killough 5/5/98: remove dependence on order of evaluation: | ||
1232 | int t = P_Random(pr_spawnpuff); | ||
1233 | z += (t - P_Random(pr_spawnpuff))<<10; | ||
1234 | |||
1235 | th = P_SpawnMobj (x,y,z, MT_PUFF); | ||
1236 | th->momz = FRACUNIT; | ||
1237 | th->tics -= P_Random(pr_spawnpuff)&3; | ||
1238 | |||
1239 | if (th->tics < 1) | ||
1240 | th->tics = 1; | ||
1241 | |||
1242 | // don't make punches spark on the wall | ||
1243 | |||
1244 | if (attackrange == MELEERANGE) | ||
1245 | P_SetMobjState (th, S_PUFF3); | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | // | ||
1250 | // P_SpawnBlood | ||
1251 | // | ||
1252 | void P_SpawnBlood(fixed_t x,fixed_t y,fixed_t z,int damage) | ||
1253 | { | ||
1254 | mobj_t* th; | ||
1255 | // killough 5/5/98: remove dependence on order of evaluation: | ||
1256 | int t = P_Random(pr_spawnblood); | ||
1257 | z += (t - P_Random(pr_spawnblood))<<10; | ||
1258 | th = P_SpawnMobj(x,y,z, MT_BLOOD); | ||
1259 | th->momz = FRACUNIT*2; | ||
1260 | th->tics -= P_Random(pr_spawnblood)&3; | ||
1261 | |||
1262 | if (th->tics < 1) | ||
1263 | th->tics = 1; | ||
1264 | |||
1265 | if (damage <= 12 && damage >= 9) | ||
1266 | P_SetMobjState (th,S_BLOOD2); | ||
1267 | else if (damage < 9) | ||
1268 | P_SetMobjState (th,S_BLOOD3); | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | // | ||
1273 | // P_CheckMissileSpawn | ||
1274 | // Moves the missile forward a bit | ||
1275 | // and possibly explodes it right there. | ||
1276 | // | ||
1277 | |||
1278 | void P_CheckMissileSpawn (mobj_t* th) | ||
1279 | { | ||
1280 | th->tics -= P_Random(pr_missile)&3; | ||
1281 | if (th->tics < 1) | ||
1282 | th->tics = 1; | ||
1283 | |||
1284 | // move a little forward so an angle can | ||
1285 | // be computed if it immediately explodes | ||
1286 | |||
1287 | th->x += (th->momx>>1); | ||
1288 | th->y += (th->momy>>1); | ||
1289 | th->z += (th->momz>>1); | ||
1290 | |||
1291 | // killough 8/12/98: for non-missile objects (e.g. grenades) | ||
1292 | if (!(th->flags & MF_MISSILE) && mbf_features) | ||
1293 | return; | ||
1294 | |||
1295 | // killough 3/15/98: no dropoff (really = don't care for missiles) | ||
1296 | |||
1297 | if (!P_TryMove (th, th->x, th->y, false)) | ||
1298 | P_ExplodeMissile (th); | ||
1299 | } | ||
1300 | |||
1301 | |||
1302 | // | ||
1303 | // P_SpawnMissile | ||
1304 | // | ||
1305 | |||
1306 | mobj_t* P_SpawnMissile(mobj_t* source,mobj_t* dest,mobjtype_t type) | ||
1307 | { | ||
1308 | mobj_t* th; | ||
1309 | angle_t an; | ||
1310 | int dist; | ||
1311 | |||
1312 | th = P_SpawnMobj (source->x,source->y,source->z + 4*8*FRACUNIT,type); | ||
1313 | |||
1314 | if (th->info->seesound) | ||
1315 | S_StartSound (th, th->info->seesound); | ||
1316 | |||
1317 | P_SetTarget(&th->target, source); // where it came from | ||
1318 | an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y); | ||
1319 | |||
1320 | // fuzzy player | ||
1321 | |||
1322 | if (dest->flags & MF_SHADOW) | ||
1323 | { // killough 5/5/98: remove dependence on order of evaluation: | ||
1324 | int t = P_Random(pr_shadow); | ||
1325 | an += (t - P_Random(pr_shadow))<<20; | ||
1326 | } | ||
1327 | |||
1328 | th->angle = an; | ||
1329 | an >>= ANGLETOFINESHIFT; | ||
1330 | th->momx = FixedMul (th->info->speed, finecosine[an]); | ||
1331 | th->momy = FixedMul (th->info->speed, finesine[an]); | ||
1332 | |||
1333 | dist = P_AproxDistance (dest->x - source->x, dest->y - source->y); | ||
1334 | dist = dist / th->info->speed; | ||
1335 | |||
1336 | if (dist < 1) | ||
1337 | dist = 1; | ||
1338 | |||
1339 | th->momz = (dest->z - source->z) / dist; | ||
1340 | P_CheckMissileSpawn (th); | ||
1341 | |||
1342 | return th; | ||
1343 | } | ||
1344 | |||
1345 | |||
1346 | // | ||
1347 | // P_SpawnPlayerMissile | ||
1348 | // Tries to aim at a nearby monster | ||
1349 | // | ||
1350 | |||
1351 | void P_SpawnPlayerMissile(mobj_t* source,mobjtype_t type) | ||
1352 | { | ||
1353 | mobj_t *th; | ||
1354 | fixed_t x, y, z, slope = 0; | ||
1355 | |||
1356 | // see which target is to be aimed at | ||
1357 | |||
1358 | angle_t an = source->angle; | ||
1359 | |||
1360 | // killough 7/19/98: autoaiming was not in original beta | ||
1361 | { | ||
1362 | // killough 8/2/98: prefer autoaiming at enemies | ||
1363 | uint_64_t mask = mbf_features ? MF_FRIEND : 0; | ||
1364 | |||
1365 | do | ||
1366 | { | ||
1367 | slope = P_AimLineAttack(source, an, 16*64*FRACUNIT, mask); | ||
1368 | if (!linetarget) | ||
1369 | slope = P_AimLineAttack(source, an += 1<<26, 16*64*FRACUNIT, mask); | ||
1370 | if (!linetarget) | ||
1371 | slope = P_AimLineAttack(source, an -= 2<<26, 16*64*FRACUNIT, mask); | ||
1372 | if (!linetarget) | ||
1373 | an = source->angle, slope = 0; | ||
1374 | } | ||
1375 | while (mask && (mask=0, !linetarget)); // killough 8/2/98 | ||
1376 | } | ||
1377 | |||
1378 | x = source->x; | ||
1379 | y = source->y; | ||
1380 | z = source->z + 4*8*FRACUNIT; | ||
1381 | |||
1382 | th = P_SpawnMobj (x,y,z, type); | ||
1383 | |||
1384 | if (th->info->seesound) | ||
1385 | S_StartSound (th, th->info->seesound); | ||
1386 | |||
1387 | P_SetTarget(&th->target, source); | ||
1388 | th->angle = an; | ||
1389 | th->momx = FixedMul(th->info->speed,finecosine[an>>ANGLETOFINESHIFT]); | ||
1390 | th->momy = FixedMul(th->info->speed,finesine[an>>ANGLETOFINESHIFT]); | ||
1391 | th->momz = FixedMul(th->info->speed,slope); | ||
1392 | |||
1393 | P_CheckMissileSpawn(th); | ||
1394 | } | ||