📄 p_map.c
字号:
// damage / explode damage = ((P_Random()%8)+1)*tmthing->info->damage; if( P_DamageMobj (thing, tmthing, tmthing->target, damage) && (thing->flags & MF_NOBLOOD)==0 && demoversion>=129 ) P_SpawnBloodSplats (tmthing->x,tmthing->y,tmthing->z, damage, thing->momx, thing->momy); // don't traverse any more return false; } if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH)) { // Push thing thing->momx += tmthing->momx >> 2; thing->momy += tmthing->momy >> 2; } // check for special pickup if (thing->flags & MF_SPECIAL) { solid = thing->flags&MF_SOLID; if (tmflags&MF_PICKUP) { // can remove thing P_TouchSpecialThing (thing, tmthing); } return !solid; } // check again for special pickup if(demoversion>=132 && tmthing->flags & MF_SPECIAL) { solid = tmthing->flags&MF_SOLID; if (thing->flags&MF_PICKUP) { // can remove thing P_TouchSpecialThing (tmthing, thing); } return !solid; } //added:24-02-98:compatibility with old demos, it used to return with... //added:27-02-98:for version 112+, nonsolid things pass through other things if (demoversion<112 || demoversion>=132 || !(tmthing->flags & MF_SOLID)) return !(thing->flags & MF_SOLID); //added:22-02-98: added z checking at last //SoM: 3/10/2000: Treat noclip things as non-solid! if ((thing->flags & MF_SOLID) && (tmthing->flags & MF_SOLID) && !(thing->flags & MF_NOCLIP) && !(tmthing->flags & MF_NOCLIP)) { // pass under tmtopz = tmthing->z + tmthing->height; if ( tmtopz < thing->z) { if (thing->z < tmceilingz) tmceilingz = thing->z; return true; } topz = thing->z + thing->height + FRACUNIT; // block only when jumping not high enough, // (dont climb max. 24units while already in air) // if not in air, let P_TryMove() decide if its not too high if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) // block while in air return false; if (topz > tmfloorz) { tmfloorz = topz; tmfloorthing = thing; //thing we may stand on } } // not solid not blocked return true;}// SoM: 3/15/2000// PIT_CrossLine// Checks to see if a PE->LS trajectory line crosses a blocking// line. Returns false if it does.//// tmbbox holds the bounding box of the trajectory. If that box// does not touch the bounding box of the line in question,// then the trajectory is not blocked. If the PE is on one side// of the line and the LS is on the other side, then the// trajectory is blocked.//// Currently this assumes an infinite line, which is not quite// correct. A more correct solution would be to check for an// intersection of the trajectory and the line, but that takes// longer and probably really isn't worth the effort.//static boolean PIT_CrossLine (line_t* ld) { if (!(ld->flags & ML_TWOSIDED) || (ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS))) if (!(tmbbox[BOXLEFT] > ld->bbox[BOXRIGHT] || tmbbox[BOXRIGHT] < ld->bbox[BOXLEFT] || tmbbox[BOXTOP] < ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP])) if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld)) return(false); // line blocks trajectory return(true); // line doesn't block trajectory }//// P_CheckWallPortals// Checks a lines wallportal list to see if a mobj can pass through one of// them... returns NULL if a mobj can't pass through, otherwise, returns a// pointer to the portal the thing is passing through.wallportal_t* P_CheckWallPortals(mobj_t* thing, line_t* line){ wallportal_t* wpr; fixed_t thingtop, thingbot; if(!line->wallportals) return NULL; thingbot = thing->z; thingtop = thingbot + thing->height; for(wpr = line->wallportals; wpr; wpr = wpr->next) if(thingtop > *wpr->bottomheight && thingbot < *wpr->topheight) return wpr; return NULL;}//// PIT_CheckLine// Adjusts tmfloorz and tmceilingz as lines are contacted//boolean PIT_CheckLine (line_t* ld){ wallportal_t* wpr = NULL; if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) return true; if (P_BoxOnLineSide (tmbbox, ld) != -1) return true; // A line has been hit // The moving thing's destination position will cross // the given line. // If this should not be allowed, return false. // If the line is special, keep track of it // to process later if the move is proven ok. // NOTE: specials are NOT sorted by order, // so two special lines that are only 8 pixels apart // could be crossed in either order. // 10-12-99 BP: moved this line to out of the if so upper and // lower texture can be hit by a splat blockingline = ld; if (!ld->backsector) { if(ld->wallportals && (wpr = P_CheckWallPortals(tmthing, ld))) goto ldspecial; if(demoversion>=132 && tmthing->flags & MF_MISSILE && ld->special) add_spechit(ld); return false; // one sided line } // missil and Camera can cross uncrossable line if (!(tmthing->flags & MF_MISSILE) && !(tmthing->type == MT_CHASECAM) ) { if (ld->flags & ML_BLOCKING) return false; // explicitly blocking everything if ( !(tmthing->player) && ld->flags & ML_BLOCKMONSTERS ) return false; // block monsters only } // set openrange, opentop, openbottom P_LineOpening (ld); // adjust floor / ceiling heights if (opentop < tmceilingz) { tmsectorceilingz = tmceilingz = opentop; ceilingline = ld; } if (openbottom > tmfloorz) tmsectorfloorz = tmfloorz = openbottom; if (lowfloor < tmdropoffz) tmdropoffz = lowfloor; if((wpr = P_CheckWallPortals(tmthing, ld))) { tmfloorz = tmsectorfloorz = openbottom; tmceilingz = tmsectorceilingz = opentop; } ldspecial: if(ld->wallportals && wpr) { fixed_t bx, by, xl, xh, yl, yh; fixed_t xoff, yoff; fixed_t oldbox[4]; wpr->portal->mline->validcount = validcount; // Store the old bounding box (for recursive purposes) for(bx = 0; bx < 4; bx++) oldbox[bx] = tmbbox[bx]; xoff = (wpr->portal->mline->v2->x - ld->v1->x); yoff = (wpr->portal->mline->v2->y - ld->v1->y); tmbbox[BOXTOP] += yoff; tmbbox[BOXBOTTOM] += yoff; tmbbox[BOXLEFT] += xoff; tmbbox[BOXRIGHT] += xoff; // SoM: Check lines on the "other side" of the portal... if(!(tmthing->flags & MF_NOCLIPTHING)) { xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) return false; } // check lines xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) return false; for(bx = 0; bx < 4; bx++) tmbbox[bx] = oldbox[bx]; } // if contacted a special line, add it to the list if (ld->special) add_spechit(ld); return true;}// =========================================================================// MOVEMENT CLIPPING// =========================================================================//// P_CheckPosition// This is purely informative, nothing is modified// (except things picked up).//// in:// a mobj_t (can be valid or invalid)// a position to be checked// (doesn't need to be related to the mobj_t->x,y)//// during:// special things are touched if MF_PICKUP// early out on solid lines?//// out:// newsubsec// tmfloorz// tmceilingz// tmdropoffz// the lowest point contacted// (monsters won't move to a dropoff)// speciallines[]// numspeciallines////added:27-02-98://// tmfloorz// the nearest floor or thing's top under tmthing// tmceilingz// the nearest ceiling or thing's bottom over tmthing//boolean P_CheckPosition ( mobj_t* thing, fixed_t x, fixed_t y ){ int xl; int xh; int yl; int yh; int bx; int by; subsector_t* newsubsec; tmthing = thing; tmflags = thing->flags; tmx = x; tmy = y; tmbbox[BOXTOP] = y + tmthing->radius; tmbbox[BOXBOTTOM] = y - tmthing->radius; tmbbox[BOXRIGHT] = x + tmthing->radius; tmbbox[BOXLEFT] = x - tmthing->radius; newsubsec = R_PointInSubsector (x,y); ceilingline = blockingline = NULL; // The base floor / ceiling is from the subsector // that contains the point. // Any contacted lines the step closer together // will adjust them. tmfloorz = tmsectorfloorz = tmdropoffz = newsubsec->sector->floorheight; tmceilingz = tmsectorceilingz = newsubsec->sector->ceilingheight; //SoM: 3/23/2000: Check list of fake floors and see if //tmfloorz/tmceilingz need to be altered. if(newsubsec->sector->ffloors) { ffloor_t* rover; fixed_t delta1; fixed_t delta2; int thingtop = thing->z + thing->height; for(rover = newsubsec->sector->ffloors; rover; rover = rover->next) { if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue; delta1 = thing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)); if(*rover->topheight > tmfloorz && abs(delta1) < abs(delta2)) tmfloorz = tmdropoffz = *rover->topheight; if(*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2)) tmceilingz = *rover->bottomheight; } } // tmfloorthing is set when tmfloorz comes from a thing's top tmfloorthing = NULL; validcount++; numspechit = 0; if ( tmflags & MF_NOCLIP ) return true; // Check things first, possibly picking things up. // The bounding box is extended by MAXRADIUS // because mobj_ts are grouped into mapblocks // based on their origin point, and can overlap // into adjacent blocks by up to MAXRADIUS units. // BP: added MF_NOCLIPTHING :used by camera to don't be blocked by things if(!(thing->flags & MF_NOCLIPTHING)) { xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockThingsIterator(bx,by,PIT_CheckThing)) return false; } // check lines xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; for (bx=xl ; bx<=xh ; bx++) for (by=yl ; by<=yh ; by++) if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) return false; return true;}//==========================================================================//// CheckMissileImpact////==========================================================================static void CheckMissileImpact(mobj_t *mobj){ int i; if( demoversion<132 || !numspechit || !(mobj->flags&MF_MISSILE) || !mobj->target) return; if(!mobj->target->player) return; for(i = numspechit-1; i >= 0; i--) P_ShootSpecialLine(mobj->target, lines + spechit[i]);}//// P_TryMove// Attempt to move to a new position,// crossing special lines unless MF_TELEPORT is set.//boolean P_TryMove ( mobj_t* thing, fixed_t x, fixed_t y, boolean allowdropoff){ fixed_t oldx; fixed_t oldy; int side; int oldside; line_t* ld; floatok = false; if (!P_CheckPosition (thing, x, y)) { CheckMissileImpact(thing); return false; // solid wall or thing }#ifdef CLIENTPREDICTION2 if ( !(thing->flags & MF_NOCLIP) && !(thing->eflags & MF_NOZCHECKING))#else if ( !(thing->flags & MF_NOCLIP) )#endif { fixed_t maxstep = MAXSTEPMOVE; if (tmceilingz - tmfloorz < thing->height) { CheckMissileImpact(thing); return false; // doesn't fit } floatok = true; if ( !(thing->flags & MF_TELEPORT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -