📄 p_mobj.c
字号:
//**************************************************************************//**//** p_mobj.c : Heretic 2 : Raven Software, Corp.//**//** $RCSfile: p_mobj.c,v $//** $Revision: 1.133 $//** $Date: 96/01/12 12:31:43 $//** $Author: bgokey $//**//**************************************************************************// HEADER FILES ------------------------------------------------------------#include "h2def.h"#include "p_local.h"#include "sounds.h"#include "soundst.h"// MACROS ------------------------------------------------------------------#define MAX_TID_COUNT 200// TYPES -------------------------------------------------------------------// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------void G_PlayerReborn(int player);void P_MarkAsLeaving(mobj_t *corpse);// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------void P_SpawnMapThing(mapthing_t *mthing);// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj);// EXTERNAL DATA DECLARATIONS ----------------------------------------------extern mobj_t LavaInflictor;// PUBLIC DATA DEFINITIONS -------------------------------------------------mobjtype_t PuffType;mobj_t *MissileMobj;fixed_t FloatBobOffsets[64] ={ 0, 51389, 102283, 152192, 200636, 247147, 291278, 332604, 370727, 405280, 435929, 462380, 484378, 501712, 514213, 521763, 524287, 521763, 514213, 501712, 484378, 462380, 435929, 405280, 370727, 332604, 291278, 247147, 200636, 152192, 102283, 51389, -1, -51390, -102284, -152193, -200637, -247148, -291279, -332605, -370728, -405281, -435930, -462381, -484380, -501713, -514215, -521764, -524288, -521764, -514214, -501713, -484379, -462381, -435930, -405280, -370728, -332605, -291279, -247148, -200637, -152193, -102284, -51389};// PRIVATE DATA DEFINITIONS ------------------------------------------------static int TIDList[MAX_TID_COUNT+1]; // +1 for termination markerstatic mobj_t *TIDMobj[MAX_TID_COUNT];// CODE --------------------------------------------------------------------//==========================================================================//// P_SetMobjState//// Returns true if the mobj is still present.////==========================================================================boolean P_SetMobjState(mobj_t *mobj, statenum_t state){ state_t *st; if(state == S_NULL) { // Remove mobj mobj->state = S_NULL; P_RemoveMobj(mobj); return(false); } st = &states[state]; mobj->state = st; mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; if(st->action) { // Call action function st->action(mobj); } return(true);}//==========================================================================//// P_SetMobjStateNF//// Same as P_SetMobjState, but does not call the state function.////==========================================================================boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state){ state_t *st; if(state == S_NULL) { // Remove mobj mobj->state = S_NULL; P_RemoveMobj(mobj); return(false); } st = &states[state]; mobj->state = st; mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; return(true);}//----------------------------------------------------------------------------//// PROC P_ExplodeMissile////----------------------------------------------------------------------------void P_ExplodeMissile(mobj_t *mo){ mo->momx = mo->momy = mo->momz = 0; P_SetMobjState(mo, mobjinfo[mo->type].deathstate); //mo->tics -= P_Random()&3; mo->flags &= ~MF_MISSILE; switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: S_StartSound(NULL, SFX_SORCERER_BIGBALLEXPLODE); break; case MT_SORCFX1: S_StartSound(NULL, SFX_SORCERER_HEADSCREAM); break; default: if(mo->info->deathsound) { S_StartSound(mo, mo->info->deathsound); } break; }}//----------------------------------------------------------------------------//// PROC P_FloorBounceMissile////----------------------------------------------------------------------------void P_FloorBounceMissile(mobj_t *mo){ if(P_HitFloor(mo) >= FLOOR_LIQUID) { switch(mo->type) { case MT_SORCFX1: case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: break; default: P_RemoveMobj(mo); return; } } switch(mo->type) { case MT_SORCFX1: mo->momz = -mo->momz; // no energy absorbed break; case MT_SGSHARD1: case MT_SGSHARD2: case MT_SGSHARD3: case MT_SGSHARD4: case MT_SGSHARD5: case MT_SGSHARD6: case MT_SGSHARD7: case MT_SGSHARD8: case MT_SGSHARD9: case MT_SGSHARD0: mo->momz = FixedMul(mo->momz, -0.3*FRACUNIT); if(abs(mo->momz) < (FRACUNIT/2)) { P_SetMobjState(mo, S_NULL); return; } break; default: mo->momz = FixedMul(mo->momz, -0.7*FRACUNIT); break; } mo->momx = 2*mo->momx/3; mo->momy = 2*mo->momy/3; if(mo->info->seesound) { switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: if (!mo->args[0]) S_StartSound(mo, mo->info->seesound); break; default: S_StartSound(mo, mo->info->seesound); break; } S_StartSound(mo, mo->info->seesound); }// P_SetMobjState(mo, mobjinfo[mo->type].deathstate);}//----------------------------------------------------------------------------//// PROC P_ThrustMobj////----------------------------------------------------------------------------void P_ThrustMobj(mobj_t *mo, angle_t angle, fixed_t move){ angle >>= ANGLETOFINESHIFT; mo->momx += FixedMul(move, finecosine[angle]); mo->momy += FixedMul(move, finesine[angle]);}//----------------------------------------------------------------------------//// FUNC P_FaceMobj//// Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs// to turn counter clockwise. 'delta' is set to the amount 'source'// needs to turn.////----------------------------------------------------------------------------int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta){ angle_t diff; angle_t angle1; angle_t angle2; angle1 = source->angle; angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y); if(angle2 > angle1) { diff = angle2-angle1; if(diff > ANGLE_180) { *delta = ANGLE_MAX-diff; return(0); } else { *delta = diff; return(1); } } else { diff = angle1-angle2; if(diff > ANGLE_180) { *delta = ANGLE_MAX-diff; return(1); } else { *delta = diff; return(0); } }}//----------------------------------------------------------------------------////// The missile special1 field must be mobj_t *target. Returns true if// target was tracked, false if not.////----------------------------------------------------------------------------boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax){ int dir; int dist; angle_t delta; angle_t angle; mobj_t *target; target = (mobj_t *)actor->special1; if(target == NULL) { return(false); } if(!(target->flags&MF_SHOOTABLE)) { // Target died actor->special1 = 0; return(false); } dir = P_FaceMobj(actor, target, &delta); if(delta > thresh) { delta >>= 1; if(delta > turnMax) { delta = turnMax; } } if(dir) { // Turn clockwise actor->angle += delta; } else { // Turn counter clockwise actor->angle -= delta; } angle = actor->angle>>ANGLETOFINESHIFT; actor->momx = FixedMul(actor->info->speed, finecosine[angle]); actor->momy = FixedMul(actor->info->speed, finesine[angle]); if(actor->z+actor->height < target->z || target->z+target->height < actor->z) { // Need to seek vertically dist = P_AproxDistance(target->x-actor->x, target->y-actor->y); dist = dist/actor->info->speed; if(dist < 1) { dist = 1; } actor->momz = (target->z+(target->height>>1) -(actor->z+(actor->height>>1)))/dist; } return(true);}//----------------------------------------------------------------------------//// PROC P_XYMovement////----------------------------------------------------------------------------#define STOPSPEED 0x1000#define FRICTION_NORMAL 0xe800#define FRICTION_LOW 0xf900#define FRICTION_FLY 0xeb00void P_XYMovement(mobj_t *mo){ fixed_t ptryx, ptryy; player_t *player; fixed_t xmove, ymove; int special; angle_t angle; static int windTab[3] = {2048*5, 2048*10, 2048*25}; if(!mo->momx && !mo->momy) { if(mo->flags&MF_SKULLFLY) { // A flying mobj slammed into something mo->flags &= ~MF_SKULLFLY; mo->momx = mo->momy = mo->momz = 0; P_SetMobjState(mo, mo->info->seestate); } return; } special = mo->subsector->sector->special; if(mo->flags2&MF2_WINDTHRUST) { switch(special) { case 40: case 41: case 42: // Wind_East P_ThrustMobj(mo, 0, windTab[special-40]); break; case 43: case 44: case 45: // Wind_North P_ThrustMobj(mo, ANG90, windTab[special-43]); break; case 46: case 47: case 48: // Wind_South P_ThrustMobj(mo, ANG270, windTab[special-46]); break; case 49: case 50: case 51: // Wind_West P_ThrustMobj(mo, ANG180, windTab[special-49]); break; } } player = mo->player; if(mo->momx > MAXMOVE) { mo->momx = MAXMOVE; } else if(mo->momx < -MAXMOVE) { mo->momx = -MAXMOVE; } if(mo->momy > MAXMOVE) { mo->momy = MAXMOVE; } else if(mo->momy < -MAXMOVE) { mo->momy = -MAXMOVE; } xmove = mo->momx; ymove = mo->momy; do { if(xmove > MAXMOVE/2 || ymove > MAXMOVE/2) { ptryx = mo->x+xmove/2; ptryy = mo->y+ymove/2; xmove >>= 1; ymove >>= 1; } else { ptryx = mo->x + xmove; ptryy = mo->y + ymove; xmove = ymove = 0; } if(!P_TryMove(mo, ptryx, ptryy)) { // Blocked move if(mo->flags2&MF2_SLIDE) { // Try to slide along it if(BlockingMobj == NULL) { // Slide against wall P_SlideMove(mo); } else { // Slide against mobj //if(P_TryMove(mo, mo->x, mo->y+mo->momy)) if(P_TryMove(mo, mo->x, ptryy)) { mo->momx = 0; } //else if(P_TryMove(mo, mo->x+mo->momx, mo->y)) else if(P_TryMove(mo, ptryx, mo->y)) { mo->momy = 0; } else { mo->momx = mo->momy = 0; } } } else if(mo->flags&MF_MISSILE) { if(mo->flags2&MF2_FLOORBOUNCE) { if(BlockingMobj) { if ((BlockingMobj->flags2&MF2_REFLECTIVE) || ((!BlockingMobj->player) && (!(BlockingMobj->flags&MF_COUNTKILL)))) { fixed_t speed; angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y) +ANGLE_1*((P_Random()%16)-8); speed = P_AproxDistance(mo->momx, mo->momy); speed = FixedMul(speed, 0.75*FRACUNIT); mo->angle = angle; angle >>= ANGLETOFINESHIFT; mo->momx = FixedMul(speed, finecosine[angle]); mo->momy = FixedMul(speed, finesine[angle]); if(mo->info->seesound) { S_StartSound(mo, mo->info->seesound); } return; } else { // Struck a player/creature P_ExplodeMissile(mo); } } else { // Struck a wall P_BounceWall(mo); switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: case MT_SORCFX1: break; default: if(mo->info->seesound) { S_StartSound(mo, mo->info->seesound); } break; } return; } } if(BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE)) { angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y); // Change angle for delflection/reflection switch(BlockingMobj->type) { case MT_CENTAUR: case MT_CENTAURLEADER: if ( abs(angle-BlockingMobj->angle)>>24 > 45) goto explode; if (mo->type == MT_HOLY_FX) goto explode; // Drop through to sorcerer full reflection case MT_SORCBOSS: // Deflection if (P_Random()<128) angle += ANGLE_45; else angle -= ANGLE_45; break; default: // Reflection angle += ANGLE_1 * ((P_Random()%16)-8); break; } // Reflect the missile along angle mo->angle = angle; angle >>= ANGLETOFINESHIFT; mo->momx = FixedMul(mo->info->speed>>1, finecosine[angle]); mo->momy = FixedMul(mo->info->speed>>1, finesine[angle]);// mo->momz = -mo->momz; if (mo->flags2 & MF2_SEEKERMISSILE) { mo->special1 = (int)(mo->target); } mo->target = BlockingMobj; return; }explode: // Explode a missile if(ceilingline && ceilingline->backsector && ceilingline->backsector->ceilingpic == skyflatnum) { // Hack to prevent missiles exploding against the sky if(mo->type == MT_BLOODYSKULL) { mo->momx = mo->momy = 0; mo->momz = -FRACUNIT; } else if(mo->type == MT_HOLY_FX) { P_ExplodeMissile(mo); } else { P_RemoveMobj(mo); } return; } P_ExplodeMissile(mo); } //else if(mo->info->crashstate) //{ // mo->momx = mo->momy = 0; // P_SetMobjState(mo, mo->info->crashstate); // return; //} else { mo->momx = mo->momy = 0; } } } while(xmove || ymove); // Friction if(player && player->cheats&CF_NOMOMENTUM) { // Debug option for no sliding at all mo->momx = mo->momy = 0; return; } if(mo->flags&(MF_MISSILE|MF_SKULLFLY)) { // No friction for missiles return; } if(mo->z > mo->floorz && !(mo->flags2&MF2_FLY) && !(mo->flags2&MF2_ONMOBJ)) { // No friction when falling if (mo->type != MT_BLASTEFFECT) return; } if(mo->flags&MF_CORPSE) { // Don't stop sliding if halfway off a step with some momentum if(mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4 || mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -