1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
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.
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.
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
28 * Moving object handling. Spawn functions.
30 *-----------------------------------------------------------------------------*/
46 #include "rockmacros.h"
49 // Returns true if the mobj is still present.
52 statenum_t i IBSS_ATTR
; // initial state
53 statenum_t seenstate_tab
[NUMSTATES
] IBSS_ATTR
; // fast transition table
55 boolean
P_SetMobjState(mobj_t
* mobj
,statenum_t state
)
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
62 boolean ret
= true; // return value
64 if (recursion
++) // if recursion detected,
65 memset(seenstate
,0,sizeof(seenstate_tab
)); // clear state table
71 mobj
->state
= (state_t
*) S_NULL
;
74 break; // killough 4/9/98
79 mobj
->tics
= st
->tics
;
80 mobj
->sprite
= st
->sprite
;
81 mobj
->frame
= st
->frame
;
84 // Call action functions when the state is set
89 seenstate
[state
] = 1 + st
->nextstate
; // killough 4/9/98
91 state
= st
->nextstate
;
92 } while (!mobj
->tics
&& !seenstate
[state
]); // killough 4/9/98
94 if (ret
&& !mobj
->tics
) // killough 4/9/98: detect state cycles
95 doom_printf("Warning: State Cycle Detected");
98 for (;(state
=seenstate
[i
]);i
=state
-1)
99 seenstate
[i
] = 0; // killough 4/9/98: erase memory of states
109 void P_ExplodeMissile (mobj_t
* mo
)
111 mo
->momx
= mo
->momy
= mo
->momz
= 0;
113 P_SetMobjState (mo
, mobjinfo
[mo
->type
].deathstate
);
115 mo
->tics
-= P_Random(pr_explode
)&3;
120 mo
->flags
&= ~MF_MISSILE
;
122 if (mo
->info
->deathsound
)
123 S_StartSound (mo
, mo
->info
->deathsound
);
130 // Attempts to move something if it has momentum.
133 void P_XYMovement (mobj_t
* mo
)
136 fixed_t xmove
, ymove
;
142 fixed_t oldx
,oldy
; // phares 9/10/98: reducing bobbing/momentum on ice
143 // when up against walls
145 if (!(mo
->momx
| mo
->momy
)) // Any momentum?
147 if (mo
->flags
& MF_SKULLFLY
)
150 // the skull slammed into something
152 mo
->flags
&= ~MF_SKULLFLY
;
155 P_SetMobjState (mo
, mo
->info
->spawnstate
);
162 if (mo
->momx
> MAXMOVE
)
164 else if (mo
->momx
< -MAXMOVE
)
167 if (mo
->momy
> MAXMOVE
)
169 else if (mo
->momy
< -MAXMOVE
)
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
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
190 if (xmove
> MAXMOVE
/2 || ymove
> MAXMOVE
/2 ||
191 (!comp
[comp_moveblock
]
192 && (xmove
< -MAXMOVE
/2 || ymove
< -MAXMOVE
/2)))
194 ptryx
= mo
->x
+ xmove
/2;
195 ptryy
= mo
->y
+ ymove
/2;
201 ptryx
= mo
->x
+ xmove
;
202 ptryy
= mo
->y
+ ymove
;
206 // killough 3/15/98: Allow objects to drop off
208 if (!P_TryMove (mo
, ptryx
, ptryy
, true))
212 // killough 8/11/98: bouncing off walls
214 // Add ability for objects other than players to bounce on ice
216 if (!(mo
->flags
& MF_MISSILE
) &&
218 (mo
->flags
& MF_BOUNCES
||
219 (!player
&& blockline
&&
220 variable_friction
&& mo
->z
<= mo
->floorz
&&
221 P_GetFriction(mo
, NULL
) > ORIG_FRICTION
)))
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
);
232 // reflect momentum away from wall
234 mo
->momx
= x
*2 - mo
->momx
;
235 mo
->momy
= y
*2 - mo
->momy
;
237 // if under gravity, slow down in
238 // direction perpendicular to wall.
240 if (!(mo
->flags
& MF_NOGRAVITY
))
242 mo
->momx
= (mo
->momx
+ x
)/2;
243 mo
->momy
= (mo
->momy
+ y
)/2;
247 mo
->momx
= mo
->momy
= 0;
250 if (player
) // try to slide along it
253 if (mo
->flags
& MF_MISSILE
)
258 ceilingline
->backsector
&&
259 ceilingline
->backsector
->ceilingpic
== skyflatnum
)
260 if (demo_compatibility
|| // killough
261 mo
->z
> ceilingline
->backsector
->ceilingheight
)
263 // Hack to prevent missiles exploding
265 // Does not handle sky floors.
270 P_ExplodeMissile (mo
);
272 else // whatever else it is, it is now standing still in (x,y)
273 mo
->momx
= mo
->momy
= 0;
275 } while (xmove
|| ymove
);
279 #if 0 /* killough 10/98: this is unused code (except maybe in .deh files?) */
280 if (player
&& player
->cheats
& CF_NOMOMENTUM
)
282 // debug option for no sliding at all
283 mo
->momx
= mo
->momy
= 0;
284 player
->momx
= player
->momy
= 0; /* killough 10/98 */
289 /* no friction for missiles or skulls ever, no friction when airborne */
290 if (mo
->flags
& (MF_MISSILE
| MF_SKULLFLY
) || mo
->z
> mo
->floorz
)
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
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
305 // Stop voodoo dolls that have come to rest, despite any
306 // moving corresponding player, except in old demos:
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
)))
313 // if in a walking frame, stop moving
316 // Don't affect main player when voodoo dolls stop, except in old demos:
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
);
322 mo
->momx
= mo
->momy
= 0;
324 /* killough 10/98: kill any bobbing momentum too (except in voodoo dolls)
325 * cph - DEMOSYNC - needs compatibility check?
327 if (player
&& player
->mo
== mo
)
328 player
->momx
= player
->momy
= 0;
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
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).
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.
346 * cph - DEMOSYNC - need old code for Boom demos?
349 fixed_t friction
= P_GetFriction(mo
, NULL
);
351 mo
->momx
= FixedMul(mo
->momx
, friction
);
352 mo
->momy
= FixedMul(mo
->momy
, friction
);
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.
359 if (player
&& player
->mo
== mo
) /* Not voodoo dolls */
361 player
->momx
= FixedMul(player
->momx
, ORIG_FRICTION
);
362 player
->momy
= FixedMul(player
->momy
, ORIG_FRICTION
);
372 // Attempt vertical movement.
374 static void P_ZMovement (mobj_t
* mo
)
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)
382 if (mo
->flags
& MF_BOUNCES
&& mo
->momz
) {
384 if (mo
->z
<= mo
->floorz
) { /* bounce off floors */
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)) ;
395 /* Bring it to rest below a certain speed */
396 if (abs(mo
->momz
) <= mo
->info
->mass
*(GRAVITY
*4/256))
400 /* killough 11/98: touchy objects explode on impact */
401 if (mo
->flags
& MF_TOUCHY
&& mo
->intflags
& MIF_ARMED
403 P_DamageMobj(mo
, NULL
, NULL
, mo
->health
);
404 else if (mo
->flags
& MF_FLOAT
&& sentient(mo
))
408 } else if (mo
->z
>= mo
->ceilingz
- mo
->height
) {
409 /* bounce off ceilings */
410 mo
->z
= mo
->ceilingz
- mo
->height
;
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
419 if (mo
->flags
& MF_FLOAT
&& sentient(mo
))
425 if (!(mo
->flags
& MF_NOGRAVITY
)) /* free-fall under gravity */
426 mo
->momz
-= mo
->info
->mass
*(GRAVITY
/256);
428 if (mo
->flags
& MF_FLOAT
&& sentient(mo
)) goto floater
;
435 if (mo
->flags
& MF_MISSILE
) {
437 ceilingline
->backsector
&&
438 ceilingline
->backsector
->ceilingpic
== skyflatnum
&&
439 mo
->z
> ceilingline
->backsector
->ceilingheight
)
440 P_RemoveMobj(mo
); /* don't explode on skies */
442 P_ExplodeMissile(mo
);
445 if (mo
->flags
& MF_FLOAT
&& sentient(mo
)) goto floater
;
449 /* killough 8/9/98: end bouncing object code */
451 // check for smooth step up
454 mo
->player
->mo
== mo
&& // killough 5/12/98: exclude voodoo dolls
457 mo
->player
->viewheight
-= mo
->floorz
-mo
->z
;
458 mo
->player
->deltaviewheight
= (VIEWHEIGHT
- mo
->player
->viewheight
)>>3;
466 if ((mo
->flags
& MF_FLOAT
) && mo
->target
)
468 // float down towards target if too close
470 if (!((mo
->flags
^ MF_FLOAT
) & (MF_FLOAT
| MF_SKULLFLY
| MF_INFLOAT
)) &&
471 mo
->target
) /* killough 11/98: simplify */
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
;
481 if (mo
->z
<= mo
->floorz
)
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.)
497 int correct_lost_soul_bounce
= !demo_compatibility
|| (gamemission
!= doom2
);
499 if (correct_lost_soul_bounce
&& mo
->flags
& MF_SKULLFLY
)
500 mo
->momz
= -mo
->momz
; // the skull slammed into something
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
);
508 if (mo
->player
&& /* killough 5/12/98: exclude voodoo dolls */
509 mo
->player
->mo
== mo
&& mo
->momz
< -GRAVITY
*8)
512 // Decrease viewheight for a moment
513 // after hitting the ground (hard),
514 // and utter appropriate sound.
516 mo
->player
->deltaviewheight
= mo
->momz
>>3;
517 if (mo
->health
) /* cph - prevent "oof" when dead */
518 S_StartSound (mo
, sfx_oof
);
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.
529 if (!correct_lost_soul_bounce
&& mo
->flags
& MF_SKULLFLY
)
530 mo
->momz
= -mo
->momz
; // the skull slammed into something
532 if ( (mo
->flags
& MF_MISSILE
) && !(mo
->flags
& MF_NOCLIP
) )
534 P_ExplodeMissile (mo
);
538 else // still above the floor // phares
539 if (!(mo
->flags
& MF_NOGRAVITY
))
546 if (mo
->z
+ mo
->height
> mo
->ceilingz
)
554 mo
->z
= mo
->ceilingz
- mo
->height
;
556 if (mo
->flags
& MF_SKULLFLY
)
557 mo
->momz
= -mo
->momz
; // the skull slammed into something
559 if ( (mo
->flags
& MF_MISSILE
) && !(mo
->flags
& MF_NOCLIP
) )
561 P_ExplodeMissile (mo
);
568 // P_NightmareRespawn
571 void P_NightmareRespawn(mobj_t
* mobj
)
580 x
= mobj
->spawnpoint
.x
<< FRACBITS
;
581 y
= mobj
->spawnpoint
.y
<< FRACBITS
;
583 /* haleyjd: stupid nightmare respawning bug fix
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.
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*
595 if(!comp
[comp_respawn
] && !x
&& !y
)
597 // spawnpoint was zeroed out, so use point of death instead
602 // something is occupying its position?
604 if (!P_CheckPosition (mobj
, x
, y
) )
605 return; // no respwan
607 // spawn a teleport fog at old spot
608 // because of removal of the body?
610 mo
= P_SpawnMobj (mobj
->x
,
612 mobj
->subsector
->sector
->floorheight
,
615 // initiate teleport sound
617 S_StartSound (mo
, sfx_telept
);
619 // spawn a teleport fog at the new spot
621 ss
= R_PointInSubsector (x
,y
);
623 mo
= P_SpawnMobj (x
, y
, ss
->sector
->floorheight
, MT_TFOG
);
625 S_StartSound (mo
, sfx_telept
);
627 // spawn the new monster
629 mthing
= &mobj
->spawnpoint
;
630 if (mobj
->info
->flags
& MF_SPAWNCEILING
)
635 // inherit attributes from deceased one
637 mo
= P_SpawnMobj (x
,y
,z
, mobj
->type
);
638 mo
->spawnpoint
= mobj
->spawnpoint
;
639 mo
->angle
= ANG45
* (mthing
->angle
/45);
641 if (mthing
->options
& MTF_AMBUSH
)
642 mo
->flags
|= MF_AMBUSH
;
644 /* killough 11/98: transfer friendliness from deceased */
645 mo
->flags
= (mo
->flags
& ~MF_FRIEND
) | (mobj
->flags
& MF_FRIEND
);
647 mo
->reactiontime
= 18;
649 // remove the old monster,
659 void P_MobjThinker (mobj_t
* mobj
)
662 // removed old code which looked at target references
663 // (we use pointer reference counting now)
666 if (mobj
->momx
| mobj
->momy
|| mobj
->flags
& MF_SKULLFLY
)
669 if (mobj
->thinker
.function
!= P_MobjThinker
) // cph - Must've been removed
670 return; // killough - mobj was removed
673 if (mobj
->z
!= mobj
->floorz
|| mobj
->momz
)
676 if (mobj
->thinker
.function
!= P_MobjThinker
) // cph - Must've been removed
677 return; // killough - mobj was removed
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
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
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
692 mobj
->intflags
&= ~MIF_FALLING
, mobj
->gear
= 0; // Reset torque
695 // cycle through states,
696 // calling action functions at transitions
698 if (mobj
->tics
!= -1)
702 // you can cycle through multiple states in a tic
705 if (!P_SetMobjState (mobj
, mobj
->state
->nextstate
) )
706 return; // freed itself
711 // check for nightmare respawn
713 if (! (mobj
->flags
& MF_COUNTKILL
) )
716 if (!respawnmonsters
)
721 if (mobj
->movecount
< 12*35)
727 if (P_Random (pr_respawn
) > 4)
730 P_NightmareRespawn (mobj
);
739 mobj_t
* P_SpawnMobj(fixed_t x
,fixed_t y
,fixed_t z
,mobjtype_t type
)
745 mobj
= Z_Malloc (sizeof(*mobj
), PU_LEVEL
, NULL
);
746 memset (mobj
, 0, sizeof (*mobj
));
747 info
= &mobjinfo
[type
];
752 mobj
->radius
= info
->radius
;
753 mobj
->height
= info
->height
; // phares
754 mobj
->flags
= info
->flags
;
756 /* killough 8/23/98: no friends, bouncers, or touchy things in old demos */
758 mobj
->flags
&= ~(MF_BOUNCES
| MF_FRIEND
| MF_TOUCHY
);
760 if (type
== MT_PLAYER
) // Except in old demos, players
761 mobj
->flags
|= MF_FRIEND
; // are always friends.
763 mobj
->health
= info
->spawnhealth
;
765 if (gameskill
!= sk_nightmare
)
766 mobj
->reactiontime
= info
->reactiontime
;
768 mobj
->lastlook
= P_Random (pr_lastlook
) % MAXPLAYERS
;
770 // do not set the state with P_SetMobjState,
771 // because action routines can not be called yet
773 st
= &states
[info
->spawnstate
];
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
781 // set subsector and/or block links
783 P_SetThingPosition (mobj
);
785 mobj
->dropoffz
= /* killough 11/98: for tracking dropoffs */
786 mobj
->floorz
= mobj
->subsector
->sector
->floorheight
;
787 mobj
->ceilingz
= mobj
->subsector
->sector
->ceilingheight
;
789 mobj
->z
= z
== ONFLOORZ
? mobj
->floorz
: z
== ONCEILINGZ
?
790 mobj
->ceilingz
- mobj
->height
: z
;
792 mobj
->thinker
.function
= P_MobjThinker
;
793 mobj
->above_thing
= 0; // phares
794 mobj
->below_thing
= 0; // phares
796 mobj
->target
= mobj
->tracer
= mobj
->lastenemy
= NULL
;
797 P_AddThinker (&mobj
->thinker
);
798 if (!((mobj
->flags
^ MF_COUNTKILL
) & (MF_FRIEND
| MF_COUNTKILL
)))
804 mapthing_t itemrespawnque
[ITEMQUESIZE
];
805 int itemrespawntime
[ITEMQUESIZE
];
814 void P_RemoveMobj (mobj_t
* mobj
)
816 if ((mobj
->flags
& MF_SPECIAL
)
817 && !(mobj
->flags
& MF_DROPPED
)
818 && (mobj
->type
!= MT_INV
)
819 && (mobj
->type
!= MT_INS
))
821 itemrespawnque
[iquehead
] = mobj
->spawnpoint
;
822 itemrespawntime
[iquehead
] = leveltime
;
823 iquehead
= (iquehead
+1)&(ITEMQUESIZE
-1);
825 // lose one off the end?
827 if (iquehead
== iquetail
)
828 iquetail
= (iquetail
+1)&(ITEMQUESIZE
-1);
831 // unlink from sector and block lists
833 P_UnsetThingPosition (mobj
);
835 // Delete all nodes on the current sector_list phares 3/16/98
839 P_DelSeclist(sector_list
);
843 // stop any playing sound
849 // Remove any references to other mobjs.
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.
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
);
865 // P_RemoveThinker ((thinker_t*)mobj);
866 P_RemoveThinker (&mobj
->thinker
);
873 * Finds a mobj type with a matching doomednum
875 * killough 8/24/98: rewrote to use hashing
878 int P_FindDoomedNum(unsigned type
)
880 static struct { int first
, next
; } *hash
;
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)
891 unsigned h
= (unsigned) mobjinfo
[i
].doomednum
% NUMMOBJTYPES
;
892 hash
[i
].next
= hash
[h
].first
;
897 i
= hash
[type
% NUMMOBJTYPES
].first
;
898 while ((i
< NUMMOBJTYPES
) && ((unsigned)mobjinfo
[i
].doomednum
!= type
))
907 void P_RespawnSpecials (void)
917 // only respawn items in deathmatch
922 // nothing left to respawn?
924 if (iquehead
== iquetail
)
927 // wait at least 30 seconds
929 if (leveltime
- itemrespawntime
[iquetail
] < 30*35)
932 mthing
= &itemrespawnque
[iquetail
];
934 x
= mthing
->x
<< FRACBITS
;
935 y
= mthing
->y
<< FRACBITS
;
937 // spawn a teleport fog at the new spot
939 ss
= R_PointInSubsector (x
,y
);
940 mo
= P_SpawnMobj (x
, y
, ss
->sector
->floorheight
, MT_IFOG
);
941 S_StartSound (mo
, sfx_itmbk
);
943 // find which type to spawn
945 /* killough 8/23/98: use table for faster lookup */
946 i
= P_FindDoomedNum(mthing
->type
);
950 if (mobjinfo
[i
].flags
& MF_SPAWNCEILING
)
955 mo
= P_SpawnMobj (x
,y
,z
, i
);
956 mo
->spawnpoint
= *mthing
;
957 mo
->angle
= ANG45
* (mthing
->angle
/45);
959 // pull it from the queue
961 iquetail
= (iquetail
+1)&(ITEMQUESIZE
-1);
966 // Called when a player is spawned on the level.
967 // Most of the player structure stays unchanged
971 extern byte playernumtotrans
[MAXPLAYERS
];
973 void P_SpawnPlayer (mapthing_t
* mthing
)
984 if (!playeringame
[mthing
->type
-1])
987 p
= &players
[mthing
->type
-1];
989 if (p
->playerstate
== PST_REBORN
)
990 G_PlayerReborn (mthing
->type
-1);
992 x
= mthing
->x
<< FRACBITS
;
993 y
= mthing
->y
<< FRACBITS
;
995 mobj
= P_SpawnMobj (x
,y
,z
, MT_PLAYER
);
997 // set color translations for player sprites
999 if (mthing
->type
> 0)
1000 mobj
->flags
|= playernumtotrans
[mthing
->type
-1]<<MF_TRANSSHIFT
;
1002 mobj
->angle
= ANG45
* (mthing
->angle
/45);
1004 mobj
->health
= p
->health
;
1007 p
->playerstate
= PST_LIVE
;
1013 p
->fixedcolormap
= 0;
1014 p
->viewheight
= VIEWHEIGHT
;
1016 p
->momx
= p
->momy
= 0; // killough 10/98: initialize bobbing to 0.
1018 // setup gun psprite
1020 P_SetupPsprites (p
);
1022 // give all cards in death match mode
1025 for (i
= 0 ; i
< NUMCARDS
; i
++)
1028 if (mthing
->type
-1 == consoleplayer
)
1030 ST_Start(); // wake up the status bar
1031 HU_Start(); // wake up the heads up text
1038 // The fields of the mapthing should
1039 // already be in host byte order.
1042 void P_SpawnMapThing (mapthing_t
* mthing
)
1051 // killough 2/26/98: Ignore type-0 things as NOPs
1052 // phares 5/14/98: Ignore Player 5-8 starts (for now)
1054 switch(mthing
->type
)
1064 // killough 11/98: clear flags unused by Doom
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.
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
;
1081 // count deathmatch start positions
1083 // doom2.exe has at most 10 deathmatch starts
1084 if (mthing
->type
== 11 && (!compatibility
|| deathmatch_p
-deathmatchstarts
< 10))
1086 // 1/11/98 killough -- new code removes limit on deathmatch starts:
1088 size_t offset
= deathmatch_p
- deathmatchstarts
;
1090 if (offset
>= num_deathmatchstarts
)
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
;
1099 memcpy(deathmatch_p
++, mthing
, sizeof(*mthing
));
1103 // check for players specially
1105 if (mthing
->type
<= 4 && mthing
->type
> 0) // killough 2/26/98 -- fix crashes
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;
1114 // killough 10/98: force it to be a friend
1115 mthing
->options
|= MTF_FRIEND
;
1122 // save spots for respawning in network games
1124 playerstarts
[mthing
->type
-1] = *mthing
;
1126 P_SpawnPlayer (mthing
);
1130 // check for apropriate skill level
1132 /* jff "not single" thing flag */
1133 if (!netgame
&& mthing
->options
& MTF_NOTSINGLE
)
1136 //jff 3/30/98 implement "not deathmatch" thing flag
1138 if (netgame
&& deathmatch
&& mthing
->options
& MTF_NOTDM
)
1141 //jff 3/30/98 implement "not cooperative" thing flag
1143 if (netgame
&& !deathmatch
&& mthing
->options
& MTF_NOTCOOP
)
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
))
1153 // find which type to spawn
1155 // killough 8/23/98: use table for faster lookup
1156 i
= P_FindDoomedNum(mthing
->type
);
1159 // Do not abort because of an unknown thing. Ignore it, but post a
1160 // warning message for the player.
1162 if (i
== NUMMOBJTYPES
)
1164 doom_printf("Unknown Thing type %i at (%i, %i)",mthing
->type
,mthing
->x
,mthing
->y
);
1168 // don't spawn keycards and players in deathmatch
1170 if (deathmatch
&& mobjinfo
[i
].flags
& MF_NOTDMATCH
)
1173 // don't spawn any monsters if -nomonsters
1175 if (nomonsters
&& (i
== MT_SKULL
|| (mobjinfo
[i
].flags
& MF_COUNTKILL
)))
1183 x
= mthing
->x
<< FRACBITS
;
1184 y
= mthing
->y
<< FRACBITS
;
1186 if (mobjinfo
[i
].flags
& MF_SPAWNCEILING
)
1191 mobj
= P_SpawnMobj (x
,y
,z
, i
);
1192 mobj
->spawnpoint
= *mthing
;
1195 mobj
->tics
= 1 + (P_Random (pr_spawnthing
) % mobj
->tics
);
1197 if (!(mobj
->flags
& MF_FRIEND
) &&
1198 mthing
->options
& MTF_FRIEND
&&
1201 mobj
->flags
|= MF_FRIEND
; // killough 10/98:
1202 P_UpdateThinker(&mobj
->thinker
); // transfer friendliness flag
1205 /* killough 7/20/98: exclude friends */
1206 if (!((mobj
->flags
^ MF_COUNTKILL
) & (MF_FRIEND
| MF_COUNTKILL
)))
1209 if (mobj
->flags
& MF_COUNTITEM
)
1212 mobj
->angle
= ANG45
* (mthing
->angle
/45);
1213 if (mthing
->options
& MTF_AMBUSH
)
1214 mobj
->flags
|= MF_AMBUSH
;
1219 // GAME SPAWN FUNCTIONS
1226 extern fixed_t attackrange
;
1228 void P_SpawnPuff(fixed_t x
,fixed_t y
,fixed_t z
)
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;
1235 th
= P_SpawnMobj (x
,y
,z
, MT_PUFF
);
1236 th
->momz
= FRACUNIT
;
1237 th
->tics
-= P_Random(pr_spawnpuff
)&3;
1242 // don't make punches spark on the wall
1244 if (attackrange
== MELEERANGE
)
1245 P_SetMobjState (th
, S_PUFF3
);
1252 void P_SpawnBlood(fixed_t x
,fixed_t y
,fixed_t z
,int damage
)
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;
1265 if (damage
<= 12 && damage
>= 9)
1266 P_SetMobjState (th
,S_BLOOD2
);
1267 else if (damage
< 9)
1268 P_SetMobjState (th
,S_BLOOD3
);
1273 // P_CheckMissileSpawn
1274 // Moves the missile forward a bit
1275 // and possibly explodes it right there.
1278 void P_CheckMissileSpawn (mobj_t
* th
)
1280 th
->tics
-= P_Random(pr_missile
)&3;
1284 // move a little forward so an angle can
1285 // be computed if it immediately explodes
1287 th
->x
+= (th
->momx
>>1);
1288 th
->y
+= (th
->momy
>>1);
1289 th
->z
+= (th
->momz
>>1);
1291 // killough 8/12/98: for non-missile objects (e.g. grenades)
1292 if (!(th
->flags
& MF_MISSILE
) && mbf_features
)
1295 // killough 3/15/98: no dropoff (really = don't care for missiles)
1297 if (!P_TryMove (th
, th
->x
, th
->y
, false))
1298 P_ExplodeMissile (th
);
1306 mobj_t
* P_SpawnMissile(mobj_t
* source
,mobj_t
* dest
,mobjtype_t type
)
1312 th
= P_SpawnMobj (source
->x
,source
->y
,source
->z
+ 4*8*FRACUNIT
,type
);
1314 if (th
->info
->seesound
)
1315 S_StartSound (th
, th
->info
->seesound
);
1317 P_SetTarget(&th
->target
, source
); // where it came from
1318 an
= R_PointToAngle2 (source
->x
, source
->y
, dest
->x
, dest
->y
);
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;
1329 an
>>= ANGLETOFINESHIFT
;
1330 th
->momx
= FixedMul (th
->info
->speed
, finecosine
[an
]);
1331 th
->momy
= FixedMul (th
->info
->speed
, finesine
[an
]);
1333 dist
= P_AproxDistance (dest
->x
- source
->x
, dest
->y
- source
->y
);
1334 dist
= dist
/ th
->info
->speed
;
1339 th
->momz
= (dest
->z
- source
->z
) / dist
;
1340 P_CheckMissileSpawn (th
);
1347 // P_SpawnPlayerMissile
1348 // Tries to aim at a nearby monster
1351 void P_SpawnPlayerMissile(mobj_t
* source
,mobjtype_t type
)
1354 fixed_t x
, y
, z
, slope
= 0;
1356 // see which target is to be aimed at
1358 angle_t an
= source
->angle
;
1360 // killough 7/19/98: autoaiming was not in original beta
1362 // killough 8/2/98: prefer autoaiming at enemies
1363 uint_64_t mask
= mbf_features
? MF_FRIEND
: 0;
1367 slope
= P_AimLineAttack(source
, an
, 16*64*FRACUNIT
, mask
);
1369 slope
= P_AimLineAttack(source
, an
+= 1<<26, 16*64*FRACUNIT
, mask
);
1371 slope
= P_AimLineAttack(source
, an
-= 2<<26, 16*64*FRACUNIT
, mask
);
1373 an
= source
->angle
, slope
= 0;
1375 while (mask
&& (mask
=0, !linetarget
)); // killough 8/2/98
1380 z
= source
->z
+ 4*8*FRACUNIT
;
1382 th
= P_SpawnMobj (x
,y
,z
, type
);
1384 if (th
->info
->seesound
)
1385 S_StartSound (th
, th
->info
->seesound
);
1387 P_SetTarget(&th
->target
, source
);
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
);
1393 P_CheckMissileSpawn(th
);