Unstable 1.2.4.0

This commit is contained in:
Markus Isberg
2023-11-30 13:53:00 +02:00
parent 8a2e2ea0ae
commit fb5ea537bf
210 changed files with 4201 additions and 1283 deletions
@@ -505,51 +505,58 @@ namespace Barotrauma
minWidth += padding;
minHeight += padding;
Vector2 limits = GetHorizontalLimits(spawnPos, minWidth, minHeight, 0);
if (verticalMoveDir != 0)
int iterations = 0;
const int maxIterations = 5;
do
{
verticalMoveDir = Math.Sign(verticalMoveDir);
//do a raycast towards the top/bottom of the level depending on direction
Vector2 potentialPos = new Vector2(spawnPos.X, verticalMoveDir > 0 ? Level.Loaded.Size.Y : 0);
//3 raycasts (left, middle and right side of the sub, so we don't accidentally raycast up a passage too narrow for the sub)
for (int x = -1; x <= 1; x++)
Vector2 potentialPos = spawnPos;
if (verticalMoveDir != 0)
{
Vector2 xOffset = Vector2.UnitX * minWidth / 2 * x;
if (PickBody(
ConvertUnits.ToSimUnits(spawnPos + xOffset),
ConvertUnits.ToSimUnits(potentialPos + xOffset),
collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) != null)
verticalMoveDir = Math.Sign(verticalMoveDir);
//do a raycast towards the top/bottom of the level depending on direction
Vector2 rayEnd = new Vector2(potentialPos.X, verticalMoveDir > 0 ? Level.Loaded.Size.Y : 0);
Vector2 closestPickedPos = rayEnd;
//multiple raycast across the width of the sub (so we don't accidentally raycast up a passage too narrow for the sub)
for (float x = -1; x <= 1; x += 0.2f)
{
int offsetFromWall = 10 * -verticalMoveDir;
//if the raycast hit a wall, attempt to place the spawnpos there
if (verticalMoveDir > 0)
Vector2 xOffset = Vector2.UnitX * minWidth / 2 * x;
xOffset.X += subDockingPortOffset;
if (PickBody(
ConvertUnits.ToSimUnits(potentialPos + xOffset),
ConvertUnits.ToSimUnits(rayEnd + xOffset),
collisionCategory: Physics.CollisionLevel | Physics.CollisionWall,
customPredicate: (Fixture f) =>
{
return f.UserData is not VoronoiCell { IsDestructible: true };
}) != null)
{
potentialPos.Y = Math.Min(potentialPos.Y, ConvertUnits.ToDisplayUnits(LastPickedPosition.Y) + offsetFromWall);
}
else
{
potentialPos.Y = Math.Max(potentialPos.Y, ConvertUnits.ToDisplayUnits(LastPickedPosition.Y) + offsetFromWall);
//if the raycast hit a wall, attempt to place the spawnpos there
int offsetFromWall = 10 * -verticalMoveDir;
float pickedPos = ConvertUnits.ToDisplayUnits(LastPickedPosition.Y) + offsetFromWall;
closestPickedPos.Y =
verticalMoveDir > 0 ?
Math.Min(closestPickedPos.Y, pickedPos) :
Math.Max(closestPickedPos.Y, pickedPos);
}
}
potentialPos.Y = closestPickedPos.Y;
}
//step away from the top/bottom of the level, or from whatever wall the raycast hit,
//until we found a spot where there's enough room to place the sub
float dist = Math.Abs(potentialPos.Y - spawnPos.Y);
for (float d = dist; d > 0; d -= 100.0f)
Vector2 limits = GetHorizontalLimits(new Vector2(potentialPos.X, potentialPos.Y - (dockedBorders.Height * 0.5f * verticalMoveDir)),
maxHorizontalMoveAmount: minWidth, minHeight, verticalMoveDir, padding);
if (limits.Y - limits.X >= minWidth)
{
float y = spawnPos.Y + verticalMoveDir * d;
limits = GetHorizontalLimits(new Vector2(spawnPos.X, y), minWidth, minHeight, verticalMoveDir);
if (limits.Y - limits.X > minWidth)
{
spawnPos = new Vector2(spawnPos.X, y - (dockedBorders.Height * 0.5f * verticalMoveDir));
break;
}
}
}
Vector2 newSpawnPos = new Vector2(spawnPos.X, potentialPos.Y - (dockedBorders.Height * 0.5f * verticalMoveDir));
bool couldMoveInVerticalMoveDir = Math.Sign(newSpawnPos.Y - spawnPos.Y) == Math.Sign(verticalMoveDir);
if (!couldMoveInVerticalMoveDir) { break; }
spawnPos = ClampToHorizontalLimits(newSpawnPos, limits);
}
static Vector2 GetHorizontalLimits(Vector2 spawnPos, float minWidth, float minHeight, int verticalMoveDir)
iterations++;
} while (iterations < maxIterations);
Vector2 GetHorizontalLimits(Vector2 spawnPos, float maxHorizontalMoveAmount, float minHeight, int verticalMoveDir, int padding)
{
Vector2 refPos = spawnPos - Vector2.UnitY * minHeight * 0.5f * Math.Sign(verticalMoveDir);
@@ -580,34 +587,44 @@ namespace Barotrauma
if (Math.Abs(ruin.Area.Center.Y - refPos.Y) > (minHeight + ruin.Area.Height) * 0.5f) { continue; }
if (ruin.Area.Center.X < refPos.X)
{
minX = Math.Max(minX, ruin.Area.Right + 100.0f);
minX = Math.Max(minX, ruin.Area.Right + padding);
}
else
{
maxX = Math.Min(maxX, ruin.Area.X - 100.0f);
maxX = Math.Min(maxX, ruin.Area.X - padding);
}
}
return new Vector2(Math.Max(minX, spawnPos.X - minWidth), Math.Min(maxX, spawnPos.X + minWidth));
minX += subDockingPortOffset;
maxX += subDockingPortOffset;
return new Vector2(
Math.Max(Math.Max(minX, spawnPos.X - maxHorizontalMoveAmount - padding), 0),
Math.Min(Math.Min(maxX, spawnPos.X + maxHorizontalMoveAmount + padding), Level.Loaded.Size.X));
}
if (limits.X < 0.0f && limits.Y > Level.Loaded.Size.X)
Vector2 ClampToHorizontalLimits(Vector2 spawnPos, Vector2 limits)
{
//no walls found at either side, just use the initial spawnpos and hope for the best
}
else if (limits.X < 0)
{
//no wall found at the left side, spawn to the left from the right-side wall
spawnPos.X = limits.Y - minWidth * 0.5f - 100.0f + subDockingPortOffset;
}
else if (limits.Y > Level.Loaded.Size.X)
{
//no wall found at right side, spawn to the right from the left-side wall
spawnPos.X = limits.X + minWidth * 0.5f + 100.0f + subDockingPortOffset;
}
else
{
//walls found at both sides, use their midpoint
spawnPos.X = (limits.X + limits.Y) / 2 + subDockingPortOffset;
if (limits.X < 0.0f && limits.Y > Level.Loaded.Size.X)
{
//no walls found at either side, just use the initial spawnpos and hope for the best
}
else if (limits.X < 0)
{
//no wall found at the left side, spawn to the left from the right-side wall
spawnPos.X = limits.Y - minWidth * 0.5f - 100.0f + subDockingPortOffset;
}
else if (limits.Y > Level.Loaded.Size.X)
{
//no wall found at right side, spawn to the right from the left-side wall
spawnPos.X = limits.X + minWidth * 0.5f + 100.0f + subDockingPortOffset;
}
else
{
//walls found at both sides, use their midpoint
spawnPos.X = (limits.X + limits.Y) / 2 + subDockingPortOffset;
}
return spawnPos;
}
spawnPos.Y = MathHelper.Clamp(spawnPos.Y, dockedBorders.Height / 2 + 10, Level.Loaded.Size.Y - dockedBorders.Height / 2 - padding * 2);
@@ -929,11 +946,17 @@ namespace Barotrauma
return true;
}
/// <summary>
/// check visibility between two points (in sim units)
/// Check visibility between two points (in sim units).
/// </summary>
/// <returns>a physics body that was between the points (or null)</returns>
public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel = false, bool ignoreSubs = false, bool ignoreSensors = true, bool ignoreDisabledWalls = true, bool ignoreBranches = true)
///
/// <param name="ignoreBranches">Should plants' branches be ignored?</param>
/// <param name="blocksVisibilityPredicate">If the predicate returns false, the fixture is ignored even if it would normally block visibility.</param>
/// <returns>A physics body that was between the points (or null)</returns>
public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel = false, bool ignoreSubs = false, bool ignoreSensors = true, bool ignoreDisabledWalls = true, bool ignoreBranches = true,
Predicate<Fixture> blocksVisibilityPredicate = null)
{
Body closestBody = null;
float closestFraction = 1.0f;
@@ -968,7 +991,10 @@ namespace Barotrauma
if (sectionIndex > -1 && structure.SectionBodyDisabled(sectionIndex)) { return -1; }
}
}
if (blocksVisibilityPredicate != null && !blocksVisibilityPredicate(fixture))
{
return -1;
}
if (fraction < closestFraction)
{
closestBody = fixture.Body;
@@ -1885,12 +1911,11 @@ namespace Barotrauma
Unloading = true;
try
{
#if CLIENT
RoundSound.RemoveAllRoundSounds();
GameMain.LightManager?.ClearLights();
depthSortedDamageable.Clear();
#endif
var _loaded = new List<Submarine>(loaded);
foreach (Submarine sub in _loaded)
{
@@ -1925,9 +1950,11 @@ namespace Barotrauma
Ragdoll.RemoveAll();
PhysicsBody.RemoveAll();
StatusEffect.StopAll();
GameMain.World = null;
Powered.Grids.Clear();
Powered.ChangedConnections.Clear();
GC.Collect();
@@ -1947,6 +1974,7 @@ namespace Barotrauma
outdoorNodes?.Clear();
outdoorNodes = null;
obstructedNodes.Clear();
GameMain.GameSession?.Campaign?.UpgradeManager?.OnUpgradesChanged?.TryDeregister(upgradeEventIdentifier);
@@ -1958,11 +1986,17 @@ namespace Barotrauma
visibleEntities = null;
bodyDist.Clear();
bodies.Clear();
if (MainSub == this) { MainSub = null; }
if (MainSubs[1] == this) { MainSubs[1] = null; }
ConnectedDockingPorts?.Clear();
Powered.ChangedConnections.Clear();
Powered.Grids.Clear();
loaded.Remove(this);
}