X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_panel.pas;h=52722d38b5b033d3275382c9f29490215c3d9306;hb=176b2c983b32841d4d93dd322f3b3a5d1f1549b2;hp=bcf0883385f89309450a420e89616af331eadbc7;hpb=ba69b47c522858ed70d450d1fec26933472c080b;p=d2df-sdl.git diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index bcf0883..52722d3 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -2,8 +2,7 @@ * * 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 @@ -98,7 +97,9 @@ type FCurFrame: Integer; FCurFrameCount: Byte; FX, FY: Integer; + FOldX, FOldY: Integer; FWidth, FHeight: Word; + FOldW, FOldH: Word; FPanelType: Word; FEnabled: Boolean; FDoor: Boolean; @@ -147,6 +148,8 @@ type function gncNeedSend (): Boolean; inline; procedure setDirty (); inline; // why `dirty`? 'cause i may introduce property `needSend` later + procedure lerp (t: Single; out tX, tY, tW, tH: Integer); + public property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive @@ -219,7 +222,7 @@ implementation uses {$INCLUDE ../nogl/noGLuses.inc} - e_texture, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons, g_triggers, + e_texture, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons, g_triggers, g_items, g_console, g_language, g_monsters, g_player, g_grid, e_log, geom, utils, xstreams; const @@ -237,8 +240,12 @@ var begin X := PanelRec.X; Y := PanelRec.Y; + FOldX := X; + FOldY := Y; Width := PanelRec.Width; Height := PanelRec.Height; + FOldW := Width; + FOldH := Height; FAlpha := 0; FBlending := False; FCurFrame := 0; @@ -382,6 +389,24 @@ begin Inherited; end; +procedure TPanel.lerp (t: Single; out tX, tY, tW, tH: Integer); +begin + if mMovingActive then + begin + tX := nlerp(FOldX, FX, t); + tY := nlerp(FOldY, FY, t); + tW := nlerp(FOldW, FWidth, t); + tH := nlerp(FOldH, FHeight, t); + end + else + begin + tX := FX; + tY := FY; + tW := FWidth; + tH := FHeight; + end; +end; + 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; @@ -427,6 +452,7 @@ procedure TPanel.setDirty (); inline; begin mNeedSend := true; end; procedure TPanel.Draw (hasAmbient: Boolean; constref ambColor: TDFColor); var + tx, ty, tw, th: Integer; xx, yy: Integer; NoTextureID: DWORD; NW, NH: Word; @@ -435,45 +461,46 @@ begin (Width > 0) and (Height > 0) and (FAlpha < 255) {and g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)} then begin + lerp(gLerpFactor, tx, ty, tw, th); 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 + for xx := 0 to (tw div FTextureWidth)-1 do + for yy := 0 to (th div FTextureHeight)-1 do FTextureIDs[FCurTexture].AnTex.Draw( - X + xx*FTextureWidth, - Y + yy*FTextureHeight, TMirrorType.None); + tx + xx*FTextureWidth, + ty + yy*FTextureHeight, TMirrorType.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, TBlending.Filter); - LongWord(TEXTURE_SPECIAL_ACID1): e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1, 0, 128, 0, 0, TBlending.Filter); - LongWord(TEXTURE_SPECIAL_ACID2): e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1, 128, 0, 0, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_WATER): e_DrawFillQuad(tx, ty, tx+tw-1, ty+th-1, 0, 0, 255, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_ACID1): e_DrawFillQuad(tx, ty, tx+tw-1, ty+th-1, 0, 230, 0, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_ACID2): e_DrawFillQuad(tx, ty, tx+tw-1, ty+th-1, 230, 0, 0, 0, TBlending.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); + e_DrawFill(NoTextureID, tx, ty, tw div NW, th 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); + xx := tx + (tw div 2); + yy := ty + (th div 2); + e_DrawFillQuad(tx, ty, xx, yy, 255, 0, 255, 0); + e_DrawFillQuad(xx, ty, tx+tw-1, yy, 255, 255, 0, 0); + e_DrawFillQuad(tx, yy, xx, ty+th-1, 255, 255, 0, 0); + e_DrawFillQuad(xx, yy, tx+tw-1, ty+th-1, 255, 0, 255, 0); end; else begin if not mMovingActive then - e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y, Width div FTextureWidth, Height div FTextureHeight, FAlpha, True, FBlending, hasAmbient) + e_DrawFill(FTextureIDs[FCurTexture].Tex, tx, ty, tw div FTextureWidth, th div FTextureHeight, FAlpha, True, FBlending, hasAmbient) else - e_DrawFillX(FTextureIDs[FCurTexture].Tex, X, Y, Width, Height, FAlpha, True, FBlending, g_dbg_scale, hasAmbient); - if hasAmbient then e_AmbientQuad(X, Y, Width, Height, ambColor.r, ambColor.g, ambColor.b, ambColor.a); + e_DrawFillX(FTextureIDs[FCurTexture].Tex, tx, ty, tw, th, FAlpha, True, FBlending, g_dbg_scale, hasAmbient); + if hasAmbient then e_AmbientQuad(tx, ty, tw, th, ambColor.r, ambColor.g, ambColor.b, ambColor.a); end; end; end; @@ -481,6 +508,9 @@ begin end; procedure TPanel.DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer); +var + tx, ty, tw, th: Integer; + procedure extrude (x: Integer; y: Integer); begin glVertex2i(x+(x-lightX)*500, y+(y-lightY)*500); @@ -502,8 +532,9 @@ procedure TPanel.DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Inte 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 + g_Collide(X, Y, tw, th, sX, sY, sWidth, sHeight)} then begin + lerp(gLerpFactor, tx, ty, tw, th); if not FTextureIDs[FCurTexture].Anim then begin case FTextureIDs[FCurTexture].Tex of @@ -513,17 +544,17 @@ begin 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); + if (tx+tw < lightX-radius) then exit; + if (ty+th < lightY-radius) then exit; + if (tx > lightX+radius) then exit; + if (ty > lightY+radius) then exit; + //e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y, tw div FTextureWidth, th 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 + drawLine(tx, ty, tx+tw, ty); // top + drawLine(tx+tw, ty, tx+tw, ty+th); // right + drawLine(tx+tw, ty+th, tx, ty+th); // bottom + drawLine(tx, ty+th, tx, ty); // left glEnd(); end; end; @@ -576,6 +607,7 @@ var nx, ny, nw, nh: Integer; ex, ey, nex, ney: Integer; mpw, mph: Integer; + conveyor: Boolean; // 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; @@ -651,7 +683,7 @@ var dx := tex-px; dy := tey-py; result := (dx <> 0) or (dy <> 0); - if ((tag and (GridTagWall or GridTagDoor)) <> 0) then + if not conveyor and ((tag and (GridTagWall or GridTagDoor)) <> 0) then begin // 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 @@ -675,6 +707,8 @@ var gib: PGib; cor: TCorpse; mon: TMonster; + flg: PFlag; + itm: PItem; mpfrid: LongWord; ontop: Boolean; actMoveTrig: Boolean; @@ -717,10 +751,19 @@ begin mpw := Width; mph := Height; + // the mplat acts as a stationary conveyor belt when it's locked within a movement rect of zero area + conveyor := (mMovingEnd.X = mMovingStart.X) and (mMovingEnd.Y = mMovingStart.Y) + and (mMovingEnd.X = X) and (mMovingEnd.Y = Y); + nw := mpw+mSizeSpeed.w; nh := mph+mSizeSpeed.h; - nx := ox+mMovingSpeed.X; - ny := oy+mMovingSpeed.Y; + nx := ox; + ny := oy; + if not conveyor then + begin + nx += mMovingSpeed.X; + ny += mMovingSpeed.Y; + end; // force network updates only if some sudden change happened // set the flag here, so we can sync affected monsters @@ -809,6 +852,40 @@ begin end; end; + // move and push flags + if gGameSettings.GameMode = GM_CTF then + for f := FLAG_RED to FLAG_BLUE do + begin + flg := @gFlags[f]; + if (flg.State in [FLAG_STATE_NONE, FLAG_STATE_CAPTURED]) then continue; + px := flg.Obj.X+flg.Obj.Rect.X; + py := flg.Obj.Y+flg.Obj.Rect.Y; + pw := flg.Obj.Rect.Width; + ph := flg.Obj.Rect.Height; + 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 + if (pdx <> 0) or (pdy <> 0) then + begin + flg.Obj.X := flg.Obj.X + pdx; + flg.Obj.Y := flg.Obj.Y + pdy; + flg.NeedSend := true; + end; + end; + + // move and push items + itm := g_Items_NextAlive(-1); + while itm <> nil do + begin + if itm.Fall then + begin + itm.getMapBox(px, py, pw, ph); + if g_Collide(px, py, pw, ph, cx0, cy0, cw, ch) then + if tryMPlatMove(px, py, pw, ph, pdx, pdy, squash, @ontop) then + itm.moveBy(pdx, pdy); // this will call `positionChanged()` for us + end; + itm := g_Items_NextAlive(itm.myId); + end; + // collect monsters monCheckListUsed := 0; g_Mons_ForEachAt(cx0, cy0, cw, ch, monCollect); @@ -844,8 +921,12 @@ begin end; // move panel + FOldX := X; + FOldY := Y; X := nx; Y := ny; + FOldW := FWidth; + FOldH := FHeight; FWidth := nw; FHeight := nh; positionChanged(); @@ -864,21 +945,24 @@ begin 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 + if not conveyor then begin - if mMoveOnce then mMovingActive := false else mMovingSpeed.X := -mMovingSpeed.X; - actMoveTrig := true; - end; + // reverse moving direction, if necessary + if ((mMovingSpeed.X < 0) and (nx <= mMovingStart.X)) or ((mMovingSpeed.X > 0) and (nx >= mMovingEnd.X)) then + begin + if mMoveOnce then mMovingActive := false else mMovingSpeed.X := -mMovingSpeed.X; + actMoveTrig := true; + end; - if ((mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y)) or ((mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y)) then - begin - if mMoveOnce then mMovingActive := false else mMovingSpeed.Y := -mMovingSpeed.Y; - actMoveTrig := true; - end; + if ((mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y)) or ((mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y)) then + begin + if mMoveOnce then mMovingActive := false else mMovingSpeed.Y := -mMovingSpeed.Y; + actMoveTrig := true; + end; - if (mOldMovingActive <> mMovingActive) then mNeedSend := true; - mOldMovingActive := mMovingActive; + if (mOldMovingActive <> mMovingActive) then mNeedSend := true; + mOldMovingActive := mMovingActive; + end; if not g_Game_IsClient then begin @@ -1090,8 +1174,12 @@ begin // Êîîðäèíàòû è ðàçìåð FX := utils.readLongInt(st); FY := utils.readLongInt(st); + FOldX := FX; + FOldY := FY; FWidth := utils.readWord(st); FHeight := utils.readWord(st); + FOldW := FWidth; + FOldH := FHeight; // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà if utils.readBool(st) then begin