X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_panel.pas;h=f9b7371f213c2f8b4b380e02ec61bd7b03b6672f;hb=16342bee09fa001d05697571124e48a93cd35f2c;hp=7651b48a17326b5ea5efd06b208f55de3e2229f5;hpb=e3862af724594e026b2eda52e284d21fc580aa71;p=d2df-sdl.git diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index 7651b48..f9b7371 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -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 @@ -20,43 +19,46 @@ unit g_panel; interface uses - MAPDEF, BinEditor, g_textures, xdynrec; + SysUtils, Classes, + MAPDEF, g_textures, xdynrec; type - TAddTextureArray = Array of - record - Texture: Cardinal; - Anim: Boolean; - end; + TAddTextureArray = array of record + Texture: Cardinal; // Textures[Texture] + end; + + ATextureID = array of record + Texture: Cardinal; // Textures[Texture] + case Anim: Boolean of + False: (); + True: (AnTex: TAnimationState); + end; + PPanel = ^TPanel; TPanel = Class (TObject) private const private mGUID: Integer; // will be assigned in "g_map.pas" - FTextureWidth: Word; - FTextureHeight: Word; FAlpha: Byte; FBlending: Boolean; - FTextureIDs: Array of - record - case Anim: Boolean of - False: (Tex: Cardinal); - True: (AnTex: TAnimation); - end; - + FTextureIDs: ATextureID; mMovingSpeed: TDFPoint; mMovingStart: TDFPoint; mMovingEnd: TDFPoint; mMovingActive: Boolean; mMoveOnce: Boolean; + mOldMovingActive: Boolean; + mSizeSpeed: TDFSize; mSizeEnd: TDFSize; mEndPosTrig: Integer; mEndSizeTrig: Integer; + mNeedSend: Boolean; // for network + private function getx1 (): Integer; inline; function gety1 (): Integer; inline; @@ -77,6 +79,16 @@ type function getMovingEndY (): Integer; inline; procedure setMovingEndY (v: Integer); inline; + function getSizeSpeedX (): Integer; inline; + procedure setSizeSpeedX (v: Integer); inline; + function getSizeSpeedY (): Integer; inline; + procedure setSizeSpeedY (v: Integer); inline; + + function getSizeEndX (): Integer; inline; + procedure setSizeEndX (v: Integer); inline; + function getSizeEndY (): Integer; inline; + procedure setSizeEndY (v: Integer); inline; + public FCurTexture: Integer; // Íîìåð òåêóùåé òåêñòóðû FCurFrame: Integer; @@ -84,10 +96,8 @@ type FX, FY: Integer; FWidth, FHeight: Word; FPanelType: Word; - FSaveIt: Boolean; // Ñîõðàíÿòü ïðè SaveState? FEnabled: Boolean; FDoor: Boolean; - FMoved: Boolean; FLiftType: Byte; FLastAnimLoop: Byte; // sorry, there fields are public to allow setting 'em in g_map; this should be fixed later @@ -96,6 +106,7 @@ type 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 + hasTexTrigger: Boolean; // HACK: true when there's a trigger than can change my texture constructor Create(PanelRec: TDynRecord; AddTextures: TAddTextureArray; @@ -103,17 +114,16 @@ type var Textures: TLevelTextureArray; aguid: Integer); destructor Destroy(); override; - procedure Draw(); - procedure DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer); procedure Update(); procedure SetFrame(Frame: Integer; Count: Byte); procedure NextTexture(AnimLoop: Byte = 0); procedure SetTexture(ID: Integer; AnimLoop: Byte = 0); function GetTextureID(): Cardinal; function GetTextureCount(): Integer; + function CanChangeTexture(): Boolean; - procedure SaveState(var Mem: TBinMemoryWriter); - procedure LoadState(var Mem: TBinMemoryReader); + procedure SaveState (st: TStream); + procedure LoadState (st: TStream); procedure positionChanged (); inline; @@ -127,6 +137,10 @@ type function getIsGLift (): Boolean; inline; // gLifts function getIsGBlockMon (): Boolean; inline; // gBlockMon + // get-and-clear + function gncNeedSend (): Boolean; inline; + procedure setDirty (); inline; // why `dirty`? 'cause i may introduce property `needSend` later + public property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive @@ -141,12 +155,10 @@ type 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 enabled: Boolean read FEnabled write FEnabled; + property door: Boolean read FDoor write FDoor; + property liftType: Byte read FLiftType write FLiftType; + property lastAnimLoop: Byte read FLastAnimLoop write FLastAnimLoop; property movingSpeedX: Integer read getMovingSpeedX write setMovingSpeedX; property movingSpeedY: Integer read getMovingSpeedY write setMovingSpeedY; @@ -157,6 +169,11 @@ type property movingActive: Boolean read mMovingActive write mMovingActive; property moveOnce: Boolean read mMoveOnce write mMoveOnce; + property sizeSpeedX: Integer read getSizeSpeedX write setSizeSpeedX; + property sizeSpeedY: Integer read getSizeSpeedY write setSizeSpeedY; + property sizeEndX: Integer read getSizeEndX write setSizeEndX; + property sizeEndY: Integer read getSizeEndY write setSizeEndY; + property isGBack: Boolean read getIsGBack; property isGStep: Boolean read getIsGStep; property isGWall: Boolean read getIsGWall; @@ -167,17 +184,31 @@ type property isGLift: Boolean read getIsGLift; property isGBlockMon: Boolean read getIsGBlockMon; + (* private state *) + property Alpha: Byte read FAlpha; + property Blending: Boolean read FBlending; + property TextureIDs: ATextureID read FTextureIDs; + public property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed; property movingStart: TDFPoint read mMovingStart write mMovingStart; property movingEnd: TDFPoint read mMovingEnd write mMovingEnd; + property sizeSpeed: TDFSize read mSizeSpeed write mSizeSpeed; + property sizeEnd: TDFSize read mSizeEnd write mSizeEnd; + property endPosTrigId: Integer read mEndPosTrig write mEndPosTrig; property endSizeTrigId: Integer read mEndSizeTrig write mEndSizeTrig; end; TPanelArray = Array of TPanel; +const + LIFTTYPE_UP = 0; + LIFTTYPE_DOWN = 1; + LIFTTYPE_LEFT = 2; + LIFTTYPE_RIGHT = 3; + var g_dbgpan_mplat_active: Boolean = {$IF DEFINED(D2F_DEBUG)}true{$ELSE}true{$ENDIF}; g_dbgpan_mplat_step: Boolean = false; // one step, and stop @@ -185,21 +216,46 @@ var implementation -uses - SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons, g_triggers, - g_console, g_language, g_monsters, g_player, g_grid, e_log, GL, utils; + uses + {$IFDEF ENABLE_GFX} + g_gfx, + {$ENDIF} + {$IFDEF ENABLE_GIBS} + g_gibs, + {$ENDIF} + g_basic, g_map, g_game, g_weapons, g_triggers, + g_console, g_language, g_monsters, g_player, g_grid, e_log, geom, utils, xstreams + ; const PANEL_SIGNATURE = $4C4E4150; // 'PANL' { T P a n e l : } + function FindTextureByName (const name: String): Integer; + var i: Integer; + begin + Result := -1; + if Textures <> nil then + begin + for i := 0 to High(Textures) do + begin + if Textures[i].TextureName = name then + begin + Result := i; + break; + end + end + end + end; + constructor TPanel.Create(PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; var Textures: TLevelTextureArray; aguid: Integer); var i: Integer; + tnum: Integer; begin X := PanelRec.X; Y := PanelRec.Y; @@ -210,7 +266,6 @@ begin FCurFrame := 0; FCurFrameCount := 0; LastAnimLoop := 0; - Moved := False; mapId := PanelRec.id; mGUID := aguid; @@ -218,7 +273,8 @@ begin mMovingSpeed := PanelRec.moveSpeed; mMovingStart := PanelRec.moveStart; mMovingEnd := PanelRec.moveEnd; - mMovingActive := PanelRec['move_active'].varvalue; + mMovingActive := PanelRec['move_active'].value; + mOldMovingActive := mMovingActive; mMoveOnce := PanelRec.moveOnce; mSizeSpeed := PanelRec.sizeSpeed; @@ -227,42 +283,22 @@ begin mEndPosTrig := PanelRec.endPosTrig; mEndSizeTrig := PanelRec.endSizeTrig; + mNeedSend := false; + // Òèï ïàíåëè: PanelType := PanelRec.PanelType; Enabled := True; Door := False; - LiftType := 0; - SaveIt := False; + LiftType := LIFTTYPE_UP; + hasTexTrigger := False; case PanelType of - PANEL_OPENDOOR: - begin - Enabled := False; - Door := True; - SaveIt := True; - end; - PANEL_CLOSEDOOR: - begin - Door := True; - SaveIt := True; - end; - PANEL_LIFTUP: - SaveIt := True; - PANEL_LIFTDOWN: - begin - LiftType := 1; - SaveIt := True; - end; - PANEL_LIFTLEFT: - begin - LiftType := 2; - SaveIt := True; - end; - PANEL_LIFTRIGHT: - begin - LiftType := 3; - SaveIt := True; - end; + PANEL_OPENDOOR: begin Enabled := False; Door := True; end; + PANEL_CLOSEDOOR: Door := True; + PANEL_LIFTUP: LiftType := LIFTTYPE_UP; //??? + PANEL_LIFTDOWN: LiftType := LIFTTYPE_DOWN; + PANEL_LIFTLEFT: LiftType := LIFTTYPE_LEFT; + PANEL_LIFTRIGHT: LiftType := LIFTTYPE_RIGHT; end; // Íåâèäèìàÿ: @@ -291,16 +327,11 @@ begin begin SetLength(FTextureIDs, 1); FTextureIDs[0].Anim := False; - case PanelRec.PanelType of - PANEL_WATER: - FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_WATER); - PANEL_ACID1: - FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_ACID1); - PANEL_ACID2: - FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_ACID2); + PANEL_WATER: FTextureIDs[0].Texture := FindTextureByName(TEXTURE_NAME_WATER); + PANEL_ACID1: FTextureIDs[0].Texture := FindTextureByName(TEXTURE_NAME_ACID1); + PANEL_ACID2: FTextureIDs[0].Texture := FindTextureByName(TEXTURE_NAME_ACID2); end; - FCurTexture := 0; Exit; end; @@ -317,39 +348,29 @@ begin for i := 0 to Length(FTextureIDs)-1 do begin - FTextureIDs[i].Anim := AddTextures[i].Anim; + FTextureIDs[i].Texture := AddTextures[i].Texture; + FTextureIDs[i].Anim := Textures[AddTextures[i].Texture].FramesCount > 0; if FTextureIDs[i].Anim then - begin // Àíèìèðîâàííàÿ òåêñòóðà - FTextureIDs[i].AnTex := - TAnimation.Create(Textures[AddTextures[i].Texture].FramesID, - True, Textures[AddTextures[i].Texture].Speed); - FTextureIDs[i].AnTex.Blending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING); - FTextureIDs[i].AnTex.Alpha := PanelRec.Alpha; - SaveIt := True; - end - else - begin // Îáû÷íàÿ òåêñòóðà - FTextureIDs[i].Tex := Textures[AddTextures[i].Texture].TextureID; - end; + begin // Àíèìèðîâàííàÿ òåêñòóðà + FTextureIDs[i].AnTex := TAnimationState.Create(True, Textures[AddTextures[i].Texture].Speed, Textures[AddTextures[i].Texture].FramesCount); + end end; // Òåêñòóð íåñêîëüêî - íóæíî ñîõðàíÿòü òåêóùóþ: - if Length(FTextureIDs) > 1 then - SaveIt := True; + //if Length(FTextureIDs) > 1 then SaveIt := True; + + if (PanelRec.TextureRec = nil) then tnum := -1 else tnum := PanelRec.tagInt; + if (tnum < 0) then tnum := Length(Textures); // Åñëè íå ñïåöòåêñòóðà, òî çàäàåì ðàçìåðû: - if PanelRec.TextureNum > High(Textures) then + if ({PanelRec.TextureNum}tnum > High(Textures)) then begin - e_WriteLog(Format('WTF?! PanelRec.TextureNum is out of limits! (%d : %d)', [PanelRec.TextureNum, High(Textures)]), MSG_FATALERROR); - FTextureWidth := 2; - FTextureHeight := 2; + e_WriteLog(Format('WTF?! tnum is out of limits! (%d : %d)', [tnum, High(Textures)]), TMsgType.Warning); FAlpha := 0; FBlending := ByteBool(0); end - else if not g_Map_IsSpecialTexture(Textures[PanelRec.TextureNum].TextureName) then + else if not g_Map_IsSpecialTexture(Textures[{PanelRec.TextureNum}tnum].TextureName) then begin - FTextureWidth := Textures[PanelRec.TextureNum].Width; - FTextureHeight := Textures[PanelRec.TextureNum].Height; FAlpha := PanelRec.Alpha; FBlending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING); end; @@ -386,6 +407,16 @@ procedure TPanel.setMovingEndX (v: Integer); inline; begin mMovingEnd.X := v; en function TPanel.getMovingEndY (): Integer; inline; begin result := mMovingEnd.Y; end; procedure TPanel.setMovingEndY (v: Integer); inline; begin mMovingEnd.Y := v; end; +function TPanel.getSizeSpeedX (): Integer; inline; begin result := mSizeSpeed.w; end; +procedure TPanel.setSizeSpeedX (v: Integer); inline; begin mSizeSpeed.w := v; end; +function TPanel.getSizeSpeedY (): Integer; inline; begin result := mSizeSpeed.h; end; +procedure TPanel.setSizeSpeedY (v: Integer); inline; begin mSizeSpeed.h := v; end; + +function TPanel.getSizeEndX (): Integer; inline; begin result := mSizeEnd.w; end; +procedure TPanel.setSizeEndX (v: Integer); inline; begin mSizeEnd.w := v; end; +function TPanel.getSizeEndY (): Integer; inline; begin result := mSizeEnd.h; end; +procedure TPanel.setSizeEndY (v: Integer); inline; begin mSizeEnd.h := 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; @@ -396,116 +427,8 @@ function TPanel.getIsGFore (): Boolean; inline; begin result := ((tag and GridTa 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; - NoTextureID: DWORD; - NW, NH: Word; -begin - if {Enabled and} (FCurTexture >= 0) and - (Width > 0) and (Height > 0) and (FAlpha < 255) and - ((g_dbg_scale <> 1.0) or g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)) then - begin - if FTextureIDs[FCurTexture].Anim then - begin // Àíèìèðîâàííàÿ òåêñòóðà - if FTextureIDs[FCurTexture].AnTex = nil then - Exit; - - for xx := 0 to (Width div FTextureWidth)-1 do - for yy := 0 to (Height div FTextureHeight)-1 do - FTextureIDs[FCurTexture].AnTex.Draw( - X + xx*FTextureWidth, - Y + yy*FTextureHeight, M_NONE); - end - else - begin // Îáû÷íàÿ òåêñòóðà - case FTextureIDs[FCurTexture].Tex of - LongWord(TEXTURE_SPECIAL_WATER): - e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1, - 0, 0, 255, 0, B_FILTER); - LongWord(TEXTURE_SPECIAL_ACID1): - e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1, - 0, 128, 0, 0, B_FILTER); - LongWord(TEXTURE_SPECIAL_ACID2): - e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1, - 128, 0, 0, 0, B_FILTER); - LongWord(TEXTURE_NONE): - if g_Texture_Get('NOTEXTURE', NoTextureID) then - begin - e_GetTextureSize(NoTextureID, @NW, @NH); - e_DrawFill(NoTextureID, X, Y, Width div NW, Height div NH, - 0, False, False); - end else - begin - xx := X + (Width div 2); - yy := Y + (Height div 2); - e_DrawFillQuad(X, Y, xx, yy, - 255, 0, 255, 0); - e_DrawFillQuad(xx, Y, X+Width-1, yy, - 255, 255, 0, 0); - e_DrawFillQuad(X, yy, xx, Y+Height-1, - 255, 255, 0, 0); - e_DrawFillQuad(xx, yy, X+Width-1, Y+Height-1, - 255, 0, 255, 0); - end; - - else - if not mMovingActive then - e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y, Width div FTextureWidth, Height div FTextureHeight, FAlpha, True, FBlending) - else - e_DrawFillX(FTextureIDs[FCurTexture].Tex, X, Y, Width, Height, FAlpha, True, FBlending, g_dbg_scale); - end; - end; - end; -end; - -procedure TPanel.DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer); - procedure extrude (x: Integer; y: Integer); - begin - glVertex2i(x+(x-lightX)*500, y+(y-lightY)*500); - //e_WriteLog(Format(' : (%d,%d)', [x+(x-lightX)*300, y+(y-lightY)*300]), MSG_WARNING); - end; - - procedure drawLine (x0: Integer; y0: Integer; x1: Integer; y1: Integer); - begin - // does this side facing the light? - if ((x1-x0)*(lightY-y0)-(lightX-x0)*(y1-y0) >= 0) then exit; - //e_WriteLog(Format('lightpan: (%d,%d)-(%d,%d)', [x0, y0, x1, y1]), MSG_WARNING); - // this edge is facing the light, extrude and draw it - glVertex2i(x0, y0); - glVertex2i(x1, y1); - extrude(x1, y1); - extrude(x0, y0); - end; - -begin - if radius < 4 then exit; - 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 - begin - if not FTextureIDs[FCurTexture].Anim then - begin - case FTextureIDs[FCurTexture].Tex of - 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; - if (Y+Height < lightY-radius) then exit; - if (X > lightX+radius) then exit; - if (Y > lightY+radius) then exit; - //e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y, Width div FTextureWidth, Height div FTextureHeight, FAlpha, True, FBlending); - - glBegin(GL_QUADS); - drawLine(x, y, x+width, y); // top - drawLine(x+width, y, x+width, y+height); // right - drawLine(x+width, y+height, x, y+height); // bottom - drawLine(x, y+height, x, y); // left - glEnd(); - end; -end; - +function TPanel.gncNeedSend (): Boolean; inline; begin result := mNeedSend; mNeedSend := false; end; +procedure TPanel.setDirty (); inline; begin mNeedSend := true; end; procedure TPanel.positionChanged (); inline; var @@ -520,7 +443,9 @@ 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); + {$IFDEF ENABLE_GFX} + g_Mark(px, py, pw, ph, MARK_WALL, false); + {$ENDIF} if (Width < 1) or (Height < 1) then begin mapGrid.proxyEnabled[proxyId] := false; @@ -537,7 +462,9 @@ begin begin mapGrid.moveBody(proxyId, X, Y); end; - g_Mark(X, Y, Width, Height, MARK_WALL); + {$IFDEF ENABLE_GFX} + g_Mark(X, Y, Width, Height, MARK_WALL); + {$ENDIF} end; end; end; @@ -551,19 +478,18 @@ var procedure TPanel.Update(); var ox, oy: Integer; - nx, ny: Integer; + nx, ny, nw, nh: Integer; ex, ey, nex, ney: Integer; mpw, mph: Integer; // return `true` if we should move by dx,dy function tryMPlatMove (px, py, pw, ph: Integer; out dx, dy: Integer; out squash: Boolean; ontop: PBoolean=nil): Boolean; var - u0, u1: Single; + u0: Single; tex, tey: Integer; pdx, pdy: Integer; - pan: TPanel; trtag: Integer; - hedge: Integer; + szdx, szdy: Integer; begin squash := false; tex := px; @@ -574,32 +500,41 @@ var if (py+ph = oy) then begin if (ontop <> nil) then ontop^ := true; - // yes, move with it; but skip steps - pan := mapGrid.traceBox(tex, tey, px, py, pw, ph, pdx, pdy, nil, (GridTagWall or GridTagDoor)); - if (pan <> nil) then - begin - //e_LogWritefln('entity on the platform; tracing=(%s,%s); endpoint=(%s,%s); mustbe=(%s,%s)', [px, py, tex, tey, px+pdx, py+pdy]); - // if we cannot move, only walls should squash the entity - { - if ((tag and (GridTagWall or GridTagDoor)) <> 0) then - begin - if (tex = px) and (tey = py) then squash := true; - end; - } - end; + // yes, move with it; but skip steps (no need to process size change here, 'cause platform top cannot be changed with it) + mapGrid.traceBox(tex, tey, px, py, pw, ph, pdx, pdy, (GridTagWall or GridTagDoor)); end else begin if (ontop <> nil) then ontop^ := false; // not standing on the platform: trace platform to see if it hits the entity - // hitedge (for `it`): 0: top; 1: right; 2: bottom; 3: left - { - if g_Collide(px, py, pw, ph, ox, oy, mpw, mph) then + // first, process size change (as we cannot sweeptest both move and size change) + // but we don't have to check for pushing if the panel is shrinking + szdx := nw-mpw; + szdy := nh-mph; + if (szdx > 0) or (szdy > 0) then begin - e_LogWritefln('entity is embedded: plr=(%s,%s)-(%s,%s); mpl=(%s,%s)-(%s,%s)', [px, py, px+pw-1, py+ph-1, ox, oy, ox+mpw-1, oy+mph-1]); + // ignore shrinking dimension + if (szdx < 0) then szdx := 0; + if (szdy < 0) then szdy := 0; + // move platform by szd* back, and check for szd* movement + if sweepAABB(ox-szdx, oy-szdy, nw, nh, szdx, szdy, px, py, pw, ph, @u0) then + begin + // yes, platform hits the entity, push the entity in the resizing direction + u0 := 1.0-u0; // how much path left? + szdx := trunc(szdx*u0); + szdy := trunc(szdy*u0); + if (szdx <> 0) or (szdy <> 0) then + begin + // has some path to go, trace the entity + trtag := (GridTagWall or GridTagDoor); + // if we're moving down, consider steps too + if (szdy > 0) then trtag := trtag or GridTagStep; + mapGrid.traceBox(tex, tey, px, py, pw, ph, szdx, szdy, trtag); + end; + end; end; - } - if sweepAABB(ox, oy, mpw, mph, pdx, pdy, px, py, pw, ph, @u0, @hedge, @u1) then + // second, process platform movement, using te* as entity starting point + if sweepAABB(ox, oy, nw, nh, pdx, pdy, tex, tey, pw, ph, @u0) then begin //e_LogWritefln('T: platsweep; u0=%s; u1=%s; hedge=%s; sweepAABB(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', [u0, u1, hedge, ox, oy, mpw, mph, pdx, pdy, px-1, py-1, pw+2, ph+2]); // yes, platform hits the entity, push the entity in the direction of the platform @@ -613,31 +548,18 @@ var trtag := (GridTagWall or GridTagDoor); // if we're moving down, consider steps too if (pdy > 0) then trtag := trtag or GridTagStep; - pan := mapGrid.traceBox(tex, tey, px, py, pw, ph, pdx, pdy, nil, trtag); - //e_LogWritefln(' tracebox: te=(%s,%s)', [tex, tey]); - // if we cannot move, only walls should squash the entity - { - if ((tag and (GridTagWall or GridTagDoor)) <> 0) then - begin - if (pan <> nil) and (tex = px) and (tey = py) then squash := true; - end; - } + mapGrid.traceBox(tex, tey, px, py, pw, ph, pdx, pdy, trtag); end; - end - else - begin - // no collistion, but may be embedded - //e_LogWritefln('F: platsweep; u0=%s; u1=%s; sweepAABB(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', [u0, u1, ox, oy, mpw, mph, pdx, pdy, px-1, py-1, pw+2, ph+2]); - //squash := (u1 >= 0.0); end; end; + // done with entity movement, new coords are in te* dx := tex-px; dy := tey-py; result := (dx <> 0) or (dy <> 0); - if (not squash) and ((tag and (GridTagWall or GridTagDoor)) <> 0) then + if ((tag and (GridTagWall or GridTagDoor)) <> 0) then begin - squash := g_Collide(tex, tey, pw, ph, nx, ny, mpw, mph); // still in platform? - //if not squash then squash := g_Map_CollidePanel(tex, tey, pw, ph, (PANEL_WALL or PANEL_OPENDOOR or PANEL_CLOSEDOOR)); + // check for squashing; as entity cannot be pushed into a wall, check only collision with the platform itself + squash := g_Collide(tex, tey, pw, ph, nx, ny, nw, nh); // squash, if still in platform end; end; @@ -655,7 +577,9 @@ var px, py, pw, ph, pdx, pdy: Integer; squash: Boolean; plr: TPlayer; - gib: PGib; + {$IFDEF ENABLE_GIBS} + gib: PGib; + {$ENDIF} cor: TCorpse; mon: TMonster; mpfrid: LongWord; @@ -677,6 +601,9 @@ begin if not g_dbgpan_mplat_active then exit; + if (mOldMovingActive <> mMovingActive) then mNeedSend := true; + mOldMovingActive := mMovingActive; + if not mMovingActive then exit; if mMovingSpeed.isZero and mSizeSpeed.isZero then exit; @@ -692,141 +619,159 @@ begin * try to push entity * if we can't push entity all the way, squash it *) + ox := X; + oy := Y; mpw := Width; mph := Height; - // old rect - ox := X; - oy := Y; - ex := ox+mpw-1; - ey := ox+mph-1; - // new rect + nw := mpw+mSizeSpeed.w; + nh := mph+mSizeSpeed.h; nx := ox+mMovingSpeed.X; ny := oy+mMovingSpeed.Y; - nex := nx+mpw-1; - ney := ny+mph-1; - // full rect - cx0 := nmin(ox, nx); - cy0 := nmin(oy, ny); - cx1 := nmax(ex, nex); - cy1 := nmax(ey, ney); - // extrude - cx0 -= 1; - cy0 -= 1; - cx1 += 1; - cy1 += 1; - cw := cx1-cx0+1; - ch := cy1-cy0+1; - - // process "obstacle" panels - if ((tag and GridTagObstacle) <> 0) then + + // force network updates only if some sudden change happened + // set the flag here, so we can sync affected monsters + if not mSizeSpeed.isZero and (nw = mSizeEnd.w) and (nh = mSizeEnd.h) then + begin + mNeedSend := true; + end + else if ((mMovingSpeed.X < 0) and (nx <= mMovingStart.X)) or ((mMovingSpeed.X > 0) and (nx >= mMovingEnd.X)) then + begin + mNeedSend := true; + end + else if ((mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y)) or ((mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y)) then begin - // temporarily turn off this panel, so it won't interfere with collision checks - mapGrid.proxyEnabled[proxyId] := false; + mNeedSend := true; + end; - // process players - for f := 0 to High(gPlayers) do + // if pannel disappeared, we don't have to do anything + if (nw > 0) and (nh > 0) then + begin + // old rect + ex := ox+mpw-1; + ey := ox+mph-1; + // new rect + nex := nx+nw-1; + ney := ny+nh-1; + // full rect + cx0 := nmin(ox, nx); + cy0 := nmin(oy, ny); + cx1 := nmax(ex, nex); + cy1 := nmax(ey, ney); + // extrude + cx0 -= 1; + cy0 -= 1; + cx1 += 1; + cy1 += 1; + cw := cx1-cx0+1; + ch := cy1-cy0+1; + + // process "obstacle" panels + if ((tag and GridTagObstacle) <> 0) then begin - plr := gPlayers[f]; - if (plr = nil) or (not plr.alive) then continue; - plr.getMapBox(px, py, pw, ph); - if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; - if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then - begin - // set new position - plr.moveBy(pdx, pdy); // this will call `positionChanged()` for us - end; - // squash player, if necessary - if squash then plr.Damage(15000, 0, 0, 0, HIT_TRAP); - end; + // temporarily turn off this panel, so it won't interfere with collision checks + mapGrid.proxyEnabled[proxyId] := false; - // process gibs - for f := 0 to High(gGibs) do - begin - gib := @gGibs[f]; - if not gib.alive then continue; - gib.getMapBox(px, py, pw, ph); - if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; - if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then + // process players + for f := 0 to High(gPlayers) do begin - // set new position - gib.moveBy(pdx, pdy); // this will call `positionChanged()` for us - { - if ontop then + plr := gPlayers[f]; + if (plr = nil) or (not plr.alive) then continue; + plr.getMapBox(px, py, pw, ph); + if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; + if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then begin - gib.Obj.Vel.X += pdx; - gib.Obj.Vel.Y += pdy; + // set new position + plr.moveBy(pdx, pdy); // this will call `positionChanged()` for us end; - } + // squash player, if necessary + if not g_Game_IsClient and squash then plr.Damage(15000, 0, 0, 0, HIT_TRAP); end; - end; - // move and push corpses - for f := 0 to High(gCorpses) do - begin - cor := gCorpses[f]; - if (cor = nil) then continue; - cor.getMapBox(px, py, pw, ph); - if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; - if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then + {$IFDEF ENABLE_GIBS} + // process gibs + for f := 0 to High(gGibs) do + begin + gib := @gGibs[f]; + if not gib.alive then continue; + gib.getMapBox(px, py, pw, ph); + if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; + if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then + begin + // set new position + gib.moveBy(pdx, pdy); // this will call `positionChanged()` for us + end; + end; + {$ENDIF} + + // move and push corpses + for f := 0 to High(gCorpses) do begin - // set new position - cor.moveBy(pdx, pdy); // this will call `positionChanged()` for us - { - if ontop then + cor := gCorpses[f]; + if (cor = nil) then continue; + cor.getMapBox(px, py, pw, ph); + if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; + if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then begin - cor.ObjPtr.Vel.X += pdx; - cor.ObjPtr.Vel.Y += pdy; + // set new position + cor.moveBy(pdx, pdy); // this will call `positionChanged()` for us end; - } end; - end; - // collect monsters - monCheckListUsed := 0; - g_Mons_ForEachAt(cx0, cy0, cw, ch, monCollect); + // collect monsters + monCheckListUsed := 0; + g_Mons_ForEachAt(cx0, cy0, cw, ch, monCollect); - // process collected monsters - if (monCheckListUsed > 0) then - begin - mpfrid := g_Mons_getNewMPlatFrameId(); - for f := 0 to monCheckListUsed do + // process collected monsters + if (monCheckListUsed > 0) then begin - mon := monCheckList[f]; - if (mon = nil) or (not mon.alive) or (mon.mplatCheckFrameId = mpfrid) then continue; - mon.mplatCheckFrameId := mpfrid; - mon.getMapBox(px, py, pw, ph); - //if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; - if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then + mpfrid := g_Mons_getNewMPlatFrameId(); + for f := 0 to monCheckListUsed do begin - // set new position - mon.moveBy(pdx, pdy); // this will call `positionChanged()` for us + mon := monCheckList[f]; + if (mon = nil) or (not mon.alive) or (mon.mplatCheckFrameId = mpfrid) then continue; + mon.mplatCheckFrameId := mpfrid; + mon.getMapBox(px, py, pw, ph); + //if not g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then continue; + if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash) then + begin + // set new position + mon.moveBy(pdx, pdy); // this will call `positionChanged()` for us + //???FIXME: do we really need to send monsters over the net? + // i don't think so, as dead reckoning should take care of 'em + // ok, send new monster position only if platform is going to change it's direction + if mNeedSend then mon.setDirty(); + end; + // squash monster, if necessary + if not g_Game_IsClient and squash then mon.Damage(15000, 0, 0, 0, HIT_TRAP); end; - // squash player, if necessary - if squash then mon.Damage(15000, 0, 0, 0, HIT_TRAP); end; - end; - // restore panel state - mapGrid.proxyEnabled[proxyId] := true; + // restore panel state + mapGrid.proxyEnabled[proxyId] := true; + end; end; // move panel X := nx; Y := ny; - FWidth += mSizeSpeed.w; - FHeight += mSizeSpeed.h; + FWidth := nw; + FHeight := nh; positionChanged(); actMoveTrig := false; actSizeTrig := false; - { - if not mSizeSpeed.isZero then + // `mNeedSend` was set above + + // check "size stop" + if not mSizeSpeed.isZero and (nw = mSizeEnd.w) and (nh = mSizeEnd.h) then begin - e_LogWritefln('ss: size_speed=(%s,%s); size=(%s,%s); move_speed=(%s,%s); oy=%s; ny=%s; etp:%s; ets:%s', [mSizeSpeed.w, mSizeSpeed.h, FWidth, FHeight, mMovingSpeed.X, mMovingSpeed.Y, oy, ny, mEndPosTrig, mEndSizeTrig]); + mSizeSpeed.w := 0; + mSizeSpeed.h := 0; + actSizeTrig := true; + if (nw < 1) or (nh < 1) then mMovingActive := false; //HACK! end; - } // reverse moving direction, if necessary if ((mMovingSpeed.X < 0) and (nx <= mMovingStart.X)) or ((mMovingSpeed.X > 0) and (nx >= mMovingEnd.X)) then @@ -841,29 +786,23 @@ begin actMoveTrig := true; end; - // check "size stop" - if not mSizeSpeed.isZero and (Width = mSizeEnd.w) and (Height = mSizeEnd.h) then - begin - mSizeSpeed.w := 0; - mSizeSpeed.h := 0; - actSizeTrig := true; - if (Width < 1) or (Height < 1) then mMovingActive := false; //HACK! - //e_LogWritefln('FUUUUUUUUUUUUUU', []); - end; - + if (mOldMovingActive <> mMovingActive) then mNeedSend := true; + mOldMovingActive := mMovingActive; - if actMoveTrig then + if not g_Game_IsClient then begin - g_Triggers_Press(mEndPosTrig, ACTIVATE_CUSTOM); + if actMoveTrig then g_Triggers_Press(mEndPosTrig, ACTIVATE_CUSTOM); + if actSizeTrig then g_Triggers_Press(mEndSizeTrig, ACTIVATE_CUSTOM); end; - if actSizeTrig then - begin - g_Triggers_Press(mEndSizeTrig, ACTIVATE_CUSTOM); - end; + // some triggers may activate this, don't delay sending + //TODO: when triggers will be able to control speed and size, check that here too + if (mOldMovingActive <> mMovingActive) then mNeedSend := true; + mOldMovingActive := mMovingActive; end; end; + procedure TPanel.SetFrame(Frame: Integer; Count: Byte); function ClampInt(X, A, B: Integer): Integer; @@ -878,7 +817,7 @@ begin (FTextureIDs[FCurTexture].AnTex <> nil) and (Width > 0) and (Height > 0) and (FAlpha < 255) then begin - FCurFrame := ClampInt(Frame, 0, FTextureIDs[FCurTexture].AnTex.TotalFrames); + FCurFrame := ClampInt(Frame, 0, FTextureIDs[FCurTexture].AnTex.TotalFrames - 1); FCurFrameCount := Count; FTextureIDs[FCurTexture].AnTex.CurrentFrame := FCurFrame; FTextureIDs[FCurTexture].AnTex.CurrentCounter := FCurFrameCount; @@ -934,22 +873,8 @@ end; procedure TPanel.SetTexture(ID: Integer; AnimLoop: Byte = 0); begin -// Íåò òåêñòóð: - if Length(FTextureIDs) = 0 then - FCurTexture := -1 - else - // Òîëüêî îäíà òåêñòóðà: - if Length(FTextureIDs) = 1 then - begin - if (ID = 0) or (ID = -1) then - FCurTexture := ID; - end - else - // Áîëüøå îäíîé òåêñòóðû: - begin - if (ID >= -1) and (ID <= High(FTextureIDs)) then - FCurTexture := ID; - end; + if (ID >= -1) and (ID < Length(FTextureIDs)) then + FCurTexture := ID; // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó: if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then @@ -972,18 +897,20 @@ begin LastAnimLoop := AnimLoop; end; -function TPanel.GetTextureID(): DWORD; -begin - Result := LongWord(TEXTURE_NONE); - - if (FCurTexture >= 0) then + function TPanel.GetTextureID(): DWORD; + var Texture: Integer; begin - if FTextureIDs[FCurTexture].Anim then - Result := FTextureIDs[FCurTexture].AnTex.FramesID - else - Result := FTextureIDs[FCurTexture].Tex; + Result := LongWord(TEXTURE_NONE); + if (FCurTexture >= 0) then + begin + Texture := FTextureIDs[FCurTexture].Texture; + case Textures[Texture].TextureName of + TEXTURE_NAME_WATER: Result := DWORD(TEXTURE_SPECIAL_WATER); + TEXTURE_NAME_ACID1: Result := DWORD(TEXTURE_SPECIAL_ACID1); + TEXTURE_NAME_ACID2: Result := DWORD(TEXTURE_SPECIAL_ACID2); + end + end end; -end; function TPanel.GetTextureCount(): Integer; begin @@ -995,98 +922,120 @@ begin Result := Result + 100; end; -procedure TPanel.SaveState(Var Mem: TBinMemoryWriter); +function TPanel.CanChangeTexture(): Boolean; +begin + Result := (GetTextureCount() > 1) or hasTexTrigger; +end; + +const + PAN_SAVE_VERSION = 1; + +procedure TPanel.SaveState (st: TStream); var - sig: DWORD; anim: Boolean; begin - if (Mem = nil) then exit; - //if not SaveIt then exit; - -// Ñèãíàòóðà ïàíåëè: - sig := PANEL_SIGNATURE; // 'PANL' - Mem.WriteDWORD(sig); -// Îòêðûòà/çàêðûòà, åñëè äâåðü: - Mem.WriteBoolean(FEnabled); -// Íàïðàâëåíèå ëèôòà, åñëè ëèôò: - Mem.WriteByte(FLiftType); -// Íîìåð òåêóùåé òåêñòóðû: - Mem.WriteInt(FCurTexture); -// Êîîðäû - Mem.WriteInt(FX); - Mem.WriteInt(FY); -// Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà: + if (st = nil) then exit; + + // Ñèãíàòóðà ïàíåëè + utils.writeSign(st, 'PANL'); + utils.writeInt(st, Byte(PAN_SAVE_VERSION)); + // Îòêðûòà/çàêðûòà, åñëè äâåðü + utils.writeBool(st, FEnabled); + // Íàïðàâëåíèå ëèôòà, åñëè ëèôò + utils.writeInt(st, Byte(FLiftType)); + // Íîìåð òåêóùåé òåêñòóðû + utils.writeInt(st, Integer(FCurTexture)); + // Êîîðäèíàòû è ðàçìåð + utils.writeInt(st, Integer(FX)); + utils.writeInt(st, Integer(FY)); + utils.writeInt(st, Word(FWidth)); + utils.writeInt(st, Word(FHeight)); + // Àíèìèðîâàíà ëè òåêóùàÿ òåêñòóðà if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) then - begin - Assert(FTextureIDs[FCurTexture].AnTex <> nil, - 'TPanel.SaveState: No animation object'); - anim := True; - end + begin + assert(FTextureIDs[FCurTexture].AnTex <> nil, 'TPanel.SaveState: No animation object'); + anim := true; + end else - anim := False; - Mem.WriteBoolean(anim); -// Åñëè äà - ñîõðàíÿåì àíèìàöèþ: - if anim then - FTextureIDs[FCurTexture].AnTex.SaveState(Mem); + begin + anim := false; + end; + utils.writeBool(st, anim); + // Åñëè äà - ñîõðàíÿåì àíèìàöèþ + if anim then FTextureIDs[FCurTexture].AnTex.SaveState(st, FAlpha, FBlending); + // 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); + utils.writeInt(st, Integer(mMovingSpeed.X)); + utils.writeInt(st, Integer(mMovingSpeed.Y)); + utils.writeInt(st, Integer(mMovingStart.X)); + utils.writeInt(st, Integer(mMovingStart.Y)); + utils.writeInt(st, Integer(mMovingEnd.X)); + utils.writeInt(st, Integer(mMovingEnd.Y)); + + utils.writeInt(st, Integer(mSizeSpeed.w)); + utils.writeInt(st, Integer(mSizeSpeed.h)); + utils.writeInt(st, Integer(mSizeEnd.w)); + utils.writeInt(st, Integer(mSizeEnd.h)); + + utils.writeBool(st, mMovingActive); + utils.writeBool(st, mMoveOnce); + + utils.writeInt(st, Integer(mEndPosTrig)); + utils.writeInt(st, Integer(mEndSizeTrig)); end; -procedure TPanel.LoadState(var Mem: TBinMemoryReader); -var - sig: DWORD; - anim: Boolean; - //ox, oy: Integer; -begin - if (Mem = nil) then exit; - //if not SaveIt then exit; -// Ñèãíàòóðà ïàíåëè: - Mem.ReadDWORD(sig); - if sig <> PANEL_SIGNATURE then // 'PANL' - begin - raise EBinSizeError.Create('TPanel.LoadState: Wrong Panel Signature'); - end; -// Îòêðûòà/çàêðûòà, åñëè äâåðü: - Mem.ReadBoolean(FEnabled); -// Íàïðàâëåíèå ëèôòà, åñëè ëèôò: - Mem.ReadByte(FLiftType); -// Íîìåð òåêóùåé òåêñòóðû: - Mem.ReadInt(FCurTexture); -// Êîîðäû - //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); -// Åñëè äà - çàãðóæàåì àíèìàöèþ: - if anim then +procedure TPanel.LoadState (st: TStream); +begin + if (st = nil) then exit; + + // Ñèãíàòóðà ïàíåëè + if not utils.checkSign(st, 'PANL') then raise XStreamError.create('wrong panel signature'); + if (utils.readByte(st) <> PAN_SAVE_VERSION) then raise XStreamError.create('wrong panel version'); + // Îòêðûòà/çàêðûòà, åñëè äâåðü + FEnabled := utils.readBool(st); + // Íàïðàâëåíèå ëèôòà, åñëè ëèôò + FLiftType := utils.readByte(st); + // Íîìåð òåêóùåé òåêñòóðû + FCurTexture := utils.readLongInt(st); + // Êîîðäèíàòû è ðàçìåð + FX := utils.readLongInt(st); + FY := utils.readLongInt(st); + FWidth := utils.readWord(st); + FHeight := utils.readWord(st); + // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà + if utils.readBool(st) then begin + // Åñëè äà - çàãðóæàåì àíèìàöèþ Assert((FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) and (FTextureIDs[FCurTexture].AnTex <> nil), 'TPanel.LoadState: No animation object'); - FTextureIDs[FCurTexture].AnTex.LoadState(Mem); + FTextureIDs[FCurTexture].AnTex.LoadState(st, FAlpha, FBlending); 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); + mMovingSpeed.X := utils.readLongInt(st); + mMovingSpeed.Y := utils.readLongInt(st); + mMovingStart.X := utils.readLongInt(st); + mMovingStart.Y := utils.readLongInt(st); + mMovingEnd.X := utils.readLongInt(st); + mMovingEnd.Y := utils.readLongInt(st); + + mSizeSpeed.w := utils.readLongInt(st); + mSizeSpeed.h := utils.readLongInt(st); + mSizeEnd.w := utils.readLongInt(st); + mSizeEnd.h := utils.readLongInt(st); + + mMovingActive := utils.readBool(st); + mMoveOnce := utils.readBool(st); + + mEndPosTrig := utils.readLongInt(st); + mEndSizeTrig := utils.readLongInt(st); positionChanged(); //mapGrid.proxyEnabled[proxyId] := FEnabled; // done in g_map.pas end; + end.