9 void G_PlayerReborn (int player);
10 void P_SpawnMapThing (mapthing_t *mthing);
15 static fixed_t FloatBobOffsets[64] =
17 0, 51389, 102283, 152192,
18 200636, 247147, 291278, 332604,
19 370727, 405280, 435929, 462380,
20 484378, 501712, 514213, 521763,
21 524287, 521763, 514213, 501712,
22 484378, 462380, 435929, 405280,
23 370727, 332604, 291278, 247147,
24 200636, 152192, 102283, 51389,
25 -1, -51390, -102284, -152193,
26 -200637, -247148, -291279, -332605,
27 -370728, -405281, -435930, -462381,
28 -484380, -501713, -514215, -521764,
29 -524288, -521764, -514214, -501713,
30 -484379, -462381, -435930, -405280,
31 -370728, -332605, -291279, -247148,
32 -200637, -152193, -102284, -51389
35 //----------------------------------------------------------------------------
37 // FUNC P_SetMobjState
39 // Returns true if the mobj is still present.
41 //----------------------------------------------------------------------------
43 boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
55 mobj->tics = st->tics;
56 mobj->sprite = st->sprite;
57 mobj->frame = st->frame;
59 { // Call action function
65 //----------------------------------------------------------------------------
67 // FUNC P_SetMobjStateNF
69 // Same as P_SetMobjState, but does not call the state function.
71 //----------------------------------------------------------------------------
73 boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
85 mobj->tics = st->tics;
86 mobj->sprite = st->sprite;
87 mobj->frame = st->frame;
91 //----------------------------------------------------------------------------
93 // PROC P_ExplodeMissile
95 //----------------------------------------------------------------------------
97 void P_ExplodeMissile(mobj_t *mo)
99 if(mo->type == MT_WHIRLWIND)
101 if(++mo->special2 < 60)
106 mo->momx = mo->momy = mo->momz = 0;
107 P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
108 //mo->tics -= P_Random()&3;
109 mo->flags &= ~MF_MISSILE;
110 if(mo->info->deathsound)
112 S_StartSound(mo, mo->info->deathsound);
116 //----------------------------------------------------------------------------
118 // PROC P_FloorBounceMissile
120 //----------------------------------------------------------------------------
122 void P_FloorBounceMissile(mobj_t *mo)
124 mo->momz = -mo->momz;
125 P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
128 //----------------------------------------------------------------------------
132 //----------------------------------------------------------------------------
134 void P_ThrustMobj(mobj_t *mo, angle_t angle, fixed_t move)
136 angle >>= ANGLETOFINESHIFT;
137 mo->momx += FixedMul(move, finecosine[angle]);
138 mo->momy += FixedMul(move, finesine[angle]);
141 //----------------------------------------------------------------------------
145 // Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs
146 // to turn counter clockwise. 'delta' is set to the amount 'source'
149 //----------------------------------------------------------------------------
151 int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta)
157 angle1 = source->angle;
158 angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y);
161 diff = angle2-angle1;
164 *delta = ANGLE_MAX-diff;
175 diff = angle1-angle2;
178 *delta = ANGLE_MAX-diff;
189 //----------------------------------------------------------------------------
191 // FUNC P_SeekerMissile
193 // The missile special1 field must be mobj_t *target. Returns true if
194 // target was tracked, false if not.
196 //----------------------------------------------------------------------------
198 boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax)
206 target = (mobj_t *)actor->special1;
211 if(!(target->flags&MF_SHOOTABLE))
216 dir = P_FaceMobj(actor, target, &delta);
227 actor->angle += delta;
230 { // Turn counter clockwise
231 actor->angle -= delta;
233 angle = actor->angle>>ANGLETOFINESHIFT;
234 actor->momx = FixedMul(actor->info->speed, finecosine[angle]);
235 actor->momy = FixedMul(actor->info->speed, finesine[angle]);
236 if(actor->z+actor->height < target->z ||
237 target->z+target->height < actor->z)
238 { // Need to seek vertically
239 dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
240 dist = dist/actor->info->speed;
245 actor->momz = (target->z-actor->z)/dist;
250 //----------------------------------------------------------------------------
254 //----------------------------------------------------------------------------
256 #define STOPSPEED 0x1000
257 #define FRICTION_NORMAL 0xe800
258 #define FRICTION_LOW 0xf900
259 #define FRICTION_FLY 0xeb00
261 void P_XYMovement(mobj_t *mo)
263 fixed_t ptryx, ptryy;
265 fixed_t xmove, ymove;
267 static int windTab[3] = {2048*5, 2048*10, 2048*25};
269 if(!mo->momx && !mo->momy)
271 if(mo->flags&MF_SKULLFLY)
272 { // A flying mobj slammed into something
273 mo->flags &= ~MF_SKULLFLY;
274 mo->momx = mo->momy = mo->momz = 0;
275 P_SetMobjState(mo, mo->info->seestate);
279 special = mo->subsector->sector->special;
280 if(mo->flags2&MF2_WINDTHRUST)
284 case 40: case 41: case 42: // Wind_East
285 P_ThrustMobj(mo, 0, windTab[special-40]);
287 case 43: case 44: case 45: // Wind_North
288 P_ThrustMobj(mo, ANG90, windTab[special-43]);
290 case 46: case 47: case 48: // Wind_South
291 P_ThrustMobj(mo, ANG270, windTab[special-46]);
293 case 49: case 50: case 51: // Wind_West
294 P_ThrustMobj(mo, ANG180, windTab[special-49]);
299 if(mo->momx > MAXMOVE)
303 else if(mo->momx < -MAXMOVE)
307 if(mo->momy > MAXMOVE)
311 else if(mo->momy < -MAXMOVE)
319 if(xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
321 ptryx = mo->x+xmove/2;
322 ptryy = mo->y+ymove/2;
328 ptryx = mo->x + xmove;
329 ptryy = mo->y + ymove;
332 if(!P_TryMove(mo, ptryx, ptryy))
334 if(mo->flags2&MF2_SLIDE)
335 { // Try to slide along it
338 else if(mo->flags&MF_MISSILE)
339 { // Explode a missile
340 if(ceilingline && ceilingline->backsector
341 && ceilingline->backsector->ceilingpic == skyflatnum)
342 { // Hack to prevent missiles exploding against the sky
343 if(mo->type == MT_BLOODYSKULL)
345 mo->momx = mo->momy = 0;
346 mo->momz = -FRACUNIT;
354 P_ExplodeMissile(mo);
356 //else if(mo->info->crashstate)
358 // mo->momx = mo->momy = 0;
359 // P_SetMobjState(mo, mo->info->crashstate);
364 mo->momx = mo->momy = 0;
367 } while(xmove || ymove);
371 if(player && player->cheats&CF_NOMOMENTUM)
372 { // Debug option for no sliding at all
373 mo->momx = mo->momy = 0;
376 if(mo->flags&(MF_MISSILE|MF_SKULLFLY))
377 { // No friction for missiles
380 if(mo->z > mo->floorz && !(mo->flags2&MF2_FLY) && !(mo->flags2&MF2_ONMOBJ))
381 { // No friction when falling
384 if(mo->flags&MF_CORPSE)
385 { // Don't stop sliding if halfway off a step with some momentum
386 if(mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4
387 || mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4)
389 if(mo->floorz != mo->subsector->sector->floorheight)
395 if(mo->momx > -STOPSPEED && mo->momx < STOPSPEED
396 && mo->momy > -STOPSPEED && mo->momy < STOPSPEED
397 && (!player || (player->cmd.forwardmove == 0
398 && player->cmd.sidemove == 0)))
399 { // If in a walking frame, stop moving
402 if(player->chickenTics)
404 if((unsigned)((player->mo->state-states)
405 -S_CHICPLAY_RUN1) < 4)
407 P_SetMobjState(player->mo, S_CHICPLAY);
412 if((unsigned)((player->mo->state-states)
415 P_SetMobjState(player->mo, S_PLAY);
424 if(mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
425 &&!(mo->flags2&MF2_ONMOBJ))
427 mo->momx = FixedMul(mo->momx, FRICTION_FLY);
428 mo->momy = FixedMul(mo->momy, FRICTION_FLY);
430 else if(special == 15) // Friction_Low
432 mo->momx = FixedMul(mo->momx, FRICTION_LOW);
433 mo->momy = FixedMul(mo->momy, FRICTION_LOW);
437 mo->momx = FixedMul(mo->momx, FRICTION_NORMAL);
438 mo->momy = FixedMul(mo->momy, FRICTION_NORMAL);
452 void P_ZMovement(mobj_t *mo)
457 // check for smooth step up
459 if (mo->player && mo->z < mo->floorz)
461 mo->player->viewheight -= mo->floorz-mo->z;
462 mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3;
468 if(mo->flags&MF_FLOAT && mo->target)
469 { // float down towards target if too close
470 if(!(mo->flags&MF_SKULLFLY) && !(mo->flags&MF_INFLOAT))
472 dist = P_AproxDistance(mo->x-mo->target->x, mo->y-mo->target->y);
473 delta =( mo->target->z+(mo->height>>1))-mo->z;
474 if (delta < 0 && dist < -(delta*3))
476 else if (delta > 0 && dist < (delta*3))
480 if(mo->player && mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
483 mo->z += finesine[(FINEANGLES/20*leveltime>>2)&FINEMASK];
489 if(mo->z <= mo->floorz)
491 if(mo->flags&MF_MISSILE)
494 if(mo->flags2&MF2_FLOORBOUNCE)
496 P_FloorBounceMissile(mo);
499 else if(mo->type == MT_MNTRFX2)
500 { // Minotaur floor fire can go up steps
505 P_ExplodeMissile(mo);
509 if(mo->z-mo->momz > mo->floorz)
510 { // Spawn splashes, etc.
516 if(mo->player && mo->momz < -GRAVITY*8
517 && !(mo->flags2&MF2_FLY)) // squat down
519 mo->player->deltaviewheight = mo->momz>>3;
520 S_StartSound(mo, sfx_plroof);
524 mo->player->centering = true;
527 mo->player->centering = true;
532 if(mo->flags&MF_SKULLFLY)
533 { // The skull slammed into something
534 mo->momz = -mo->momz;
536 if(mo->info->crashstate && (mo->flags&MF_CORPSE))
538 P_SetMobjState(mo, mo->info->crashstate);
542 else if(mo->flags2&MF2_LOGRAV)
545 mo->momz = -(GRAVITY>>3)*2;
547 mo->momz -= GRAVITY>>3;
549 else if (! (mo->flags & MF_NOGRAVITY) )
552 mo->momz = -GRAVITY*2;
557 if (mo->z + mo->height > mo->ceilingz)
561 mo->z = mo->ceilingz - mo->height;
562 if (mo->flags & MF_SKULLFLY)
563 { // the skull slammed into something
564 mo->momz = -mo->momz;
566 if (mo->flags & MF_MISSILE)
568 if(mo->subsector->sector->ceilingpic == skyflatnum)
570 if(mo->type == MT_BLOODYSKULL)
572 mo->momx = mo->momy = 0;
573 mo->momz = -FRACUNIT;
581 P_ExplodeMissile(mo);
596 void P_NightmareRespawn (mobj_t *mobj)
603 x = mobj->spawnpoint.x << FRACBITS;
604 y = mobj->spawnpoint.y << FRACBITS;
606 if (!P_CheckPosition (mobj, x, y) )
607 return; // somthing is occupying it's position
610 // spawn a teleport fog at old spot
612 mo = P_SpawnMobj (mobj->x, mobj->y,
613 mobj->subsector->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
614 S_StartSound (mo, sfx_telept);
616 // spawn a teleport fog at the new spot
617 ss = R_PointInSubsector (x,y);
618 mo = P_SpawnMobj (x, y, ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
619 S_StartSound (mo, sfx_telept);
621 // spawn the new monster
622 mthing = &mobj->spawnpoint;
625 if (mobj->info->flags & MF_SPAWNCEILING)
629 mo = P_SpawnMobj (x,y,z, mobj->type);
630 mo->spawnpoint = mobj->spawnpoint;
631 mo->angle = ANG45 * (mthing->angle/45);
632 if (mthing->options & MTF_AMBUSH)
633 mo->flags |= MF_AMBUSH;
635 mo->reactiontime = 18;
637 // remove the old monster
641 //----------------------------------------------------------------------------
643 // PROC P_BlasterMobjThinker
645 // Thinker for the ultra-fast blaster PL2 ripper-spawning missile.
647 //----------------------------------------------------------------------------
649 void P_BlasterMobjThinker(mobj_t *mobj)
659 if(mobj->momx || mobj->momy ||
660 (mobj->z != mobj->floorz) || mobj->momz)
662 xfrac = mobj->momx>>3;
663 yfrac = mobj->momy>>3;
664 zfrac = mobj->momz>>3;
665 changexy = xfrac || yfrac;
666 for(i = 0; i < 8; i++)
670 if(!P_TryMove(mobj, mobj->x+xfrac, mobj->y+yfrac))
672 P_ExplodeMissile(mobj);
677 if(mobj->z <= mobj->floorz)
679 mobj->z = mobj->floorz;
681 P_ExplodeMissile(mobj);
684 if(mobj->z+mobj->height > mobj->ceilingz)
686 mobj->z = mobj->ceilingz-mobj->height;
687 P_ExplodeMissile(mobj);
690 if(changexy && (P_Random() < 64))
692 z = mobj->z-8*FRACUNIT;
697 P_SpawnMobj(mobj->x, mobj->y, z, MT_BLASTERSMOKE);
707 if(!P_SetMobjState(mobj, mobj->state->nextstate))
708 { // mobj was removed
715 //----------------------------------------------------------------------------
717 // PROC P_MobjThinker
719 //----------------------------------------------------------------------------
721 void P_MobjThinker(mobj_t *mobj)
725 // Handle X and Y momentums
726 if(mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY))
729 if(mobj->thinker.function == (think_t)-1)
730 { // mobj was removed
734 if(mobj->flags2&MF2_FLOATBOB)
735 { // Floating item bobbing motion
736 mobj->z = mobj->floorz+FloatBobOffsets[(mobj->health++)&63];
738 else if((mobj->z != mobj->floorz) || mobj->momz)
739 { // Handle Z momentum and gravity
740 if(mobj->flags2&MF2_PASSMOBJ)
742 if(!(onmo = P_CheckOnmobj(mobj)))
748 if(mobj->player && mobj->momz < 0)
750 mobj->flags2 |= MF2_ONMOBJ;
753 if(mobj->player && (onmo->player || onmo->type == MT_POD))
755 mobj->momx = onmo->momx;
756 mobj->momy = onmo->momy;
757 if(onmo->z < onmo->floorz)
759 mobj->z += onmo->floorz-onmo->z;
762 onmo->player->viewheight -= onmo->floorz-onmo->z;
763 onmo->player->deltaviewheight = (VIEWHEIGHT-
764 onmo->player->viewheight)>>3;
766 onmo->z = onmo->floorz;
775 if(mobj->thinker.function == (think_t)-1)
776 { // mobj was removed
782 // cycle through states, calling action functions at transitions
787 // you can cycle through multiple states in a tic
790 if(!P_SetMobjState(mobj, mobj->state->nextstate))
791 { // mobj was removed
797 { // Check for monster respawn
798 if(!(mobj->flags&MF_COUNTKILL))
807 if(mobj->movecount < 12*35)
819 P_NightmareRespawn(mobj);
831 mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
838 mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
839 memset(mobj, 0, sizeof(*mobj));
840 info = &mobjinfo[type];
845 mobj->radius = info->radius;
846 mobj->height = info->height;
847 mobj->flags = info->flags;
848 mobj->flags2 = info->flags2;
849 mobj->damage = info->damage;
850 mobj->health = info->spawnhealth;
851 if(gameskill != sk_nightmare)
853 mobj->reactiontime = info->reactiontime;
855 mobj->lastlook = P_Random()%MAXPLAYERS;
857 // Set the state, but do not use P_SetMobjState, because action
858 // routines can't be called yet. If the spawnstate has an action
859 // routine, it will not be called.
860 st = &states[info->spawnstate];
862 mobj->tics = st->tics;
863 mobj->sprite = st->sprite;
864 mobj->frame = st->frame;
866 // Set subsector and/or block links.
867 P_SetThingPosition(mobj);
868 mobj->floorz = mobj->subsector->sector->floorheight;
869 mobj->ceilingz = mobj->subsector->sector->ceilingheight;
872 mobj->z = mobj->floorz;
874 else if(z == ONCEILINGZ)
876 mobj->z = mobj->ceilingz-mobj->info->height;
878 else if(z == FLOATRANDZ)
880 space = ((mobj->ceilingz)-(mobj->info->height))-mobj->floorz;
881 if(space > 48*FRACUNIT)
883 space -= 40*FRACUNIT;
884 mobj->z = ((space*P_Random())>>8)+mobj->floorz+40*FRACUNIT;
888 mobj->z = mobj->floorz;
895 if(mobj->flags2&MF2_FOOTCLIP && P_GetThingFloorType(mobj) != FLOOR_SOLID
896 && mobj->floorz == mobj->subsector->sector->floorheight)
898 mobj->flags2 |= MF2_FEETARECLIPPED;
902 mobj->flags2 &= ~MF2_FEETARECLIPPED;
905 mobj->thinker.function = P_MobjThinker;
906 P_AddThinker(&mobj->thinker);
918 void P_RemoveMobj(mobj_t *mobj)
920 // unlink from sector and block lists
921 P_UnsetThingPosition (mobj);
922 // stop any playing sound
925 P_RemoveThinker((thinker_t *)mobj);
928 //=============================================================================
936 = Called when a player is spawned on the level
937 = Most of the player structure stays unchanged between levels
941 void P_SpawnPlayer(mapthing_t *mthing)
947 extern int playerkeys;
949 if (!playeringame[mthing->type-1])
950 return; // not playing
952 p = &players[mthing->type-1];
954 if (p->playerstate == PST_REBORN)
955 G_PlayerReborn (mthing->type-1);
957 x = mthing->x << FRACBITS;
958 y = mthing->y << FRACBITS;
961 mobj = P_SpawnMobj (x,y,z, MT_PLAYER);
962 if (mthing->type > 1) // set color translations for player sprites
963 mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
965 mobj->angle = ANG45 * (mthing->angle/45);
967 mobj->health = p->health;
969 p->playerstate = PST_LIVE;
978 p->fixedcolormap = 0;
979 p->viewheight = VIEWHEIGHT;
980 P_SetupPsprites(p); // setup gun psprite
982 { // Give all keys in death match mode
983 for(i = 0; i < NUMKEYS; i++)
986 if(p == &players[consoleplayer])
989 UpdateState |= I_STATBAR;
993 else if(p == &players[consoleplayer])
996 UpdateState |= I_STATBAR;
1000 //----------------------------------------------------------------------------
1002 // PROC P_SpawnMapThing
1004 // The fields of the mapthing should already be in host byte order.
1006 //----------------------------------------------------------------------------
1008 void P_SpawnMapThing(mapthing_t *mthing)
1015 // count deathmatch start positions
1016 if(mthing->type == 11)
1018 if(deathmatch_p < &deathmatchstarts[10])
1020 memcpy(deathmatch_p, mthing, sizeof(*mthing));
1026 // check for players specially
1027 if(mthing->type <= 4)
1029 // save spots for respawning in network games
1030 playerstarts[mthing->type-1] = *mthing;
1033 P_SpawnPlayer(mthing);
1038 // Ambient sound sequences
1039 if(mthing->type >= 1200 && mthing->type < 1300)
1041 P_AddAmbientSfx(mthing->type-1200);
1045 // Check for boss spots
1046 if(mthing->type == 56) // Monster_BossSpot
1048 P_AddBossSpot(mthing->x<<FRACBITS, mthing->y<<FRACBITS,
1049 ANG45*(mthing->angle/45));
1053 // check for apropriate skill level
1054 if (!netgame && (mthing->options & 16) )
1057 if (gameskill == sk_baby)
1059 else if (gameskill == sk_nightmare)
1062 bit = 1<<(gameskill-1);
1063 if (!(mthing->options & bit) )
1066 // find which type to spawn
1067 for (i=0 ; i< NUMMOBJTYPES ; i++)
1068 if (mthing->type == mobjinfo[i].doomednum)
1071 if (i==NUMMOBJTYPES)
1072 I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",mthing->type
1073 , mthing->x, mthing->y);
1075 // don't spawn keys and players in deathmatch
1076 if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
1079 // don't spawn any monsters if -nomonsters
1080 if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL) )
1087 case MT_WPHOENIXROD:
1088 case MT_AMSKRDWIMPY:
1089 case MT_AMSKRDHEFTY:
1090 case MT_AMPHRDWIMPY:
1091 case MT_AMPHRDHEFTY:
1092 case MT_AMMACEWIMPY:
1093 case MT_AMMACEHEFTY:
1094 case MT_ARTISUPERHEAL:
1095 case MT_ARTITELEPORT:
1096 case MT_ITEMSHIELD2:
1098 { // Don't place on map in shareware version
1104 { // Put in the mace spot list
1105 P_AddMaceSpot(mthing);
1112 x = mthing->x<<FRACBITS;
1113 y = mthing->y<<FRACBITS;
1114 if(mobjinfo[i].flags&MF_SPAWNCEILING)
1118 else if(mobjinfo[i].flags2&MF2_SPAWNFLOAT)
1126 mobj = P_SpawnMobj(x, y, z, i);
1127 if(mobj->flags2&MF2_FLOATBOB)
1128 { // Seed random starting index for bobbing motion
1129 mobj->health = P_Random();
1133 mobj->tics = 1+(P_Random()%mobj->tics);
1135 if(mobj->flags&MF_COUNTKILL)
1138 mobj->spawnpoint = *mthing;
1140 if(mobj->flags&MF_COUNTITEM)
1144 mobj->angle = ANG45*(mthing->angle/45);
1145 if(mthing->options&MTF_AMBUSH)
1147 mobj->flags |= MF_AMBUSH;
1152 ===============================================================================
1154 GAME SPAWN FUNCTIONS
1156 ===============================================================================
1159 //---------------------------------------------------------------------------
1163 //---------------------------------------------------------------------------
1165 extern fixed_t attackrange;
1167 void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
1171 z += ((P_Random()-P_Random())<<10);
1172 puff = P_SpawnMobj(x, y, z, PuffType);
1173 if(puff->info->attacksound)
1175 S_StartSound(puff, puff->info->attacksound);
1181 puff->momz = FRACUNIT;
1183 case MT_GAUNTLETPUFF1:
1184 case MT_GAUNTLETPUFF2:
1185 puff->momz = .8*FRACUNIT;
1200 void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
1204 z += ((P_Random()-P_Random())<<10);
1205 th = P_SpawnMobj (x,y,z, MT_BLOOD);
1206 th->momz = FRACUNIT*2;
1207 th->tics -= P_Random()&3;
1209 if (damage <= 12 && damage >= 9)
1210 P_SetMobjState (th,S_BLOOD2);
1211 else if (damage < 9)
1212 P_SetMobjState (th,S_BLOOD3);
1216 //---------------------------------------------------------------------------
1218 // PROC P_BloodSplatter
1220 //---------------------------------------------------------------------------
1222 void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
1226 mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
1227 mo->target = originator;
1228 mo->momx = (P_Random()-P_Random())<<9;
1229 mo->momy = (P_Random()-P_Random())<<9;
1230 mo->momz = FRACUNIT*2;
1233 //---------------------------------------------------------------------------
1235 // PROC P_RipperBlood
1237 //---------------------------------------------------------------------------
1239 void P_RipperBlood(mobj_t *mo)
1244 x = mo->x+((P_Random()-P_Random())<<12);
1245 y = mo->y+((P_Random()-P_Random())<<12);
1246 z = mo->z+((P_Random()-P_Random())<<12);
1247 th = P_SpawnMobj(x, y, z, MT_BLOOD);
1248 th->flags |= MF_NOGRAVITY;
1249 th->momx = mo->momx>>1;
1250 th->momy = mo->momy>>1;
1251 th->tics += P_Random()&3;
1254 //---------------------------------------------------------------------------
1256 // FUNC P_GetThingFloorType
1258 //---------------------------------------------------------------------------
1260 int P_GetThingFloorType(mobj_t *thing)
1262 return(TerrainTypes[thing->subsector->sector->floorpic]);
1264 if(thing->subsector->sector->floorpic
1265 == W_GetNumForName("FLTWAWA1")-firstflat)
1267 return(FLOOR_WATER);
1271 return(FLOOR_SOLID);
1276 //---------------------------------------------------------------------------
1280 //---------------------------------------------------------------------------
1282 int P_HitFloor(mobj_t *thing)
1286 if(thing->floorz != thing->subsector->sector->floorheight)
1287 { // don't splash if landing on the edge above water/lava/etc....
1288 return(FLOOR_SOLID);
1290 switch(P_GetThingFloorType(thing))
1293 P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
1294 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
1296 mo->momx = (P_Random()-P_Random())<<8;
1297 mo->momy = (P_Random()-P_Random())<<8;
1298 mo->momz = 2*FRACUNIT+(P_Random()<<8);
1299 S_StartSound(mo, sfx_gloop);
1300 return(FLOOR_WATER);
1302 P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
1303 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE);
1304 mo->momz = FRACUNIT+(P_Random()<<7);
1305 S_StartSound(mo, sfx_burn);
1308 P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGESPLASH);
1309 mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK);
1311 mo->momx = (P_Random()-P_Random())<<8;
1312 mo->momy = (P_Random()-P_Random())<<8;
1313 mo->momz = FRACUNIT+(P_Random()<<8);
1314 return(FLOOR_SLUDGE);
1316 return(FLOOR_SOLID);
1319 //---------------------------------------------------------------------------
1321 // FUNC P_CheckMissileSpawn
1323 // Returns true if the missile is at a valid spawn point, otherwise
1324 // explodes it and returns false.
1326 //---------------------------------------------------------------------------
1328 boolean P_CheckMissileSpawn(mobj_t *missile)
1330 //missile->tics -= P_Random()&3;
1332 // move a little forward so an angle can be computed if it
1333 // immediately explodes
1334 missile->x += (missile->momx>>1);
1335 missile->y += (missile->momy>>1);
1336 missile->z += (missile->momz>>1);
1337 if(!P_TryMove(missile, missile->x, missile->y))
1339 P_ExplodeMissile(missile);
1345 //---------------------------------------------------------------------------
1347 // FUNC P_SpawnMissile
1349 // Returns NULL if the missile exploded immediately, otherwise returns
1350 // a mobj_t pointer to the missile.
1352 //---------------------------------------------------------------------------
1354 mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
1363 case MT_MNTRFX1: // Minotaur swing attack missile
1364 z = source->z+40*FRACUNIT;
1366 case MT_MNTRFX2: // Minotaur floor fire missile
1369 case MT_SRCRFX1: // Sorcerer Demon fireball
1370 z = source->z+48*FRACUNIT;
1372 case MT_KNIGHTAXE: // Knight normal axe
1373 case MT_REDAXE: // Knight red power axe
1374 z = source->z+36*FRACUNIT;
1377 z = source->z+32*FRACUNIT;
1380 if(source->flags2&MF2_FEETARECLIPPED)
1384 th = P_SpawnMobj(source->x, source->y, z, type);
1385 if(th->info->seesound)
1387 S_StartSound(th, th->info->seesound);
1389 th->target = source; // Originator
1390 an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
1391 if(dest->flags&MF_SHADOW)
1392 { // Invisible target
1393 an += (P_Random()-P_Random())<<21;
1396 an >>= ANGLETOFINESHIFT;
1397 th->momx = FixedMul(th->info->speed, finecosine[an]);
1398 th->momy = FixedMul(th->info->speed, finesine[an]);
1399 dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
1400 dist = dist/th->info->speed;
1405 th->momz = (dest->z-source->z)/dist;
1406 return(P_CheckMissileSpawn(th) ? th : NULL);
1409 //---------------------------------------------------------------------------
1411 // FUNC P_SpawnMissileAngle
1413 // Returns NULL if the missile exploded immediately, otherwise returns
1414 // a mobj_t pointer to the missile.
1416 //---------------------------------------------------------------------------
1418 mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
1419 angle_t angle, fixed_t momz)
1426 case MT_MNTRFX1: // Minotaur swing attack missile
1427 z = source->z+40*FRACUNIT;
1429 case MT_MNTRFX2: // Minotaur floor fire missile
1432 case MT_SRCRFX1: // Sorcerer Demon fireball
1433 z = source->z+48*FRACUNIT;
1436 z = source->z+32*FRACUNIT;
1439 if(source->flags2&MF2_FEETARECLIPPED)
1443 mo = P_SpawnMobj(source->x, source->y, z, type);
1444 if(mo->info->seesound)
1446 S_StartSound(mo, mo->info->seesound);
1448 mo->target = source; // Originator
1450 angle >>= ANGLETOFINESHIFT;
1451 mo->momx = FixedMul(mo->info->speed, finecosine[angle]);
1452 mo->momy = FixedMul(mo->info->speed, finesine[angle]);
1454 return(P_CheckMissileSpawn(mo) ? mo : NULL);
1460 = P_SpawnPlayerMissile
1462 = Tries to aim at a nearby monster
1466 mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type)
1469 fixed_t x, y, z, slope;
1471 // Try to find a target
1473 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
1477 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
1481 slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
1486 slope = ((source->player->lookdir)<<FRACBITS)/173;
1491 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
1492 if(source->flags2&MF2_FEETARECLIPPED)
1496 MissileMobj = P_SpawnMobj(x, y, z, type);
1497 if(MissileMobj->info->seesound)
1499 S_StartSound(MissileMobj, MissileMobj->info->seesound);
1501 MissileMobj->target = source;
1502 MissileMobj->angle = an;
1503 MissileMobj->momx = FixedMul(MissileMobj->info->speed,
1504 finecosine[an>>ANGLETOFINESHIFT]);
1505 MissileMobj->momy = FixedMul(MissileMobj->info->speed,
1506 finesine[an>>ANGLETOFINESHIFT]);
1507 MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope);
1508 if(MissileMobj->type == MT_BLASTERFX1)
1509 { // Ultra-fast ripper spawning missile
1510 MissileMobj->x += (MissileMobj->momx>>3);
1511 MissileMobj->y += (MissileMobj->momy>>3);
1512 MissileMobj->z += (MissileMobj->momz>>3);
1516 MissileMobj->x += (MissileMobj->momx>>1);
1517 MissileMobj->y += (MissileMobj->momy>>1);
1518 MissileMobj->z += (MissileMobj->momz>>1);
1520 if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
1521 { // Exploded immediately
1522 P_ExplodeMissile(MissileMobj);
1525 return(MissileMobj);
1528 //---------------------------------------------------------------------------
1532 //---------------------------------------------------------------------------
1534 mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle)
1538 fixed_t x, y, z, slope;
1541 // see which target is to be aimed at
1544 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
1548 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
1552 slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
1557 slope = ((source->player->lookdir)<<FRACBITS)/173;
1562 z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
1563 if(source->flags2&MF2_FEETARECLIPPED)
1567 th = P_SpawnMobj(x, y, z, type);
1568 if(th->info->seesound)
1570 S_StartSound(th, th->info->seesound);
1572 th->target = source;
1574 th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
1575 th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
1576 th->momz = FixedMul(th->info->speed, slope);
1577 return(P_CheckMissileSpawn(th) ? th : NULL);
1580 //---------------------------------------------------------------------------
1582 // PROC A_ContMobjSound
1584 //---------------------------------------------------------------------------
1586 void A_ContMobjSound(mobj_t *actor)
1591 S_StartSound(actor, sfx_kgtatk);
1594 S_StartSound(actor, sfx_mumhed);