diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas
index 19a6af815b51077098b1fec363f77bfabdf4370e..685c245ffe075590491851c94d6e95699296e8c1 100644 (file)
--- a/src/game/g_panel.pas
+++ b/src/game/g_panel.pas
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
{$INCLUDE ../shared/a_modes.inc}
+{$M+}
unit g_panel;
interface
uses
- MAPSTRUCT, BinEditor, g_textures;
+ MAPDEF, BinEditor, g_textures, xdynrec;
type
TAddTextureArray = Array of
True: (AnTex: TAnimation);
end;
+ mMovingSpeed: TDFPoint;
+ mMovingStart: TDFPoint;
+ mMovingEnd: TDFPoint;
+ mMovingActive: Boolean;
+
private
function getx1 (): Integer; inline;
function gety1 (): Integer; inline;
FCurTexture: Integer; // Íîìåð òåêóùåé òåêñòóðû
FCurFrame: Integer;
FCurFrameCount: Byte;
- X, Y: Integer;
- Width, Height: Word;
- PanelType: Word;
- SaveIt: Boolean; // Ñîõðàíÿòü ïðè SaveState?
- Enabled: Boolean;
- Door: Boolean;
- Moved: Boolean;
- LiftType: Byte;
- LastAnimLoop: Byte;
+ FX, FY: Integer;
+ FWidth, FHeight: Word;
+ FPanelType: Word;
+ FSaveIt: Boolean; // Ñîõðàíÿòü ïðè SaveState?
+ FEnabled: Boolean;
+ FDoor: Boolean;
+ FMoved: Boolean;
+ FLiftType: Byte;
+ FLastAnimLoop: Byte;
arrIdx: Integer; // index in one of internal arrays; sorry
tag: Integer; // used in coldets and such; sorry
proxyId: Integer; // proxy id in map grid (DO NOT USE!)
- constructor Create(PanelRec: TPanelRec_1;
+ constructor Create(PanelRec: TDynRecord;
AddTextures: TAddTextureArray;
CurTex: Integer;
var Textures: TLevelTextureArray);
procedure SaveState(var Mem: TBinMemoryWriter);
procedure LoadState(var Mem: TBinMemoryReader);
- property x0: Integer read X;
- property y0: Integer read Y;
+ public
+ property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive
+
+ published
+ property x0: Integer read FX;
+ property y0: Integer read FY;
property x1: Integer read getx1; // inclusive!
property y1: Integer read gety1; // inclusive!
- property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive
+ property x: Integer read FX write FX;
+ property y: Integer read FY write FY;
+ property width: Word read FWidth write FWidth;
+ property height: Word read FHeight write FHeight;
+ property panelType: Word read FPanelType write FPanelType;
+ property saveIt: Boolean read FSaveIt write FSaveIt; // Ñîõðàíÿòü ïðè SaveState?
+ property enabled: Boolean read FEnabled write FEnabled; // Ñîõðàíÿòü ïðè SaveState?
+ property door: Boolean read FDoor write FDoor; // Ñîõðàíÿòü ïðè SaveState?
+ property moved: Boolean read FMoved write FMoved; // Ñîõðàíÿòü ïðè SaveState?
+ property liftType: Byte read FLiftType write FLiftType; // Ñîõðàíÿòü ïðè SaveState?
+ property lastAnimLoop: Byte read FLastAnimLoop write FLastAnimLoop; // Ñîõðàíÿòü ïðè SaveState?
+
+ property movingActive: Boolean read mMovingActive write mMovingActive;
+
+ public
+ property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed;
+ property movingStart: TDFPoint read mMovingStart write mMovingStart;
+ property movingEnd: TDFPoint read mMovingEnd write mMovingEnd;
end;
- PPanel = ^TPanel;
TPanelArray = Array of TPanel;
implementation
uses
- SysUtils, g_basic, g_map, MAPDEF, g_game, e_graphics,
- g_console, g_language, e_log, GL;
+ SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics,
+ g_console, g_language, g_monsters, g_player, e_log, GL;
const
PANEL_SIGNATURE = $4C4E4150; // 'PANL'
{ T P a n e l : }
-constructor TPanel.Create(PanelRec: TPanelRec_1;
+constructor TPanel.Create(PanelRec: TDynRecord;
AddTextures: TAddTextureArray;
CurTex: Integer;
var Textures: TLevelTextureArray);
LastAnimLoop := 0;
Moved := False;
+ mMovingSpeed := PanelRec.moveSpeed;
+ mMovingStart := PanelRec.moveStart;
+ mMovingEnd := PanelRec.moveEnd;
+ mMovingActive := PanelRec['move_active'].varvalue;
+
// Òèï ïàíåëè:
PanelType := PanelRec.PanelType;
Enabled := True;
case PanelRec.PanelType of
PANEL_WATER:
- FTextureIDs[0].Tex := TEXTURE_SPECIAL_WATER;
+ FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_WATER);
PANEL_ACID1:
- FTextureIDs[0].Tex := TEXTURE_SPECIAL_ACID1;
+ FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_ACID1);
PANEL_ACID2:
- FTextureIDs[0].Tex := TEXTURE_SPECIAL_ACID2;
+ FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_ACID2);
end;
FCurTexture := 0;
NoTextureID: DWORD;
NW, NH: Word;
begin
- if Enabled and (FCurTexture >= 0) and
+ if {Enabled and} (FCurTexture >= 0) and
(Width > 0) and (Height > 0) and (FAlpha < 255) and
- g_Collide(X, Y, Width, Height,
- sX, sY, sWidth, sHeight) then
+ (g_dbg_scale_05 or g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)) then
begin
if FTextureIDs[FCurTexture].Anim then
begin // Àíèìèðîâàííàÿ òåêñòóðà
else
begin // Îáû÷íàÿ òåêñòóðà
case FTextureIDs[FCurTexture].Tex of
- TEXTURE_SPECIAL_WATER:
+ LongWord(TEXTURE_SPECIAL_WATER):
e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
0, 0, 255, 0, B_FILTER);
- TEXTURE_SPECIAL_ACID1:
+ LongWord(TEXTURE_SPECIAL_ACID1):
e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
0, 128, 0, 0, B_FILTER);
- TEXTURE_SPECIAL_ACID2:
+ LongWord(TEXTURE_SPECIAL_ACID2):
e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
128, 0, 0, 0, B_FILTER);
- TEXTURE_NONE:
+ LongWord(TEXTURE_NONE):
if g_Texture_Get('NOTEXTURE', NoTextureID) then
begin
e_GetTextureSize(NoTextureID, @NW, @NH);
if not FTextureIDs[FCurTexture].Anim then
begin
case FTextureIDs[FCurTexture].Tex of
- TEXTURE_SPECIAL_WATER: exit;
- TEXTURE_SPECIAL_ACID1: exit;
- TEXTURE_SPECIAL_ACID2: exit;
- TEXTURE_NONE: exit;
+ LongWord(TEXTURE_SPECIAL_WATER): exit;
+ LongWord(TEXTURE_SPECIAL_ACID1): exit;
+ LongWord(TEXTURE_SPECIAL_ACID2): exit;
+ LongWord(TEXTURE_NONE): exit;
end;
end;
if (X+Width < lightX-radius) then exit;
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
+ result := g_Collide(px, py, pw, ph, nx, ny, Width, Height);
+ if result then
+ begin
+ // need to push
+ if (mMovingSpeed.X < 0) then dx := nx-(px+pw)
+ else if (mMovingSpeed.X > 0) then dx := (nx+Width)-px
+ else dx := 0;
+ if (mMovingSpeed.Y < 0) then dy := ny-(py+ph)
+ else if (mMovingSpeed.Y > 0) then dy := (ny+Height)-py
+ else dy := 0;
+ end
+ else
+ begin
+ dx := 0;
+ dy := 0;
+ end;
+ end;
+
+ function monMove (mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ mon.GameX := mon.GameX+mMovingSpeed.X;
+ mon.GameY := mon.GameY+mMovingSpeed.Y;
+ if (monMoveListUsed >= Length(monMoveList)) then SetLength(monMoveList, monMoveListUsed+64);
+ monMoveList[monMoveListUsed] := mon;
+ Inc(monMoveListUsed);
+ end;
+
+ function monPush (mon: TMonster): Boolean;
+ var
+ px, py, pw, ph, dx, dy: Integer;
+ begin
+ result := false; // don't stop
+ 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;
+ if (monMoveListUsed >= Length(monMoveList)) then SetLength(monMoveList, monMoveListUsed+64);
+ monMoveList[monMoveListUsed] := mon;
+ Inc(monMoveListUsed);
+ end;
+ end;
+
+ procedure plrMove (plr: TPlayer);
+ var
+ px, py, pw, ph, dx, dy: Integer;
+ begin
+ if (plr = nil) then exit;
+ plr.getMapBox(px, py, pw, ph);
+ if (py+ph <> Y) then
+ begin
+ // push player
+ if doPush(px, py, pw, ph, dx, dy) then
+ begin
+ plr.GameX := plr.GameX+dx;
+ plr.GameY := plr.GameY+dy;
+ plr.positionChanged();
+ end;
+ exit;
+ end;
+ if (px+pw <= X) then exit;
+ if (px >= X+Width) then exit;
+ plr.GameX := plr.GameX+mMovingSpeed.X;
+ plr.GameY := plr.GameY+mMovingSpeed.Y;
+ plr.positionChanged();
+ end;
+
begin
if Enabled and (FCurTexture >= 0) and
(FTextureIDs[FCurTexture].Anim) and
FCurFrame := FTextureIDs[FCurTexture].AnTex.CurrentFrame;
FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter;
end;
+
+ if mMovingActive and (not mMovingSpeed.isZero) 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);
+ // push monsters
+ g_Mons_ForEachAt(nx, ny, Width, Height, monPush);
+ // move and push players
+ for f := 0 to High(gPlayers) do plrMove(gPlayers[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();
+ end;
end;
procedure TPanel.SetFrame(Frame: Integer; Count: Byte);
function TPanel.GetTextureID(): DWORD;
begin
- Result := TEXTURE_NONE;
+ Result := LongWord(TEXTURE_NONE);
if (FCurTexture >= 0) then
begin
sig: DWORD;
anim: Boolean;
begin
- if (not SaveIt) or (Mem = nil) then
- Exit;
+ if (Mem = nil) then exit;
+ //if not SaveIt then exit;
// Ñèãíàòóðà ïàíåëè:
sig := PANEL_SIGNATURE; // 'PANL'
Mem.WriteDWORD(sig);
// Îòêðûòà/çàêðûòà, åñëè äâåðü:
- Mem.WriteBoolean(Enabled);
+ Mem.WriteBoolean(FEnabled);
// Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
- Mem.WriteByte(LiftType);
+ Mem.WriteByte(FLiftType);
// Íîìåð òåêóùåé òåêñòóðû:
Mem.WriteInt(FCurTexture);
// Êîîðäû
- Mem.WriteInt(X);
- Mem.WriteInt(Y);
+ Mem.WriteInt(FX);
+ Mem.WriteInt(FY);
// Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) then
begin
// Åñëè äà - ñîõðàíÿåì àíèìàöèþ:
if anim then
FTextureIDs[FCurTexture].AnTex.SaveState(Mem);
+ // moving platform state
+ Mem.WriteInt(mMovingSpeed.X);
+ Mem.WriteInt(mMovingSpeed.Y);
+ Mem.WriteInt(mMovingStart.X);
+ Mem.WriteInt(mMovingStart.Y);
+ Mem.WriteInt(mMovingEnd.X);
+ Mem.WriteInt(mMovingEnd.Y);
+ Mem.WriteBoolean(mMovingActive);
end;
procedure TPanel.LoadState(var Mem: TBinMemoryReader);
var
sig: DWORD;
anim: Boolean;
+ //ox, oy: Integer;
begin
- if (not SaveIt) or (Mem = nil) then
- Exit;
+ if (Mem = nil) then exit;
+ //if not SaveIt then exit;
// Ñèãíàòóðà ïàíåëè:
Mem.ReadDWORD(sig);
raise EBinSizeError.Create('TPanel.LoadState: Wrong Panel Signature');
end;
// Îòêðûòà/çàêðûòà, åñëè äâåðü:
- Mem.ReadBoolean(Enabled);
+ Mem.ReadBoolean(FEnabled);
// Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
- Mem.ReadByte(LiftType);
+ Mem.ReadByte(FLiftType);
// Íîìåð òåêóùåé òåêñòóðû:
Mem.ReadInt(FCurTexture);
// Êîîðäû
- Mem.ReadInt(X);
- Mem.ReadInt(Y);
+ //ox := FX;
+ //oy := FY;
+ Mem.ReadInt(FX);
+ Mem.ReadInt(FY);
+ //e_LogWritefln('panel %s(%s): old=(%s,%s); new=(%s,%s); delta=(%s,%s)', [arrIdx, proxyId, ox, oy, FX, FY, FX-ox, FY-oy]);
// Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
Mem.ReadBoolean(anim);
// Åñëè äà - çàãðóæàåì àíèìàöèþ:
'TPanel.LoadState: No animation object');
FTextureIDs[FCurTexture].AnTex.LoadState(Mem);
end;
+ // moving platform state
+ Mem.ReadInt(mMovingSpeed.X);
+ Mem.ReadInt(mMovingSpeed.Y);
+ Mem.ReadInt(mMovingStart.X);
+ Mem.ReadInt(mMovingStart.Y);
+ Mem.ReadInt(mMovingEnd.X);
+ Mem.ReadInt(mMovingEnd.Y);
+ Mem.ReadBoolean(mMovingActive);
+
+ if (proxyId >= 0) then mapGrid.moveBody(proxyId, X, Y);
end;
end.