This commit is contained in:
EvilFactory
2023-06-15 12:13:50 -03:00
210 changed files with 4491 additions and 2580 deletions
@@ -326,7 +326,9 @@ namespace Barotrauma
var lightComponent = item.GetComponent<LightComponent>();
if (lightComponent != null)
{
lightComponent.TemporaryFlickerTimer = Math.Min(EmpStrength * distFactor, 10.0f);
//multiply by 10 to make the effect more noticeable
//(a strength of 1 is already enough to kill power and shut down the lights, but we want weaker EMPs to make the lights flicker noticeably)
lightComponent.TemporaryFlickerTimer = Math.Min(EmpStrength * distFactor * 10.0f, 10.0f);
}
//discharge batteries
@@ -254,7 +254,7 @@ namespace Barotrauma
d.ForceRefreshFadeTimer(Math.Min(d.FadeTimer, d.FadeInTime));
}
UpdateProjSpecific(growModifier);
UpdateProjSpecific(growModifier, deltaTime);
if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
@@ -273,7 +273,7 @@ namespace Barotrauma
position.X -= GrowSpeed * growModifier * 0.5f * deltaTime;
}
partial void UpdateProjSpecific(float growModifier);
partial void UpdateProjSpecific(float growModifier, float deltaTime);
private void OnChangeHull(Vector2 pos, Hull particleHull)
{
@@ -33,6 +33,8 @@ namespace Barotrauma
/// </summary>
public bool IsDiagonal { get; }
public readonly float GlowEffectT;
//a value between 0.0f-1.0f (0.0 = closed, 1.0f = open)
private float open;
@@ -194,6 +196,8 @@ namespace Barotrauma
GapList.Add(this);
InsertToList();
GlowEffectT = Rand.Range(0.0f, 1.0f);
float blockerSize = ConvertUnits.ToSimUnits(Math.Max(rect.Width, rect.Height)) / 2;
outsideCollisionBlocker = GameMain.World.CreateEdge(-Vector2.UnitX * blockerSize, Vector2.UnitX * blockerSize,
BodyType.Static,
@@ -216,7 +220,7 @@ namespace Barotrauma
return new Gap(rect, IsHorizontal, Submarine);
}
public override void Move(Vector2 amount, bool ignoreContacts = false)
public override void Move(Vector2 amount, bool ignoreContacts = true)
{
if (!MathUtils.IsValid(amount))
{
@@ -224,7 +228,7 @@ namespace Barotrauma
return;
}
base.Move(amount);
base.Move(amount, ignoreContacts);
if (!DisableHullRechecks) { FindHulls(); }
}
@@ -337,8 +341,28 @@ namespace Barotrauma
}
}
private int updateCount;
public override void Update(float deltaTime, Camera cam)
{
int updateInterval = 4;
float flowMagnitude = flowForce.LengthSquared();
if (flowMagnitude < 1.0f)
{
//very sparse updates if there's practically no water moving
updateInterval = 8;
}
else if (linkedTo.Count == 2 && flowMagnitude > 10.0f)
{
//frequent updates if water is moving between hulls
updateInterval = 1;
}
updateCount++;
if (updateCount < updateInterval) { return; }
deltaTime *= updateCount;
updateCount = 0;
flowForce = Vector2.Zero;
outsideColliderRaycastTimer -= deltaTime;
@@ -590,7 +590,7 @@ namespace Barotrauma
return index;
}
public override void Move(Vector2 amount, bool ignoreContacts = false)
public override void Move(Vector2 amount, bool ignoreContacts = true)
{
if (!MathUtils.IsValid(amount))
{
@@ -851,7 +851,21 @@ namespace Barotrauma
{
decal.Update(deltaTime);
}
decals.RemoveAll(d => d.FadeTimer >= d.LifeTime || d.BaseAlpha <= 0.001f);
//clients don't remove decals unless the server says so
if (GameMain.NetworkMember is not { IsClient: true })
{
for (int i = decals.Count - 1; i >= 0; i--)
{
var decal = decals[i];
if (decal.FadeTimer >= decal.LifeTime || decal.BaseAlpha <= 0.001f)
{
decals.RemoveAt(i);
#if SERVER
decalUpdatePending = true;
#endif
}
}
}
if (aiTarget != null)
{
@@ -1509,9 +1523,8 @@ namespace Barotrauma
public void CleanSection(BackgroundSection section, float cleanVal, bool updateRequired)
{
bool decalsCleaned = false;
for (int i = 0; i < decals.Count; i++)
foreach (Decal decal in decals)
{
Decal decal = decals[i];
if (decal.AffectsSection(section))
{
decal.Clean(cleanVal);
@@ -1672,5 +1685,9 @@ namespace Barotrauma
return element;
}
public override string ToString()
{
return $"{base.ToString()} ({Name ?? "unnamed"})";
}
}
}
@@ -136,7 +136,7 @@ namespace Barotrauma
{
me.Move(position);
me.Submarine = sub;
if (!(me is Item item)) { continue; }
if (me is not Item item) { continue; }
Wire wire = item.GetComponent<Wire>();
//Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition;
if (wire != null)
@@ -296,9 +296,9 @@ namespace Barotrauma
Vector2 triangleCenter = (edge.Point1 + edge.Point2 + extrudedPoint) / 3;
foreach (GraphEdge nearbyEdge in nearbyCell.Edges)
{
if (!MathUtils.LinesIntersect(nearbyEdge.Point1, triangleCenter, edge.Point1, extrudedPoint) &&
!MathUtils.LinesIntersect(nearbyEdge.Point1, triangleCenter, edge.Point2, extrudedPoint) &&
!MathUtils.LinesIntersect(nearbyEdge.Point1, triangleCenter, edge.Point1, edge.Point2))
if (!MathUtils.LineSegmentsIntersect(nearbyEdge.Point1, triangleCenter, edge.Point1, extrudedPoint) &&
!MathUtils.LineSegmentsIntersect(nearbyEdge.Point1, triangleCenter, edge.Point2, extrudedPoint) &&
!MathUtils.LineSegmentsIntersect(nearbyEdge.Point1, triangleCenter, edge.Point1, edge.Point2))
{
isInside = true;
break;
@@ -1454,7 +1454,7 @@ namespace Barotrauma
if (node2.X <= pathNodes.Last().X) { continue; }
if (MathUtils.NearlyEqual(node1.X, pathNodes.Last().X)) { continue; }
if (Math.Abs(node1.Y - nodePos.Y) > tunnel.MinWidth && Math.Abs(node2.Y - nodePos.Y) > tunnel.MinWidth &&
!MathUtils.LinesIntersect(node1.ToVector2(), node2.ToVector2(), pathNodes.Last().ToVector2(), nodePos.ToVector2()))
!MathUtils.LineSegmentsIntersect(node1.ToVector2(), node2.ToVector2(), pathNodes.Last().ToVector2(), nodePos.ToVector2()))
{
continue;
}
@@ -1550,7 +1550,7 @@ namespace Barotrauma
foreach (GraphEdge edge in tunnel.Cells[i].Edges)
{
if (edge.AdjacentCell(tunnel.Cells[i])?.CellType == CellType.Solid &&
MathUtils.LinesIntersect(newWaypoint.WorldPosition, prevWayPoint.WorldPosition, edge.Point1, edge.Point2))
MathUtils.LineSegmentsIntersect(newWaypoint.WorldPosition, prevWayPoint.WorldPosition, edge.Point1, edge.Point2))
{
solidCellBetween = true;
break;
@@ -2801,7 +2801,7 @@ namespace Barotrauma
if (Vector2.DistanceSquared(c.EdgeCenter, validLocation.EdgeCenter) > (intervalRange.X * intervalRange.X)) { return true; }
// If there is a line from a previous path point to one of its existing cluster locations
// which intersects with the line from this path point to the new possible cluster location
if (MathUtils.LinesIntersect(anotherPathPoint.Position, c.EdgeCenter, pathPoint.Position, validLocation.EdgeCenter)) { return true; }
if (MathUtils.LineSegmentsIntersect(anotherPathPoint.Position, c.EdgeCenter, pathPoint.Position, validLocation.EdgeCenter)) { return true; }
return false;
}
}
@@ -2975,13 +2975,13 @@ namespace Barotrauma
}
/// <param name="rotation">Used by clients to set the rotation for the resources</param>
public List<Item> GenerateMissionResources(ItemPrefab prefab, int requiredAmount, PositionType positionType, out float rotation, IEnumerable<Cave> targetCaves = null)
public List<Item> GenerateMissionResources(ItemPrefab prefab, int requiredAmount, PositionType positionType, IEnumerable<Cave> targetCaves = null)
{
var allValidLocations = GetAllValidClusterLocations();
var placedResources = new List<Item>();
rotation = 0.0f;
if (allValidLocations.None()) { return placedResources; } // TODO: WHAT?!
// if there are no valid locations, don't place anything
if (allValidLocations.None()) { return placedResources; }
// Make sure not to pick a spot that already has other level resources
for (int i = allValidLocations.Count - 1; i >= 0; i--)
@@ -3077,7 +3077,6 @@ namespace Barotrauma
}
PlaceResources(prefab, requiredAmount, selectedLocation, out placedResources);
Vector2 edgeNormal = selectedLocation.Edge.GetNormal(selectedLocation.Cell);
rotation = MathHelper.ToDegrees(-MathUtils.VectorToAngle(edgeNormal) + MathHelper.PiOver2);
return placedResources;
static bool IsOnMainPath(ClusterLocation location) => location.Edge.NextToMainPath;
@@ -3182,13 +3181,11 @@ namespace Barotrauma
Vector2 edgeNormal = location.Edge.GetNormal(location.Cell);
float moveAmount = (item.body == null ? item.Rect.Height / 2 : ConvertUnits.ToDisplayUnits(item.body.GetMaxExtent() * 0.7f));
moveAmount += (item.GetComponent<LevelResource>()?.RandomOffsetFromWall ?? 0.0f) * Rand.Range(-0.5f, 0.5f, Rand.RandSync.ServerAndClient);
item.Move(edgeNormal * moveAmount, ignoreContacts: true);
item.Move(edgeNormal * moveAmount);
if (item.GetComponent<Holdable>() is Holdable h)
{
h.AttachToWall();
#if CLIENT
item.Rotation = MathHelper.ToDegrees(-MathUtils.VectorToAngle(edgeNormal) + MathHelper.PiOver2);
#endif
}
else if (item.body != null)
{
@@ -3509,7 +3506,7 @@ namespace Barotrauma
{
foreach (GraphEdge e in cell.Edges)
{
if (!MathUtils.LinesIntersect(closestPathCell.Center, pos.ToVector2(), e.Point1, e.Point2)) { continue; }
if (!MathUtils.LineSegmentsIntersect(closestPathCell.Center, pos.ToVector2(), e.Point1, e.Point2)) { continue; }
cell.CellType = CellType.Removed;
for (int x = 0; x < cellGrid.GetLength(0); x++)
@@ -294,40 +294,37 @@ namespace Barotrauma
throw new Exception($"Generating a campaign map failed (no locations created). Width: {Width}, height: {Height}");
}
foreach (Location location in Locations)
{
if (location.Type.Identifier != "outpost") { continue; }
SetStartLocation(location);
}
FindStartLocation(l => l.Type.Identifier == "outpost");
//if no outpost was found (using a mod that replaces the outpost location type?), find any type of outpost
if (CurrentLocation == null)
{
FindStartLocation(l => l.Type.HasOutpost);
}
void FindStartLocation(Func<Location, bool> predicate)
{
foreach (Location location in Locations)
{
if (!location.Type.HasOutpost) { continue; }
SetStartLocation(location);
if (!predicate(location)) { continue; }
if (CurrentLocation == null || location.MapPosition.X < CurrentLocation.MapPosition.X)
{
CurrentLocation = StartLocation = furthestDiscoveredLocation = location;
}
}
}
void SetStartLocation(Location location)
StartLocation.SecondaryFaction = null;
var startOutpostFaction = campaign?.Factions.FirstOrDefault(f => f.Prefab.StartOutpost);
if (startOutpostFaction != null)
{
if (CurrentLocation == null || location.MapPosition.X < CurrentLocation.MapPosition.X)
StartLocation.Faction = startOutpostFaction;
foreach (var connection in StartLocation.Connections)
{
CurrentLocation = StartLocation = furthestDiscoveredLocation = location;
StartLocation.SecondaryFaction = null;
var startOutpostFaction = campaign?.Factions.FirstOrDefault(f => f.Prefab.StartOutpost);
if (startOutpostFaction != null)
var otherLocation = connection.OtherLocation(StartLocation);
if (otherLocation.HasOutpost() && otherLocation.Type.OutpostTeam == CharacterTeamType.FriendlyNPC)
{
StartLocation.Faction = startOutpostFaction;
foreach (var connection in StartLocation.Connections)
{
var otherLocation = connection.OtherLocation(StartLocation);
if (otherLocation.HasOutpost() && otherLocation.Type.OutpostTeam == CharacterTeamType.FriendlyNPC)
{
otherLocation.Faction = startOutpostFaction;
}
}
}
otherLocation.Faction = startOutpostFaction;
}
}
}
@@ -20,7 +20,7 @@ namespace Barotrauma
public List<ushort> unresolvedLinkedToID;
public static int MapEntityUpdateInterval = 1;
public static int GapUpdateInterval = 4;
public static int GapUpdateInterval = 1;
public static int PoweredUpdateInterval = 1;
private static int mapEntityUpdateTick;
@@ -317,7 +317,7 @@ namespace Barotrauma
}
}
public virtual void Move(Vector2 amount, bool ignoreContacts = false)
public virtual void Move(Vector2 amount, bool ignoreContacts = true)
{
rect.X += (int)amount.X;
rect.Y += (int)amount.Y;
@@ -454,7 +454,7 @@ namespace Barotrauma
List<Wire> orphanedWires = new List<Wire>();
for (int i = 0; i < clones.Count; i++)
{
if (!(clones[i] is Item cloneItem)) { continue; }
if (clones[i] is not Item cloneItem) { continue; }
var door = cloneItem.GetComponent<Door>();
door?.RefreshLinkedGap();
@@ -509,10 +509,12 @@ namespace Barotrauma
}
(clones[itemIndex] as Item).Connections[connectionIndex].TryAddLink(cloneWire);
cloneWire.Connect((clones[itemIndex] as Item).Connections[connectionIndex], false);
cloneWire.Connect((clones[itemIndex] as Item).Connections[connectionIndex], n, addNode: false);
}
if ((cloneWire.Connections[0] == null || cloneWire.Connections[1] == null) && cloneItem.GetComponent<DockingPort>() == null)
if (originalWire.Connections.Any(c => c != null) &&
(cloneWire.Connections[0] == null || cloneWire.Connections[1] == null) &&
cloneItem.GetComponent<DockingPort>() == null)
{
if (!clones.Any(c => (c as Item)?.GetComponent<ConnectionPanel>()?.DisconnectedWires.Contains(cloneWire) ?? false))
{
@@ -786,7 +786,7 @@ namespace Barotrauma
//check if the connection overlaps with this module's connection
if (selfGapPos1.HasValue && selfGapPos2.HasValue &&
!gapPos1.NearlyEquals(gapPos2) && !selfGapPos1.Value.NearlyEquals(selfGapPos2.Value) &&
MathUtils.LinesIntersect(gapPos1, gapPos2, selfGapPos1.Value, selfGapPos2.Value))
MathUtils.LineSegmentsIntersect(gapPos1, gapPos2, selfGapPos1.Value, selfGapPos2.Value))
{
return true;
}
@@ -1105,8 +1105,8 @@ namespace Barotrauma
DebugConsole.AddWarning($"Failed to connect junction boxes between outpost modules (not enough free connections in module \"{module.PreviousModule.Info.Name}\")");
continue;
}
wire.Connect(thisJunctionBox.Connections[i], addNode: false);
wire.Connect(previousJunctionBox.Connections[i], addNode: false);
wire.TryConnect(thisJunctionBox.Connections[i], addNode: false);
wire.TryConnect(previousJunctionBox.Connections[i], addNode: false);
wire.SetNodes(new List<Vector2>());
}
}
@@ -1374,11 +1374,6 @@ namespace Barotrauma
endWaypoint.linkedTo.Add(prevWayPoint);
}
}
else
{
startWaypoint.linkedTo.Add(endWaypoint);
endWaypoint.linkedTo.Add(startWaypoint);
}
WayPoint closestWaypoint = null;
float closestDistSqr = 30.0f * 30.0f;
@@ -1595,10 +1590,11 @@ namespace Barotrauma
{
var startWaypoint = WayPoint.WayPointList.Find(wp => wp.ConnectedGap == bottomGap);
var endWaypoint = WayPoint.WayPointList.Find(wp => wp.ConnectedGap == topGap);
float margin = 100;
if (startWaypoint != null && endWaypoint != null)
{
WayPoint prevWaypoint = startWaypoint;
for (float y = startWaypoint.Position.Y + WayPoint.LadderWaypointInterval; y <= endWaypoint.Position.Y - WayPoint.LadderWaypointInterval; y += WayPoint.LadderWaypointInterval)
for (float y = bottomGap.Position.Y + margin; y <= topGap.Position.Y - margin; y += WayPoint.LadderWaypointInterval)
{
var wayPoint = new WayPoint(new Vector2(startWaypoint.Position.X, y), SpawnType.Path, ladder.Item.Submarine)
{
@@ -59,7 +59,7 @@ namespace Barotrauma
private static Explosion explosionOnBroken;
#if DEBUG
[Serialize(false, IsPropertySaveable.Yes), Editable]
[Serialize(false, IsPropertySaveable.Yes), ConditionallyEditable(ConditionallyEditable.ConditionType.HasBody)]
#else
[Serialize(false, IsPropertySaveable.Yes)]
#endif
@@ -104,9 +104,11 @@ namespace Barotrauma
public List<Body> Bodies { get; private set; }
[Serialize(false, IsPropertySaveable.Yes), ConditionallyEditable(ConditionallyEditable.ConditionType.HasBody)]
public bool CastShadow
{
get { return Prefab.CastShadow; }
get;
set;
}
public bool IsHorizontal { get; private set; }
@@ -118,7 +120,7 @@ namespace Barotrauma
private float? maxHealth;
[Serialize(100.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0)]
[Serialize(100.0f, IsPropertySaveable.Yes), ConditionallyEditable(ConditionallyEditable.ConditionType.HasBody, MinValueFloat = 0)]
public float MaxHealth
{
get => maxHealth ?? Prefab.Health;
@@ -189,14 +191,14 @@ namespace Barotrauma
set { spriteColor = value; }
}
[Editable, Serialize(false, IsPropertySaveable.Yes)]
[ConditionallyEditable(ConditionallyEditable.ConditionType.HasBody), Serialize(false, IsPropertySaveable.Yes)]
public bool UseDropShadow
{
get;
private set;
}
[Editable, Serialize("0,0", IsPropertySaveable.Yes, description: "The position of the drop shadow relative to the structure. If set to zero, the shadow is positioned automatically so that it points towards the sub's center of mass.")]
[ConditionallyEditable(ConditionallyEditable.ConditionType.HasBody), Serialize("0,0", IsPropertySaveable.Yes, description: "The position of the drop shadow relative to the structure. If set to zero, the shadow is positioned automatically so that it points towards the sub's center of mass.")]
public Vector2 DropShadowOffset
{
get;
@@ -367,7 +369,7 @@ namespace Barotrauma
private set;
}
public override void Move(Vector2 amount, bool ignoreContacts = false)
public override void Move(Vector2 amount, bool ignoreContacts = true)
{
if (!MathUtils.IsValid(amount))
{
@@ -375,7 +377,7 @@ namespace Barotrauma
return;
}
base.Move(amount);
base.Move(amount, ignoreContacts);
for (int i = 0; i < Sections.Length; i++)
{
@@ -440,13 +442,11 @@ namespace Barotrauma
}
else
{
float width = BodyWidth > 0.0f ? BodyWidth : rect.Width;
float height = BodyHeight > 0.0f ? BodyHeight : rect.Height;
if (BodyWidth > 0.0f && BodyHeight > 0.0f)
{
IsHorizontal = BodyWidth > BodyHeight;
}
else
{
IsHorizontal = (rect.Width > rect.Height);
IsHorizontal = width > height;
}
}
@@ -455,29 +455,28 @@ namespace Barotrauma
InitProjSpecific();
if (!HiddenInGame)
SerializableProperties = element != null ? SerializableProperty.DeserializeProperties(this, element) : SerializableProperty.GetProperties(this);
if (element?.GetAttribute(nameof(CastShadow)) == null)
{
if (Prefab.Body)
{
Bodies = new List<Body>();
WallList.Add(this);
CreateSections();
UpdateSections();
}
else
{
Sections = new WallSection[1];
Sections[0] = new WallSection(rect, this);
if (StairDirection != Direction.None)
{
CreateStairBodies();
}
}
CastShadow = Prefab.CastShadow;
}
SerializableProperties = element != null ? SerializableProperty.DeserializeProperties(this, element) : SerializableProperty.GetProperties(this);
if (Prefab.Body)
{
Bodies = new List<Body>();
WallList.Add(this);
CreateSections();
UpdateSections();
}
else if (StairDirection != Direction.None)
{
CreateStairBodies();
}
if (Sections == null)
{
Sections = new WallSection[1];
Sections[0] = new WallSection(rect, this);
}
#if CLIENT
foreach (var subElement in sp.ConfigElement.Elements())
@@ -1546,16 +1545,16 @@ namespace Barotrauma
}
}
if (element.GetAttributeBool("flippedx", false)) { s.FlipX(false); }
if (element.GetAttributeBool("flippedy", false)) { s.FlipY(false); }
if (element.GetAttributeBool(nameof(FlippedX), false)) { s.FlipX(false); }
if (element.GetAttributeBool(nameof(FlippedY), false)) { s.FlipY(false); }
//structures with a body drop a shadow by default
if (element.GetAttribute("usedropshadow") == null)
if (element.GetAttribute(nameof(UseDropShadow)) == null)
{
s.UseDropShadow = prefab.Body;
}
if (element.GetAttribute("noaitarget") == null)
if (element.GetAttribute(nameof(NoAITarget)) == null)
{
s.NoAITarget = prefab.NoAITarget;
}
@@ -1604,12 +1603,12 @@ namespace Barotrauma
(int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," +
width + "," + height));
if (FlippedX) element.Add(new XAttribute("flippedx", true));
if (FlippedY) element.Add(new XAttribute("flippedy", true));
if (FlippedX) { element.Add(new XAttribute("flippedx", true)); }
if (FlippedY) { element.Add(new XAttribute("flippedy", true)); }
for (int i = 0; i < Sections.Length; i++)
{
if (Sections[i].damage == 0.0f) continue;
if (Sections[i].damage == 0.0f) { continue; }
var sectionElement =
new XElement("section",
new XAttribute("i", i),
@@ -1619,6 +1618,11 @@ namespace Barotrauma
SerializableProperty.SerializeProperties(this, element);
if (CastShadow == Prefab.CastShadow)
{
element.GetAttribute(nameof(CastShadow))?.Remove();
}
foreach (var upgrade in Upgrades)
{
upgrade.Save(element);
@@ -7,6 +7,7 @@ using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
using Voronoi2;
@@ -427,17 +428,20 @@ namespace Barotrauma
/// <summary>
/// Returns a rect that contains the borders of this sub and all subs docked to it, excluding outposts
/// </summary>
public Rectangle GetDockedBorders()
public Rectangle GetDockedBorders(bool allowDifferentTeam = true)
{
checkSubmarineBorders.Clear();
return GetDockedBordersRecursive();
return GetDockedBordersRecursive(allowDifferentTeam);
}
private Rectangle GetDockedBordersRecursive()
private Rectangle GetDockedBordersRecursive(bool allowDifferentTeam)
{
Rectangle dockedBorders = Borders;
checkSubmarineBorders.Add(this);
var connectedSubs = DockedTo.Where(s => !checkSubmarineBorders.Contains(s) && !s.Info.IsOutpost);
var connectedSubs = DockedTo.Where(s =>
!checkSubmarineBorders.Contains(s) &&
!s.Info.IsOutpost &&
(allowDifferentTeam || s.TeamID == TeamID));
foreach (Submarine dockedSub in connectedSubs)
{
//use docking ports instead of world position to determine
@@ -446,7 +450,7 @@ namespace Barotrauma
Vector2? expectedLocation = CalculateDockOffset(this, dockedSub);
if (expectedLocation == null) { continue; }
Rectangle dockedSubBorders = dockedSub.GetDockedBordersRecursive();
Rectangle dockedSubBorders = dockedSub.GetDockedBordersRecursive(allowDifferentTeam);
dockedSubBorders.Location += MathUtils.ToPoint(expectedLocation.Value);
dockedBorders.Y = -dockedBorders.Y;
@@ -458,23 +462,23 @@ namespace Barotrauma
return dockedBorders;
}
/// <summary>
/// Don't use this directly, because the list is updated only when GetConnectedSubs() is called. The method is called so frequently that we don't want to create new list here.
/// </summary>
private readonly List<Submarine> connectedSubs = new List<Submarine>(2);
private readonly HashSet<Submarine> connectedSubs;
/// <summary>
/// Returns a list of all submarines that are connected to this one via docking ports, including this sub.
/// </summary>
public List<Submarine> GetConnectedSubs()
public IEnumerable<Submarine> GetConnectedSubs()
{
return connectedSubs;
}
public void RefreshConnectedSubs()
{
connectedSubs.Clear();
connectedSubs.Add(this);
GetConnectedSubsRecursive(connectedSubs);
return connectedSubs;
}
private void GetConnectedSubsRecursive(List<Submarine> subs)
private void GetConnectedSubsRecursive(HashSet<Submarine> subs)
{
foreach (Submarine dockedSub in DockedTo)
{
@@ -1067,6 +1071,8 @@ namespace Barotrauma
public void Update(float deltaTime)
{
RefreshConnectedSubs();
if (Info.IsWreck)
{
WreckAI?.Update(deltaTime);
@@ -1393,6 +1399,13 @@ namespace Barotrauma
public Submarine(SubmarineInfo info, bool showErrorMessages = true, Func<Submarine, List<MapEntity>> loadEntities = null, IdRemap linkedRemap = null) : base(null, Entity.NullEntityID)
{
Stopwatch sw = Stopwatch.StartNew();
connectedSubs = new HashSet<Submarine>(2)
{
this
};
upgradeEventIdentifier = new Identifier($"Submarine{ID}");
Loading = true;
GameMain.World.Enabled = false;
@@ -1489,8 +1502,14 @@ namespace Barotrauma
if (me.Submarine != this) { continue; }
if (me is Item item)
{
item.SpawnedInCurrentOutpost = info.OutpostGenerationParams != null;
item.AllowStealing = info.OutpostGenerationParams?.AllowStealing ?? true;
item.AllowStealing = true;
if (info.OutpostGenerationParams != null)
{
item.SpawnedInCurrentOutpost = true;
item.AllowStealing =
info.OutpostGenerationParams.AllowStealing ||
item.RootContainer is { Prefab: { AllowStealingContainedItems: true } };
}
if (item.GetComponent<Repairable>() != null && indestructible)
{
item.Indestructible = true;
@@ -1569,6 +1588,7 @@ namespace Barotrauma
#if CLIENT
GameMain.LightManager.OnMapLoaded();
Lights.ConvexHull.RecalculateAll(this);
#endif
//if the sub was made using an older version,
//halve the brightness of the lights to make them look (almost) right on the new lighting formula
@@ -1596,6 +1616,10 @@ namespace Barotrauma
Loading = false;
GameMain.World.Enabled = true;
}
sw.Stop();
string debugMsg = $"Loading {Info?.Name ?? "unknown"} took {sw.ElapsedMilliseconds} ms.";
DebugConsole.Log(debugMsg);
System.Diagnostics.Debug.WriteLine(debugMsg);
}
protected override ushort DetermineID(ushort id, Submarine submarine)
@@ -1745,8 +1769,7 @@ namespace Barotrauma
}
#endif
if (e.Submarine != this) { continue; }
var rootContainer = item.GetRootContainer();
if (rootContainer != null && rootContainer.Submarine != this) { continue; }
if (item.RootContainer != null && item.RootContainer.Submarine != this) { continue; }
}
else
{
@@ -777,12 +777,14 @@ namespace Barotrauma
characterList ??= GameSession.GetSessionCrewCharacters(CharacterType.Both);
float price = Price;
if (location.Faction is { } faction && Faction.GetPlayerAffiliationStatus(faction) is FactionAffiliation.Positive)
if (characterList.Any())
{
price *= 1f - characterList.Max(static c => c.GetStatValue(StatTypes.ShipyardBuyMultiplierAffiliated));
if (location.Faction is { } faction && Faction.GetPlayerAffiliationStatus(faction) is FactionAffiliation.Positive)
{
price *= 1f - characterList.Max(static c => c.GetStatValue(StatTypes.ShipyardBuyMultiplierAffiliated));
}
price *= 1f - characterList.Max(static c => c.GetStatValue(StatTypes.ShipyardBuyMultiplier));
}
price *= 1f - characterList.Max(static c => c.GetStatValue(StatTypes.ShipyardBuyMultiplier));
return (int)price;
}
@@ -19,7 +19,7 @@ namespace Barotrauma
public static bool ShowWayPoints = true, ShowSpawnPoints = true;
public const float LadderWaypointInterval = 55.0f;
public const float LadderWaypointInterval = 75.0f;
protected SpawnType spawnType;
private string[] idCardTags;