📄 p_map.c
字号:
} } } } } return true;pushline: if(!(thing->flags&(MF_TELEPORT|MF_NOCLIP))) { int numSpecHitTemp; if (tmthing->flags2&MF2_BLASTED) { P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass>>5); } numSpecHitTemp = numspechit; while (numSpecHitTemp > 0) { numSpecHitTemp--; // see if the line was crossed ld = spechit[numSpecHitTemp]; side = P_PointOnLineSide (thing->x, thing->y, ld); CheckForPushSpecial(ld, side, thing); } } return false;}/*==================== P_ThingHeightClip== Takes a valid thing and adjusts the thing->floorz, thing->ceilingz,= anf 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; thing->floorpic = tmfloorpic; if (onfloor) { // walking monsters rise and fall with the floor if((thing->z-thing->floorz < 9*FRACUNIT) || (thing->flags&MF_NOGRAVITY)) { thing->z = thing->floorz; } } else { // don't adjust a floating monster unless forced to if (thing->z+thing->height > thing->ceilingz) thing->z = thing->ceilingz - thing->height; } if (thing->ceilingz - thing->floorz < thing->height) return false; return true;}/*============================================================================== SLIDE MOVEAllows the player to slide along any angled walls==============================================================================*/fixed_t bestslidefrac, secondslidefrac;line_t *bestslideline, *secondslideline;mobj_t *slidemo;fixed_t tmxmove, 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, moveangle, deltaangle; fixed_t movelen, 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; if (!in->isaline) I_Error ("PTR_SlideTraverse: not a line?"); li = in->d.line; if ( ! (li->flags & ML_TWOSIDED) ) { if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) return true; // don't hit the back side goto isblocking; } P_LineOpening (li); // set openrange, opentop, openbottom 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 return true; // this line doesn't block movement// the line does block movement, see if it is closer than best so farisblocking: 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, leady; fixed_t trailx, traily; fixed_t newx, 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 must have hit the middle, so stairstepstairstep: if(!P_TryMove(mo, mo->x, mo->y+mo->momy)) { P_TryMove(mo, mo->x+mo->momx, mo->y); } return; } bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit if (bestslidefrac > 0) { newx = FixedMul (mo->momx, bestslidefrac); newy = FixedMul (mo->momy, bestslidefrac); if (!P_TryMove (mo, mo->x+newx, mo->y+newy)) goto stairstep; }//// now continue along the wall// bestslidefrac = FRACUNIT-(bestslidefrac+0x800); // remainder 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)) { goto retry; }}//============================================================================//// PTR_BounceTraverse////============================================================================boolean PTR_BounceTraverse(intercept_t *in){ line_t *li; if (!in->isaline) I_Error ("PTR_BounceTraverse: not a line?"); li = in->d.line; if (!(li->flags&ML_TWOSIDED)) { if (P_PointOnLineSide (slidemo->x, slidemo->y, li)) return true; // don't hit the back side goto bounceblocking; } P_LineOpening (li); // set openrange, opentop, openbottom if (openrange < slidemo->height) goto bounceblocking; // doesn't fit if (opentop - slidemo->z < slidemo->height) goto bounceblocking; // mobj is too high return true; // this line doesn't block movement// the line does block movement, see if it is closer than best so farbounceblocking: if (in->frac < bestslidefrac) { secondslidefrac = bestslidefrac; secondslideline = bestslideline; bestslidefrac = in->frac; bestslideline = li; } return false; // stop}//============================================================================//// P_BounceWall////============================================================================void P_BounceWall(mobj_t *mo){ fixed_t leadx, leady; int side; angle_t lineangle, moveangle, deltaangle; fixed_t movelen; slidemo = mo;//// trace along the three leading corners// if(mo->momx > 0) { leadx = mo->x+mo->radius; } else { leadx = mo->x-mo->radius; } if(mo->momy > 0) { leady = mo->y+mo->radius; } else { leady = mo->y-mo->radius; } bestslidefrac = FRACUNIT+1; P_PathTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy, PT_ADDLINES, PTR_BounceTraverse); side = P_PointOnLineSide(mo->x, mo->y, bestslideline); lineangle = R_PointToAngle2(0, 0, bestslideline->dx, bestslideline->dy); if(side == 1) lineangle += ANG180; moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy); deltaangle = (2*lineangle)-moveangle;// if (deltaangle > ANG180)// deltaangle += ANG180;// I_Error ("SlideLine: ang>ANG180"); lineangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT; movelen = P_AproxDistance(mo->momx, mo->momy); movelen = FixedMul(movelen, 0.75*FRACUNIT); // friction if (movelen < FRACUNIT) movelen = 2*FRACUNIT; mo->momx = FixedMul(movelen, finecosine[deltaangle]); mo->momy = FixedMul(movelen, finesine[deltaangle]);}/*============================================================================== P_LineAttack==============================================================================*/mobj_t *PuffSpawned;mobj_t *linetarget; // who got hit (or NULL)mobj_t *shootthing;fixed_t shootz; // height if not aiming up or down // ???: use slope for monsters?int la_damage;fixed_t attackrange;fixed_t aimslope;extern fixed_t topslope, bottomslope; // slopes to top and bottom of target/*================================================================================= PTR_AimTraverse== Sets linetaget and aimslope when a target is aimed at===============================================================================*/boolean PTR_AimTraverse (intercept_t *in){ line_t *li; mobj_t *th; fixed_t slope, thingtopslope, thingbottomslope; fixed_t dist; 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 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) topslope = slope; } if (topslope <= bottomslope) return false; // stop return true; // shot continues }//// shoot a thing// th = in->d.thing; if (th == shootthing) return true; // can't shoot self if(!(th->flags&MF_SHOOTABLE)) { // corpse or something return true; } if(th->player && netgame && !deathmatch) { // don't aim at fellow co-op players return true; }// check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac); thingtopslope = FixedDiv (th->z+th->height - shootz , dist); if (thingtopslope < bottomslope) return true; // shot over the thing thingbottomslope = FixedDiv (th->z - shootz, dist); if (thingbottomslope > topslope) return true; // shot under the thing//// this thing can be hit!// if (thingtopslope > topslope) thingtopslope = topslope; if (thingbottomslope < bottomslope) thingbottomslope = bottomslope; aimslope = (thingtopslope+thingbottomslope)/2; linetarget = th; return false; // don't go any farther}/*================================================================================ PTR_ShootTraverse===============================================================================*/boolean PTR_ShootTraverse (intercept_t *in){ fixed_t x,y,z; fixed_t frac; line_t *li; mobj_t *th; fixed_t slope; fixed_t dist; fixed_t thingtopslope, thingbottomslope; extern mobj_t LavaInflictor; if (in->isaline) { li = in->d.line; if (li->special) { P_ActivateLine(li, shootthing, 0, SPAC_IMPACT);// P_ShootSpecialLine (shootthing, li); } if ( !(li->flags & ML_TWOSIDED) ) goto hitline;//// crosses a two sided line// P_LineOpening (li); dist = FixedMul (attackrange, in->frac); if (li->frontsector->floorheight != li->backsector->floorheight) { slope = FixedDiv (openbottom - shootz , dist); if (slope > aimslope) goto hitline; } if (li->frontsector->ceilingheight != li->backsector->ceilingheight) { slope = FixedDiv (opentop - shootz , dist); if (slope < aimslope) goto hitline; } return true; // shot continues//// hit line//hitline: // position a bit closer frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); x = trace.x + FixedMul (trace.dx, frac); y = trace.y + FixedMul (trace.dy, frac); z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); if (li->frontsector->ceilingpic == skyflatnum) { if (z > li->frontsector->ceilingheight) return false; // don't shoot the sky!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -