diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas
index 685c245ffe075590491851c94d6e95699296e8c1..bcd1c4c1d4040d2dc820e8c2747a663dd237b82b 100644 (file)
--- a/src/game/g_panel.pas
+++ b/src/game/g_panel.pas
TPanel = Class (TObject)
private
+ const
+ private
+ mGUID: Integer; // will be assigned in "g_map.pas"
FTextureWidth: Word;
FTextureHeight: Word;
FAlpha: Byte;
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;
FMoved: Boolean;
FLiftType: Byte;
FLastAnimLoop: Byte;
+ // sorry, there fields are public to allow setting 'em in g_map; this should be fixed later
+ // for now, PLEASE, don't modify 'em, or all hell will break loose
arrIdx: Integer; // index in one of internal arrays; sorry
- tag: Integer; // used in coldets and such; sorry
+ tag: Integer; // used in coldets and such; sorry; see g_map.GridTagXXX
proxyId: Integer; // proxy id in map grid (DO NOT USE!)
+ mapId: AnsiString; // taken directly from map file; dunno why it is here
constructor Create(PanelRec: TDynRecord;
AddTextures: TAddTextureArray;
CurTex: Integer;
- var Textures: TLevelTextureArray);
+ var Textures: TLevelTextureArray; aguid: Integer);
destructor Destroy(); override;
procedure Draw();
procedure SaveState(var Mem: TBinMemoryWriter);
procedure LoadState(var Mem: TBinMemoryReader);
+ procedure positionChanged (); inline;
+
+ 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
published
+ property guid: Integer read mGUID; // will be assigned in "g_map.pas"
property x0: Integer read FX;
property y0: Integer read FY;
property x1: Integer read getx1; // inclusive!
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;
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
constructor TPanel.Create(PanelRec: TDynRecord;
AddTextures: TAddTextureArray;
CurTex: Integer;
- var Textures: TLevelTextureArray);
+ var Textures: TLevelTextureArray; aguid: Integer);
var
i: Integer;
begin
LastAnimLoop := 0;
Moved := False;
+ mapId := PanelRec.id;
+ mGUID := aguid;
+
mMovingSpeed := PanelRec.moveSpeed;
mMovingStart := PanelRec.moveStart;
mMovingEnd := PanelRec.moveEnd;
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.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
xx, yy: Integer;
begin
if {Enabled and} (FCurTexture >= 0) and
(Width > 0) and (Height > 0) and (FAlpha < 255) and
- (g_dbg_scale_05 or g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)) then
+ ((g_dbg_scale <> 1.0) or g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)) then
begin
if FTextureIDs[FCurTexture].Anim then
begin // Àíèìèðîâàííàÿ òåêñòóðà
end;
+procedure TPanel.positionChanged (); inline;
+var
+ px, py, pw, ph: Integer;
+begin
+ if (proxyId >= 0) then
+ begin
+ 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);
+ g_Mark(X, Y, Width, Height, MARK_WALL);
+ end;
+ end;
+end;
+
+
var
monMoveList: array of TMonster = nil;
monMoveListUsed: Integer = 0;
procedure TPanel.Update();
var
nx, ny: Integer;
- f: Integer;
function doPush (px, py, pw, ph: Integer; out dx, dy: Integer): Boolean;
begin
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);
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);
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
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;
plr.positionChanged();
end;
+ procedure gibMove (gib: PGib);
+ var
+ px, py, pw, ph, dx, dy: Integer;
+ begin
+ if (gib = nil) or not gib.alive then exit;
+ gib.getMapBox(px, py, pw, ph);
+ {
+ writeln('gib: p=(', px, ',', py, '); obj=(', gib.Obj.X, ',', gib.Obj.Y, ')');
+ px := gib.Obj.X;
+ py := gib.Obj.Y;
+ }
+ if (py+ph <> Y) then
+ begin
+ // push gib
+ if doPush(px, py, pw, ph, dx, dy) then
+ begin
+ gib.Obj.X += dx;
+ gib.Obj.Y += dy;
+ gib.positionChanged();
+ end;
+ exit;
+ end;
+ if (px+pw <= X) then exit;
+ if (px >= X+Width) then exit;
+ gib.Obj.X += mMovingSpeed.X;
+ gib.Obj.Y += mMovingSpeed.Y;
+ gib.positionChanged();
+ end;
+
+ procedure corpseMove (cor: TCorpse);
+ var
+ px, py, pw, ph, dx, dy: Integer;
+ begin
+ if (cor = nil) then exit;
+ cor.getMapBox(px, py, pw, ph);
+ if (py+ph <> Y) then
+ begin
+ // push gib
+ if doPush(px, py, pw, ph, dx, dy) then
+ begin
+ cor.moveBy(dx, dy); // will call `positionChanged()` for us
+ end;
+ exit;
+ end;
+ if (px+pw <= X) then exit;
+ if (px >= X+Width) then exit;
+ cor.moveBy(mMovingSpeed.X, mMovingSpeed.Y); // will call `positionChanged()` for us
+ end;
+
+var
+ f: Integer;
+ mon: TMonster;
+ px, py, pw, ph: Integer;
begin
if Enabled and (FCurTexture >= 0) and
(FTextureIDs[FCurTexture].Anim) and
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
for f := 0 to High(gPlayers) do plrMove(gPlayers[f]);
+ // move and push gibs
+ for f := 0 to High(gGibs) do gibMove(@gGibs[f]);
+ // move and push corpses
+ for f := 0 to High(gCorpses) do corpseMove(gCorpses[f]);
// reverse moving direction, if necessary
if (mMovingSpeed.X < 0) and (nx <= mMovingStart.X) then mMovingSpeed.X := -mMovingSpeed.X
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
- if (proxyId >= 0) then mapGrid.moveBody(proxyId, nx, ny);
// 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;
Mem.ReadInt(mMovingEnd.Y);
Mem.ReadBoolean(mMovingActive);
- if (proxyId >= 0) then mapGrid.moveBody(proxyId, X, Y);
+ positionChanged();
+ //mapGrid.proxyEnabled[proxyId] := FEnabled; // done in g_map.pas
end;
end.