DEADSOFTWARE

field namefix: `FLive` -> `FAlive`; `live` -> `alive`
[d2df-sdl.git] / src / game / g_panel.pas
index 94e7b877488b8963eb05bbcb924d0161fe7a7bf4..0a3f8f7900c6f417115570d89c89a581ecb035e5 100644 (file)
@@ -55,6 +55,21 @@ type
     function gety1 (): Integer; inline;
     function getvisvalid (): Boolean; inline;
 
+    function getMovingSpeedX (): Integer; inline;
+    procedure setMovingSpeedX (v: Integer); inline;
+    function getMovingSpeedY (): Integer; inline;
+    procedure setMovingSpeedY (v: Integer); inline;
+
+    function getMovingStartX (): Integer; inline;
+    procedure setMovingStartX (v: Integer); inline;
+    function getMovingStartY (): Integer; inline;
+    procedure setMovingStartY (v: Integer); inline;
+
+    function getMovingEndX (): Integer; inline;
+    procedure setMovingEndX (v: Integer); inline;
+    function getMovingEndY (): Integer; inline;
+    procedure setMovingEndY (v: Integer); inline;
+
   public
     FCurTexture:      Integer; // Íîìåð òåêóùåé òåêñòóðû
     FCurFrame:        Integer;
@@ -95,16 +110,15 @@ type
 
     procedure positionChanged (); inline;
 
-    function isGBack (): Boolean; inline; // gRenderBackgrounds
-    function isGStep (): Boolean; inline; // gSteps
-    function isGWall (): Boolean; inline; // gWalls
-    function isGAcid1 (): Boolean; inline; // gAcid1
-    function isGAcid2 (): Boolean; inline; // gAcid2
-    function isGWater (): Boolean; inline; // gWater
-    function isGFore (): Boolean; inline; // gRenderForegrounds
-    function isGLift (): Boolean; inline; // gLifts
-    function isGBlockMon (): Boolean; inline; // gBlockMon
-
+    function getIsGBack (): Boolean; inline; // gRenderBackgrounds
+    function getIsGStep (): Boolean; inline; // gSteps
+    function getIsGWall (): Boolean; inline; // gWalls
+    function getIsGAcid1 (): Boolean; inline; // gAcid1
+    function getIsGAcid2 (): Boolean; inline; // gAcid2
+    function getIsGWater (): Boolean; inline; // gWater
+    function getIsGFore (): Boolean; inline; // gRenderForegrounds
+    function getIsGLift (): Boolean; inline; // gLifts
+    function getIsGBlockMon (): Boolean; inline; // gBlockMon
 
   public
     property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive
@@ -127,8 +141,24 @@ type
     property liftType: Byte read FLiftType write FLiftType; // Ñîõðàíÿòü ïðè SaveState?
     property lastAnimLoop: Byte read FLastAnimLoop write FLastAnimLoop; // Ñîõðàíÿòü ïðè SaveState?
 
+    property movingSpeedX: Integer read getMovingSpeedX write setMovingSpeedX;
+    property movingSpeedY: Integer read getMovingSpeedY write setMovingSpeedY;
+    property movingStartX: Integer read getMovingStartX write setMovingStartX;
+    property movingStartY: Integer read getMovingStartY write setMovingStartY;
+    property movingEndX: Integer read getMovingEndX write setMovingEndX;
+    property movingEndY: Integer read getMovingEndY write setMovingEndY;
     property movingActive: Boolean read mMovingActive write mMovingActive;
 
+    property isGBack: Boolean read getIsGBack;
+    property isGStep: Boolean read getIsGStep;
+    property isGWall: Boolean read getIsGWall;
+    property isGAcid1: Boolean read getIsGAcid1;
+    property isGAcid2: Boolean read getIsGAcid2;
+    property isGWater: Boolean read getIsGWater;
+    property isGFore: Boolean read getIsGFore;
+    property isGLift: Boolean read getIsGLift;
+    property isGBlockMon: Boolean read getIsGBlockMon;
+
   public
     property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed;
     property movingStart: TDFPoint read mMovingStart write mMovingStart;
@@ -137,10 +167,15 @@ type
 
   TPanelArray = Array of TPanel;
 
+var
+  g_dbgpan_mplat_active: Boolean = {$IF DEFINED(D2F_DEBUG)}false{$ELSE}true{$ENDIF};
+  g_dbgpan_mplat_step: Boolean = false; // one step, and stop
+
+
 implementation
 
 uses
-  SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics,
+  SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons,
   g_console, g_language, g_monsters, g_player, e_log, GL;
 
 const
@@ -318,15 +353,30 @@ function TPanel.getx1 (): Integer; inline; begin result := X+Width-1; end;
 function TPanel.gety1 (): Integer; inline; begin result := Y+Height-1; end;
 function TPanel.getvisvalid (): Boolean; inline; begin result := (Width > 0) and (Height > 0); end;
 
-function TPanel.isGBack (): Boolean; inline; begin result := ((tag and GridTagBack) <> 0); end;
-function TPanel.isGStep (): Boolean; inline; begin result := ((tag and GridTagStep) <> 0); end;
-function TPanel.isGWall (): Boolean; inline; begin result := ((tag and (GridTagWall or GridTagDoor)) <> 0); end;
-function TPanel.isGAcid1 (): Boolean; inline; begin result := ((tag and GridTagAcid1) <> 0); end;
-function TPanel.isGAcid2 (): Boolean; inline; begin result := ((tag and GridTagAcid2) <> 0); end;
-function TPanel.isGWater (): Boolean; inline; begin result := ((tag and GridTagWater) <> 0); end;
-function TPanel.isGFore (): Boolean; inline; begin result := ((tag and GridTagFore) <> 0); end;
-function TPanel.isGLift (): Boolean; inline; begin result := ((tag and GridTagLift) <> 0); end;
-function TPanel.isGBlockMon (): Boolean; inline; begin result := ((tag and GridTagBlockMon) <> 0); end;
+function TPanel.getMovingSpeedX (): Integer; inline; begin result := mMovingSpeed.X; end;
+procedure TPanel.setMovingSpeedX (v: Integer); inline; begin mMovingSpeed.X := v; end;
+function TPanel.getMovingSpeedY (): Integer; inline; begin result := mMovingSpeed.Y; end;
+procedure TPanel.setMovingSpeedY (v: Integer); inline; begin mMovingSpeed.Y := v; end;
+
+function TPanel.getMovingStartX (): Integer; inline; begin result := mMovingStart.X; end;
+procedure TPanel.setMovingStartX (v: Integer); inline; begin mMovingStart.X := v; end;
+function TPanel.getMovingStartY (): Integer; inline; begin result := mMovingStart.Y; end;
+procedure TPanel.setMovingStartY (v: Integer); inline; begin mMovingStart.Y := v; end;
+
+function TPanel.getMovingEndX (): Integer; inline; begin result := mMovingEnd.X; end;
+procedure TPanel.setMovingEndX (v: Integer); inline; begin mMovingEnd.X := v; end;
+function TPanel.getMovingEndY (): Integer; inline; begin result := mMovingEnd.Y; end;
+procedure TPanel.setMovingEndY (v: Integer); inline; begin mMovingEnd.Y := v; end;
+
+function TPanel.getIsGBack (): Boolean; inline; begin result := ((tag and GridTagBack) <> 0); end;
+function TPanel.getIsGStep (): Boolean; inline; begin result := ((tag and GridTagStep) <> 0); end;
+function TPanel.getIsGWall (): Boolean; inline; begin result := ((tag and (GridTagWall or GridTagDoor)) <> 0); end;
+function TPanel.getIsGAcid1 (): Boolean; inline; begin result := ((tag and GridTagAcid1) <> 0); end;
+function TPanel.getIsGAcid2 (): Boolean; inline; begin result := ((tag and GridTagAcid2) <> 0); end;
+function TPanel.getIsGWater (): Boolean; inline; begin result := ((tag and GridTagWater) <> 0); end;
+function TPanel.getIsGFore (): Boolean; inline; begin result := ((tag and GridTagFore) <> 0); end;
+function TPanel.getIsGLift (): Boolean; inline; begin result := ((tag and GridTagLift) <> 0); end;
+function TPanel.getIsGBlockMon (): Boolean; inline; begin result := ((tag and GridTagBlockMon) <> 0); end;
 
 procedure TPanel.Draw();
 var
@@ -445,9 +495,13 @@ var
 begin
   if (proxyId >= 0) then
   begin
-    monsGrid.getBodyDims(proxyId, px, py, pw, ph);
+    mapGrid.getBodyDims(proxyId, px, py, pw, ph);
     if (px <> x) or (py <> y) or (pw <> Width) or (ph <> Height) then
     begin
+      {
+      e_LogWritefln('panel moved: arridx=%s; guid=%s; proxyid=%s; old:(%s,%s)-(%sx%s); new:(%s,%s)-(%sx%s)',
+        [arrIdx, mGUID, proxyId, px, py, pw, ph, x, y, width, height]);
+      }
       g_Mark(px, py, pw, ph, MARK_WALL, false);
       if (pw <> Width) or (ph <> Height) then mapGrid.moveResizeBody(proxyId, X, Y, Width, Height)
       else mapGrid.moveBody(proxyId, X, Y);
@@ -464,7 +518,6 @@ var
 procedure TPanel.Update();
 var
   nx, ny: Integer;
-  f: Integer;
 
   function doPush (px, py, pw, ph: Integer; out dx, dy: Integer): Boolean;
   begin
@@ -489,8 +542,9 @@ var
   function monMove (mon: TMonster): Boolean;
   begin
     result := false; // don't stop
-    mon.GameX := mon.GameX+mMovingSpeed.X;
-    mon.GameY := mon.GameY+mMovingSpeed.Y;
+    //mon.GameX := mon.GameX+mMovingSpeed.X;
+    //mon.GameY := mon.GameY+mMovingSpeed.Y;
+    mon.setPosition(mon.GameX+mMovingSpeed.X, mon.GameY+mMovingSpeed.Y, false); // we can't call `positionChanged()` in grid callback
     if (monMoveListUsed >= Length(monMoveList)) then SetLength(monMoveList, monMoveListUsed+64);
     monMoveList[monMoveListUsed] := mon;
     Inc(monMoveListUsed);
@@ -504,8 +558,9 @@ var
     mon.getMapBox(px, py, pw, ph);
     if doPush(px, py, pw, ph, dx, dy) then
     begin
-      mon.GameX := mon.GameX+dx;
-      mon.GameY := mon.GameY+dy;
+      //mon.GameX := mon.GameX+dx;
+      //mon.GameY := mon.GameY+dy;
+      mon.setPosition(mon.GameX+dx, mon.GameY+dy, false); // we can't call `positionChanged()` in grid callback
       if (monMoveListUsed >= Length(monMoveList)) then SetLength(monMoveList, monMoveListUsed+64);
       monMoveList[monMoveListUsed] := mon;
       Inc(monMoveListUsed);
@@ -516,7 +571,8 @@ var
   var
     px, py, pw, ph, dx, dy: Integer;
   begin
-    if (plr = nil) then exit;
+    // dead players leaves separate body entities, so don't move 'em
+    if (plr = nil) or not plr.alive then exit;
     plr.getMapBox(px, py, pw, ph);
     if (py+ph <> Y) then
     begin
@@ -526,6 +582,15 @@ var
         plr.GameX := plr.GameX+dx;
         plr.GameY := plr.GameY+dy;
         plr.positionChanged();
+        // check if we're squashed
+        if plr.alive then
+        begin
+          plr.getMapBox(px, py, pw, ph);
+          if g_Map_CollidePanel(px, py, pw, ph, (PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR)) then
+          begin
+            plr.Damage(15000, 0, 0, 0, HIT_TRAP);
+          end;
+        end;
       end;
       exit;
     end;
@@ -536,6 +601,10 @@ var
     plr.positionChanged();
   end;
 
+var
+  f: Integer;
+  mon: TMonster;
+  px, py, pw, ph: Integer;
 begin
   if Enabled and (FCurTexture >= 0) and
     (FTextureIDs[FCurTexture].Anim) and
@@ -547,13 +616,17 @@ begin
     FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter;
   end;
 
-  if mMovingActive and (not mMovingSpeed.isZero) then
+  if mMovingActive and (not mMovingSpeed.isZero) and g_dbgpan_mplat_active then
   begin
     monMoveListUsed := 0;
     nx := X+mMovingSpeed.X;
     ny := Y+mMovingSpeed.Y;
     // move monsters on lifts
     g_Mons_ForEachAt(X, Y-1, Width, 1, monMove);
+    X := nx;
+    Y := ny;
+    // fix grid
+    positionChanged();
     // push monsters
     g_Mons_ForEachAt(nx, ny, Width, Height, monPush);
     // move and push players
@@ -563,15 +636,24 @@ begin
     else if (mMovingSpeed.X > 0) and (nx >= mMovingEnd.X) then mMovingSpeed.X := -mMovingSpeed.X;
          if (mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y) then mMovingSpeed.Y := -mMovingSpeed.Y
     else if (mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y) then mMovingSpeed.Y := -mMovingSpeed.Y;
-    // awake particles
-    //g_Mark(X, Y, Width, Height, MARK_WALL, false);
-    X := nx;
-    Y := ny;
-    //g_Mark(nx, ny, Width, Height, MARK_WALL);
-    // fix grid
-    positionChanged();
     // notify moved monsters about their movement
-    for f := 0 to monMoveListUsed-1 do monMoveList[f].positionChanged();
+    for f := 0 to monMoveListUsed-1 do
+    begin
+      monMoveList[f].positionChanged();
+    end;
+    for f := 0 to monMoveListUsed-1 do
+    begin
+      mon := monMoveList[f];
+      // check if it is squashed
+      if mon.alive then
+      begin
+        mon.getMapBox(px, py, pw, ph);
+        if g_Map_CollidePanel(px, py, pw, ph, (PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR)) then
+        begin
+          mon.Damage(15000, 0, 0, 0, HIT_TRAP);
+        end;
+      end;
+    end;
   end;
 end;