From: Ketmar Dark Date: Tue, 29 Aug 2017 15:42:35 +0000 (+0300) Subject: some fixes for recursive grid queries (grid doesn't support recursive queries, but... X-Git-Url: https://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=commitdiff_plain;h=836fd31457a6f741815605633f2fbfa157e37418 some fixes for recursive grid queries (grid doesn't support recursive queries, but triggers can try that) --- diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index b4b0e32..3467702 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -102,6 +102,7 @@ type mProxyFree: TBodyProxyId; // free mProxyCount: Integer; // currently used mProxyMaxCount: Integer; + mInQuery: Boolean; public dbgShowTraceLog: Boolean; @@ -1235,6 +1236,9 @@ begin if (x+w <= 0) or (y+h <= 0) then exit; if (x >= gw*tsize) or (y >= mHeight*tsize) then exit; + if mInQuery then raise Exception.Create('recursive queries aren''t supported'); + mInQuery := true; + // increase query counter Inc(mLastQuery); if (mLastQuery = 0) then @@ -1274,11 +1278,12 @@ begin if (x0+w <= px.mX) or (y0+h <= px.mY) then continue; if assigned(cb) then begin - if cb(px.mObj, ptag) then begin result := px.mObj; exit; end; + if cb(px.mObj, ptag) then begin result := px.mObj; mInQuery := false; exit; end; end else begin result := px.mObj; + mInQuery := false; exit; end; end; @@ -1286,6 +1291,8 @@ begin end; end; end; + + mInQuery := false; end; @@ -1552,6 +1559,9 @@ begin //if (dbgShowTraceLog) then e_WriteLog(Format('raycast start: (%d,%d)-(%d,%d); xptr^=%d; yptr^=%d', [ax0, ay0, ax1, ay1, xptr^, yptr^]), MSG_NOTIFY); + if mInQuery then raise Exception.Create('recursive queries aren''t supported'); + mInQuery := true; + // increase query counter Inc(mLastQuery); if (mLastQuery = 0) then @@ -1629,6 +1639,7 @@ begin result := px.mObj; ex := x; ey := y; + mInQuery := false; exit; end; end @@ -1643,6 +1654,7 @@ begin ex := x; ey := y; result := px.mObj; + mInQuery := false; exit; end; end; @@ -1697,6 +1709,7 @@ begin result := px.mObj; ex := prevx; ey := prevy; + mInQuery := false; exit; end; end @@ -1720,8 +1733,8 @@ begin // next cell ccidx := cc.next; end; - if wasHit and not assigned(cb) then begin result := lastObj; exit; end; - if assigned(cb) and cb(nil, 0, x, y, x, y) then begin result := lastObj; exit; end; + if wasHit and not assigned(cb) then begin result := lastObj; mInQuery := false; exit; end; + if assigned(cb) and cb(nil, 0, x, y, x, y) then begin result := lastObj; mInQuery := false; exit; end; end; // skip to next tile if hopt then @@ -1778,6 +1791,7 @@ begin end; // we can travel less than one cell if wasHit and not assigned(cb) then result := lastObj else begin ex := ax1; ey := ay1; end; + mInQuery := false; exit; end; {$ENDIF} @@ -1811,11 +1825,12 @@ begin // signal cell completion if assigned(cb) then begin - if cb(nil, 0, xptr^+minx, yptr^+miny, prevx, prevy) then begin result := lastObj; exit; end; + if cb(nil, 0, xptr^+minx, yptr^+miny, prevx, prevy) then begin result := lastObj; mInQuery := false; exit; end; end else if wasHit then begin result := lastObj; + mInQuery := false; exit; end; end; @@ -1853,6 +1868,7 @@ begin result := px.mObj; ex := prevx; ey := prevy; + mInQuery := false; exit; end; end @@ -1890,11 +1906,12 @@ begin ccidx := -1; if assigned(cb) then begin - if cb(nil, 0, x, y, prevx, prevy) then begin result := lastObj; exit; end; + if cb(nil, 0, x, y, prevx, prevy) then begin result := lastObj; mInQuery := false; exit; end; end else if wasHit then begin result := lastObj; + mInQuery := false; exit; end; end; @@ -1933,6 +1950,8 @@ begin ex := ax1; // why not? ey := ay1; // why not? end; + + mInQuery := false; end; @@ -2143,6 +2162,9 @@ begin //lastGA := (yptr^ div tsize)*gw+(xptr^ div tsize); //ccidx := mGrid[lastGA]; + if mInQuery then raise Exception.Create('recursive queries aren''t supported'); + mInQuery := true; + // increase query counter Inc(mLastQuery); if (mLastQuery = 0) then @@ -2205,11 +2227,12 @@ begin px.mQueryMark := lq; // mark as processed if assigned(cb) then begin - if cb(px.mObj, ptag) then begin result := px.mObj; exit; end; + if cb(px.mObj, ptag) then begin result := px.mObj; mInQuery := false; exit; end; end else begin result := px.mObj; + mInQuery := false; exit; end; end; @@ -2271,6 +2294,7 @@ begin end; Dec(wklen, wkstep); end; + mInQuery := false; exit; end; {$ENDIF} @@ -2323,11 +2347,12 @@ begin px.mQueryMark := lq; // mark as processed if assigned(cb) then begin - if cb(px.mObj, ptag) then begin result := px.mObj; exit; end; + if cb(px.mObj, ptag) then begin result := px.mObj; mInQuery := false; exit; end; end else begin result := px.mObj; + mInQuery := false; exit; end; end; @@ -2357,6 +2382,8 @@ begin if (e >= 0) then begin yd += sty; e -= dx2; end else e += dy2; xd += stx; end; + + mInQuery := false; end; diff --git a/src/game/g_items.pas b/src/game/g_items.pas index dffeb96..672e481 100644 --- a/src/game/g_items.pas +++ b/src/game/g_items.pas @@ -892,16 +892,17 @@ begin it := @ggItems[f]; if not it.Live then continue; case it.ItemType of - ITEM_KEY_RED: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 1.0, 0.0, 0.0, 0.6); - ITEM_KEY_GREEN: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 0.0, 1.0, 0.0, 0.6); - ITEM_KEY_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 0.0, 0.0, 1.0, 0.6); + ITEM_KEY_RED: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 24, 1.0, 0.0, 0.0, 0.6); + ITEM_KEY_GREEN: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 24, 0.0, 1.0, 0.0, 0.6); + ITEM_KEY_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 24, 0.0, 0.0, 1.0, 0.6); ITEM_ARMOR_GREEN: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 42, 0.0, 1.0, 0.0, 0.6); ITEM_ARMOR_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 42, 0.0, 0.0, 1.0, 0.6); ITEM_SPHERE_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 0.0, 1.0, 0.0, 0.6); ITEM_SPHERE_WHITE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 1.0, 1.0, 1.0, 0.6); ITEM_INVUL: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 1.0, 0.0, 0.0, 0.6); ITEM_INVIS: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 1.0, 1.0, 0.0, 0.6); - ITEM_BOTTLE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32, 0.0, 0.0, 1.0, 0.6); + ITEM_BOTTLE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 16, 0.0, 0.0, 0.8, 0.6); + ITEM_HELMET: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 16, 0.0, 0.8, 0.0, 0.6); end; end; end; diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 681e182..4f86e9b 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -1359,12 +1359,16 @@ begin SetLength(s, 64); CopyMemory(@s[1], @_textures[a].Resource[0], 64); for b := 1 to Length(s) do + begin if s[b] = #0 then begin SetLength(s, b-1); Break; end; + end; + {$IF DEFINED(D2F_DEBUG)} e_WriteLog(Format(' Loading texture #%d: %s', [a, s]), MSG_NOTIFY); + {$ENDIF} //if g_Map_IsSpecialTexture(s) then e_WriteLog(' SPECIAL!', MSG_NOTIFY); // Àíèìèðîâàííàÿ òåêñòóðà: if ByteBool(_textures[a].Anim) then diff --git a/src/game/g_triggers.pas b/src/game/g_triggers.pas index e39b8c6..3b1f911 100644 --- a/src/game/g_triggers.pas +++ b/src/game/g_triggers.pas @@ -101,7 +101,7 @@ uses g_player, g_map, Math, g_gfx, g_game, g_textures, g_console, g_monsters, g_items, g_phys, g_weapons, wadreader, g_main, SysUtils, e_log, g_language, - g_options, g_net, g_netmsg; + g_options, g_net, g_netmsg, utils; const TRIGGER_SIGNATURE = $52475254; // 'TRGR' @@ -2196,29 +2196,34 @@ begin Result := find_id; end; + +// sorry; grid doesn't support recursive queries, so we have to do this +type + TSimpleMonsterList = specialize TSimpleList; + +var + tgMonsList: TSimpleMonsterList = nil; + procedure g_Triggers_Update(); var a, b, i: Integer; Affected: array of Integer; - {function monsNear (mon: TMonster): Boolean; - begin - result := false; // don't stop - if mon.Collide(gTriggers[a].X, gTriggers[a].Y, gTriggers[a].Width, gTriggers[a].Height) then - begin - gTriggers[a].ActivateUID := mon.UID; - ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE); - end; - end;} - function monsNear (mon: TMonster): Boolean; begin result := false; // don't stop + { gTriggers[a].ActivateUID := mon.UID; ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE); + } + tgMonsList.append(mon); end; +var + mon: TMonster; begin + if (tgMonsList = nil) then tgMonsList := TSimpleMonsterList.Create(); + if gTriggers = nil then Exit; SetLength(Affected, 0); @@ -2454,7 +2459,14 @@ begin begin //g_Mons_ForEach(monsNear); //Alive?! + tgMonsList.reset(); g_Mons_ForEachAt(gTriggers[a].X, gTriggers[a].Y, gTriggers[a].Width, gTriggers[a].Height, monsNear); + for mon in tgMonsList do + begin + gTriggers[a].ActivateUID := mon.UID; + ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE); + end; + tgMonsList.reset(); // just in case end; // "Ìîíñòðîâ íåò" diff --git a/src/shared/utils.pas b/src/shared/utils.pas index c182da1..49408d7 100644 --- a/src/shared/utils.pas +++ b/src/shared/utils.pas @@ -139,9 +139,125 @@ function digitInBase (ch: AnsiChar; base: Integer): Integer; function quoteStr (const s: AnsiString): AnsiString; +type + generic TSimpleList = class + private + type PItemT = ^ItemT; + + public + type + TEnumerator = record + private + mItems: PItemT; + mCount: Integer; + mCurrent: Integer; + public + constructor Create (aitems: PItemT; acount: Integer); + function MoveNext: Boolean; + function getCurrent (): ItemT; + property Current: ItemT read getCurrent; + end; + + private + mItems: array of ItemT; + mCount: Integer; // can be less than `mItems` size + + private + function getAt (idx: Integer): ItemT; inline; + + public + constructor Create (); + destructor Destroy (); override; + + function GetEnumerator (): TEnumerator; + + procedure reset (); inline; // won't resize `mItems` + procedure clear (); inline; + + procedure append (constref it: ItemT); inline; + + public + property count: Integer read mCount; + property at[idx: Integer]: ItemT read getAt; default; + end; + + implementation +// ////////////////////////////////////////////////////////////////////////// // +constructor TSimpleList.TEnumerator.Create (aitems: PItemT; acount: Integer); +begin + mItems := aitems; + mCount := acount; + mCurrent := -1; +end; + +function TSimpleList.TEnumerator.MoveNext: Boolean; +begin + Inc(mCurrent); + result := (mCurrent < mCount); +end; + +function TSimpleList.TEnumerator.getCurrent (): ItemT; +begin + result := mItems[mCurrent]; +end; + + +// ////////////////////////////////////////////////////////////////////////// // +constructor TSimpleList.Create (); +begin + mItems := nil; + mCount := 0; +end; + + +destructor TSimpleList.Destroy (); +begin + mItems := nil; + inherited; +end; + + +function TSimpleList.GetEnumerator (): TEnumerator; +begin + if (Length(mItems) > 0) then result := TEnumerator.Create(@mItems[0], mCount) + else result := TEnumerator.Create(nil, -1); +end; + + +procedure TSimpleList.reset (); inline; +begin + mCount := 0; +end; + + +procedure TSimpleList.clear (); inline; +begin + mItems := nil; + mCount := 0; +end; + + +function TSimpleList.getAt (idx: Integer): ItemT; inline; +begin + if (idx >= 0) and (idx < mCount) then result := mItems[idx] else result := Default(ItemT); +end; + + +procedure TSimpleList.append (constref it: ItemT); inline; +begin + if (mCount = Length(mItems)) then + begin + if (mCount = 0) then SetLength(mItems, 128) else SetLength(mItems, mCount*2); + end; + mItems[mCount] := it; + Inc(mCount); +end; + + +// ////////////////////////////////////////////////////////////////////////// // var wc2shitmap: array[0..65535] of AnsiChar; wc2shitmapInited: Boolean = false;