DEADSOFTWARE

added optional framebuffer and resolution scaling
[d2df-sdl.git] / src / game / g_holmes.pas
index 9c846abac45201b6e72b6a3a18c73db5d5ed8985..c173bd00312e9686a7e4cb9df0165251e0de4ce4 100644 (file)
@@ -1,9 +1,8 @@
-(* Copyright (C)  DooM 2D:Forever Developers
+(* Copyright (C)  Doom 2D: Forever Developers
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 3 of the License ONLY.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,7 +18,7 @@ unit g_holmes;
 interface
 
 uses
-  {$IFDEF USE_MEMPOOL}mempool,{$ENDIF} geom,
+  mempool, geom,
   e_log, e_input,
   g_textures, g_basic, e_graphics, g_phys, g_grid, g_player, g_monsters,
   g_window, g_map, g_triggers, g_items, g_game, g_panel, g_console, g_gfx,
@@ -48,8 +47,9 @@ var
 implementation
 
 uses
-  {rttiobj,} typinfo, e_texture,
-  SysUtils, Classes, GL, SDL2,
+  {$INCLUDE ../nogl/noGLuses.inc}
+  {rttiobj,} typinfo, e_texture, e_res,
+  SysUtils, Classes, SDL2,
   MAPDEF, g_main, g_options,
   utils, hashtable, xparser;
 
@@ -200,7 +200,7 @@ procedure createHelpWindow ();
       box.appendChild(stx);
       // span
       span := TUISpan.Create();
-      span.flDefaultSize := TLaySize.Create(4, 1);
+      span.flDefaultSize := TLaySize.Create(12, 1);
       span.flExpand := true;
       box.appendChild(span);
       // text
@@ -559,7 +559,7 @@ var
 
   procedure clearEdgeBmp ();
   begin
-    SetLength(edgeBmp, (gWinSizeX+4)*(gWinSizeY+4));
+    SetLength(edgeBmp, (gScreenWidth+4)*(gScreenHeight+4));
     FillChar(edgeBmp[0], Length(edgeBmp)*sizeof(edgeBmp[0]), 0);
   end;
 
@@ -574,19 +574,19 @@ var
     begin
       sx := pan.X-(vpx-1);
       len := pan.Width;
-      if (len > gWinSizeX+4) then len := gWinSizeX+4;
+      if (len > gScreenWidth+4) then len := gScreenWidth+4;
       if (sx < 0) then begin len += sx; sx := 0; end;
-      if (sx+len > gWinSizeX+4) then len := gWinSizeX+4-sx;
+      if (sx+len > gScreenWidth+4) then len := gScreenWidth+4-sx;
       if (len < 1) then exit;
       assert(sx >= 0);
-      assert(sx+len <= gWinSizeX+4);
+      assert(sx+len <= gScreenWidth+4);
       y0 := pan.Y-(vpy-1);
       y1 := y0+pan.Height;
       if (y0 < 0) then y0 := 0;
-      if (y1 > gWinSizeY+4) then y1 := gWinSizeY+4;
+      if (y1 > gScreenHeight+4) then y1 := gScreenHeight+4;
       while (y0 < y1) do
       begin
-        FillChar(edgeBmp[y0*(gWinSizeX+4)+sx], len*sizeof(edgeBmp[0]), 1);
+        FillChar(edgeBmp[y0*(gScreenWidth+4)+sx], len*sizeof(edgeBmp[0]), 1);
         Inc(y0);
       end;
     end
@@ -651,15 +651,15 @@ var
     glColor4f(r/255.0, g/255.0, b/255.0, 1.0);
     for y := 1 to vph do
     begin
-      a := @edgeBmp[y*(gWinSizeX+4)+1];
+      a := @edgeBmp[y*(gScreenWidth+4)+1];
       startLine(y);
       for x := 1 to vpw do
       begin
         if (a[0] <> 0) then
         begin
-          if (a[-1] = 0) or (a[1] = 0) or (a[-(gWinSizeX+4)] = 0) or (a[gWinSizeX+4] = 0) or
-             (a[-(gWinSizeX+4)-1] = 0) or (a[-(gWinSizeX+4)+1] = 0) or
-             (a[gWinSizeX+4-1] = 0) or (a[gWinSizeX+4+1] = 0) then
+          if (a[-1] = 0) or (a[1] = 0) or (a[-(gScreenWidth+4)] = 0) or (a[gScreenWidth+4] = 0) or
+             (a[-(gScreenWidth+4)-1] = 0) or (a[-(gScreenWidth+4)+1] = 0) or
+             (a[gScreenWidth+4-1] = 0) or (a[gScreenWidth+4+1] = 0) then
           begin
             putPixel(x);
           end;
@@ -684,7 +684,7 @@ var
     glColor4f(r/255.0, g/255.0, b/255.0, 1.0);
     for y := 1 to vph do
     begin
-      a := @edgeBmp[y*(gWinSizeX+4)+1];
+      a := @edgeBmp[y*(gScreenWidth+4)+1];
       startLine(y);
       for x := 1 to vpw do
       begin
@@ -951,7 +951,7 @@ procedure plrDebugDraw ();
     pdy := pmsCurMapY-(py+ph div 2);
     hlmContext.color := TGxRGBA.Create(255, 0, 255, 200);
     hlmContext.line(px+pw div 2, py+ph div 2, px+pw div 2+pdx, py+ph div 2+pdy);
-    pan := mapGrid.traceBox(ex, ey, px, py, pw, ph, pdx, pdy, nil, GridTagObstacle);
+    pan := mapGrid.traceBox(ex, ey, px, py, pw, ph, pdx, pdy, GridTagObstacle);
     if (pan = nil) then
     begin
       hlmContext.color := TGxRGBA.Create(255, 255, 255, 180);
@@ -972,6 +972,17 @@ procedure plrDebugDraw ();
     hlmContext.fillRect(cx, cy, monsGrid.tileSize, monsGrid.tileSize);
   end;
 
+  procedure hilightBodyCells (proxyId: Integer);
+  var
+    it: CellCoordIter;
+    pcellxy: PGridCellCoord;
+  begin
+    //monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
+    it := monsGrid.forEachBodyCell(proxyId);
+    for pcellxy in it do hilightCell(pcellxy^.x, pcellxy^.y);
+    it.release();
+  end;
+
   procedure hilightCell1 (cx, cy: Integer);
   begin
     //e_WriteLog(Format('h1: (%d,%d)', [cx, cy]), MSG_NOTIFY);
@@ -990,12 +1001,11 @@ procedure plrDebugDraw ();
     hlmContext.fillRect(pan.X, pan.Y, pan.Width, pan.Height);
   end;
 
-  function monsCollector (mon: TMonster; tag: Integer): Boolean;
+  procedure monsCollector (mon: TMonster);
   var
     ex, ey: Integer;
     mx, my, mw, mh: Integer;
   begin
-    result := false;
     mon.getMapBox(mx, my, mw, mh);
     hlmContext.color := TGxRGBA.Create(255, 255, 0, 160);
     hlmContext.rect(mx, my, mw, mh);
@@ -1074,7 +1084,8 @@ procedure plrDebugDraw ();
     mon.getMapBox(mx, my, mw, mh);
     //mx += mw div 2;
 
-    monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
+    //monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
+    hilightBodyCells(mon.proxyId);
 
     if showMonsInfo then
     begin
@@ -1113,7 +1124,8 @@ procedure plrDebugDraw ();
   function highlightAllMonsterCells (mon: TMonster): Boolean;
   begin
     result := false; // don't stop
-    monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
+    //monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
+    hilightBodyCells(mon.proxyId);
   end;
 
   procedure drawSelectedPlatformCells ();
@@ -1123,7 +1135,8 @@ procedure plrDebugDraw ();
     if not showGrid then exit;
     pan := g_Map_PanelByGUID(platMarkedGUID);
     if (pan = nil) then exit;
-    mapGrid.forEachBodyCell(pan.proxyId, hilightCell);
+    //mapGrid.forEachBodyCell(pan.proxyId, hilightCell);
+    hilightBodyCells(pan.proxyId);
     hlmContext.color := TGxRGBA.Create(0, 200, 0, 200);
     hlmContext.rect(pan.x, pan.y, pan.width, pan.height);
   end;
@@ -1231,9 +1244,13 @@ procedure plrDebugDraw ();
 
 var
   mon: TMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
   mx, my, mw, mh: Integer;
   //pan: TPanel;
   //ex, ey: Integer;
+  s: AnsiString;
+  dx, dy: Integer;
 begin
   if (gPlayer1 = nil) then exit;
 
@@ -1241,7 +1258,7 @@ begin
 
   gxSetContext(hlmContext);
   try
-    //glScissor(0, gWinSizeY-gPlayerScreenSize.Y-1, vpw, vph);
+    //glScissor(0, gScreenHeight-gPlayerScreenSize.Y-1, vpw, vph);
     //hlmContext.clip := TGxRect.Create(0, gScreenHeight-gPlayerScreenSize.Y-1, gPlayerScreenSize.X, gPlayerScreenSize.Y);
 
     {
@@ -1255,7 +1272,13 @@ begin
     if (showGrid) then drawTileGrid();
     drawOutlines();
 
-    if (laserSet) then g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true);
+    if (laserSet) then
+    begin
+      //g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true);
+      it := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true);
+      for mit in it do monsCollector(mit^);
+      it.release();
+    end;
 
     if (monMarkedUID <> -1) then
     begin
@@ -1302,10 +1325,19 @@ begin
 
   if showMapCurPos then
   begin
+    s := Format('mappos:(%d,%d)', [pmsCurMapX, pmsCurMapY]);
     gxSetContext(hlmContext);
     hlmContext.font := 'win8';
+    hlmContext.color := TGxRGBA.Create(0, 0, 0);
+    for dy := -1 to 1 do
+    begin
+      for dx := -1 to 1 do
+      begin
+        if (dx <> 0) or (dy <> 0) then hlmContext.drawText(4+dx, gScreenHeight-10+dy, s);
+      end;
+    end;
     hlmContext.color := TGxRGBA.Create(255, 255, 0);
-    hlmContext.drawText(4, gWinSizeY-10, Format('mappos:(%d,%d)', [pmsCurMapX, pmsCurMapY]));
+    hlmContext.drawText(4, gScreenHeight-10, s);
     gxSetContext(nil);
   end;
 end;
@@ -1515,7 +1547,7 @@ procedure dbgToggleTraceBox (arg: Integer=-1); begin if (arg < 0) then showTrace
 procedure dbgToggleHolmesPause (arg: Integer=-1); begin if (arg < 0) then g_Game_HolmesPause(not gPauseHolmes) else g_Game_HolmesPause(arg > 0); end;
 
 procedure cbAtcurSelectMonster ();
-  function monsAtDump (mon: TMonster; tag: Integer): Boolean;
+  function monsAtDump (mon: TMonster{; tag: Integer}): Boolean;
   begin
     result := true; // stop
     e_WriteLog(Format('monster #%d (UID:%u) (proxyid:%d)', [mon.arrIdx, mon.UID, mon.proxyId]), TMsgType.Notify);
@@ -1525,6 +1557,8 @@ procedure cbAtcurSelectMonster ();
 var
   plr: TPlayer;
   x, y, w, h: Integer;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   monMarkedUID := -1;
   if (Length(gPlayers) > 0) then
@@ -1540,24 +1574,34 @@ begin
     end;
   end;
   //e_WriteLog('===========================', MSG_NOTIFY);
-  monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, monsAtDump);
+  it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
+  for mit in it do monsAtDump(mit^);
+  it.release();
   //e_WriteLog('---------------------------', MSG_NOTIFY);
 end;
 
 procedure cbAtcurDumpMonsters ();
-  function monsAtDump (mon: TMonster; tag: Integer): Boolean;
+  function monsAtDump (mon: TMonster{; tag: Integer}): Boolean;
   begin
     result := false; // don't stop
     e_WriteLog(Format('monster #%d (UID:%u) (proxyid:%d)', [mon.arrIdx, mon.UID, mon.proxyId]), TMsgType.Notify);
   end;
+var
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
-  e_WriteLog('===========================', TMsgType.Notify);
-  monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, monsAtDump);
-  e_WriteLog('---------------------------', TMsgType.Notify);
+  it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
+  if (it.length > 0) then
+  begin
+    e_WriteLog('===========================', TMsgType.Notify);
+    for mit in it do monsAtDump(mit^);
+    e_WriteLog('---------------------------', TMsgType.Notify);
+  end;
+  it.release();
 end;
 
 procedure cbAtcurDumpWalls ();
-  function wallToggle (pan: TPanel; tag: Integer): Boolean;
+  function wallToggle (pan: TPanel{; tag: Integer}): Boolean;
   begin
     result := false; // don't stop
     if (platMarkedGUID = -1) then platMarkedGUID := pan.guid;
@@ -1568,11 +1612,18 @@ var
   hasTrigs: Boolean = false;
   f: Integer;
   trig: PTrigger;
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   platMarkedGUID := -1;
-  e_WriteLog('=== TOGGLE WALL ===', TMsgType.Notify);
-  mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, wallToggle, (GridTagWall or GridTagDoor));
-  e_WriteLog('--- toggle wall ---', TMsgType.Notify);
+  it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
+  if (it.length > 0) then
+  begin
+    e_WriteLog('=== TOGGLE WALL ===', TMsgType.Notify);
+    for mwit in it do wallToggle(mwit^);
+    e_WriteLog('--- toggle wall ---', TMsgType.Notify);
+  end;
+  it.release();
   if showTriggers then
   begin
     for f := 0 to High(gTriggers) do
@@ -1589,16 +1640,21 @@ begin
 end;
 
 procedure cbAtcurToggleWalls ();
-  function wallToggle (pan: TPanel; tag: Integer): Boolean;
+  function wallToggle (pan: TPanel{; tag: Integer}): Boolean;
   begin
     result := false; // don't stop
     //e_WriteLog(Format('wall #%d(%d); enabled=%d (%d); (%d,%d)-(%d,%d)', [pan.arrIdx, pan.proxyId, Integer(pan.Enabled), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.X, pan.Y, pan.Width, pan.Height]), MSG_NOTIFY);
     if pan.Enabled then g_Map_DisableWallGUID(pan.guid) else g_Map_EnableWallGUID(pan.guid);
   end;
+var
+  mwit: PPanel;
+  it: TPanelGrid.Iter;
 begin
   //e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY);
-  mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, wallToggle, (GridTagWall or GridTagDoor));
   //e_WriteLog('--- toggle wall ---', MSG_NOTIFY);
+  it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
+  for mwit in it do wallToggle(mwit^);
+  it.release();
 end;
 
 
@@ -1684,7 +1740,7 @@ begin
 
     // load bindings from file
     try
-      st := openDiskFileRO(GameDir+'holmes.rc');
+      st := e_OpenResourceRO(ConfigDirs, 'holmes.rc');
       pr := TFileTextParser.Create(st);
       conwriteln('parsing "holmes.rc"...');
       while (pr.tokType <> pr.TTEOF) do