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);
966 else if(!--mobj->special1)
968 jim allow other things to have BlasterMobjThinker()s (crossbow)
970 O.S: I don't need an #ifdef ASSASSIN here, I think..
972 else if((mobj->type == MT_CFLAME_MISSILE) && !--mobj->special1)
975 z = mobj->z-12*FRACUNIT;
980 mo = P_SpawnMobj(mobj->x, mobj->y, z, MT_CFLAMEFLOOR);
983 mo->angle = mobj->angle;
995 if(!P_SetMobjState(mobj, mobj->state->nextstate))
996 { // mobj was removed
1003 //===========================================================================
1005 // PlayerLandedOnThing
1007 //===========================================================================
1009 static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj)
1011 mo->player->deltaviewheight = mo->momz>>3;
1012 if(mo->momz < -23*FRACUNIT)
1014 P_FallingDamage(mo->player);
1015 P_NoiseAlert(mo, mo);
1017 else if(mo->momz < -GRAVITY*12
1018 && !mo->player->morphTics)
1020 S_StartSound(mo, SFX_PLAYER_LAND);
1021 switch(mo->player->class)
1023 case PCLASS_FIGHTER:
1024 S_StartSound(mo, SFX_PLAYER_FIGHTER_GRUNT);
1027 S_StartSound(mo, SFX_PLAYER_CLERIC_GRUNT);
1030 S_StartSound(mo, SFX_PLAYER_MAGE_GRUNT);
1036 else if(!mo->player->morphTics)
1038 S_StartSound(mo, SFX_PLAYER_LAND);
1040 if(mouselook && !demorecording && !demoplayback) {
1041 mo->player->centering = false;
1043 else { mo->player->centering = true;
1047 //----------------------------------------------------------------------------
1049 // PROC P_MobjThinker
1051 //----------------------------------------------------------------------------
1053 void P_MobjThinker(mobj_t *mobj)
1057 // Reset to not blasted when momentums are gone
1058 if((mobj->flags2&MF2_BLASTED) && (!(mobj->momx)) && (!(mobj->momy)))
1061 // Handle X and Y momentums
1062 BlockingMobj = NULL;
1063 if(mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY))
1066 if(mobj->thinker.function == (think_t)-1)
1067 { // mobj was removed
1071 else if(mobj->flags2&MF2_BLASTED)
1072 { // Reset to not blasted when momentums are gone
1075 if(mobj->flags2&MF2_FLOATBOB)
1076 { // Floating item bobbing motion (special1 is height)
1077 mobj->z = mobj->floorz +
1079 FloatBobOffsets[(mobj->health++)&63];
1081 else if((mobj->z != mobj->floorz) || mobj->momz || BlockingMobj)
1082 { // Handle Z momentum and gravity
1083 if(mobj->flags2&MF2_PASSMOBJ)
1085 if(!(onmo = P_CheckOnmobj(mobj)))
1088 if(mobj->player && mobj->flags&MF2_ONMOBJ)
1090 mobj->flags2 &= ~MF2_ONMOBJ;
1097 if(mobj->momz < -GRAVITY*8 && !(mobj->flags2&MF2_FLY))
1099 PlayerLandedOnThing(mobj, onmo);
1101 if(onmo->z+onmo->height-mobj->z <= 24*FRACUNIT)
1103 mobj->player->viewheight -= onmo->z+onmo->height
1105 mobj->player->deltaviewheight =
1106 (VIEWHEIGHT-mobj->player->viewheight)>>3;
1107 mobj->z = onmo->z+onmo->height;
1108 mobj->flags2 |= MF2_ONMOBJ;
1112 { // hit the bottom of the blocking mobj
1116 /* Landing on another player, and mimicking his movements
1117 if(mobj->player && onmo->player)
1119 mobj->momx = onmo->momx;
1120 mobj->momy = onmo->momy;
1121 if(onmo->z < onmo->floorz)
1123 mobj->z += onmo->floorz-onmo->z;
1126 onmo->player->viewheight -= onmo->floorz-onmo->z;
1127 onmo->player->deltaviewheight = (VIEWHEIGHT-
1128 onmo->player->viewheight)>>3;
1130 onmo->z = onmo->floorz;
1140 if(mobj->thinker.function == (think_t)-1)
1141 { // mobj was removed
1146 // Cycle through states, calling action functions at transitions
1147 if(mobj->tics != -1)
1150 // you can cycle through multiple states in a tic
1153 if(!P_SetMobjState(mobj, mobj->state->nextstate))
1154 { // mobj was removed
1161 //==========================================================================
1165 //==========================================================================
1167 mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
1174 mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
1175 memset(mobj, 0, sizeof(*mobj));
1176 info = &mobjinfo[type];
1181 mobj->radius = info->radius;
1182 mobj->height = info->height;
1183 mobj->flags = info->flags;
1184 mobj->flags2 = info->flags2;
1185 mobj->damage = info->damage;
1186 mobj->health = info->spawnhealth;
1187 if(gameskill != sk_nightmare)
1189 mobj->reactiontime = info->reactiontime;
1191 mobj->lastlook = P_Random()%MAXPLAYERS;
1193 // Set the state, but do not use P_SetMobjState, because action
1194 // routines can't be called yet. If the spawnstate has an action
1195 // routine, it will not be called.
1196 st = &states[info->spawnstate];
1198 mobj->tics = st->tics;
1199 mobj->sprite = st->sprite;
1200 mobj->frame = st->frame;
1202 // Set subsector and/or block links.
1203 P_SetThingPosition(mobj);
1204 mobj->floorz = mobj->subsector->sector->floorheight;
1205 mobj->ceilingz = mobj->subsector->sector->ceilingheight;
1208 mobj->z = mobj->floorz;
1210 else if(z == ONCEILINGZ)
1212 mobj->z = mobj->ceilingz-mobj->info->height;
1214 else if(z == FLOATRANDZ)
1216 space = ((mobj->ceilingz)-(mobj->info->height))-mobj->floorz;
1217 if(space > 48*FRACUNIT)
1219 space -= 40*FRACUNIT;
1220 mobj->z = ((space*P_Random())>>8)+mobj->floorz+40*FRACUNIT;
1224 mobj->z = mobj->floorz;
1227 else if (mobj->flags2&MF2_FLOATBOB)
1229 mobj->z = mobj->floorz + z; // artifact z passed in as height
1235 if(mobj->flags2&MF2_FLOORCLIP && P_GetThingFloorType(mobj) >= FLOOR_LIQUID
1236 && mobj->z == mobj->subsector->sector->floorheight)
1238 mobj->floorclip = 10*FRACUNIT;
1242 mobj->floorclip = 0;
1245 mobj->thinker.function = P_MobjThinker;
1246 P_AddThinker(&mobj->thinker);
1250 //==========================================================================
1254 //==========================================================================
1256 void P_RemoveMobj(mobj_t *mobj)
1258 // Remove from creature queue
1259 if(mobj->flags&MF_COUNTKILL &&
1260 mobj->flags&MF_CORPSE)
1262 A_DeQueueCorpse(mobj);
1266 { // Remove from TID list
1267 P_RemoveMobjFromTIDList(mobj);
1270 // Unlink from sector and block lists
1271 P_UnsetThingPosition(mobj);
1273 // Stop any playing sound
1277 P_RemoveThinker((thinker_t *)mobj);
1280 //==========================================================================
1284 // Called when a player is spawned on the level. Most of the player
1285 // structure stays unchanged between levels.
1287 //==========================================================================
1289 void P_SpawnPlayer(mapthing_t *mthing)
1295 if(!playeringame[mthing->type-1])
1299 p = &players[mthing->type-1];
1300 if(p->playerstate == PST_REBORN)
1302 G_PlayerReborn(mthing->type-1);
1304 x = mthing->x << FRACBITS;
1305 y = mthing->y << FRACBITS;
1307 if(randomclass && deathmatch)
1309 p->class = P_Random()%3;
1310 if(p->class == PlayerClass[mthing->type-1])
1312 p->class = (p->class+1)%3;
1314 PlayerClass[mthing->type-1] = p->class;
1319 p->class = PlayerClass[mthing->type-1];
1323 case PCLASS_FIGHTER:
1324 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER);
1327 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC);
1330 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE);
1334 mobj = P_SpawnMobj(x, y, z, MT_PLAYER_ASS);
1338 I_Error("P_SpawnPlayer: Unknown class type");
1339 /* jim never happens but keeps gcc happy */
1344 // Set translation table data
1345 if(p->class == PCLASS_FIGHTER && (mthing->type == 1 || mthing->type == 3))
1347 // The first type should be blue, and the third should be the
1348 // Fighter's original gold color
1349 if(mthing->type == 1)
1351 mobj->flags |= 2<<MF_TRANSSHIFT;
1354 else if(mthing->type > 1)
1355 { // Set color translation bits for player sprites
1356 mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
1359 mobj->angle = ANG45 * (mthing->angle/45);
1361 mobj->health = p->health;
1363 p->playerstate = PST_LIVE;
1371 p->fixedcolormap = 0;
1372 p->viewheight = VIEWHEIGHT;
1375 { // Give all keys in death match mode
1380 //==========================================================================
1384 // The fields of the mapthing should already be in host byte order.
1386 //==========================================================================
1388 void P_SpawnMapThing(mapthing_t *mthing)
1391 unsigned int spawnMask;
1394 // Put in Cleric twice, since we can't have an assassin flag.
1395 static unsigned int classFlags[] =
1405 // Count deathmatch start positions
1406 if(mthing->type == 11)
1408 if(deathmatch_p < &deathmatchstarts[MAXDEATHMATCHSTARTS])
1410 memcpy(deathmatch_p, mthing, sizeof(*mthing));
1415 if(mthing->type == PO_ANCHOR_TYPE)
1416 { // Polyobj Anchor Pt.
1419 else if(mthing->type == PO_SPAWN_TYPE
1420 || mthing->type == PO_SPAWNCRUSH_TYPE)
1421 { // Polyobj Anchor Pt.
1426 // Check for player starts 1 to 4
1427 if(mthing->type <= 4)
1429 playerstarts[mthing->arg1][mthing->type-1] = *mthing;
1430 if(!deathmatch && !mthing->arg1)
1432 P_SpawnPlayer(mthing);
1436 // Check for player starts 5 to 8
1437 if(mthing->type >= 9100 && mthing->type <= 9103)
1439 mthing->type = 5+mthing->type-9100; // Translate to 5 - 8
1440 playerstarts[mthing->arg1][mthing->type-1] = *mthing;
1441 if(!deathmatch && !mthing->arg1)
1443 P_SpawnPlayer(mthing);
1448 if(mthing->type >= 1400 && mthing->type < 1410)
1450 R_PointInSubsector(mthing->x<<FRACBITS,
1451 mthing->y<<FRACBITS)->sector->seqType = mthing->type-1400;
1455 // Check current game type with spawn flags
1456 if(netgame == false)
1458 spawnMask = MTF_GSINGLE;
1462 spawnMask = MTF_GDEATHMATCH;
1466 spawnMask = MTF_GCOOP;
1468 if(!(mthing->options&spawnMask))
1473 // Check current skill with spawn flags
1474 if(gameskill == sk_baby || gameskill == sk_easy)
1476 spawnMask = MTF_EASY;
1478 else if(gameskill == sk_hard || gameskill == sk_nightmare)
1480 spawnMask = MTF_HARD;
1484 spawnMask = MTF_NORMAL;
1486 if(!(mthing->options&spawnMask))
1491 // Check current character classes with spawn flags
1492 if(netgame == false)
1494 if((mthing->options&classFlags[PlayerClass[0]]) == 0)
1495 { // Not for current class
1499 else if(deathmatch == false)
1502 for(i = 0; i < MAXPLAYERS; i++)
1506 spawnMask |= classFlags[PlayerClass[i]];
1509 if((mthing->options&spawnMask) == 0)
1515 // Find which type to spawn
1516 for(i = 0; i < NUMMOBJTYPES; i++)
1518 if(mthing->type == mobjinfo[i].doomednum)
1524 if(i == NUMMOBJTYPES)
1525 { // Can't find thing type
1526 I_Error("P_SpawnMapThing: Unknown type %i at (%i, %i)",
1527 mthing->type, mthing->x, mthing->y);
1530 // Don't spawn keys and players in deathmatch
1531 if(deathmatch && mobjinfo[i].flags&MF_NOTDMATCH)
1536 // Don't spawn monsters if -nomonsters
1537 if(nomonsters && (mobjinfo[i].flags&MF_COUNTKILL))
1542 x = mthing->x<<FRACBITS;
1543 y = mthing->y<<FRACBITS;
1544 if(mobjinfo[i].flags&MF_SPAWNCEILING)
1548 else if(mobjinfo[i].flags2&MF2_SPAWNFLOAT)
1552 else if(mobjinfo[i].flags2&MF2_FLOATBOB)
1554 z = mthing->height<<FRACBITS;
1562 case MT_ZLYNCHED_NOHEART:
1563 P_SpawnMobj(x, y, ONFLOORZ, MT_BLOODPOOL);
1568 mobj = P_SpawnMobj(x, y, z, i);
1571 mobj->z += mthing->height<<FRACBITS;
1573 else if(z == ONCEILINGZ)
1575 mobj->z -= mthing->height<<FRACBITS;
1577 mobj->tid = mthing->tid;
1578 mobj->special = mthing->special;
1579 mobj->args[0] = mthing->arg1;
1580 mobj->args[1] = mthing->arg2;
1581 mobj->args[2] = mthing->arg3;
1582 mobj->args[3] = mthing->arg4;
1583 mobj->args[4] = mthing->arg5;
1584 if(mobj->flags2&MF2_FLOATBOB)
1585 { // Seed random starting index for bobbing motion
1586 mobj->health = P_Random();
1587 mobj->special1 = mthing->height<<FRACBITS;
1591 mobj->tics = 1+(P_Random()%mobj->tics);
1593 // if(mobj->flags&MF_COUNTITEM)
1597 if (mobj->flags&MF_COUNTKILL)
1599 // Quantize angle to 45 degree increments
1600 mobj->angle = ANG45*(mthing->angle/45);
1604 // Scale angle correctly (source is 0..359)
1605 mobj->angle = ((mthing->angle<<8)/360)<<24;
1607 if(mthing->options&MTF_AMBUSH)
1609 mobj->flags |= MF_AMBUSH;
1611 if(mthing->options&MTF_DORMANT)
1613 mobj->flags2 |= MF2_DORMANT;
1614 if(mobj->type == MT_ICEGUY)
1616 P_SetMobjState(mobj, S_ICEGUY_DORMANT);
1622 //==========================================================================
1626 //==========================================================================
1628 void P_CreateTIDList(void)
1635 for(t = thinkercap.next; t != &thinkercap; t = t->next)
1636 { // Search all current thinkers
1637 if(t->function != P_MobjThinker)
1638 { // Not a mobj thinker
1644 if(i == MAX_TID_COUNT)
1646 I_Error("P_CreateTIDList: MAX_TID_COUNT (%d) exceeded.",
1649 TIDList[i] = mobj->tid;
1650 TIDMobj[i++] = mobj;
1653 // Add termination marker
1657 //==========================================================================
1659 // P_InsertMobjIntoTIDList
1661 //==========================================================================
1663 void P_InsertMobjIntoTIDList(mobj_t *mobj, int tid)
1669 for(i = 0; TIDList[i] != 0; i++)
1671 if(TIDList[i] == -1)
1672 { // Found empty slot
1678 { // Append required
1679 if(i == MAX_TID_COUNT)
1681 I_Error("P_InsertMobjIntoTIDList: MAX_TID_COUNT (%d)"
1682 "exceeded.", MAX_TID_COUNT);
1685 TIDList[index+1] = 0;
1688 TIDList[index] = tid;
1689 TIDMobj[index] = mobj;
1692 //==========================================================================
1694 // P_RemoveMobjFromTIDList
1696 //==========================================================================
1698 void P_RemoveMobjFromTIDList(mobj_t *mobj)
1702 for(i = 0; TIDList[i] != 0; i++)
1704 if(TIDMobj[i] == mobj)
1715 //==========================================================================
1717 // P_FindMobjFromTID
1719 //==========================================================================
1721 mobj_t *P_FindMobjFromTID(int tid, int *searchPosition)
1725 for(i = *searchPosition+1; TIDList[i] != 0; i++)
1727 if(TIDList[i] == tid)
1729 *searchPosition = i;
1733 *searchPosition = -1;
1738 ===============================================================================
1740 GAME SPAWN FUNCTIONS
1742 ===============================================================================
1745 //---------------------------------------------------------------------------
1749 //---------------------------------------------------------------------------
1751 extern fixed_t attackrange;
1753 void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
1757 z += ((P_Random()-P_Random())<<10);
1758 puff = P_SpawnMobj(x, y, z, PuffType);
1759 if(linetarget && puff->info->seesound)
1760 { // Hit thing sound
1761 S_StartSound(puff, puff->info->seesound);
1763 else if(puff->info->attacksound)
1765 S_StartSound(puff, puff->info->attacksound);
1770 puff->momz = FRACUNIT;
1773 puff->momz = .8*FRACUNIT;
1790 void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
1794 z += ((P_Random()-P_Random())<<10);
1795 th = P_SpawnMobj (x,y,z, MT_BLOOD);
1796 th->momz = FRACUNIT*2;
1797 th->tics -= P_Random()&3;
1799 if (damage <= 12 && damage >= 9)
1800 P_SetMobjState (th,S_BLOOD2);
1801 else if (damage < 9)
1802 P_SetMobjState (th,S_BLOOD3);
1806 //---------------------------------------------------------------------------
1808 // PROC P_BloodSplatter
1810 //---------------------------------------------------------------------------
1812 void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1816 mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
1817 mo->target = originator;
1818 mo->momx = (P_Random()-P_Random())<<10;
1819 mo->momy = (P_Random()-P_Random())<<10;
1820 mo->momz = 3*FRACUNIT;
1823 //===========================================================================
1827 //===========================================================================
1829 void P_BloodSplatter2(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1833 mo = P_SpawnMobj(x+((P_Random()-128)<<11), y+((P_Random()-128)<<11), z,
1835 mo->target = originator;
1838 //---------------------------------------------------------------------------
1840 // PROC P_RipperBlood
1842 //---------------------------------------------------------------------------
1844 void P_RipperBlood(mobj_t *mo)
1849 x = mo->x+((P_Random()-P_Random())<<12);
1850 y = mo->y+((P_Random()-P_Random())<<12);
1851 z = mo->z+((P_Random()-P_Random())<<12);
1852 th = P_SpawnMobj(x, y, z, MT_BLOOD);
1853 // th->flags |= MF_NOGRAVITY;
1854 th->momx = mo->momx>>1;
1855 th->momy = mo->momy>>1;
1856 th->tics += P_Random()&3;
1859 //---------------------------------------------------------------------------
1861 // FUNC P_GetThingFloorType
1863 //---------------------------------------------------------------------------
1865 int P_GetThingFloorType(mobj_t *thing)
1869 return(TerrainTypes[thing->floorpic]);
1873 return(TerrainTypes[thing->subsector->sector->floorpic]);
1876 if(thing->subsector->sector->floorpic
1877 == W_GetNumForName("FLTWAWA1")-firstflat)
1879 return(FLOOR_WATER);
1883 return(FLOOR_SOLID);
1888 //---------------------------------------------------------------------------
1892 //---------------------------------------------------------------------------
1893 #define SMALLSPLASHCLIP 12<<FRACBITS;
1895 int P_HitFloor(mobj_t *thing)
1898 int smallsplash=false;
1900 if(thing->floorz != thing->subsector->sector->floorheight)
1901 { // don't splash if landing on the edge above water/lava/etc....
1902 return(FLOOR_SOLID);
1905 // Things that don't splash go here
1910 // case MT_BLOOD: // I set these to low mass -- pm
1911 // case MT_BLOODSPLATTER:
1913 case MT_SLUDGECHUNK:
1914 return(FLOOR_SOLID);
1919 // Small splash for small masses
1920 if (thing->info->mass < 10) smallsplash = true;
1922 switch(P_GetThingFloorType(thing))
1927 mo=P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1928 if (mo) mo->floorclip += SMALLSPLASHCLIP;
1929 S_StartSound(mo, SFX_AMBIENT10); // small drip
1933 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
1935 mo->momx = (P_Random()-P_Random())<<8;
1936 mo->momy = (P_Random()-P_Random())<<8;
1937 mo->momz = 2*FRACUNIT+(P_Random()<<8);
1938 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1939 if (thing->player) P_NoiseAlert(thing, thing);
1940 S_StartSound(mo, SFX_WATER_SPLASH);
1942 return(FLOOR_WATER);
1946 mo=P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1947 if (mo) mo->floorclip += SMALLSPLASHCLIP;
1951 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE);
1952 mo->momz = FRACUNIT+(P_Random()<<7);
1953 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1954 if (thing->player) P_NoiseAlert(thing, thing);
1956 S_StartSound(mo, SFX_LAVA_SIZZLE);
1957 if(thing->player && leveltime&31)
1959 P_DamageMobj(thing, &LavaInflictor, NULL, 5);
1965 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
1967 if (mo) mo->floorclip += SMALLSPLASHCLIP;
1971 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK);
1973 mo->momx = (P_Random()-P_Random())<<8;
1974 mo->momy = (P_Random()-P_Random())<<8;
1975 mo->momz = FRACUNIT+(P_Random()<<8);
1976 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ,
1978 if (thing->player) P_NoiseAlert(thing, thing);
1980 S_StartSound(mo, SFX_SLUDGE_GLOOP);
1981 return(FLOOR_SLUDGE);
1983 return(FLOOR_SOLID);
1987 //---------------------------------------------------------------------------
1989 // FUNC P_CheckMissileSpawn
1991 // Returns true if the missile is at a valid spawn point, otherwise
1992 // explodes it and returns false.
1994 //---------------------------------------------------------------------------
1996 boolean P_CheckMissileSpawn(mobj_t *missile)
1998 //missile->tics -= P_Random()&3;
2000 // move a little forward so an angle can be computed if it
2001 // immediately explodes
2003 * jim - handle fast missiles with BlasterMobjThinker()s
2004 * assume so if momentum > MAXMOVE
2005 * this is a horrible kludge, but to be honest so is the BlasterMobjThinker
2006 * stuff in the first place
2008 if ((missile->momx > MAXMOVE) || (missile->momy > MAXMOVE))
2010 missile->x += (missile->momx>>3);
2011 missile->y += (missile->momy>>3);
2012 missile->z += (missile->momz>>3);
2016 missile->x += (missile->momx>>1);
2017 missile->y += (missile->momy>>1);
2018 missile->z += (missile->momz>>1);
2020 if(!P_TryMove(missile, missile->x, missile->y))
2022 P_ExplodeMissile(missile);
2028 //---------------------------------------------------------------------------
2030 // FUNC P_SpawnMissile
2032 // Returns NULL if the missile exploded immediately, otherwise returns
2033 // a mobj_t pointer to the missile.
2035 //---------------------------------------------------------------------------
2037 mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
2046 case MT_MNTRFX1: // Minotaur swing attack missile
2047 z = source->z+40*FRACUNIT;
2049 case MT_MNTRFX2: // Minotaur floor fire missile
2050 z = ONFLOORZ+source->floorclip;
2053 z = source->z+45*FRACUNIT;
2056 z = source->z+40*FRACUNIT;
2058 case MT_HOLY_MISSILE:
2059 z = source->z+40*FRACUNIT;
2062 z = source->z+32*FRACUNIT;
2065 z -= source->floorclip;
2066 th = P_SpawnMobj(source->x, source->y, z, type);
2067 if(th->info->seesound)
2069 S_StartSound(th, th->info->seesound);
2071 th->target = source; // Originator
2072 an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
2073 if(dest->flags&MF_SHADOW)
2074 { // Invisible target
2075 an += (P_Random()-P_Random())<<21;
2078 an >>= ANGLETOFINESHIFT;
2079 th->momx = FixedMul(th->info->speed, finecosine[an]);
2080 th->momy = FixedMul(th->info->speed, finesine[an]);
2081 dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
2082 dist = dist/th->info->speed;
2087 th->momz = (dest->z-source->z)/dist;
2088 return(P_CheckMissileSpawn(th) ? th : NULL);
2091 //---------------------------------------------------------------------------
2093 // FUNC P_SpawnMissileXYZ
2095 // Returns NULL if the missile exploded immediately, otherwise returns
2096 // a mobj_t pointer to the missile.
2098 //---------------------------------------------------------------------------
2100 mobj_t *P_SpawnMissileXYZ(fixed_t x, fixed_t y, fixed_t z,
2101 mobj_t *source, mobj_t *dest, mobjtype_t type)
2107 z -= source->floorclip;
2108 th = P_SpawnMobj(x, y, z, type);
2109 if(th->info->seesound)
2111 S_StartSound(th, th->info->seesound);
2113 th->target = source; // Originator
2114 an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
2115 if(dest->flags&MF_SHADOW)
2116 { // Invisible target
2117 an += (P_Random()-P_Random())<<21;
2120 an >>= ANGLETOFINESHIFT;
2121 th->momx = FixedMul(th->info->speed, finecosine[an]);
2122 th->momy = FixedMul(th->info->speed, finesine[an]);
2123 dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
2124 dist = dist/th->info->speed;
2129 th->momz = (dest->z-source->z)/dist;
2130 return(P_CheckMissileSpawn(th) ? th : NULL);
2133 //---------------------------------------------------------------------------
2135 // FUNC P_SpawnMissileAngle
2137 // Returns NULL if the missile exploded immediately, otherwise returns
2138 // a mobj_t pointer to the missile.
2140 //---------------------------------------------------------------------------
2142 mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
2143 angle_t angle, fixed_t momz)
2150 case MT_MNTRFX1: // Minotaur swing attack missile
2151 z = source->z+40*FRACUNIT;
2153 case MT_MNTRFX2: // Minotaur floor fire missile
2154 z = ONFLOORZ+source->floorclip;
2156 case MT_ICEGUY_FX2: // Secondary Projectiles of the Ice Guy
2157 z = source->z+3*FRACUNIT;
2160 z = source->z+40*FRACUNIT;
2163 z = source->z+32*FRACUNIT;
2166 z -= source->floorclip;
2167 mo = P_SpawnMobj(source->x, source->y, z, type);
2168 if(mo->info->seesound)
2170 S_StartSound(mo, mo->info->seesound);
2172 mo->target = source; // Originator
2174 angle >>= ANGLETOFINESHIFT;
2175 mo->momx = FixedMul(mo->info->speed, finecosine[angle]);
2176 mo->momy = FixedMul(mo->info->speed, finesine[angle]);
2178 return(P_CheckMissileSpawn(mo) ? mo : NULL);
2181 //---------------------------------------------------------------------------
2183 // FUNC P_SpawnMissileAngleSpeed
2185 // Returns NULL if the missile exploded immediately, otherwise returns
2186 // a mobj_t pointer to the missile.
2188 //---------------------------------------------------------------------------
2190 mobj_t *P_SpawnMissileAngleSpeed(mobj_t *source, mobjtype_t type,
2191 angle_t angle, fixed_t momz, fixed_t speed)
2197 z -= source->floorclip;
2198 mo = P_SpawnMobj(source->x, source->y, z, type);
2199 if(mo->info->seesound)
2201 //S_StartSound(mo, mo->info->seesound);
2203 mo->target = source; // Originator
2205 angle >>= ANGLETOFINESHIFT;
2206 mo->momx = FixedMul(speed, finecosine[angle]);
2207 mo->momy = FixedMul(speed, finesine[angle]);
2209 return(P_CheckMissileSpawn(mo) ? mo : NULL);
2217 = P_SpawnPlayerMissile
2219 = Tries to aim at a nearby monster
2223 mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type)
2226 fixed_t x, y, z, slope;
2228 // Try to find a target
2230 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2234 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2238 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
2243 slope = ((source->player->lookdir)<<FRACBITS)/173;
2248 if(type == MT_LIGHTNING_FLOOR)
2253 else if(type == MT_LIGHTNING_CEILING)
2260 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2261 z -= source->floorclip;
2263 MissileMobj = P_SpawnMobj(x, y, z, type);
2264 if(MissileMobj->info->seesound)
2266 //S_StartSound(MissileMobj, MissileMobj->info->seesound);
2268 MissileMobj->target = source;
2269 MissileMobj->angle = an;
2270 MissileMobj->momx = FixedMul(MissileMobj->info->speed,
2271 finecosine[an>>ANGLETOFINESHIFT]);
2272 MissileMobj->momy = FixedMul(MissileMobj->info->speed,
2273 finesine[an>>ANGLETOFINESHIFT]);
2274 MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope);
2275 if(MissileMobj->type == MT_MWAND_MISSILE
2276 || MissileMobj->type == MT_CFLAME_MISSILE)
2277 { // Ultra-fast ripper spawning missile
2278 MissileMobj->x += (MissileMobj->momx>>3);
2279 MissileMobj->y += (MissileMobj->momy>>3);
2280 MissileMobj->z += (MissileMobj->momz>>3);
2284 MissileMobj->x += (MissileMobj->momx>>1);
2285 MissileMobj->y += (MissileMobj->momy>>1);
2286 MissileMobj->z += (MissileMobj->momz>>1);
2288 if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
2289 { // Exploded immediately
2290 P_ExplodeMissile(MissileMobj);
2293 return(MissileMobj);
2297 //----------------------------------------------------------------------------
2299 // P_SpawnPlayerMinotaur -
2301 // Special missile that has larger blocking than player
2302 //----------------------------------------------------------------------------
2305 mobj_t *P_SpawnPlayerMinotaur(mobj_t *source, mobjtype_t type)
2309 fixed_t dist=0 *FRACUNIT;
2312 x = source->x + FixedMul(dist, finecosine[an>>ANGLETOFINESHIFT]);
2313 y = source->y + FixedMul(dist, finesine[an>>ANGLETOFINESHIFT]);
2314 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2315 z -= source->floorclip;
2316 MissileMobj = P_SpawnMobj(x, y, z, type);
2317 if(MissileMobj->info->seesound)
2319 //S_StartSound(MissileMobj, MissileMobj->info->seesound);
2321 MissileMobj->target = source;
2322 MissileMobj->angle = an;
2323 MissileMobj->momx = FixedMul(MissileMobj->info->speed,
2324 finecosine[an>>ANGLETOFINESHIFT]);
2325 MissileMobj->momy = FixedMul(MissileMobj->info->speed,
2326 finesine[an>>ANGLETOFINESHIFT]);
2327 MissileMobj->momz = 0;
2329 // MissileMobj->x += (MissileMobj->momx>>3);
2330 // MissileMobj->y += (MissileMobj->momy>>3);
2331 // MissileMobj->z += (MissileMobj->momz>>3);
2333 if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
2338 return(MissileMobj);
2342 //---------------------------------------------------------------------------
2346 //---------------------------------------------------------------------------
2348 mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle)
2352 fixed_t x, y, z, slope;
2355 // see which target is to be aimed at
2358 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2362 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2366 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2371 slope = ((source->player->lookdir)<<FRACBITS)/173;
2376 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2377 z -= source->floorclip;
2378 th = P_SpawnMobj(x, y, z, type);
2379 // if(th->info->seesound)
2381 // S_StartSound(th, th->info->seesound);
2383 th->target = source;
2385 th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
2386 th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
2387 th->momz = FixedMul(th->info->speed, slope);
2388 return(P_CheckMissileSpawn(th) ? th : NULL);
2391 //===========================================================================
2395 //===========================================================================
2397 mobj_t *P_SPMAngleXYZ(mobj_t *source, fixed_t x, fixed_t y,
2398 fixed_t z, mobjtype_t type, angle_t angle)
2405 // see which target is to be aimed at
2408 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2412 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2416 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
2421 slope = ((source->player->lookdir)<<FRACBITS)/173;
2424 z += 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
2425 z -= source->floorclip;
2426 th = P_SpawnMobj(x, y, z, type);
2427 // if(th->info->seesound)
2429 // S_StartSound(th, th->info->seesound);
2431 th->target = source;
2433 th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
2434 th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
2435 th->momz = FixedMul(th->info->speed, slope);
2436 return(P_CheckMissileSpawn(th) ? th : NULL);
2439 mobj_t *P_SpawnKoraxMissile(fixed_t x, fixed_t y, fixed_t z,
2440 mobj_t *source, mobj_t *dest, mobjtype_t type)
2446 z -= source->floorclip;
2447 th = P_SpawnMobj(x, y, z, type);
2448 if(th->info->seesound)
2450 S_StartSound(th, th->info->seesound);
2452 th->target = source; // Originator
2453 an = R_PointToAngle2(x, y, dest->x, dest->y);
2454 if(dest->flags&MF_SHADOW)
2455 { // Invisible target
2456 an += (P_Random()-P_Random())<<21;
2459 an >>= ANGLETOFINESHIFT;
2460 th->momx = FixedMul(th->info->speed, finecosine[an]);
2461 th->momy = FixedMul(th->info->speed, finesine[an]);
2462 dist = P_AproxDistance(dest->x - x, dest->y - y);
2463 dist = dist/th->info->speed;
2468 th->momz = (dest->z-z+(30*FRACUNIT))/dist;
2469 return(P_CheckMissileSpawn(th) ? th : NULL);