// // 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 // floorz // ceilingz // tmdropoffz // the lowest point contacted // (monsters won't move to a dropoff) // speciallines[] // numspeciallines // boolean P_CheckPosition ( mobj_t* thing, fixed_t x, fixed_t y ) { int xl; int xh; int yl; int yh; int bx; int by; int tmradius; subsector_t*newsubsec; tmthing = thing; tmflags = thing->flags; tmx = x; tmy = y; tmradius = tmthing->radius; tmbbox[BOXTOP] = y + tmradius; tmbbox[BOXBOTTOM] = y - tmradius; tmbbox[BOXRIGHT] = x + tmradius; tmbbox[BOXLEFT] = x - tmradius; newsubsec = R_PointInSubsector (x,y); ceilingline = NULL; blockline = NULL; // The base floor / ceiling is from the subsector // that contains the point. // Any contacted lines the step closer together // will adjust them. tmfloorz = tmdropoffz = newsubsec->sector->floorheight; tmceilingz = newsubsec->sector->ceilingheight; 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. 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 // Use the pickup radius (usually larger) if the thing // is moving horizontally. // i.e. use the smaller radius when movement is vertical. // Test: Going Down, Map 15, Red skull key next to Cyberdemon. if ((thing->x != x) || (thing->y != y)) { tmradius = tmthing->info->pickupradius; tmbbox[BOXTOP] = y + tmradius; tmbbox[BOXBOTTOM] = y - tmradius; tmbbox[BOXRIGHT] = x + tmradius; tmbbox[BOXLEFT] = x - tmradius; } 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; }
// // This is purely informative, nothing is modified (except things picked up) // static void PM_CheckPosition() { int xl, xh, yl, yh, bx, by; tmflags = tmthing->flags; tmbbox[BOXTOP ] = tmy + tmthing->radius; tmbbox[BOXBOTTOM] = tmy - tmthing->radius; tmbbox[BOXRIGHT ] = tmx + tmthing->radius; tmbbox[BOXLEFT ] = tmx - tmthing->radius; newsubsec = R_PointInSubsector(tmx, tmy); // the base floor/ceiling is from the subsector that contains the point. // Any contacted lines the step closer together will adjust them. tmfloorz = tmdropoffz = newsubsec->sector->floorheight; tmceilingz = newsubsec->sector->ceilingheight; ++validcount; movething = NULL; blockline = NULL; if(tmflags & MF_NOCLIP) // thing has no clipping? { trymove2 = true; return; } // 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. xl = (tmbbox[BOXLEFT ] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT ] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP ] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; if(xl < 0) xl = 0; if(yl < 0) yl = 0; if(xh >= bmapwidth) xh = bmapwidth - 1; if(yh >= bmapheight) yh = bmapheight - 1; // check things for(bx = xl; bx <= xh; bx++) { for(by = yl; by <= yh; by++) { if(!P_BlockThingsIterator(bx, by, PIT_CheckThing)) { trymove2 = false; return; } } } // check lines xl = (tmbbox[BOXLEFT ] - bmaporgx) >> MAPBLOCKSHIFT; xh = (tmbbox[BOXRIGHT ] - bmaporgx) >> MAPBLOCKSHIFT; yl = (tmbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; yh = (tmbbox[BOXTOP ] - bmaporgy) >> MAPBLOCKSHIFT; if(xl < 0) xl = 0; if(yl < 0) yl = 0; if(xh >= bmapwidth) xh = bmapwidth - 1; if(yh >= bmapheight) yh = bmapheight - 1; for(bx = xl; bx <= xh; bx++) { for(by = yl; by <= yh; by++) { if(!P_BlockLinesIterator(bx, by, PM_CrossCheck)) { trymove2 = false; return; } } } trymove2 = true; }
/* * Returns true if it the thing can be positioned in the coordinates. */ boolean P_CheckPosXYZ(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) { int xl, xh; int yl, yh; int bx, by; subsector_t *newsubsec; checkpos_data_t data; boolean result = true; blockingMobj = NULL; thing->onmobj = NULL; thing->wallhit = false; // Prepare the data struct. data.thing = thing; data.flags = thing->ddflags; data.x = x; data.y = y; data.z = z; data.height = thing->height; data.box[BOXTOP] = y + thing->radius; data.box[BOXBOTTOM] = y - thing->radius; data.box[BOXRIGHT] = x + thing->radius; data.box[BOXLEFT] = x - thing->radius; newsubsec = R_PointInSubsector(x, y); // The base floor / ceiling is from the subsector // that contains the point. // Any contacted lines the step closer together // will adjust them. data.floorz = data.dropoffz = newsubsec->sector->floorheight; data.ceilingz = newsubsec->sector->ceilingheight; validcount++; // 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. xl = (data.box[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; xh = (data.box[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; yl = (data.box[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; yh = (data.box[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; if(!dontHitMobjs) { for(bx = xl; bx <= xh; bx++) for(by = yl; by <= yh; by++) if(!P_BlockThingsIterator(bx, by, PIT_CheckThing, &data)) { result = false; goto checkpos_done; } } // check lines xl = (data.box[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; xh = (data.box[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; yl = (data.box[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; yh = (data.box[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; for(bx = xl; bx <= xh; bx++) for(by = yl; by <= yh; by++) if(!P_BlockLinesIterator(bx, by, PIT_CheckLine, &data)) { result = false; goto checkpos_done; } checkpos_done: tmceilingz = data.ceilingz; tmfloorz = data.floorz; tmdropoffz = data.dropoffz; return result; }