📄 p_map.c
字号:
&& tmceilingz - thing->z < thing->height && !(thing->flags2&MF2_FLY)) { CheckMissileImpact(thing); return false; // mobj must lower itself to fit } if(thing->flags2&MF2_FLY) { if(thing->z+thing->height > tmceilingz) { thing->momz = -8*FRACUNIT; return false; } else if(thing->z < tmfloorz && tmfloorz-tmdropoffz > 24*FRACUNIT) { thing->momz = 8*FRACUNIT; return false; } } // jump out of water if((thing->eflags & (MF_UNDERWATER|MF_TOUCHWATER))==(MF_UNDERWATER|MF_TOUCHWATER)) maxstep=37*FRACUNIT; if ( !(thing->flags & MF_TELEPORT) // The Minotaur floor fire (MT_MNTRFX2) can step up any amount && thing->type != MT_MNTRFX2 && (tmfloorz - thing->z > maxstep ) ) { CheckMissileImpact(thing); return false; // too big a step up } if((thing->flags&MF_MISSILE) && tmfloorz > thing->z) CheckMissileImpact(thing); if ( !boomsupport || !allowdropoff) if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT)) && !tmfloorthing && tmfloorz - tmdropoffz > MAXSTEPMOVE ) return false; // don't stand over a dropoff } // the move is ok, // so link the thing into its new position P_UnsetThingPosition (thing); //added:28-02-98: gameplay hack : walk over a small wall while jumping // stop jumping it succeeded // BP: removed in 1.28 because we can move in air now if ( demoplayback>=112 && demoplayback<128 && thing->player && (thing->player->cheats & CF_JUMPOVER) ) { if (tmfloorz > thing->floorz + MAXSTEPMOVE) thing->momz >>= 2; } oldx = thing->x; oldy = thing->y; thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; thing->x = x; thing->y = y; //added:28-02-98: if (tmfloorthing) thing->eflags &= ~MF_ONGROUND; //not on real floor else thing->eflags |= MF_ONGROUND; P_SetThingPosition (thing); if (thing->flags2 & MF2_FOOTCLIP && P_GetThingFloorType (thing) != FLOOR_SOLID && gamemode == heretic ) thing->flags2 |= MF2_FEETARECLIPPED; else if (thing->flags2 & MF2_FEETARECLIPPED) thing->flags2 &= ~MF2_FEETARECLIPPED; // if any special lines were hit, do the effect if ( !(thing->flags&(MF_TELEPORT|MF_NOCLIP)) && (thing->type != MT_CHASECAM) && (thing->type != MT_SPIRIT)) { while (numspechit--) { // see if the line was crossed ld = lines + spechit[numspechit]; side = P_PointOnLineSide (thing->x, thing->y, ld); oldside = P_PointOnLineSide (oldx, oldy, ld); if (side != oldside) { if (ld->special) P_CrossSpecialLine (ld-lines, oldside, thing); } } } return true;}//// P_ThingHeightClip// Takes a valid thing and adjusts the thing->floorz,// thing->ceilingz, and possibly thing->z.// This is called for all nearby monsters// whenever a sector changes height.// If the thing doesn't fit,// the z will be set to the lowest value// and false will be returned.//boolean P_ThingHeightClip (mobj_t* thing){ boolean onfloor; onfloor = (thing->z <= thing->floorz); P_CheckPosition (thing, thing->x, thing->y); // what about stranding a monster partially off an edge? thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; if (!tmfloorthing && onfloor) { // walking monsters rise and fall with the floor thing->z = thing->floorz; } else { // don't adjust a floating monster unless forced to //added:18-04-98:test onfloor if (!onfloor) //was tmsectorceilingz if (thing->z+thing->height > tmceilingz) thing->z = thing->ceilingz - thing->height; //thing->eflags &= ~MF_ONGROUND; } //debug : be sure it falls to the floor thing->eflags &= ~MF_ONGROUND; //added:28-02-98: // test sector bouding top & bottom, not things //if (tmsectorceilingz - tmsectorfloorz < thing->height) // return false; if (thing->ceilingz - thing->floorz < thing->height) return false; return true;}//// SLIDE MOVE// Allows the player to slide along any angled walls.//fixed_t bestslidefrac;fixed_t secondslidefrac;line_t* bestslideline;line_t* secondslideline;mobj_t* slidemo;fixed_t tmxmove;fixed_t tmymove;//// P_HitSlideLine// Adjusts the xmove / ymove// so that the next move will slide along the wall.//void P_HitSlideLine (line_t* ld){ int side; angle_t lineangle; angle_t moveangle; angle_t deltaangle; fixed_t movelen; fixed_t newlen; if (ld->slopetype == ST_HORIZONTAL) { tmymove = 0; return; } if (ld->slopetype == ST_VERTICAL) { tmxmove = 0; return; } side = P_PointOnLineSide (slidemo->x, slidemo->y, ld); lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy); if (side == 1) lineangle += ANG180; moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove); deltaangle = moveangle-lineangle; if (deltaangle > ANG180) deltaangle += ANG180; // I_Error ("SlideLine: ang>ANG180"); lineangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT; movelen = P_AproxDistance (tmxmove, tmymove); newlen = FixedMul (movelen, finecosine[deltaangle]); tmxmove = FixedMul (newlen, finecosine[lineangle]); tmymove = FixedMul (newlen, finesine[lineangle]);}//// PTR_SlideTraverse//boolean PTR_SlideTraverse (intercept_t* in){ line_t* li;#ifdef PARANOIA if (!in->isaline) I_Error ("PTR_SlideTraverse: not a line?");#endif li = in->d.line; if ( ! (li->flags & ML_TWOSIDED) ) { if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) { // don't hit the back side return true; } goto isblocking; } // set openrange, opentop, openbottom P_LineOpening (li); if (openrange < slidemo->height) goto isblocking; // doesn't fit if (opentop - slidemo->z < slidemo->height) goto isblocking; // mobj is too high if (openbottom - slidemo->z > 24*FRACUNIT ) goto isblocking; // too big a step up // this line doesn't block movement return true; // the line does block movement, // see if it is closer than best so far isblocking: // SoM: Add code here for checking portals and subsiquent portal lines.. if(li->wallportals) { wallportal_t* wpr; for(wpr = li->wallportals; wpr; wpr = wpr->next) if(slidemo->z >= *wpr->bottomheight && slidemo->z + slidemo->height <= *wpr->topheight) break; if(wpr) return true; } if (in->frac < bestslidefrac) { secondslidefrac = bestslidefrac; secondslideline = bestslideline; bestslidefrac = in->frac; bestslideline = li; } return false; // stop}//// P_SlideMove// The momx / momy move is bad, so try to slide// along a wall.// Find the first line hit, move flush to it,// and slide along it//// This is a kludgy mess.//void P_SlideMove (mobj_t* mo){ fixed_t leadx; fixed_t leady; fixed_t trailx; fixed_t traily; fixed_t newx; fixed_t newy; int hitcount; slidemo = mo; hitcount = 0; retry: if (++hitcount == 3) goto stairstep; // don't loop forever // trace along the three leading corners if (mo->momx > 0) { leadx = mo->x + mo->radius; trailx = mo->x - mo->radius; } else { leadx = mo->x - mo->radius; trailx = mo->x + mo->radius; } if (mo->momy > 0) { leady = mo->y + mo->radius; traily = mo->y - mo->radius; } else { leady = mo->y - mo->radius; traily = mo->y + mo->radius; } bestslidefrac = FRACUNIT+1; P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_SlideTraverse ); P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_SlideTraverse ); P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy, PT_ADDLINES, PTR_SlideTraverse ); // move up to the wall if (bestslidefrac == FRACUNIT+1) { // the move most have hit the middle, so stairstep stairstep: if (!P_TryMove (mo, mo->x, mo->y + mo->momy, true)) //SoM: 4/10/2000 P_TryMove (mo, mo->x + mo->momx, mo->y, true); //Allow things to return; //drop off. } // fudge a bit to make sure it doesn't hit bestslidefrac -= 0x800; if (bestslidefrac > 0) { newx = FixedMul (mo->momx, bestslidefrac); newy = FixedMul (mo->momy, bestslidefrac); if (!P_TryMove (mo, mo->x+newx, mo->y+newy, true)) goto stairstep; } // Now continue along the wall. // First calculate remainder. bestslidefrac = FRACUNIT-(bestslidefrac+0x800); if (bestslidefrac > FRACUNIT) bestslidefrac = FRACUNIT; if (bestslidefrac <= 0) return; tmxmove = FixedMul (mo->momx, bestslidefrac); tmymove = FixedMul (mo->momy, bestslidefrac); P_HitSlideLine (bestslideline); // clip the moves mo->momx = tmxmove; mo->momy = tmymove; if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove, true)) { goto retry; }}//// P_LineAttack//mobj_t* linetarget; // who got hit (or NULL)mobj_t* shootthing;// Height if not aiming up or down// ???: use slope for monsters?fixed_t shootz;fixed_t lastz; //SoM: The last z height of the bullet when it crossed a lineint la_damage;fixed_t attackrange;fixed_t aimslope;//// PTR_AimTraverse// Sets linetarget and aimslope when a target is aimed at.////added:15-02-98: comment// Returns true if the thing is not shootable, else continue through..//boolean PTR_AimTraverse (intercept_t* in){ line_t* li; mobj_t* th; fixed_t slope; fixed_t thingtopslope; fixed_t thingbottomslope; fixed_t dist; int dir; if (in->isaline) { li = in->d.line; if ( !(li->flags & ML_TWOSIDED) ) return false; // stop // Crosses a two sided line. // A two sided line will restrict // the possible target ranges. tmthing = NULL; P_LineOpening (li); if (openbottom >= opentop) return false; // stop dist = FixedMul (attackrange, in->frac); if (li->frontsector->floorheight != li->backsector->floorheight) { slope = FixedDiv (openbottom - shootz , dist); if (slope > bottomslope) bottomslope = slope; } if (li->frontsector->ceilingheight != li->backsector->ceilingheight) { slope = FixedDiv (opentop - shootz , dist); if (slope < topslope)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -