DEADSOFTWARE

fixed passing thru disabled walls
[d2df-sdl.git] / src / game / g_map.pas
index 7d13205d096c4f0e259fb3411d137dab0f01e917..bbe1d6c3c7dc535a53ed9b84e1ffd31d84e459c1 100644 (file)
@@ -93,7 +93,7 @@ procedure g_Map_LoadState(Var Mem: TBinMemoryReader);
 procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius: Integer);
 
 // returns wall index in `gWalls` or -1
-function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Boolean;
+function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
 
 type
   TForEachPanelCB = function (pan: TPanel): Boolean; // return `true` to stop
@@ -184,9 +184,17 @@ var
   profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
   gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
 
+
 function panelTypeToTag (panelType: Word): Integer; // returns GridTagXXX
 
 
+type
+  TPanelGrid = specialize TBodyGridBase<TPanel>;
+
+var
+  mapGrid: TPanelGrid = nil;
+
+
 implementation
 
 uses
@@ -204,10 +212,6 @@ const
   FLAG_SIGNATURE = $47414C46; // 'FLAG'
 
 
-type
-  TPanelGrid = specialize TBodyGridBase<TPanel>;
-
-
 function panelTypeToTag (panelType: Word): Integer;
 begin
   case panelType of
@@ -255,7 +259,6 @@ var
   RespawnPoints: Array of TRespawnPoint;
   FlagPoints:    Array [FLAG_RED..FLAG_BLUE] of PFlagPoint;
   //DOMFlagPoints: Array of TFlagPoint;
-  mapGrid: TPanelGrid = nil;
 
 
 procedure g_Map_ProfilersBegin ();
@@ -279,11 +282,21 @@ end;
 
 
 // wall index in `gWalls` or -1
-function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Boolean;
+function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): TPanel;
 var
   ex, ey: Integer;
 begin
-  result := (mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, (GridTagWall or GridTagDoor)) <> nil);
+  result := mapGrid.traceRay(ex, ey, x0, y0, x1, y1, nil, (GridTagWall or GridTagDoor));
+  if (result <> nil) then
+  begin
+    if (hitx <> nil) then hitx^ := ex;
+    if (hity <> nil) then hity^ := ey;
+  end
+  else
+  begin
+    if (hitx <> nil) then hitx^ := x1;
+    if (hity <> nil) then hity^ := y1;
+  end;
 end;
 
 
@@ -1111,25 +1124,49 @@ var
     end;
   end;
 
-  procedure addPanelsToGrid (constref panels: TPanelArray; tag: Integer);
+  procedure addPanelsToGrid (constref panels: TPanelArray);
   var
     idx: Integer;
     pan: TPanel;
+    newtag: Integer;
   begin
-    tag := panelTypeToTag(tag);
-    for idx := High(panels) downto 0 do
+    //tag := panelTypeToTag(tag);
+    for idx := 0 to High(panels) do
     begin
       pan := panels[idx];
-      pan.tag := tag;
       if not pan.visvalid then continue;
-      pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, tag);
+      if (pan.proxyId <> -1) then
+      begin
+        {$IF DEFINED(D2F_DEBUG)}
+        e_WriteLog(Format('DUPLICATE wall #%d(%d) enabled (%d); type:%08x', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.PanelType]), MSG_NOTIFY);
+        {$ENDIF}
+        continue;
+      end;
+      case pan.PanelType of
+        PANEL_WALL: newtag := GridTagWall;
+        PANEL_OPENDOOR, PANEL_CLOSEDOOR: newtag := GridTagDoor;
+        PANEL_BACK: newtag := GridTagBack;
+        PANEL_FORE: newtag := GridTagFore;
+        PANEL_WATER: newtag := GridTagWater;
+        PANEL_ACID1: newtag := GridTagAcid1;
+        PANEL_ACID2: newtag := GridTagAcid2;
+        PANEL_STEP: newtag := GridTagStep;
+        PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: newtag := GridTagLift;
+        PANEL_BLOCKMON: newtag := GridTagBlockMon;
+        else continue; // oops
+      end;
+      pan.tag := newtag;
+
+      pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, newtag);
       // "enabled" flag has meaning only for doors and walls (engine assumes it); but meh...
       mapGrid.proxyEnabled[pan.proxyId] := pan.Enabled;
       {$IFDEF MAP_DEBUG_ENABLED_FLAG}
+      {
       if ((tag and (GridTagWall or GridTagDoor)) <> 0) then
       begin
         e_WriteLog(Format('INSERTED wall #%d(%d) enabled (%d)', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId])]), MSG_NOTIFY);
       end;
+      }
       {$ENDIF}
     end;
   end;
@@ -1148,21 +1185,25 @@ begin
   calcBoundingBox(gLifts);
   calcBoundingBox(gBlockMon);
 
-  e_WriteLog(Format('map dimensions: (%d,%d)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1]), MSG_WARNING);
+  e_WriteLog(Format('map dimensions: (%d,%d)-(%d,%d); editor size:(0,0)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1, gMapInfo.Width, gMapInfo.Height]), MSG_WARNING);
+
+  if (mapX0 > 0) then mapX0 := 0;
+  if (mapY0 > 0) then mapY0 := 0;
+
+  if (mapX1 < gMapInfo.Width-1) then mapX1 := gMapInfo.Width-1;
+  if (mapY1 < gMapInfo.Height-1) then mapY1 := gMapInfo.Height-1;
 
-  mapGrid := TPanelGrid.Create(mapX0-512, mapY0-512, mapX1-mapX0+1+512*2, mapY1-mapY0+1+512*2);
+  mapGrid := TPanelGrid.Create(mapX0-128, mapY0-128, mapX1-mapX0+1+128*2, mapY1-mapY0+1+128*2);
 
-  addPanelsToGrid(gWalls, PANEL_WALL);
-  addPanelsToGrid(gWalls, PANEL_CLOSEDOOR);
-  addPanelsToGrid(gWalls, PANEL_OPENDOOR);
-  addPanelsToGrid(gRenderBackgrounds, PANEL_BACK);
-  addPanelsToGrid(gRenderForegrounds, PANEL_FORE);
-  addPanelsToGrid(gWater, PANEL_WATER);
-  addPanelsToGrid(gAcid1, PANEL_ACID1);
-  addPanelsToGrid(gAcid2, PANEL_ACID2);
-  addPanelsToGrid(gSteps, PANEL_STEP);
-  addPanelsToGrid(gLifts, PANEL_LIFTUP); // it doesn't matter which LIFT type is used here
-  addPanelsToGrid(gBlockMon, PANEL_BLOCKMON);
+  addPanelsToGrid(gWalls);
+  addPanelsToGrid(gRenderBackgrounds);
+  addPanelsToGrid(gRenderForegrounds);
+  addPanelsToGrid(gWater);
+  addPanelsToGrid(gAcid1);
+  addPanelsToGrid(gAcid2);
+  addPanelsToGrid(gSteps);
+  addPanelsToGrid(gLifts); // it doesn't matter which LIFT type is used here
+  addPanelsToGrid(gBlockMon);
 
   mapGrid.dumpStats();
 
@@ -1257,6 +1298,22 @@ begin
     _textures := MapReader.GetTextures();
     _texnummap := nil;
 
+  // Çàãðóçêà îïèñàíèÿ êàðòû:
+    e_WriteLog('  Reading map info...', MSG_NOTIFY);
+    g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
+    Header := MapReader.GetMapHeader();
+
+    with gMapInfo do
+    begin
+      Name := Header.MapName;
+      Description := Header.MapDescription;
+      Author := Header.MapAuthor;
+      MusicName := Header.MusicName;
+      SkyName := Header.SkyName;
+      Height := Header.Height;
+      Width := Header.Width;
+    end;
+
   // Äîáàâëåíèå òåêñòóð â Textures[]:
     if _textures <> nil then
     begin
@@ -1516,7 +1573,6 @@ begin
     e_WriteLog('Creating map grid', MSG_NOTIFY);
     mapCreateGrid();
 
-
   // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû:
     if (triggers <> nil) and not gLoadGameMode then
     begin
@@ -1582,24 +1638,8 @@ begin
         CreateMonster(monsters[a]);
     end;
 
-  // Çàãðóçêà îïèñàíèÿ êàðòû:
-    e_WriteLog('  Reading map info...', MSG_NOTIFY);
-    g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
-    Header := MapReader.GetMapHeader();
-
     MapReader.Free();
 
-    with gMapInfo do
-    begin
-      Name := Header.MapName;
-      Description := Header.MapDescription;
-      Author := Header.MapAuthor;
-      MusicName := Header.MusicName;
-      SkyName := Header.SkyName;
-      Height := Header.Height;
-      Width := Header.Width;
-    end;
-
   // Çàãðóçêà íåáà:
     if gMapInfo.SkyName <> '' then
     begin
@@ -2013,7 +2053,7 @@ begin
   end
   else}
   begin
-    mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask, true);
+    mapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, GridDrawableMask);
   end;
   // list will be rendered in `g_game.DrawPlayer()`
 end;
@@ -2034,7 +2074,7 @@ begin
   end
   else}
   begin
-    mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor), true);
+    mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
   end;
 end;
 
@@ -2370,7 +2410,7 @@ begin
   if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(gWalls[ID].PanelType, ID);
 
   {$IFDEF MAP_DEBUG_ENABLED_FLAG}
-  e_WriteLog(Format('wall #%d(%d) enabled (%d)  (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY);
+  //e_WriteLog(Format('ENABLE: wall #%d(%d) enabled (%d)  (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY);
   {$ENDIF}
 end;
 
@@ -2388,7 +2428,7 @@ begin
   if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pan.PanelType, ID);
 
   {$IFDEF MAP_DEBUG_ENABLED_FLAG}
-  e_WriteLog(Format('wall #%d(%d) disabled (%d)  (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY);
+  //e_WriteLog(Format('DISABLE: wall #%d(%d) disabled (%d)  (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY);
   {$ENDIF}
 end;