2 //**************************************************************************
4 //** p_mobj.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
13 // HEADER FILES ------------------------------------------------------------
20 // MACROS ------------------------------------------------------------------
22 #define MAX_TID_COUNT 200
24 // TYPES -------------------------------------------------------------------
26 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
28 void G_PlayerReborn(int player);
29 void P_MarkAsLeaving(mobj_t *corpse);
31 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
33 void P_SpawnMapThing(mapthing_t *mthing);
35 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
37 static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj);
39 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
40 extern boolean demorecording;
41 extern boolean demoplayback;
42 extern mobj_t LavaInflictor;
44 // PUBLIC DATA DEFINITIONS -------------------------------------------------
49 fixed_t FloatBobOffsets[64] =
51 0, 51389, 102283, 152192,
52 200636, 247147, 291278, 332604,
53 370727, 405280, 435929, 462380,
54 484378, 501712, 514213, 521763,
55 524287, 521763, 514213, 501712,
56 484378, 462380, 435929, 405280,
57 370727, 332604, 291278, 247147,
58 200636, 152192, 102283, 51389,
59 -1, -51390, -102284, -152193,
60 -200637, -247148, -291279, -332605,
61 -370728, -405281, -435930, -462381,
62 -484380, -501713, -514215, -521764,
63 -524288, -521764, -514214, -501713,
64 -484379, -462381, -435930, -405280,
65 -370728, -332605, -291279, -247148,
66 -200637, -152193, -102284, -51389
69 // PRIVATE DATA DEFINITIONS ------------------------------------------------
71 static int TIDList[MAX_TID_COUNT+1]; // +1 for termination marker
72 static mobj_t *TIDMobj[MAX_TID_COUNT];
74 // CODE --------------------------------------------------------------------
76 //==========================================================================
80 // Returns true if the mobj is still present.
82 //==========================================================================
84 boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
96 mobj->tics = st->tics;
97 mobj->sprite = st->sprite;
98 mobj->frame = st->frame;
100 { // Call action function
106 //==========================================================================
110 // Same as P_SetMobjState, but does not call the state function.
112 //==========================================================================
114 boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
120 mobj->state = S_NULL;
126 mobj->tics = st->tics;
127 mobj->sprite = st->sprite;
128 mobj->frame = st->frame;
132 //----------------------------------------------------------------------------
134 // PROC P_ExplodeMissile
136 //----------------------------------------------------------------------------
138 void P_ExplodeMissile(mobj_t *mo)
140 mo->momx = mo->momy = mo->momz = 0;
141 P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
142 //mo->tics -= P_Random()&3;
143 mo->flags &= ~MF_MISSILE;
150 S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE);
153 S_StartSound(NULL, SFX_SORCERER_HEADSCREAM);
156 if(mo->info->deathsound)
158 S_StartSound(mo, mo->info->deathsound);
164 //----------------------------------------------------------------------------
166 // PROC P_FloorBounceMissile
168 //----------------------------------------------------------------------------
170 void P_FloorBounceMissile(mobj_t *mo)
172 if(P_HitFloor(mo) >= FLOOR_LIQUID)
189 mo->momz = -mo->momz; // no energy absorbed
201 mo->momz = FixedMul(mo->momz, -0.3*FRACUNIT);
202 if(abs(mo->momz) < (FRACUNIT/2))
204 P_SetMobjState(mo, S_NULL);
209 mo->momz = FixedMul(mo->momz, -0.7*FRACUNIT);
212 mo->momx = 2*mo->momx/3;
213 mo->momy = 2*mo->momy/3;
214 if(mo->info->seesound)
221 if (!mo->args[0]) S_StartSound(mo, mo->info->seesound);
224 S_StartSound(mo, mo->info->seesound);
227 S_StartSound(mo, mo->info->seesound);
229 // P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
232 //----------------------------------------------------------------------------
236 //----------------------------------------------------------------------------
238 void P_ThrustMobj(mobj_t *mo, angle_t angle, fixed_t move)
240 angle >>= ANGLETOFINESHIFT;
241 mo->momx += FixedMul(move, finecosine[angle]);
242 mo->momy += FixedMul(move, finesine[angle]);
245 //----------------------------------------------------------------------------
249 // Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs
250 // to turn counter clockwise. 'delta' is set to the amount 'source'
253 //----------------------------------------------------------------------------
255 int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta)
261 angle1 = source->angle;
262 angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y);
265 diff = angle2-angle1;
268 *delta = ANGLE_MAX-diff;
279 diff = angle1-angle2;
282 *delta = ANGLE_MAX-diff;
293 //----------------------------------------------------------------------------
296 // The missile special1 field must be mobj_t *target. Returns true if
297 // target was tracked, false if not.
299 //----------------------------------------------------------------------------
301 boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax)
309 target = (mobj_t *)actor->special1;
314 if(!(target->flags&MF_SHOOTABLE))
319 dir = P_FaceMobj(actor, target, &delta);
330 actor->angle += delta;
333 { // Turn counter clockwise
334 actor->angle -= delta;
336 angle = actor->angle>>ANGLETOFINESHIFT;
337 actor->momx = FixedMul(actor->info->speed, finecosine[angle]);
338 actor->momy = FixedMul(actor->info->speed, finesine[angle]);
339 if(actor->z+actor->height < target->z
340 || target->z+target->height < actor->z)
341 { // Need to seek vertically
342 dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
343 dist = dist/actor->info->speed;
348 actor->momz = (target->z+(target->height>>1)
349 -(actor->z+(actor->height>>1)))/dist;
354 //----------------------------------------------------------------------------
358 //----------------------------------------------------------------------------
360 #define STOPSPEED 0x1000
361 #define FRICTION_NORMAL 0xe800
362 #define FRICTION_LOW 0xf900
363 #define FRICTION_FLY 0xeb00
365 void P_XYMovement(mobj_t *mo)
367 fixed_t ptryx, ptryy;
369 fixed_t xmove, ymove;
372 static int windTab[3] = {2048*5, 2048*10, 2048*25};
374 if(!mo->momx && !mo->momy)
376 if(mo->flags&MF_SKULLFLY)
377 { // A flying mobj slammed into something
378 mo->flags &= ~MF_SKULLFLY;
379 mo->momx = mo->momy = mo->momz = 0;
380 P_SetMobjState(mo, mo->info->seestate);
384 special = mo->subsector->sector->special;
385 if(mo->flags2&MF2_WINDTHRUST)
389 case 40: case 41: case 42: // Wind_East
390 P_ThrustMobj(mo, 0, windTab[special-40]);
392 case 43: case 44: case 45: // Wind_North
393 P_ThrustMobj(mo, ANG90, windTab[special-43]);
395 case 46: case 47: case 48: // Wind_South
396 P_ThrustMobj(mo, ANG270, windTab[special-46]);
398 case 49: case 50: case 51: // Wind_West
399 P_ThrustMobj(mo, ANG180, windTab[special-49]);
404 if(mo->momx > MAXMOVE)
408 else if(mo->momx < -MAXMOVE)
412 if(mo->momy > MAXMOVE)
416 else if(mo->momy < -MAXMOVE)
424 if(xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
426 ptryx = mo->x+xmove/2;
427 ptryy = mo->y+ymove/2;
433 ptryx = mo->x + xmove;
434 ptryy = mo->y + ymove;
437 if(!P_TryMove(mo, ptryx, ptryy))
439 if(mo->flags2&MF2_SLIDE)
440 { // Try to slide along it
441 if(BlockingMobj == NULL)
442 { // Slide against wall
446 { // Slide against mobj
447 //if(P_TryMove(mo, mo->x, mo->y+mo->momy))
448 if(P_TryMove(mo, mo->x, ptryy))
452 //else if(P_TryMove(mo, mo->x+mo->momx, mo->y))
453 else if(P_TryMove(mo, ptryx, mo->y))
459 mo->momx = mo->momy = 0;
463 else if(mo->flags&MF_MISSILE)
465 if(mo->flags2&MF2_FLOORBOUNCE)
469 if ((BlockingMobj->flags2&MF2_REFLECTIVE) ||
470 ((!BlockingMobj->player) &&
471 (!(BlockingMobj->flags&MF_COUNTKILL))))
475 angle = R_PointToAngle2(BlockingMobj->x,
476 BlockingMobj->y, mo->x, mo->y)
477 +ANGLE_1*((P_Random()%16)-8);
478 speed = P_AproxDistance(mo->momx, mo->momy);
479 speed = FixedMul(speed, 0.75*FRACUNIT);
481 angle >>= ANGLETOFINESHIFT;
482 mo->momx = FixedMul(speed, finecosine[angle]);
483 mo->momy = FixedMul(speed, finesine[angle]);
484 if(mo->info->seesound)
486 S_StartSound(mo, mo->info->seesound);
491 { // Struck a player/creature
492 P_ExplodeMissile(mo);
506 if(mo->info->seesound)
508 S_StartSound(mo, mo->info->seesound);
516 (BlockingMobj->flags2 & MF2_REFLECTIVE))
518 angle = R_PointToAngle2(BlockingMobj->x,
522 // Change angle for delflection/reflection
523 switch(BlockingMobj->type)
526 case MT_CENTAURLEADER:
527 if ( abs(angle-BlockingMobj->angle)>>24 > 45)
529 if (mo->type == MT_HOLY_FX)
531 // Drop through to sorcerer full reflection
541 angle += ANGLE_1 * ((P_Random()%16)-8);
545 // Reflect the missile along angle
547 angle >>= ANGLETOFINESHIFT;
548 mo->momx = FixedMul(mo->info->speed>>1, finecosine[angle]);
549 mo->momy = FixedMul(mo->info->speed>>1, finesine[angle]);
550 // mo->momz = -mo->momz;
551 if (mo->flags2 & MF2_SEEKERMISSILE)
553 mo->special1 = (int)(mo->target);
555 mo->target = BlockingMobj;
560 if(ceilingline && ceilingline->backsector
561 && ceilingline->backsector->ceilingpic == skyflatnum)
562 { // Hack to prevent missiles exploding against the sky
563 if(mo->type == MT_BLOODYSKULL)
565 mo->momx = mo->momy = 0;
566 mo->momz = -FRACUNIT;
568 else if(mo->type == MT_HOLY_FX)
570 P_ExplodeMissile(mo);
578 P_ExplodeMissile(mo);
580 //else if(mo->info->crashstate)
582 // mo->momx = mo->momy = 0;
583 // P_SetMobjState(mo, mo->info->crashstate);
588 mo->momx = mo->momy = 0;
591 } while(xmove || ymove);
595 if(player && player->cheats&CF_NOMOMENTUM)
596 { // Debug option for no sliding at all
597 mo->momx = mo->momy = 0;
600 if(mo->flags&(MF_MISSILE|MF_SKULLFLY))
601 { // No friction for missiles
604 if(mo->z > mo->floorz && !(mo->flags2&MF2_FLY) && !(mo->flags2&MF2_ONMOBJ))
605 { // No friction when falling
606 if (mo->type != MT_BLASTEFFECT)
609 if(mo->flags&MF_CORPSE)
610 { // Don't stop sliding if halfway off a step with some momentum
611 if(mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4
612 || mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4)
614 if(mo->floorz != mo->subsector->sector->floorheight)
620 if(mo->momx > -STOPSPEED && mo->momx < STOPSPEED
621 && mo->momy > -STOPSPEED && mo->momy < STOPSPEED
622 && (!player || (player->cmd.forwardmove == 0
623 && player->cmd.sidemove == 0)))
624 { // If in a walking frame, stop moving
627 if((unsigned)((player->mo->state-states)
628 -PStateRun[player->class]) < 4)
630 P_SetMobjState(player->mo, PStateNormal[player->class]);
638 if(mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
639 &&!(mo->flags2&MF2_ONMOBJ))
641 mo->momx = FixedMul(mo->momx, FRICTION_FLY);
642 mo->momy = FixedMul(mo->momy, FRICTION_FLY);
644 else if(P_GetThingFloorType(mo) == FLOOR_ICE)
646 mo->momx = FixedMul(mo->momx, FRICTION_LOW);
647 mo->momy = FixedMul(mo->momy, FRICTION_LOW);
651 mo->momx = FixedMul(mo->momx, FRICTION_NORMAL);
652 mo->momy = FixedMul(mo->momy, FRICTION_NORMAL);
658 // Move this to p_inter ***
659 void P_MonsterFallingDamage(mobj_t *mo)
665 if(mom > 35*FRACUNIT)
671 damage = ((mom - (23*FRACUNIT) )*6)>>FRACBITS;
673 damage=10000; // always kill 'em
674 P_DamageMobj(mo, NULL, NULL, damage);
687 void P_ZMovement(mobj_t *mo)
692 // check for smooth step up
694 if (mo->player && mo->z < mo->floorz)
696 mo->player->viewheight -= mo->floorz-mo->z;
697 mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3;
703 if(mo->flags&MF_FLOAT && mo->target)
704 { // float down towards target if too close
705 if(!(mo->flags&MF_SKULLFLY) && !(mo->flags&MF_INFLOAT))
707 dist = P_AproxDistance(mo->x-mo->target->x, mo->y-mo->target->y);
708 delta =( mo->target->z+(mo->height>>1))-mo->z;
709 if (delta < 0 && dist < -(delta*3))
711 else if (delta > 0 && dist < (delta*3))
715 if(mo->player && mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
718 mo->z += finesine[(FINEANGLES/20*leveltime>>2)&FINEMASK];
724 if(mo->z <= mo->floorz)
726 if(mo->flags&MF_MISSILE)
729 if(mo->flags2&MF2_FLOORBOUNCE)
731 P_FloorBounceMissile(mo);
734 else if(mo->type == MT_HOLY_FX)
735 { // The spirit struck the ground
740 else if(mo->type == MT_MNTRFX2 || mo->type == MT_LIGHTNING_FLOOR)
741 { // Minotaur floor fire can go up steps
747 P_ExplodeMissile(mo);
751 if(mo->flags&MF_COUNTKILL) // Blasted mobj falling
753 if(mo->momz < -(23*FRACUNIT))
755 P_MonsterFallingDamage(mo);
758 if(mo->z-mo->momz > mo->floorz)
759 { // Spawn splashes, etc.
765 if(mo->flags2&MF2_ICEDAMAGE && mo->momz < -GRAVITY*8)
775 mo->player->jumpTics = 7;// delay any jumping for a short time
776 if(mo->momz < -GRAVITY*8 && !(mo->flags2&MF2_FLY))
778 mo->player->deltaviewheight = mo->momz>>3;
779 if(mo->momz < -23*FRACUNIT)
781 P_FallingDamage(mo->player);
782 P_NoiseAlert(mo, mo);
784 else if(mo->momz < -GRAVITY*12 && !mo->player->morphTics)
786 S_StartSound(mo, SFX_PLAYER_LAND);
787 switch(mo->player->class)
790 S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT);
793 S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT);
796 S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT);
802 else if ((P_GetThingFloorType(mo) < FLOOR_LIQUID) &&
803 (!mo->player->morphTics))
805 S_StartSound(mo, SFX_PLAYER_LAND);
807 if(mouselook && !demorecording && !demoplayback) {
808 mo->player->centering = false;
811 mo->player->centering = true;
815 else if(mo->type >= MT_POTTERY1
816 && mo->type <= MT_POTTERY3)
818 P_DamageMobj(mo, NULL, NULL, 25);
820 else if(mo->flags&MF_COUNTKILL)
822 if(mo->momz < -23*FRACUNIT)
829 if(mo->flags&MF_SKULLFLY)
830 { // The skull slammed into something
831 mo->momz = -mo->momz;
833 if(mo->info->crashstate &&
834 (mo->flags&MF_CORPSE) &&
835 !(mo->flags2&MF2_ICEDAMAGE))
837 P_SetMobjState(mo, mo->info->crashstate);
841 else if(mo->flags2&MF2_LOGRAV)
844 mo->momz = -(GRAVITY>>3)*2;
846 mo->momz -= GRAVITY>>3;
848 else if (! (mo->flags & MF_NOGRAVITY) )
851 mo->momz = -GRAVITY*2;
856 if (mo->z + mo->height > mo->ceilingz)
860 mo->z = mo->ceilingz - mo->height;
861 if(mo->flags2&MF2_FLOORBOUNCE)
863 // Maybe reverse momentum here for ceiling bounce
864 // Currently won't happen
866 if(mo->info->seesound)
868 S_StartSound(mo, mo->info->seesound);
872 if (mo->flags & MF_SKULLFLY)
873 { // the skull slammed into something
874 mo->momz = -mo->momz;
876 if(mo->flags&MF_MISSILE)
878 if(mo->type == MT_LIGHTNING_CEILING)
882 if(mo->subsector->sector->ceilingpic == skyflatnum)
884 if(mo->type == MT_BLOODYSKULL)
886 mo->momx = mo->momy = 0;
887 mo->momz = -FRACUNIT;
889 else if(mo->type == MT_HOLY_FX)
891 P_ExplodeMissile(mo);
899 P_ExplodeMissile(mo);
905 //----------------------------------------------------------------------------
907 // PROC P_BlasterMobjThinker
910 //----------------------------------------------------------------------------
912 void P_BlasterMobjThinker(mobj_t *mobj)
923 if(mobj->momx || mobj->momy ||
924 (mobj->z != mobj->floorz) || mobj->momz)
926 xfrac = mobj->momx>>3;
927 yfrac = mobj->momy>>3;
928 zfrac = mobj->momz>>3;
929 changexy = xfrac || yfrac;
930 for(i = 0; i < 8; i++)
934 if(!P_TryMove(mobj, mobj->x+xfrac, mobj->y+yfrac))
936 P_ExplodeMissile(mobj);
941 if(mobj->z <= mobj->floorz)
943 mobj->z = mobj->floorz;
945 P_ExplodeMissile(mobj);
948 if(mobj->z+mobj->height > mobj->ceilingz)
950 mobj->z = mobj->ceilingz-mobj->height;
951 P_ExplodeMissile(mobj);
956 if(mobj->type == MT_MWAND_MISSILE && (P_Random() < 128))
958 z = mobj->z-8*FRACUNIT;
963 P_SpawnMobj(mobj->x, mobj->y, z, MT_MWANDSMOKE);
965 /* jim allow other things to have BlasterMobjThinker()s (crossbow) */
966 else if((mobj->type == MT_CFLAME_MISSILE) &&
970 z = mobj->z-12*FRACUNIT;
975 mo = P_SpawnMobj(mobj->x, mobj->y, z, MT_CFLAMEFLOOR);
978 mo->angle = mobj->angle;
990 if(!P_SetMobjState(mobj, mobj->state->nextstate))
991 { // mobj was removed
998 //===========================================================================
1000 // PlayerLandedOnThing
1002 //===========================================================================
1004 static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj)
1006 mo->player->deltaviewheight = mo->momz>>3;
1007 if(mo->momz < -23*FRACUNIT)
1009 P_FallingDamage(mo->player);
1010 P_NoiseAlert(mo, mo);
1012 else if(mo->momz < -GRAVITY*12
1013 && !mo->player->morphTics)
1015 S_StartSound(mo, SFX_PLAYER_LAND);
1016 switch(mo->player->class)
1018 case PCLASS_FIGHTER:
1019 S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT);
1022 S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT);
1025 S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT);
1031 else if(!mo->player->morphTics)
1033 S_StartSound(mo, SFX_PLAYER_LAND);
1035 if(mouselook && !demorecording && !demoplayback) {
1036 mo->player->centering = false;
1038 else { mo->player->centering = true;
1042 //----------------------------------------------------------------------------
1044 // PROC P_MobjThinker
1046 //----------------------------------------------------------------------------
1048 void P_MobjThinker(mobj_t *mobj)
1052 // Reset to not blasted when momentums are gone
1053 if((mobj->flags2&MF2_BLASTED) && (!(mobj->momx)) && (!(mobj->momy)))
1056 // Handle X and Y momentums
1057 BlockingMobj = NULL;
1058 if(mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY))
1061 if(mobj->thinker.function == (think_t)-1)
1062 { // mobj was removed
1066 else if(mobj->flags2&MF2_BLASTED)
1067 { // Reset to not blasted when momentums are gone
1070 if(mobj->flags2&MF2_FLOATBOB)
1071 { // Floating item bobbing motion (special1 is height)
1072 mobj->z = mobj->floorz +
1074 FloatBobOffsets[(mobj->health++)&63];
1076 else if((mobj->z != mobj->floorz) || mobj->momz || BlockingMobj)
1077 { // Handle Z momentum and gravity
1078 if(mobj->flags2&MF2_PASSMOBJ)
1080 if(!(onmo = P_CheckOnmobj(mobj)))
1083 if(mobj->player && mobj->flags&MF2_ONMOBJ)
1085 mobj->flags2 &= ~MF2_ONMOBJ;
1092 if(mobj->momz < -GRAVITY*8 && !(mobj->flags2&MF2_FLY))
1094 PlayerLandedOnThing(mobj, onmo);
1096 if(onmo->z+onmo->height-mobj->z <= 24*FRACUNIT)
1098 mobj->player->viewheight -= onmo->z+onmo->height
1100 mobj->player->deltaviewheight =
1101 (VIEWHEIGHT-mobj->player->viewheight)>>3;
1102 mobj->z = onmo->z+onmo->height;
1103 mobj->flags2 |= MF2_ONMOBJ;
1107 { // hit the bottom of the blocking mobj
1111 /* Landing on another player, and mimicking his movements
1112 if(mobj->player && onmo->player)
1114 mobj->momx = onmo->momx;
1115 mobj->momy = onmo->momy;
1116 if(onmo->z < onmo->floorz)
1118 mobj->z += onmo->floorz-onmo->z;
1121 onmo->player->viewheight -= onmo->floorz-onmo->z;
1122 onmo->player->deltaviewheight = (VIEWHEIGHT-
1123 onmo->player->viewheight)>>3;
1125 onmo->z = onmo->floorz;
1135 if(mobj->thinker.function == (think_t)-1)
1136 { // mobj was removed
1141 // Cycle through states, calling action functions at transitions
1142 if(mobj->tics != -1)
1145 // you can cycle through multiple states in a tic
1148 if(!P_SetMobjState(mobj, mobj->state->nextstate))
1149 { // mobj was removed
1156 //==========================================================================
1160 //==========================================================================
1162 mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
1169 mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
1170 memset(mobj, 0, sizeof(*mobj));
1171 info = &mobjinfo[type];
1176 mobj->radius = info->radius;
1177 mobj->height = info->height;
1178 mobj->flags = info->flags;
1179 mobj->flags2 = info->flags2;
1180 mobj->damage = info->damage;
1181 mobj->health = info->spawnhealth;
1182 if(gameskill != sk_nightmare)
1184 mobj->reactiontime = info->reactiontime;
1186 mobj->lastlook = P_Random()%MAXPLAYERS;
1188 // Set the state, but do not use P_SetMobjState, because action
1189 // routines can't be called yet. If the spawnstate has an action
1190 // routine, it will not be called.
1191 st = &states[info->spawnstate];
1193 mobj->tics = st->tics;
1194 mobj->sprite = st->sprite;
1195 mobj->frame = st->frame;
1197 // Set subsector and/or block links.
1198 P_SetThingPosition(mobj);
1199 mobj->floorz = mobj->subsector->sector->floorheight;
1200 mobj->ceilingz = mobj->subsector->sector->ceilingheight;
1203 mobj->z = mobj->floorz;
1205 else if(z == ONCEILINGZ)
1207 mobj->z = mobj->ceilingz-mobj->info->height;
1209 else if(z == FLOATRANDZ)
1211 space = ((mobj->ceilingz)-(mobj->info->height))-mobj->floorz;
1212 if(space > 48*FRACUNIT)
1214 space -= 40*FRACUNIT;
1215 mobj->z = ((space*P_Random())>>8)+mobj->floorz+40*FRACUNIT;
1219 mobj->z = mobj->floorz;
1222 else if (mobj->flags2&MF2_FLOATBOB)
1224 mobj->z = mobj->floorz + z; // artifact z passed in as height
1230 if(mobj->flags2&MF2_FLOORCLIP && P_GetThingFloorType(mobj) >= FLOOR_LIQUID
1231 && mobj->z == mobj->subsector->sector->floorheight)
1233 mobj->floorclip = 10*FRACUNIT;
1237 mobj->floorclip = 0;
1240 mobj->thinker.function = P_MobjThinker;
1241 P_AddThinker(&mobj->thinker);
1245 //==========================================================================
1249 //==========================================================================
1251 void P_RemoveMobj(mobj_t *mobj)
1253 // Remove from creature queue
1254 if(mobj->flags&MF_COUNTKILL &&
1255 mobj->flags&MF_CORPSE)
1257 A_DeQueueCorpse(mobj);
1261 { // Remove from TID list
1262 P_RemoveMobjFromTIDList(mobj);
1265 // Unlink from sector and block lists
1266 P_UnsetThingPosition(mobj);
1268 // Stop any playing sound
1272 P_RemoveThinker((thinker_t *)mobj);
1275 //==========================================================================
1279 // Called when a player is spawned on the level. Most of the player
1280 // structure stays unchanged between levels.
1282 //==========================================================================
1284 void P_SpawnPlayer(mapthing_t *mthing)
1290 if(!playeringame[mthing->type-1])
1294 p = &players[mthing->type-1];
1295 if(p->playerstate == PST_REBORN)
1297 G_PlayerReborn(mthing->type-1);
1299 x = mthing->x << FRACBITS;
1300 y = mthing->y << FRACBITS;
1302 if(randomclass && deathmatch)
1304 p->class = P_Random()%3;
1305 if(p->class == PlayerClass[mthing->type-1])
1307 p->class = (p->class+1)%3;
1309 PlayerClass[mthing->type-1] = p->class;
1314 p->class = PlayerClass[mthing->type-1];
1318 case PCLASS_FIGHTER:
1319 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER);
1322 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC);
1325 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE);
1328 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_ASS);
1331 I_Error("P_SpawnPlayer: Unknown class type");
1332 /* jim never happens but keeps gcc happy */
1337 // Set translation table data
1338 if(p->class == PCLASS_FIGHTER && (mthing->type == 1 || mthing->type == 3))
1340 // The first type should be blue, and the third should be the
1341 // Fighter's original gold color
1342 if(mthing->type == 1)
1344 mobj->flags |= 2<<MF_TRANSSHIFT;
1347 else if(mthing->type > 1)
1348 { // Set color translation bits for player sprites
1349 mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
1352 mobj->angle = ANG45 * (mthing->angle/45);
1354 mobj->health = p->health;
1356 p->playerstate = PST_LIVE;
1364 p->fixedcolormap = 0;
1365 p->viewheight = VIEWHEIGHT;
1368 { // Give all keys in death match mode
1373 //==========================================================================
1377 // The fields of the mapthing should already be in host byte order.
1379 //==========================================================================
1381 void P_SpawnMapThing(mapthing_t *mthing)
1384 unsigned int spawnMask;
1387 // Put in Cleric twice, since we can't have an assassin flag.
1388 static unsigned int classFlags[] =
1396 // Count deathmatch start positions
1397 if(mthing->type == 11)
1399 if(deathmatch_p < &deathmatchstarts[MAXDEATHMATCHSTARTS])
1401 memcpy(deathmatch_p, mthing, sizeof(*mthing));
1406 if(mthing->type == PO_ANCHOR_TYPE)
1407 { // Polyobj Anchor Pt.
1410 else if(mthing->type == PO_SPAWN_TYPE
1411 || mthing->type == PO_SPAWNCRUSH_TYPE)
1412 { // Polyobj Anchor Pt.
1417 // Check for player starts 1 to 4
1418 if(mthing->type <= 4)
1420 playerstarts[mthing->arg1][mthing->type-1] = *mthing;
1421 if(!deathmatch && !mthing->arg1)
1423 P_SpawnPlayer(mthing);
1427 // Check for player starts 5 to 8
1428 if(mthing->type >= 9100 && mthing->type <= 9103)
1430 mthing->type = 5+mthing->type-9100; // Translate to 5 - 8
1431 playerstarts[mthing->arg1][mthing->type-1] = *mthing;
1432 if(!deathmatch && !mthing->arg1)
1434 P_SpawnPlayer(mthing);
1439 if(mthing->type >= 1400 && mthing->type < 1410)
1441 R_PointInSubsector(mthing->x<<FRACBITS,
1442 mthing->y<<FRACBITS)->sector->seqType = mthing->type-1400;
1446 // Check current game type with spawn flags
1447 if(netgame == false)
1449 spawnMask = MTF_GSINGLE;
1453 spawnMask = MTF_GDEATHMATCH;
1457 spawnMask = MTF_GCOOP;
1459 if(!(mthing->options&spawnMask))
1464 // Check current skill with spawn flags
1465 if(gameskill == sk_baby || gameskill == sk_easy)
1467 spawnMask = MTF_EASY;
1469 else if(gameskill == sk_hard || gameskill == sk_nightmare)
1471 spawnMask = MTF_HARD;
1475 spawnMask = MTF_NORMAL;
1477 if(!(mthing->options&spawnMask))
1482 // Check current character classes with spawn flags
1483 if(netgame == false)
1485 if((mthing->options&classFlags[PlayerClass[0]]) == 0)
1486 { // Not for current class
1490 else if(deathmatch == false)
1493 for(i = 0; i < MAXPLAYERS; i++)
1497 spawnMask |= classFlags[PlayerClass[i]];
1500 if((mthing->options&spawnMask) == 0)
1506 // Find which type to spawn
1507 for(i = 0; i < NUMMOBJTYPES; i++)
1509 if(mthing->type == mobjinfo[i].doomednum)
1515 if(i == NUMMOBJTYPES)
1516 { // Can't find thing type
1517 I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)",
1518 mthing->type, mthing->x, mthing->y);
1521 // Don't spawn keys and players in deathmatch
1522 if(deathmatch && mobjinfo[i].flags&MF_NOTDMATCH)
1527 // Don't spawn monsters if -nomonsters
1528 if(nomonsters && (mobjinfo[i].flags&MF_COUNTKILL))
1533 x = mthing->x<<FRACBITS;
1534 y = mthing->y<<FRACBITS;
1535 if(mobjinfo[i].flags&MF_SPAWNCEILING)
1539 else if(mobjinfo[i].flags2&MF2_SPAWNFLOAT)
1543 else if(mobjinfo[i].flags2&MF2_FLOATBOB)
1545 z = mthing->height<<FRACBITS;
1553 case MT_ZLYNCHED_NOHEART:
1554 P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODPOOL);
1559 mobj = P_SpawnMobj(x, y, z, i);
1562 mobj->z += mthing->height<<FRACBITS;
1564 else if(z == ONCEILINGZ)
1566 mobj->z -= mthing->height<<FRACBITS;
1568 mobj->tid = mthing->tid;
1569 mobj->special = mthing->special;
1570 mobj->args[0] = mthing->arg1;
1571 mobj->args[1] = mthing->arg2;
1572 mobj->args[2] = mthing->arg3;
1573 mobj->args[3] = mthing->arg4;
1574 mobj->args[4] = mthing->arg5;
1575 if(mobj->flags2&MF2_FLOATBOB)
1576 { // Seed random starting index for bobbing motion
1577 mobj->health = P_Random();
1578 mobj->special1 = mthing->height<<FRACBITS;
1582 mobj->tics = 1+(P_Random()%mobj->tics);
1584 // if(mobj->flags&MF_COUNTITEM)
1588 if (mobj->flags&MF_COUNTKILL)
1590 // Quantize angle to 45 degree increments
1591 mobj->angle = ANG45*(mthing->angle/45);
1595 // Scale angle correctly (source is 0..359)
1596 mobj->angle = ((mthing->angle<<8)/360)<<24;
1598 if(mthing->options&MTF_AMBUSH)
1600 mobj->flags |= MF_AMBUSH;
1602 if(mthing->options&MTF_DORMANT)
1604 mobj->flags2 |= MF2_DORMANT;
1605 if(mobj->type == MT_ICEGUY)
1607 P_SetMobjState(mobj, S_ICEGUY_DORMANT);
1613 //==========================================================================
1617 //==========================================================================
1619 void P_CreateTIDList(void)
1626 for(t = thinkercap.next; t != &thinkercap; t = t->next)
1627 { // Search all current thinkers
1628 if(t->function != P_MobjThinker)
1629 { // Not a mobj thinker
1635 if(i == MAX_TID_COUNT)
1637 I_Error("P_CreateTIDList: MAX_TID_COUNT (%d) exceeded.",
1640 TIDList[i] = mobj->tid;
1641 TIDMobj[i++] = mobj;
1644 // Add termination marker
1648 //==========================================================================
1650 // P_InsertMobjIntoTIDList
1652 //==========================================================================
1654 void P_InsertMobjIntoTIDList(mobj_t *mobj, int tid)
1660 for(i = 0; TIDList[i] != 0; i++)
1662 if(TIDList[i] == -1)
1663 { // Found empty slot
1669 { // Append required
1670 if(i == MAX_TID_COUNT)
1672 I_Error("P_InsertMobjIntoTIDList: MAX_TID_COUNT (%d)"
1673 "exceeded.", MAX_TID_COUNT);
1676 TIDList[index+1] = 0;
1679 TIDList[index] = tid;
1680 TIDMobj[index] = mobj;
1683 //==========================================================================
1685 // P_RemoveMobjFromTIDList
1687 //==========================================================================
1689 void P_RemoveMobjFromTIDList(mobj_t *mobj)
1693 for(i = 0; TIDList[i] != 0; i++)
1695 if(TIDMobj[i] == mobj)
1706 //==========================================================================
1708 // P_FindMobjFromTID
1710 //==========================================================================
1712 mobj_t *P_FindMobjFromTID(int tid, int *searchPosition)
1716 for(i = *searchPosition+1; TIDList[i] != 0; i++)
1718 if(TIDList[i] == tid)
1720 *searchPosition = i;
1724 *searchPosition = -1;
1729 ===============================================================================
1731 GAME SPAWN FUNCTIONS
1733 ===============================================================================
1736 //---------------------------------------------------------------------------
1740 //---------------------------------------------------------------------------
1742 extern fixed_t attackrange;
1744 void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
1748 z += ((P_Random()-P_Random())<<10);
1749 puff = P_SpawnMobj(x, y, z, PuffType);
1750 if(linetarget && puff->info->seesound)
1751 { // Hit thing sound
1752 S_StartSound(puff, puff->info->seesound);
1754 else if(puff->info->attacksound)
1756 S_StartSound(puff, puff->info->attacksound);
1761 puff->momz = FRACUNIT;
1764 puff->momz = .8*FRACUNIT;
1781 void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
1785 z += ((P_Random()-P_Random())<<10);
1786 th = P_SpawnMobj (x,y,z, MT_BLOOD);
1787 th->momz = FRACUNIT*2;
1788 th->tics -= P_Random()&3;
1790 if (damage <= 12 && damage >= 9)
1791 P_SetMobjState (th,S_BLOOD2);
1792 else if (damage < 9)
1793 P_SetMobjState (th,S_BLOOD3);
1797 //---------------------------------------------------------------------------
1799 // PROC P_BloodSplatter
1801 //---------------------------------------------------------------------------
1803 void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1807 mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
1808 mo->target = originator;
1809 mo->momx = (P_Random()-P_Random())<<10;
1810 mo->momy = (P_Random()-P_Random())<<10;
1811 mo->momz = 3*FRACUNIT;
1814 //===========================================================================
1818 //===========================================================================
1820 void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1824 mo = P_SpawnMobj(x+((P_Random()-128)<<11), y+((P_Random()-128)<<11), z,
1826 mo->target = originator;
1829 //---------------------------------------------------------------------------
1831 // PROC P_RipperBlood
1833 //---------------------------------------------------------------------------
1835 void P_RipperBlood(mobj_t *mo)
1840 x = mo->x+((P_Random()-P_Random())<<12);
1841 y = mo->y+((P_Random()-P_Random())<<12);
1842 z = mo->z+((P_Random()-P_Random())<<12);
1843 th = P_SpawnMobj(x, y, z, MT_BLOOD);
1844 // th->flags |= MF_NOGRAVITY;
1845 th->momx = mo->momx>>1;
1846 th->momy = mo->momy>>1;
1847 th->tics += P_Random()&3;
1850 //---------------------------------------------------------------------------
1852 // FUNC P_GetThingFloorType
1854 //---------------------------------------------------------------------------
1856 int P_GetThingFloorType(mobj_t *thing)
1860 return(TerrainTypes[thing->floorpic]);
1864 return(TerrainTypes[thing->subsector->sector->floorpic]);
1867 if(thing->subsector->sector->floorpic
1868 == W_GetNumForName("FLTWAWA1")-firstflat)
1870 return(FLOOR_WATER);
1874 return(FLOOR_SOLID);
1879 //---------------------------------------------------------------------------
1883 //---------------------------------------------------------------------------
1884 #define SMALLSPLASHCLIP 12<<FRACBITS;
1886 int P_HitFloor(mobj_t *thing)
1889 int smallsplash=false;
1891 if(thing->floorz != thing->subsector->sector->floorheight)
1892 { // don't splash if landing on the edge above water/lava/etc....
1893 return(FLOOR_SOLID);
1896 // Things that don't splash go here
1901 // case MT_BLOOD: // I set these to low mass -- pm
1902 // case MT_BLOODSPLATTER:
1904 case MT_SLUDGECHUNK:
1905 return(FLOOR_SOLID);
1910 // Small splash for small masses
1911 if (thing->info->mass < 10) smallsplash = true;
1913 switch(P_GetThingFloorType(thing))
1918 mo=P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1919 if (mo) mo->floorclip += SMALLSPLASHCLIP;
1920 S_StartSound(mo, SFX_AMBIENT10); // small drip
1924 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
1926 mo->momx = (P_Random()-P_Random())<<8;
1927 mo->momy = (P_Random()-P_Random())<<8;
1928 mo->momz = 2*FRACUNIT+(P_Random()<<8);
1929 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1930 if (thing->player) P_NoiseAlert(thing, thing);
1931 S_StartSound(mo, SFX_WATER_SPLASH);
1933 return(FLOOR_WATER);
1937 mo=P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1938 if (mo) mo->floorclip += SMALLSPLASHCLIP;
1942 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE);
1943 mo->momz = FRACUNIT+(P_Random()<<7);
1944 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1945 if (thing->player) P_NoiseAlert(thing, thing);
1947 S_StartSound(mo, SFX_LAVA_SIZZLE);
1948 if(thing->player && leveltime&31)
1950 P_DamageMobj(thing, &LavaInflictor, NULL, 5);
1956 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
1958 if (mo) mo->floorclip += SMALLSPLASHCLIP;
1962 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK);
1964 mo->momx = (P_Random()-P_Random())<<8;
1965 mo->momy = (P_Random()-P_Random())<<8;
1966 mo->momz = FRACUNIT+(P_Random()<<8);
1967 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
1969 if (thing->player) P_NoiseAlert(thing, thing);
1971 S_StartSound(mo, SFX_SLUDGE_GLOOP);
1972 return(FLOOR_SLUDGE);
1974 return(FLOOR_SOLID);
1978 //---------------------------------------------------------------------------
1980 // FUNC P_CheckMissileSpawn
1982 // Returns true if the missile is at a valid spawn point, otherwise
1983 // explodes it and returns false.
1985 //---------------------------------------------------------------------------
1987 boolean P_CheckMissileSpawn(mobj_t *missile)
1989 //missile->tics -= P_Random()&3;
1991 // move a little forward so an angle can be computed if it
1992 // immediately explodes
1994 * jim - handle fast missiles with BlasterMobjThinker()s
1995 * assume so if momentum > MAXMOVE
1996 * this is a horrible kludge, but to be honest so is the BlasterMobjThinker
1997 * stuff in the first place
1999 if ((missile->momx > MAXMOVE) || (missile->momy > MAXMOVE))
2001 missile->x += (missile->momx>>3);
2002 missile->y += (missile->momy>>3);
2003 missile->z += (missile->momz>>3);
2007 missile->x += (missile->momx>>1);
2008 missile->y += (missile->momy>>1);
2009 missile->z += (missile->momz>>1);
2011 if(!P_TryMove(missile, missile->x, missile->y))
2013 P_ExplodeMissile(missile);
2019 //---------------------------------------------------------------------------
2021 // FUNC P_SpawnMissile
2023 // Returns NULL if the missile exploded immediately, otherwise returns
2024 // a mobj_t pointer to the missile.
2026 //---------------------------------------------------------------------------
2028 mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
2037 case MT_MNTRFX1: // Minotaur swing attack missile
2038 z = source->z+40*FRACUNIT;
2040 case MT_MNTRFX2: // Minotaur floor fire missile
2041 z = ONFLOORZ+source->floorclip;
2044 z = source->z+45*FRACUNIT;
2047 z = source->z+40*FRACUNIT;
2049 case MT_HOLY_MISSILE:
2050 z = source->z+40*FRACUNIT;
2053 z = source->z+32*FRACUNIT;
2056 z -= source->floorclip;
2057 th = P_SpawnMobj(source->x, source->y, z, type);
2058 if(th->info->seesound)
2060 S_StartSound(th, th->info->seesound);
2062 th->target = source; // Originator
2063 an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
2064 if(dest->flags&MF_SHADOW)
2065 { // Invisible target
2066 an += (P_Random()-P_Random())<<21;
2069 an >>= ANGLETOFINESHIFT;
2070 th->momx = FixedMul(th->info->speed, finecosine[an]);
2071 th->momy = FixedMul(th->info->speed, finesine[an]);
2072 dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
2073 dist = dist/th->info->speed;
2078 th->momz = (dest->z-source->z)/dist;
2079 return(P_CheckMissileSpawn(th) ? th : NULL);
2082 //---------------------------------------------------------------------------
2084 // FUNC P_SpawnMissileXYZ
2086 // Returns NULL if the missile exploded immediately, otherwise returns
2087 // a mobj_t pointer to the missile.
2089 //---------------------------------------------------------------------------
2091 mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z,
2092 mobj_t *source, mobj_t *dest, mobjtype_t type)
2098 z -= source->floorclip;
2099 th = P_SpawnMobj(x, y, z, type);
2100 if(th->info->seesound)
2102 S_StartSound(th, th->info->seesound);
2104 th->target = source; // Originator
2105 an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
2106 if(dest->flags&MF_SHADOW)
2107 { // Invisible target
2108 an += (P_Random()-P_Random())<<21;
2111 an >>= ANGLETOFINESHIFT;
2112 th->momx = FixedMul(th->info->speed, finecosine[an]);
2113 th->momy = FixedMul(th->info->speed, finesine[an]);
2114 dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
2115 dist = dist/th->info->speed;
2120 th->momz = (dest->z-source->z)/dist;
2121 return(P_CheckMissileSpawn(th) ? th : NULL);
2124 //---------------------------------------------------------------------------
2126 // FUNC P_SpawnMissileAngle
2128 // Returns NULL if the missile exploded immediately, otherwise returns
2129 // a mobj_t pointer to the missile.
2131 //---------------------------------------------------------------------------
2133 mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
2134 angle_t angle, fixed_t momz)
2141 case MT_MNTRFX1: // Minotaur swing attack missile
2142 z = source->z+40*FRACUNIT;
2144 case MT_MNTRFX2: // Minotaur floor fire missile
2145 z = ONFLOORZ+source->floorclip;
2147 case MT_ICEGUY_FX2: // Secondary Projectiles of the Ice Guy
2148 z = source->z+3*FRACUNIT;
2151 z = source->z+40*FRACUNIT;
2154 z = source->z+32*FRACUNIT;
2157 z -= source->floorclip;
2158 mo = P_SpawnMobj(source->x, source->y, z, type);
2159 if(mo->info->seesound)
2161 S_StartSound(mo, mo->info->seesound);
2163 mo->target = source; // Originator
2165 angle >>= ANGLETOFINESHIFT;
2166 mo->momx = FixedMul(mo->info->speed, finecosine[angle]);
2167 mo->momy = FixedMul(mo->info->speed, finesine[angle]);
2169 return(P_CheckMissileSpawn(mo) ? mo : NULL);
2172 //---------------------------------------------------------------------------
2174 // FUNC P_SpawnMissileAngleSpeed
2176 // Returns NULL if the missile exploded immediately, otherwise returns
2177 // a mobj_t pointer to the missile.
2179 //---------------------------------------------------------------------------
2181 mobj_t *P_SpawnMissileAngleSpeed(mobj_t *source, mobjtype_t type,
2182 angle_t angle, fixed_t momz, fixed_t speed)
2188 z -= source->floorclip;
2189 mo = P_SpawnMobj(source->x, source->y, z, type);
2190 if(mo->info->seesound)
2192 //S_StartSound(mo, mo->info->seesound);
2194 mo->target = source; // Originator
2196 angle >>= ANGLETOFINESHIFT;
2197 mo->momx = FixedMul(speed, finecosine[angle]);
2198 mo->momy = FixedMul(speed, finesine[angle]);
2200 return(P_CheckMissileSpawn(mo) ? mo : NULL);
2208 = P_SpawnPlayerMissile
2210 = Tries to aim at a nearby monster
2214 mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type)
2217 fixed_t x, y, z, slope;
2219 // Try to find a target
2221 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2225 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2229 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2234 slope = ((source->player->lookdir)<<FRACBITS)/173;
2239 if(type == MT_LIGHTNING_FLOOR)
2244 else if(type == MT_LIGHTNING_CEILING)
2251 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2252 z -= source->floorclip;
2254 MissileMobj = P_SpawnMobj(x, y, z, type);
2255 if(MissileMobj->info->seesound)
2257 //S_StartSound(MissileMobj, MissileMobj->info->seesound);
2259 MissileMobj->target = source;
2260 MissileMobj->angle = an;
2261 MissileMobj->momx = FixedMul(MissileMobj->info->speed,
2262 finecosine[an>>ANGLETOFINESHIFT]);
2263 MissileMobj->momy = FixedMul(MissileMobj->info->speed,
2264 finesine[an>>ANGLETOFINESHIFT]);
2265 MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope);
2266 if(MissileMobj->type == MT_MWAND_MISSILE
2267 || MissileMobj->type == MT_CFLAME_MISSILE)
2268 { // Ultra-fast ripper spawning missile
2269 MissileMobj->x += (MissileMobj->momx>>3);
2270 MissileMobj->y += (MissileMobj->momy>>3);
2271 MissileMobj->z += (MissileMobj->momz>>3);
2275 MissileMobj->x += (MissileMobj->momx>>1);
2276 MissileMobj->y += (MissileMobj->momy>>1);
2277 MissileMobj->z += (MissileMobj->momz>>1);
2279 if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
2280 { // Exploded immediately
2281 P_ExplodeMissile(MissileMobj);
2284 return(MissileMobj);
2288 //----------------------------------------------------------------------------
2290 // P_SpawnPlayerMinotaur -
2292 // Special missile that has larger blocking than player
2293 //----------------------------------------------------------------------------
2296 mobj_t *P_SpawnPlayerMinotaur(mobj_t *source, mobjtype_t type)
2300 fixed_t dist=0 *FRACUNIT;
2303 x = source->x + FixedMul(dist, finecosine[an>>ANGLETOFINESHIFT]);
2304 y = source->y + FixedMul(dist, finesine[an>>ANGLETOFINESHIFT]);
2305 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2306 z -= source->floorclip;
2307 MissileMobj = P_SpawnMobj(x, y, z, type);
2308 if(MissileMobj->info->seesound)
2310 //S_StartSound(MissileMobj, MissileMobj->info->seesound);
2312 MissileMobj->target = source;
2313 MissileMobj->angle = an;
2314 MissileMobj->momx = FixedMul(MissileMobj->info->speed,
2315 finecosine[an>>ANGLETOFINESHIFT]);
2316 MissileMobj->momy = FixedMul(MissileMobj->info->speed,
2317 finesine[an>>ANGLETOFINESHIFT]);
2318 MissileMobj->momz = 0;
2320 // MissileMobj->x += (MissileMobj->momx>>3);
2321 // MissileMobj->y += (MissileMobj->momy>>3);
2322 // MissileMobj->z += (MissileMobj->momz>>3);
2324 if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
2329 return(MissileMobj);
2333 //---------------------------------------------------------------------------
2337 //---------------------------------------------------------------------------
2339 mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle)
2343 fixed_t x, y, z, slope;
2346 // see which target is to be aimed at
2349 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2353 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2357 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2362 slope = ((source->player->lookdir)<<FRACBITS)/173;
2367 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2368 z -= source->floorclip;
2369 th = P_SpawnMobj(x, y, z, type);
2370 // if(th->info->seesound)
2372 // S_StartSound(th, th->info->seesound);
2374 th->target = source;
2376 th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
2377 th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
2378 th->momz = FixedMul(th->info->speed, slope);
2379 return(P_CheckMissileSpawn(th) ? th : NULL);
2382 //===========================================================================
2386 //===========================================================================
2388 mobj_t *P_SPMAngleXYZ(mobj_t *source, fixed_t x, fixed_t y,
2389 fixed_t z, mobjtype_t type, angle_t angle)
2396 // see which target is to be aimed at
2399 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2403 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2407 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2412 slope = ((source->player->lookdir)<<FRACBITS)/173;
2415 z += 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2416 z -= source->floorclip;
2417 th = P_SpawnMobj(x, y, z, type);
2418 // if(th->info->seesound)
2420 // S_StartSound(th, th->info->seesound);
2422 th->target = source;
2424 th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
2425 th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
2426 th->momz = FixedMul(th->info->speed, slope);
2427 return(P_CheckMissileSpawn(th) ? th : NULL);
2430 mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z,
2431 mobj_t *source, mobj_t *dest, mobjtype_t type)
2437 z -= source->floorclip;
2438 th = P_SpawnMobj(x, y, z, type);
2439 if(th->info->seesound)
2441 S_StartSound(th, th->info->seesound);
2443 th->target = source; // Originator
2444 an = R_PointToAngle2(x, y, dest->x, dest->y);
2445 if(dest->flags&MF_SHADOW)
2446 { // Invisible target
2447 an += (P_Random()-P_Random())<<21;
2450 an >>= ANGLETOFINESHIFT;
2451 th->momx = FixedMul(th->info->speed, finecosine[an]);
2452 th->momy = FixedMul(th->info->speed, finesine[an]);
2453 dist = P_AproxDistance(dest->x - x, dest->y - y);
2454 dist = dist/th->info->speed;
2459 th->momz = (dest->z-z+(30*FRACUNIT))/dist;
2460 return(P_CheckMissileSpawn(th) ? th : NULL);