Fixes explosive depressurization and improves high pressure movements (#1683)

This commit is contained in:
Víctor Aguilera Puerto
2020-08-15 22:43:55 +02:00
committed by GitHub
parent 33baa73f06
commit a7fc2bccbd
2 changed files with 59 additions and 54 deletions

View File

@@ -49,21 +49,25 @@ namespace Content.Server.Atmos
{ {
if (maxForce > ThrowForce && throwTarget != GridCoordinates.InvalidGrid) if (maxForce > ThrowForce)
{ {
var moveForce = MathF.Min(maxForce * FloatMath.Clamp(moveProb, 0, 100) / 100f, 50f); if (throwTarget != GridCoordinates.InvalidGrid)
var pos = throwTarget.Position - transform.GridPosition.Position; {
var moveForce = maxForce * FloatMath.Clamp(moveProb, 0, 100) / 150f;
var pos = ((throwTarget.Position - transform.GridPosition.Position).Normalized + direction.ToVec()).Normalized;
LinearVelocity = pos * moveForce; LinearVelocity = pos * moveForce;
} }
else else
{ {
var moveForce = MathF.Min(maxForce * FloatMath.Clamp(moveProb, 0, 100) / 100f, 25f); var moveForce = MathF.Min(maxForce * FloatMath.Clamp(moveProb, 0, 100) / 2500f, 20f);
LinearVelocity = direction.ToVec() * moveForce; LinearVelocity = direction.ToVec() * moveForce;
} }
pressureComponent.LastHighPressureMovementAirCycle = cycle; pressureComponent.LastHighPressureMovementAirCycle = cycle;
} }
} }
}
public override void UpdateAfterProcessing() public override void UpdateAfterProcessing()
{ {
@@ -72,7 +76,7 @@ namespace Content.Server.Atmos
if (ControlledComponent != null && !_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.GridPosition)) if (ControlledComponent != null && !_physicsManager.IsWeightless(ControlledComponent.Owner.Transform.GridPosition))
{ {
LinearVelocity *= 0.85f; LinearVelocity *= 0.85f;
if (LinearVelocity.Length < 1f) if (MathF.Abs(LinearVelocity.Length) < 1f)
Stop(); Stop();
} }
} }

View File

@@ -17,6 +17,7 @@ using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Random; using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Random; using Robust.Shared.Random;
@@ -105,6 +106,7 @@ namespace Content.Server.Atmos
GridIndex = gridIndex; GridIndex = gridIndex;
GridIndices = gridIndices; GridIndices = gridIndices;
Air = mixture; Air = mixture;
ResetTileAtmosInfo();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -180,6 +182,8 @@ namespace Content.Server.Atmos
|| ContainerHelpers.IsInContainer(entity)) || ContainerHelpers.IsInContainer(entity))
continue; continue;
physics.WakeBody();
var pressureMovements = physics.EnsureController<HighPressureMovementController>(); var pressureMovements = physics.EnsureController<HighPressureMovementController>();
if (pressure.LastHighPressureMovementAirCycle < _gridAtmosphereComponent.UpdateCounter) if (pressure.LastHighPressureMovementAirCycle < _gridAtmosphereComponent.UpdateCounter)
{ {
@@ -328,7 +332,7 @@ namespace Content.Server.Atmos
var tile = tiles[i]; var tile = tiles[i];
tile._tileAtmosInfo.FastDone = true; tile._tileAtmosInfo.FastDone = true;
if (!(tile._tileAtmosInfo.MoleDelta > 0)) continue; if (!(tile._tileAtmosInfo.MoleDelta > 0)) continue;
Direction eligibleAdjBits = 0; var eligibleDirections = new List<Direction>();
var amtEligibleAdj = 0; var amtEligibleAdj = 0;
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
@@ -338,16 +342,17 @@ namespace Content.Server.Atmos
if (tile2._tileAtmosInfo.FastDone || tile2._tileAtmosInfo.LastQueueCycle != queueCycle) if (tile2._tileAtmosInfo.FastDone || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
continue; continue;
eligibleAdjBits |= direction; eligibleDirections.Add(direction);
amtEligibleAdj++; amtEligibleAdj++;
} }
if (amtEligibleAdj <= 0) if (amtEligibleAdj <= 0)
continue; // Oof we've painted ourselves into a corner. Bad luck. Next part will handle this. continue; // Oof we've painted ourselves into a corner. Bad luck. Next part will handle this.
var molesToMove = tile._tileAtmosInfo.MoleDelta / amtEligibleAdj; var molesToMove = tile._tileAtmosInfo.MoleDelta / amtEligibleAdj;
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
if ((eligibleAdjBits & direction) == 0 || if (eligibleDirections.Contains(direction) ||
!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue; !tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
tile.AdjustEqMovement(direction, molesToMove); tile.AdjustEqMovement(direction, molesToMove);
tile._tileAtmosInfo.MoleDelta -= molesToMove; tile._tileAtmosInfo.MoleDelta -= molesToMove;
@@ -394,13 +399,10 @@ namespace Content.Server.Atmos
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue; if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
if (giver._tileAtmosInfo.MoleDelta <= 0) if (giver._tileAtmosInfo.MoleDelta <= 0) break; // We're done here now. Let's not do more work than needed.
break; // We're done here now. Let's not do more work than needed. if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
if (tile2?._tileAtmosInfo == null || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
continue;
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue; if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
queue[queueLength++] = tile2; queue[queueLength++] = tile2;
tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow; tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
tile2._tileAtmosInfo.CurrentTransferDirection = direction.GetOpposite(); tile2._tileAtmosInfo.CurrentTransferDirection = direction.GetOpposite();
@@ -458,7 +460,7 @@ namespace Content.Server.Atmos
var queueLength = 0; var queueLength = 0;
queue[queueLength++] = taker; queue[queueLength++] = taker;
taker._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow; taker._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
for (int i = 0; i < queueLength; i++) for (var i = 0; i < queueLength; i++)
{ {
if (taker._tileAtmosInfo.MoleDelta >= 0) if (taker._tileAtmosInfo.MoleDelta >= 0)
break; // We're done here now. Let's not do more work than needed. break; // We're done here now. Let's not do more work than needed.
@@ -469,11 +471,8 @@ namespace Content.Server.Atmos
if (!tile._adjacentTiles.ContainsKey(direction)) continue; if (!tile._adjacentTiles.ContainsKey(direction)) continue;
var tile2 = tile._adjacentTiles[direction]; var tile2 = tile._adjacentTiles[direction];
if (taker._tileAtmosInfo.MoleDelta >= 0) if (taker._tileAtmosInfo.MoleDelta >= 0) break; // We're done here now. Let's not do more work than needed.
break; // We're done here now. Let's not do more work than needed. if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
if (tile2?._tileAtmosInfo == null || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
continue;
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue; if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
queue[queueLength++] = tile2; queue[queueLength++] = tile2;
tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow; tile2._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
@@ -552,38 +551,34 @@ namespace Content.Server.Atmos
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
var amount = _tileAtmosInfo[direction]; var amount = _tileAtmosInfo[direction];
transferDirections[direction] = amount;
if (amount == 0) continue; if (amount == 0) continue;
transferDirections[direction] = amount;
_tileAtmosInfo[direction] = 0; _tileAtmosInfo[direction] = 0;
hasTransferDirs = true; hasTransferDirs = true;
} }
if (!hasTransferDirs) return; if (!hasTransferDirs) return;
foreach (var direction in Cardinal) foreach (var (direction, amount) in transferDirections)
{ {
var amount = transferDirections[direction];
if (!_adjacentTiles.TryGetValue(direction, out var tile) || tile.Air == null) continue; if (!_adjacentTiles.TryGetValue(direction, out var tile) || tile.Air == null) continue;
if (amount > 0) if (amount > 0)
{ {
// Prevent infinite recursion.
tile._tileAtmosInfo[direction.GetOpposite()] = 0;
if (Air.TotalMoles < amount) if (Air.TotalMoles < amount)
FinalizeEqNeighbors(); FinalizeEqNeighbors(transferDirections.Keys);
tile.Air.Merge(Air.Remove(amount)); tile.Air.Merge(Air.Remove(amount));
UpdateVisuals(); UpdateVisuals();
tile.UpdateVisuals(); tile.UpdateVisuals();
ConsiderPressureDifference(tile, amount); ConsiderPressureDifference(direction, amount);
} }
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void FinalizeEqNeighbors() private void FinalizeEqNeighbors(IEnumerable<Direction> directions)
{ {
foreach (var direction in Cardinal) foreach (var direction in directions)
{ {
var amount = _tileAtmosInfo[direction]; var amount = _tileAtmosInfo[direction];
if(amount < 0 && _adjacentTiles.TryGetValue(direction, out var adjacent)) if(amount < 0 && _adjacentTiles.TryGetValue(direction, out var adjacent))
@@ -592,13 +587,13 @@ namespace Content.Server.Atmos
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ConsiderPressureDifference(TileAtmosphere tile, float difference) private void ConsiderPressureDifference(Direction direction, float difference)
{ {
_gridAtmosphereComponent.AddHighPressureDelta(this); _gridAtmosphereComponent.AddHighPressureDelta(this);
if (difference > PressureDifference) if (difference > PressureDifference)
{ {
PressureDifference = difference; PressureDifference = difference;
_pressureDirection = ((Vector2i) (GridIndices - tile.GridIndices)).GetCardinalDir(); _pressureDirection = difference < 0 ? direction.GetOpposite() : direction;
} }
} }
@@ -631,7 +626,7 @@ namespace Content.Server.Atmos
_currentCycle = fireCount; _currentCycle = fireCount;
var adjacentTileLength = 0; var adjacentTileLength = 0;
foreach (var (_, enemyTile) in _adjacentTiles) foreach (var (direction, enemyTile) in _adjacentTiles)
{ {
// If the tile is null or has no air, we don't do anything // If the tile is null or has no air, we don't do anything
if(enemyTile?.Air == null) continue; if(enemyTile?.Air == null) continue;
@@ -681,11 +676,11 @@ namespace Content.Server.Atmos
// Space wind! // Space wind!
if (difference > 0) if (difference > 0)
{ {
ConsiderPressureDifference(enemyTile, difference); ConsiderPressureDifference(direction, difference);
} }
else else
{ {
enemyTile.ConsiderPressureDifference(this, -difference); enemyTile.ConsiderPressureDifference(direction.GetOpposite(), -difference);
} }
LastShareCheck(); LastShareCheck();
@@ -952,10 +947,10 @@ namespace Content.Server.Atmos
} }
else else
{ {
if (i > Atmospherics.ZumosHardTileLimit) continue; if (i > Atmospherics.ZumosTileLimit) continue;
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
if (!_adjacentTiles.TryGetValue(direction, out var tile2)) continue; if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
if (tile2?.Air == null) continue; if (tile2?.Air == null) continue;
if (tile2._tileAtmosInfo.LastQueueCycle == queueCycle) continue; if (tile2._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
tile.ConsiderFirelocks(tile2); tile.ConsiderFirelocks(tile2);
@@ -985,7 +980,7 @@ namespace Content.Server.Atmos
var tile = progressionOrder[i]; var tile = progressionOrder[i];
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
if (!_adjacentTiles.TryGetValue(direction, out var tile2)) continue; if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
if (tile2?._tileAtmosInfo.LastQueueCycle != queueCycle) continue; if (tile2?._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue; if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
if(tile2.Air.Immutable) continue; if(tile2.Air.Immutable) continue;
@@ -998,14 +993,12 @@ namespace Content.Server.Atmos
} }
} }
for (int i = 0; i < progressionCount; i++) for (var i = progressionCount - 1; i >= 0; i--)
{ {
var tile = progressionOrder[i]; var tile = progressionOrder[i];
if (tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid) continue; if (tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid) continue;
var hpdLength = _gridAtmosphereComponent.HighPressureDeltaCount;
var inHdp = _gridAtmosphereComponent.HasHighPressureDelta(tile);
if(!inHdp)
_gridAtmosphereComponent.AddHighPressureDelta(tile); _gridAtmosphereComponent.AddHighPressureDelta(tile);
_gridAtmosphereComponent.AddActiveTile(tile);
if (!tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection, out var tile2) || tile2.Air == null) continue; if (!tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection, out var tile2) || tile2.Air == null) continue;
var sum = tile2.Air.TotalMoles; var sum = tile2.Air.TotalMoles;
totalGasesRemoved += sum; totalGasesRemoved += sum;
@@ -1013,11 +1006,13 @@ namespace Content.Server.Atmos
tile2._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount; tile2._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount;
tile.PressureDifference = tile._tileAtmosInfo.CurrentTransferAmount; tile.PressureDifference = tile._tileAtmosInfo.CurrentTransferAmount;
tile._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection; tile._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
if (tile2._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid) if (tile2._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid)
{ {
tile2.PressureDifference = tile2._tileAtmosInfo.CurrentTransferAmount; tile2.PressureDifference = tile2._tileAtmosInfo.CurrentTransferAmount;
tile2._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection; tile2._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
} }
tile.Air.Clear(); tile.Air.Clear();
tile.UpdateVisuals(); tile.UpdateVisuals();
tile.HandleDecompressionFloorRip(sum); tile.HandleDecompressionFloorRip(sum);
@@ -1026,7 +1021,8 @@ namespace Content.Server.Atmos
private void HandleDecompressionFloorRip(float sum) private void HandleDecompressionFloorRip(float sum)
{ {
if (sum > 20 && _robustRandom.Prob(FloatMath.Clamp(sum / 100, 0.005f, 0.5f))) var chance = FloatMath.Clamp(sum / 500, 0.005f, 0.5f);
if (sum > 20 && _robustRandom.Prob(chance))
_gridAtmosphereComponent.PryTile(GridIndices); _gridAtmosphereComponent.PryTile(GridIndices);
} }
@@ -1067,13 +1063,18 @@ namespace Content.Server.Atmos
{ {
foreach (var direction in Cardinal) foreach (var direction in Cardinal)
{ {
if(!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction))) if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
_adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction)); {
var adjacent = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
_adjacentTiles[direction] = adjacent;
adjacent.UpdateAdjacent(direction.GetOpposite());
}
} }
} }
public void UpdateAdjacent(Direction direction) public void UpdateAdjacent(Direction direction)
{ {
if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
_adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction)); _adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
} }