📄 p_maputl.c
字号:
thing->subsector = ss; if ( ! (thing->flags & MF_NOSECTOR) ) { // invisible things don't go into the sector links sec = ss->sector;#ifdef PARANOIA if ( thing->sprev != NULL || thing->snext != NULL ) I_Error("linking a think(%d) that is allready linked",thing->type);#endif thing->sprev = NULL; thing->snext = sec->thinglist; if (sec->thinglist) sec->thinglist->sprev = thing; sec->thinglist = thing; //SoM: 4/6/2000 // // If sector_list isn't NULL, it has a collection of sector // nodes that were just removed from this Thing. // Collect the sectors the object will live in by looking at // the existing sector_list and adding new nodes and deleting // obsolete ones. // When a node is deleted, its sector links (the links starting // at sector_t->touching_thinglist) are broken. When a node is // added, new sector links are created. P_CreateSecNodeList(thing,thing->x,thing->y); thing->touching_sectorlist = sector_list; // Attach to Thing's mobj_t sector_list = NULL; // clear for next time } // link into blockmap if ( ! (thing->flags & MF_NOBLOCKMAP) ) { // inert things don't need to be in blockmap blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky < bmapheight) { link = &blocklinks[blocky*bmapwidth+blockx]; thing->bprev = NULL; thing->bnext = *link; if (*link) (*link)->bprev = thing; *link = thing; } else { // thing is off the map thing->bnext = thing->bprev = NULL; } }}//// BLOCK MAP ITERATORS// For each line/thing in the given mapblock,// call the passed PIT_* function.// If the function returns false,// exit with false without checking anything else.////// P_BlockLinesIterator// The validcount flags are used to avoid checking lines// that are marked in multiple mapblocks,// so increment validcount before the first call// to P_BlockLinesIterator, then make one or more calls// to it.//boolean P_BlockLinesIterator (int x, int y, boolean (*func)(line_t*) ){ int offset; short* list; line_t* ld; if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) { return true; } offset = y*bmapwidth+x; offset = *(blockmap+offset); for ( list = blockmaplump+offset ; *list != -1 ; list++) { ld = &lines[*list]; if (ld->validcount == validcount) continue; // line has already been checked ld->validcount = validcount; if ( !func(ld) ) return false; } return true; // everything was checked}//// P_BlockThingsIterator//boolean P_BlockThingsIterator ( int x, int y, boolean(*func)(mobj_t*) ){ mobj_t* mobj; if ( x<0 || y<0 || x>=bmapwidth || y>=bmapheight) { return true; } //added:15-02-98: check interaction (ligne de tir, ...) // avec les objets dans le blocmap for (mobj = blocklinks[y*bmapwidth+x] ; mobj ; mobj = mobj->bnext) { if (!func( mobj ) ) return false; } return true;}//// INTERCEPT ROUTINES////SoM: 4/6/2000: Limit removalintercept_t* intercepts = NULL;intercept_t* intercept_p = NULL;divline_t trace;boolean earlyout;int ptflags;//SoM: 4/6/2000: Remove limit on intercepts.void P_CheckIntercepts(){static int max_intercepts = 0; int count = intercept_p - intercepts; if(max_intercepts <= count) { if(!max_intercepts) max_intercepts = 128; else max_intercepts = max_intercepts * 2; intercepts = realloc(intercepts, sizeof(intercept_t) * max_intercepts); intercept_p = intercepts + count; }}//// PIT_AddLineIntercepts.// Looks for lines in the given block// that intercept the given trace// to add to the intercepts list.//// A line is crossed if its endpoints// are on opposite sides of the trace.// Returns true if earlyout and a solid line hit.//booleanPIT_AddLineIntercepts (line_t* ld){ int s1; int s2; fixed_t frac; divline_t dl; // avoid precision problems with two routines if ( trace.dx > FRACUNIT*16 || trace.dy > FRACUNIT*16 || trace.dx < -FRACUNIT*16 || trace.dy < -FRACUNIT*16) { s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); } else { s1 = P_PointOnLineSide (trace.x, trace.y, ld); s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); } if (s1 == s2) return true; // line isn't crossed // hit the line P_MakeDivline (ld, &dl); frac = P_InterceptVector (&trace, &dl); if (frac < 0) return true; // behind source // try to early out the check if (earlyout && frac < FRACUNIT && !ld->backsector) { return false; // stop checking } //SoM: 4/6/2000: Limit removal P_CheckIntercepts(); intercept_p->frac = frac; intercept_p->isaline = true; intercept_p->d.line = ld; intercept_p++; return true; // continue}//// PIT_AddThingIntercepts//boolean PIT_AddThingIntercepts (mobj_t* thing){ fixed_t x1; fixed_t y1; fixed_t x2; fixed_t y2; int s1; int s2; boolean tracepositive; divline_t dl; fixed_t frac; tracepositive = (trace.dx ^ trace.dy)>0; // check a corner to corner crossection for hit if (tracepositive) { x1 = thing->x - thing->radius; y1 = thing->y + thing->radius; x2 = thing->x + thing->radius; y2 = thing->y - thing->radius; } else { x1 = thing->x - thing->radius; y1 = thing->y - thing->radius; x2 = thing->x + thing->radius; y2 = thing->y + thing->radius; } s1 = P_PointOnDivlineSide (x1, y1, &trace); s2 = P_PointOnDivlineSide (x2, y2, &trace); if (s1 == s2) return true; // line isn't crossed dl.x = x1; dl.y = y1; dl.dx = x2-x1; dl.dy = y2-y1; frac = P_InterceptVector (&trace, &dl); if (frac < 0) return true; // behind source P_CheckIntercepts(); intercept_p->frac = frac; intercept_p->isaline = false; intercept_p->d.thing = thing; intercept_p++; return true; // keep going}//// P_TraverseIntercepts// Returns true if the traverser function returns true// for all lines.//boolean P_TraverseIntercepts ( traverser_t func, fixed_t maxfrac ){ int count; fixed_t dist; intercept_t* scan; intercept_t* in; count = intercept_p - intercepts; in = 0; // shut up compiler warning while (count--) { dist = MAXINT; for (scan = intercepts ; scan<intercept_p ; scan++) { if (scan->frac < dist) { dist = scan->frac; in = scan; } } if (dist > maxfrac) return true; // checked everything in range#if 0 // UNUSED { // don't check these yet, there may be others inserted in = scan = intercepts; for ( scan = intercepts ; scan<intercept_p ; scan++) if (scan->frac > maxfrac) *in++ = *scan; intercept_p = in; return false; }#endif // appelle la fonction en commencant par l' intercept_t le plus // proche if ( !func (in) ) return false; // don't bother going farther in->frac = MAXINT; } return true; // everything was traversed}//// P_PathTraverse// Traces a line from x1,y1 to x2,y2,// calling the traverser function for each.// Returns true if the traverser function returns true// for all lines.//boolean P_PathTraverse ( fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, traverser_t trav){ fixed_t xt1; fixed_t yt1; fixed_t xt2; fixed_t yt2; fixed_t xstep; fixed_t ystep; fixed_t partial; fixed_t xintercept; fixed_t yintercept; int mapx; int mapy; int mapxstep; int mapystep; int count; earlyout = flags & PT_EARLYOUT; validcount++; intercept_p = intercepts; if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) x1 += FRACUNIT; // don't side exactly on a line if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) y1 += FRACUNIT; // don't side exactly on a line trace.x = x1; trace.y = y1; trace.dx = x2 - x1; trace.dy = y2 - y1; x1 -= bmaporgx; y1 -= bmaporgy; xt1 = x1>>MAPBLOCKSHIFT; yt1 = y1>>MAPBLOCKSHIFT; x2 -= bmaporgx; y2 -= bmaporgy; xt2 = x2>>MAPBLOCKSHIFT; yt2 = y2>>MAPBLOCKSHIFT; if (xt2 > xt1) { mapxstep = 1; partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); ystep = FixedDiv (y2-y1,abs(x2-x1)); } else if (xt2 < xt1) { mapxstep = -1; partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); ystep = FixedDiv (y2-y1,abs(x2-x1)); } else { mapxstep = 0; partial = FRACUNIT; ystep = 256*FRACUNIT; } yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep); if (yt2 > yt1) { mapystep = 1; partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); xstep = FixedDiv (x2-x1,abs(y2-y1)); } else if (yt2 < yt1) { mapystep = -1; partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); xstep = FixedDiv (x2-x1,abs(y2-y1)); } else { mapystep = 0; partial = FRACUNIT; xstep = 256*FRACUNIT; } xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep); // Step through map blocks. // Count is present to prevent a round off error // from skipping the break. mapx = xt1; mapy = yt1; for (count = 0 ; count < 64 ; count++) { if (flags & PT_ADDLINES) { if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts)) return false; // early out } if (flags & PT_ADDTHINGS) { if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts)) return false; // early out } if (mapx == xt2 && mapy == yt2) { break; } if ( (yintercept >> FRACBITS) == mapy) { yintercept += ystep; mapx += mapxstep; } else if ( (xintercept >> FRACBITS) == mapx) { xintercept += xstep; mapy += mapystep; } } // go through the sorted list return P_TraverseIntercepts ( trav, FRACUNIT );}// =========================================================================// BLOCKMAP ITERATORS// =========================================================================// blockmap iterator for all sorts of use// your routine must return FALSE to exit the loop earlier// returns FALSE if the loop exited early after a false return// value from your user function//abandoned, maybe I'll need it someday.. /*boolean P_RadiusLinesCheck ( fixed_t radius, fixed_t x, fixed_t y, boolean (*func)(line_t*)){ int xl, xh, yl, yh; int bx, by; tmbbox[BOXTOP] = y + radius; tmbbox[BOXBOTTOM] = y - radius; tmbbox[BOXRIGHT] = x + radius; tmbbox[BOXLEFT] = x - radius; // 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,func)) return false; return true;}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -