diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas
index 8bdbf88400547702ff9f29aff9e964f1e15d2276..bd8d9ae5567495f7b857f9f3a77575c024d4596a 100644 (file)
--- a/src/game/g_gfx.pas
+++ b/src/game/g_gfx.pas
state := TPartState.Normal;
floorY := Unknown;
ceilingY := Unknown;
+ wallEndY := Unknown;
if (velY = 0) then velY := 0.1;
if (accelY = 0) then accelY := 0.5;
end;
TPartType.Water: result := (Random(30) = 15);
else raise Exception.Create('internal error in particle engine: drip');
end;
- if result then begin velY := 0.5; accelY := 0.15; end;
+ if result then
+ begin
+ velY := 0.5;
+ accelY := 0.15;
+ // if we're falling from ceiling, switch to normal mode
+ if (state = TPartState.Stuck) and (stickDX = 0) then state := TPartState.Normal;
+ end;
end;
// switch to freefall mode
procedure applyGravity (inLiquid: Boolean);
begin
state := TPartState.Normal;
- if (inLiquid) then
+ if inLiquid then
begin
velY := 0.5;
accelY := 0.15;
end;
label
- _done;
+ _done, _gravityagain, _stuckagain;
var
pan: TPanel;
dX, dY: SmallInt;
ex, ey: Integer;
checkEnv: Boolean;
+ floorJustTraced: Boolean;
begin
if not gpart_dbg_phys_enabled then goto _done;
else
begin
// stuck to a wall
- assert(wallEndY <> Unknown);
+ if (wallEndY = Unknown) then
+ begin
+ // this can happen if mplat was moved out; find new `wallEndY`
+ findFloor(true); // force trace, just in case
+ if (floorType = TFloorType.LiquidOut) then env := TEnvType.ELiquid else env := TEnvType.EAir;
+ mapGrid.traceOrthoRayWhileIn(ex, wallEndY, x+stickDX, y, x+stickDX, floorY+1, (GridTagWall or GridTagDoor or GridTagStep));
+ end;
+ _stuckagain:
// floor transition?
if (wallEndY <= floorY) and (y >= floorY) then
begin
case floorType of
TFloorType.Wall: // hit the ground
begin
- sleep();
- goto _done; // nothing to do anymore
+ // check if our ground wasn't moved since the last scan
+ findFloor(true); // force trace
+ if (y = floorY) then
+ begin
+ sleep();
+ goto _done; // nothing to do anymore
+ end;
+ // otherwise, do it again
+ goto _stuckagain;
end;
TFloorType.LiquidIn: // entering the liquid
begin
// gravity, if not stuck
if (state <> TPartState.Stuck) and (abs(velX) < 0.1) and (abs(velY) < 0.1) then
begin
- if (floorY = Unknown) then findFloor();
+ floorJustTraced := (floorY = Unknown);
+ if floorJustTraced then findFloor();
+ _gravityagain:
// floor transition?
if (y = floorY) then
begin
case floorType of
TFloorType.Wall: // hit the ground
begin
- // nothing to do
+ // check if our ground wasn't moved since the last scan
+ if not floorJustTraced then
+ begin
+ findFloor(true); // force trace
+ if (floorType = TFloorType.LiquidOut) then env := TEnvType.ELiquid else env := TEnvType.EAir;
+ if (y <> floorY) then goto _gravityagain;
+ end;
+ // otherwise, nothing to do
end;
TFloorType.LiquidIn: // entering the liquid
begin
while (dY > 0) do
begin
// falling down
- if (floorY = Unknown) then findFloor(); // need to do this anyway
+ floorJustTraced := (floorY = Unknown);
+ if floorJustTraced then findFloor();
if (floorType = TFloorType.LiquidOut) then env := TEnvType.ELiquid else env := TEnvType.EAir;
y += dY;
//e_LogWritefln('floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
case floorType of
TFloorType.Wall: // hit the ground
begin
+ // check if our ground wasn't moved since the last scan
+ if not floorJustTraced then
+ begin
+ e_LogWritefln('force rescanning vpart at (%d,%d); floorY=%d', [x, y, floorY]);
+ findFloor(true); // force trace
+ e_LogWritefln(' rescanned vpart at (%d,%d); floorY=%d', [x, y, floorY]);
+ if (floorType = TFloorType.LiquidOut) then env := TEnvType.ELiquid else env := TEnvType.EAir;
+ if (y <> floorY) then continue;
+ end;
// environment didn't changed
hitAFloor();
break; // done with vertical movement
procedure g_GFX_Draw ();
var
a, len: Integer;
+ scaled: Boolean;
begin
if not gpart_dbg_enabled then exit;
glBegin(GL_POINTS);
+ scaled := (g_dbg_scale <> 1.0);
+
len := High(Particles);
for a := 0 to len do
begin
with Particles[a] do
begin
- if alive and (x >= sX) and (y >= sY) and (x <= sX+sWidth) and (sY <= sY+sHeight) then
+ if not alive then continue;
+ if scaled or ((x >= sX) and (y >= sY) and (x <= sX+sWidth) and (sY <= sY+sHeight)) then
begin
glColor4ub(red, green, blue, alpha);
glVertex2f(x+0.37, y+0.37);