X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_grid.pas;h=19c4d0d2ca8f31fc39170217693375c3d8cc5de2;hb=a17222535319cb4089e3f9a92711731c015819b3;hp=b1b157f8d3c685b3b65d457ed5620051d2bbb4dc;hpb=df5fff669125c1fbd1324ce02a0afe28612f1ddc;p=d2df-sdl.git diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index b1b157f..19c4d0d 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -17,6 +17,7 @@ {$INCLUDE ../shared/a_modes.inc} {$IF DEFINED(D2F_DEBUG)} {.$DEFINE D2F_DEBUG_RAYTRACE} + {.$DEFINE D2F_DEBUG_XXQ} {$ENDIF} unit g_grid; @@ -142,12 +143,14 @@ type // you can set enabled/disabled flag, tho (but iterator can still return objects disabled inside it) // cb with `(nil)` will be called before processing new tile // no callback: return `true` on the nearest hit + //WARNING: don't change tags in callbacks here! function traceRay (const x0, y0, x1, y1: Integer; cb: TGridRayQueryCB; tagmask: Integer=-1): ITP; overload; function traceRay (out ex, ey: Integer; const ax0, ay0, ax1, ay1: Integer; cb: TGridRayQueryCB; tagmask: Integer=-1): ITP; //WARNING: don't modify grid while any query is in progress (no checks are made!) // you can set enabled/disabled flag, tho (but iterator can still return objects disabled inside it) // trace line along the grid, calling `cb` for all objects in passed cells, in no particular order + //WARNING: don't change tags in callbacks here! function forEachAlongLine (const x0, y0, x1, y1: Integer; cb: TGridAlongQueryCB; tagmask: Integer=-1; log: Boolean=false): ITP; // debug @@ -675,22 +678,42 @@ begin pc := mGrid[grida]; if (pc <> -1) then begin - pi := @mCells[pc]; - // check "has room" flag - if (pi.bodies[GridCellBucketSize-1] = -1) then + {$IF DEFINED(D2F_DEBUG)} + cidx := pc; + while (cidx <> -1) do begin - // can add here + pi := @mCells[cidx]; for f := 0 to GridCellBucketSize-1 do begin - if (pi.bodies[f] = -1) then + if (pi.bodies[f] = -1) then break; + if (pi.bodies[f] = bodyId) then raise Exception.Create('trying to insert already inserted proxy'); + end; + cidx := pi.next; + end; + {$ENDIF} + cidx := pc; + while (cidx <> -1) do + begin + pi := @mCells[cidx]; + // check "has room" flag + if (pi.bodies[GridCellBucketSize-1] = -1) then + begin + // can add here + for f := 0 to GridCellBucketSize-1 do begin - pi.bodies[f] := bodyId; - if (f+1 < GridCellBucketSize) then pi.bodies[f+1] := -1; - exit; + if (pi.bodies[f] = -1) then + begin + pi.bodies[f] := bodyId; + if (f+1 < GridCellBucketSize) then pi.bodies[f+1] := -1; + exit; + end; end; + raise Exception.Create('internal error in grid inserter'); end; - raise Exception.Create('internal error in grid inserter'); + // no room, go to next cell in list (if there is any) + cidx := pi.next; end; + // no room in cells, add new cell to list end; // either no room, or no cell at all cidx := allocCell(); @@ -975,12 +998,21 @@ begin tagmask := tagmask and TagFullMask; if (tagmask = 0) then exit; + {$IF DEFINED(D2F_DEBUG_XXQ)} + if (assigned(cb)) then e_WriteLog(Format('0: grid pointquery: (%d,%d)', [x, y]), MSG_NOTIFY); + {$ENDIF} + // make coords (0,0)-based Dec(x, mMinX); Dec(y, mMinY); if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then exit; curci := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)]; + + {$IF DEFINED(D2F_DEBUG_XXQ)} + if (assigned(cb)) then e_WriteLog(Format('1: grid pointquery: (%d,%d) (%d,%d) %d', [x, y, (x div mTileSize), (y div mTileSize), curci]), MSG_NOTIFY); + {$ENDIF} + // restore coords Inc(x, mMinX); Inc(y, mMinY); @@ -995,19 +1027,31 @@ begin end; lq := mLastQuery; + {$IF DEFINED(D2F_DEBUG_XXQ)} + if (assigned(cb)) then e_WriteLog(Format('2: grid pointquery: (%d,%d); lq=%u', [x, y, lq]), MSG_NOTIFY); + {$ENDIF} + while (curci <> -1) do begin + {$IF DEFINED(D2F_DEBUG_XXQ)} + if (assigned(cb)) then e_WriteLog(Format(' cell #%d', [curci]), MSG_NOTIFY); + {$ENDIF} cc := @mCells[curci]; for f := 0 to GridCellBucketSize-1 do begin if (cc.bodies[f] = -1) then break; px := @mProxies[cc.bodies[f]]; - ptag := px.mTag; - if ((ptag and TagDisabled) = 0) and ((ptag and tagmask) <> 0) and (px.mQueryMark <> lq) then + {$IF DEFINED(D2F_DEBUG_XXQ)} + if (assigned(cb)) then e_WriteLog(Format(' proxy #%d; qm:%u; tag:%08x; tagflag:%d %u', [cc.bodies[f], px.mQueryMark, px.mTag, (px.mTag and tagmask), LongWord(px.mObj)]), MSG_NOTIFY); + {$ENDIF} + // shit. has to do it this way, so i can change tag in callback + if (px.mQueryMark <> lq) then begin - if (x >= px.mX) and (y >= px.mY) and (x < px.mX+px.mWidth) and (y < px.mY+px.mHeight) then + px.mQueryMark := lq; + ptag := px.mTag; + if ((ptag and TagDisabled) = 0) and ((ptag and tagmask) <> 0) and + (x >= px.mX) and (y >= px.mY) and (x < px.mX+px.mWidth) and (y < px.mY+px.mHeight) then begin - px.mQueryMark := lq; if assigned(cb) then begin if cb(px.mObj, ptag) then begin result := px.mObj; exit; end; @@ -1089,24 +1133,22 @@ begin begin if (cc.bodies[f] = -1) then break; px := @mProxies[cc.bodies[f]]; + // shit. has to do it this way, so i can change tag in callback + if (px.mQueryMark = lq) then continue; + px.mQueryMark := lq; ptag := px.mTag; if (not allowDisabled) and ((ptag and TagDisabled) <> 0) then continue; - if ((ptag and tagmask) <> 0) and (px.mQueryMark <> lq) then - //if ((ptag and TagDisabled) = 0) and ((ptag and tagmask) <> 0) and (px.mQueryMark <> lq) then - //if ( ((ptag and TagDisabled) = 0) = ignoreDisabled) and ((ptag and tagmask) <> 0) and (px.mQueryMark <> lq) then + if ((ptag and tagmask) = 0) then continue; + if (x0 >= px.mX+px.mWidth) or (y0 >= px.mY+px.mHeight) then continue; + if (x0+w <= px.mX) or (y0+h <= px.mY) then continue; + if assigned(cb) then begin - if (x0 >= px.mX+px.mWidth) or (y0 >= px.mY+px.mHeight) then continue; - if (x0+w <= px.mX) or (y0+h <= px.mY) then continue; - px.mQueryMark := lq; - if assigned(cb) then - begin - if cb(px.mObj, ptag) then begin result := px.mObj; exit; end; - end - else - begin - result := px.mObj; - exit; - end; + if cb(px.mObj, ptag) then begin result := px.mObj; exit; end; + end + else + begin + result := px.mObj; + exit; end; end; curci := cc.next;