📄 p_map.c
字号:
topslope = slope; } if (topslope <= bottomslope) return false; // stop if(li->frontsector->ffloors || li->backsector->ffloors) { int frontflag; dir = aimslope > 0 ? 1 : aimslope < 0 ? -1 : 0; frontflag = P_PointOnLineSide(shootthing->x, shootthing->y, li); //SoM: Check 3D FLOORS! if(li->frontsector->ffloors) { ffloor_t* rover = li->frontsector->ffloors; fixed_t highslope, lowslope; for(; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; highslope = FixedDiv (*rover->topheight - shootz, dist); lowslope = FixedDiv (*rover->bottomheight - shootz, dist); if((aimslope >= lowslope && aimslope <= highslope)) return false; if(lastz > *rover->topheight && dir == -1 && aimslope < highslope) frontflag |= 0x2; if(lastz < *rover->bottomheight && dir == 1 && aimslope > lowslope) frontflag |= 0x2; } } if(li->backsector->ffloors) { ffloor_t* rover = li->backsector->ffloors; fixed_t highslope, lowslope; for(; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; highslope = FixedDiv (*rover->topheight - shootz, dist); lowslope = FixedDiv (*rover->bottomheight - shootz, dist); if((aimslope >= lowslope && aimslope <= highslope)) return false; if(lastz > *rover->topheight && dir == -1 && aimslope < highslope) frontflag |= 0x4; if(lastz < *rover->bottomheight && dir == 1 && aimslope > lowslope) frontflag |= 0x4; } } if((!(frontflag & 0x1) && frontflag & 0x2) || (frontflag & 0x1 && frontflag & 0x4)) return false; } lastz = FixedMul (aimslope, dist) + shootz; 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)) || (th->flags&MF_CORPSE) || (th->type == MT_POD)) return true; // corpse or something // check angles to see if the thing can be aimed at dist = FixedMul (attackrange, in->frac); thingtopslope = FixedDiv (th->z+th->height - shootz , dist); //added:15-02-98: bottomslope is negative! 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; //added:15-02-98: find the slope just in the middle(y) of the thing! aimslope = (thingtopslope+thingbottomslope)/2; linetarget = th; return false; // don't go any farther}//// PTR_ShootTraverse////added:18-02-98: added clipping the shots on the floor and ceiling.//boolean PTR_ShootTraverse (intercept_t* in){ fixed_t x; fixed_t y; fixed_t z; fixed_t frac; line_t* li; sector_t* sector=NULL; mobj_t* th; fixed_t slope; fixed_t dist; fixed_t thingtopslope; fixed_t thingbottomslope; fixed_t floorz; //SoM: Bullets should hit fake floors! fixed_t ceilingz; //added:18-02-98: fixed_t distz; //dist between hit z on wall and gun z fixed_t clipz; //dist between hit z on floor/ceil and gun z boolean hitplane; //true if we clipped z on floor/ceil plane boolean diffheights; //check for sky hacks with different ceil heights int sectorside; int dir; if(aimslope > 0) dir = 1; else if(aimslope < 0) dir = -1; else dir = 0; if (in->isaline) { //shut up compiler, otherwise it's only used when TWOSIDED diffheights = false; li = in->d.line; if (li->special) P_ShootSpecialLine (shootthing, li); if ( !(li->flags & ML_TWOSIDED) ) goto hitline; // crosses a two sided line //added:16-02-98: Fab comments : sets opentop, openbottom, openrange // lowfloor is the height of the lowest floor // (be it front or back) tmthing = NULL; P_LineOpening (li); dist = FixedMul (attackrange, in->frac); // hit lower texture ? if (li->frontsector->floorheight != li->backsector->floorheight) { //added:18-02-98: comments : // find the slope aiming on the border between the two floors slope = FixedDiv (openbottom - shootz , dist); if (slope > aimslope) goto hitline; } // hit upper texture ? if (li->frontsector->ceilingheight != li->backsector->ceilingheight) { //added:18-02-98: remember : diff ceil heights diffheights = true; slope = FixedDiv (opentop - shootz , dist); if (slope < aimslope) goto hitline; } if(li->frontsector->ffloors || li->backsector->ffloors) { int frontflag; frontflag = P_PointOnLineSide(shootthing->x, shootthing->y, li); //SoM: Check 3D FLOORS! if(li->frontsector->ffloors) { ffloor_t* rover = li->frontsector->ffloors; fixed_t highslope, lowslope; for(; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; highslope = FixedDiv (*rover->topheight - shootz, dist); lowslope = FixedDiv (*rover->bottomheight - shootz, dist); if((aimslope >= lowslope && aimslope <= highslope)) goto hitline; if(lastz > *rover->topheight && dir == -1 && aimslope < highslope) frontflag |= 0x2; if(lastz < *rover->bottomheight && dir == 1 && aimslope > lowslope) frontflag |= 0x2; } } if(li->backsector->ffloors) { ffloor_t* rover = li->backsector->ffloors; fixed_t highslope, lowslope; for(; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; highslope = FixedDiv (*rover->topheight - shootz, dist); lowslope = FixedDiv (*rover->bottomheight - shootz, dist); if((aimslope >= lowslope && aimslope <= highslope)) goto hitline; if(lastz > *rover->topheight && dir == -1 && aimslope < highslope) frontflag |= 0x4; if(lastz < *rover->bottomheight && dir == 1 && aimslope > lowslope) frontflag |= 0x4; } } if((!(frontflag & 0x1) && frontflag & 0x2) || (frontflag & 0x1 && frontflag & 0x4)) goto hitline; } lastz = FixedMul (aimslope, dist) + shootz; // shot continues return true; // hit line hitline: // position a bit closer frac = in->frac - FixedDiv (4*FRACUNIT,attackrange); dist = FixedMul (frac, attackrange); //dist to hit on line distz = FixedMul (aimslope, dist); //z add between gun z and hit z z = shootz + distz; // hit z on wall //added:17-02-98: clip shots on floor and ceiling // use a simple triangle stuff a/b = c/d ... // BP:13-3-99: fix the side usage hitplane = false; sectorside=P_PointOnLineSide(shootthing->x,shootthing->y,li); if( li->sidenum[sectorside] != -1 ) // can happen in nocliping mode { sector = sides[li->sidenum[sectorside]].sector; floorz = sector->floorheight; ceilingz = sector->ceilingheight; if(sector->ffloors) { ffloor_t* rover; for(rover = sector->ffloors; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID)) continue; if(dir == 1 && *rover->bottomheight < ceilingz && *rover->bottomheight > lastz) ceilingz = *rover->bottomheight; if(dir == -1 && *rover->topheight > floorz && *rover->topheight < lastz) floorz = *rover->topheight; } } if ((z > ceilingz) && distz) { clipz = ceilingz - shootz; frac = FixedDiv( FixedMul(frac,clipz), distz ); hitplane = true; } else if ((z < floorz) && distz) { clipz = shootz - floorz; frac = -FixedDiv( FixedMul(frac,clipz), distz ); hitplane = true; } if(sector->ffloors) { if(dir == 1 && z > ceilingz) z = ceilingz; if(dir == -1 && z < floorz) z = floorz; } } //SPLAT TEST ---------------------------------------------------------- #ifdef WALLSPLATS if (!hitplane && demoversion>=129) { divline_t divl; fixed_t frac; P_MakeDivline (li, &divl); frac = P_InterceptVector (&divl, &trace); R_AddWallSplat (li, sectorside, "A_DMG1", z, frac, SPLATDRAWMODE_SHADE); } #endif // --------------------------------------------------------- SPLAT TEST x = trace.x + FixedMul (trace.dx, frac); y = trace.y + FixedMul (trace.dy, frac); if (li->frontsector->ceilingpic == skyflatnum) { // don't shoot the sky! if (z > li->frontsector->ceilingheight) return false; //added:24-02-98: compatibility with older demos if (demoversion<112) { diffheights = true; hitplane = false; } // it's a sky hack wall if ((!hitplane && //added:18-02-98:not for shots on planes li->backsector && diffheights && //added:18-02-98:skip only REAL sky hacks // eg: they use different ceil heights. li->backsector->ceilingpic == skyflatnum)) return false; } if(sector && sector->ffloors) { if(dir == 1 && z + (16 << FRACBITS) > ceilingz) z = ceilingz - (16 << FRACBITS); if(dir == -1 && z < floorz) z = floorz; } // Spawn bullet puffs. P_SpawnPuff (x,y,z); // don't go any farther return false; } // shoot a thing th = in->d.thing; if (th == shootthing) return true; // can't shoot self if (!(th->flags&MF_SHOOTABLE)) return true; // corpse or something// check for physical attacks on a ghost if (gamemode == heretic && (th->flags & MF_SHADOW) && shootthing->player->readyweapon == wp_staff) 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 < aimslope) return true; // shot over the thing thingbottomslope = FixedDiv (th->z - shootz, dist); if (thingbottomslope > aimslope) return true; // shot under the thing // SoM: SO THIS IS THE PROBLEM!!! // heh. // A bullet would travel through a 3D floor until it hit a LINEDEF! Thus // it appears that the bullet hits the 3D floor but it actually just hits // the line behind it. Thus allowing a bullet to hit things under a 3D // floor and still be clipped a 3D floor. if(th->subsector->sector->ffloors) { sector_t* sector = th->subsector->sector; ffloor_t* rover; for(rover = sector->ffloors; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID)) continue; if(dir == -1 && *rover->topheight < lastz && *rover->topheight > th->z + th->height) return true; if(dir == 1 && *rover->bottomheight > lastz && *rover->bottomheight < th->z) return true; } } // hit thing // position a bit closer frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); x = trace.x + FixedMul (trace.dx, frac); y = trace.y + FixedMul (trace.dy, frac); z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); if (demoversion<125) { // Spawn bullet puffs or blood spots, // depending on target type. if (in->d.thing->flags & MF_NOBLOOD) P_SpawnPuff (x,y,z); else P_SpawnBlood (x,y,z, la_damage); } if (la_damage) hitplane = P_DamageMobj (th, shootthing, shootthing, la_damage); else hitplane = false; if (demoversion>=125) { // Spawn bullet puffs or blood spots, // depending on target type. if (in->d.thing->flags & MF_NOBLOOD && gamemode != heretic ) P_SpawnPuff (x,y,z); else { if( gamemode == heretic ) { if(PuffType == MT_BLASTERPUFF1) // Make blaster big puff S_StartSound(P_SpawnMobj(x, y, z, MT_BLASTERPUFF2), sfx_blshit); else P_SpawnPuff(x, y, z); } if (hitplane) { P_SpawnBloodSplats (x,y,z, la_damage, trace.dx, trace.dy); return false; } } } // don't go any farther return false;}//// P_AimLineAttack//fixed_t P_AimLineAttack ( mobj_t* t1, angle_t angle, fixed_t distance ){ fixed_t x2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -