v1.0.21.0 (summer patch hotfix)
This commit is contained in:
@@ -201,9 +201,9 @@ namespace Barotrauma
|
||||
keys[(int)InputType.Use].Held = useInput;
|
||||
keys[(int)InputType.Use].SetState(false, useInput);
|
||||
|
||||
bool crouching = msg.ReadBoolean();
|
||||
if (AnimController is HumanoidAnimController)
|
||||
{
|
||||
bool crouching = msg.ReadBoolean();
|
||||
keys[(int)InputType.Crouch].Held = crouching;
|
||||
keys[(int)InputType.Crouch].SetState(false, crouching);
|
||||
}
|
||||
@@ -269,7 +269,34 @@ namespace Barotrauma
|
||||
if (readStatus)
|
||||
{
|
||||
ReadStatus(msg);
|
||||
AIController?.ClientRead(msg);
|
||||
bool isEnemyAi = msg.ReadBoolean();
|
||||
if (isEnemyAi)
|
||||
{
|
||||
byte aiState = msg.ReadByte();
|
||||
if (AIController is EnemyAIController enemyAi)
|
||||
{
|
||||
enemyAi.State = (AIState)aiState;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.AddWarning($"Received enemy AI data for a character with no {nameof(EnemyAIController)}. Ignoring...");
|
||||
}
|
||||
bool isPet = msg.ReadBoolean();
|
||||
if (isPet)
|
||||
{
|
||||
byte happiness = msg.ReadByte();
|
||||
byte hunger = msg.ReadByte();
|
||||
if ((AIController as EnemyAIController)?.PetBehavior is PetBehavior petBehavior)
|
||||
{
|
||||
petBehavior.Happiness = (float)happiness / byte.MaxValue * petBehavior.MaxHappiness;
|
||||
petBehavior.Hunger = (float)hunger / byte.MaxValue * petBehavior.MaxHunger;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.AddWarning($"Received pet AI data for a character with no {nameof(PetBehavior)}. Ignoring...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg.ReadPadBits();
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static float AspectRatioAdjustment => HorizontalAspectRatio < 1.4f ? (1.0f - (1.4f - HorizontalAspectRatio)) : 1.0f;
|
||||
|
||||
public static bool IsUltrawide => HorizontalAspectRatio > 2.0f;
|
||||
public static bool IsUltrawide => HorizontalAspectRatio > 2.3f;
|
||||
|
||||
public static int UIWidth
|
||||
{
|
||||
@@ -2438,13 +2438,15 @@ namespace Barotrauma
|
||||
|
||||
var pauseMenuInner = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.3f), PauseMenu.RectTransform, Anchor.Center) { MinSize = new Point(250, 300) });
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 0.6f), pauseMenuInner.RectTransform, Anchor.Center))
|
||||
float padding = 0.06f;
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 0.8f), pauseMenuInner.RectTransform, Anchor.BottomCenter) { RelativeOffset = new Vector2(0.0f, padding) })
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.1f, 0.1f), pauseMenuInner.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point((int)(15 * GUI.Scale)) },
|
||||
new GUIButton(new RectTransform(new Vector2(0.1f, 0.07f), pauseMenuInner.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(padding) },
|
||||
"", style: "GUIBugButton")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
@@ -2520,6 +2522,13 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GUITextBlock.AutoScaleAndNormalize(buttonContainer.Children.Where(c => c is GUIButton).Select(c => ((GUIButton)c).TextBlock));
|
||||
//scale to ensure there's enough room for all the buttons
|
||||
pauseMenuInner.RectTransform.MinSize = new Point(
|
||||
pauseMenuInner.RectTransform.MinSize.X,
|
||||
Math.Max(
|
||||
(int)(buttonContainer.Children.Sum(c => c.Rect.Height + buttonContainer.Rect.Height * buttonContainer.RelativeSpacing)),
|
||||
pauseMenuInner.RectTransform.MinSize.X));
|
||||
|
||||
}
|
||||
|
||||
void CreateButton(string textTag, GUIComponent parent, Action action, string verificationTextTag = null)
|
||||
|
||||
@@ -160,8 +160,9 @@ namespace Barotrauma
|
||||
int crewAreaY = ButtonAreaTop.Bottom + Padding;
|
||||
int crewAreaHeight = ObjectiveAnchor.Top - Padding - crewAreaY;
|
||||
|
||||
float crewAreaWidthMultiplier = GUI.IsUltrawide ? GUI.HorizontalAspectRatio : 1.0f;
|
||||
CrewArea = new Rectangle(Padding, crewAreaY, (int)(Math.Max(400 * GUI.Scale, 220) * crewAreaWidthMultiplier), crewAreaHeight);
|
||||
CrewArea = new Rectangle(Padding, crewAreaY,
|
||||
(int)MathHelper.Clamp(400 * GUI.Scale, 220, GameMain.GraphicsHeight * 0.4f),
|
||||
crewAreaHeight);
|
||||
InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY);
|
||||
|
||||
int healthWindowWidth = (int)(GameMain.GraphicsWidth * 0.5f);
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace Barotrauma
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
crewArea.RectTransform.NonScaledSize = HUDLayoutSettings.CrewArea.Size;
|
||||
|
||||
// AbsoluteOffset is set in UpdateProjectSpecific based on crewListOpenState
|
||||
crewList = new GUIListBox(new RectTransform(Vector2.One, crewArea.RectTransform), style: null, isScrollBarOnDefaultSide: false)
|
||||
|
||||
@@ -561,7 +561,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (IsSegmentFacing(losVertices[0].Pos, losVertices[1].Pos, lightSourcePos))
|
||||
{
|
||||
Array.Reverse(ShadowVertices);
|
||||
Array.Reverse(ShadowVertices, 0, ShadowVertexCount);
|
||||
}
|
||||
|
||||
CalculateLosPenumbraVertices(lightSourcePos);
|
||||
|
||||
@@ -482,7 +482,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
foreach (MapEntity e in (Submarine.VisibleEntities ?? MapEntity.mapEntityList))
|
||||
{
|
||||
if (e is Item item && item.GetComponent<Wire>() is Wire wire)
|
||||
if (e is Item item && !item.HiddenInGame && item.GetComponent<Wire>() is Wire wire)
|
||||
{
|
||||
wire.DebugDraw(spriteBatch, alpha: 0.4f);
|
||||
}
|
||||
@@ -719,6 +719,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
foreach (var ch in convexHulls)
|
||||
{
|
||||
if (!ch.Enabled) { continue; }
|
||||
Vector2 currentViewPos = pos;
|
||||
Vector2 defaultViewPos = ViewTarget.DrawPosition;
|
||||
if (ch.ParentEntity?.Submarine != null)
|
||||
@@ -742,10 +743,13 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
if (!convexHull.Enabled || !convexHull.Intersects(camView)) { continue; }
|
||||
|
||||
Vector2 relativeLightPos = pos;
|
||||
if (convexHull.ParentEntity?.Submarine != null) { relativeLightPos -= convexHull.ParentEntity.Submarine.Position; }
|
||||
Vector2 relativeViewPos = pos;
|
||||
if (convexHull.ParentEntity?.Submarine != null)
|
||||
{
|
||||
relativeViewPos -= convexHull.ParentEntity.Submarine.DrawPosition;
|
||||
}
|
||||
|
||||
convexHull.CalculateLosVertices(relativeLightPos);
|
||||
convexHull.CalculateLosVertices(relativeViewPos);
|
||||
|
||||
for (int i = 0; i < convexHull.ShadowVertexCount; i++)
|
||||
{
|
||||
|
||||
@@ -206,6 +206,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
private readonly List<ConvexHullList> convexHullsInRange;
|
||||
|
||||
private readonly HashSet<ConvexHull> visibleConvexHulls = new HashSet<ConvexHull>();
|
||||
|
||||
public Texture2D texture;
|
||||
|
||||
public SpriteEffects LightSpriteEffect;
|
||||
@@ -717,6 +719,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
public void RayCastTask(Vector2 drawPos, float rotation)
|
||||
{
|
||||
visibleConvexHulls.Clear();
|
||||
|
||||
Vector2 drawOffset = Vector2.Zero;
|
||||
float boundsExtended = TextureRange;
|
||||
if (OverrideLightTexture != null)
|
||||
@@ -904,17 +908,12 @@ namespace Barotrauma.Lights
|
||||
bool isPoint1 = MathUtils.LineToPointDistanceSquared(seg1.Start.WorldPos, seg1.End.WorldPos, p.WorldPos) < 25.0f;
|
||||
bool isPoint2 = MathUtils.LineToPointDistanceSquared(seg2.Start.WorldPos, seg2.End.WorldPos, p.WorldPos) < 25.0f;
|
||||
|
||||
bool markAsVisible = false;
|
||||
if (isPoint1 && isPoint2)
|
||||
{
|
||||
//hit at the current segmentpoint -> place the segmentpoint into the list
|
||||
verts.Add(p.WorldPos);
|
||||
|
||||
foreach (ConvexHullList hullList in convexHullsInRange)
|
||||
{
|
||||
hullList.IsHidden.Remove(p.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg1.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg2.ConvexHull);
|
||||
}
|
||||
markAsVisible = true;
|
||||
}
|
||||
else if (intersection1.index != intersection2.index)
|
||||
{
|
||||
@@ -922,13 +921,13 @@ namespace Barotrauma.Lights
|
||||
//we definitely want to generate new geometry here
|
||||
verts.Add(isPoint1 ? p.WorldPos : intersection1.pos);
|
||||
verts.Add(isPoint2 ? p.WorldPos : intersection2.pos);
|
||||
|
||||
foreach (ConvexHullList hullList in convexHullsInRange)
|
||||
{
|
||||
hullList.IsHidden.Remove(p.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg1.ConvexHull);
|
||||
hullList.IsHidden.Remove(seg2.ConvexHull);
|
||||
}
|
||||
markAsVisible = true;
|
||||
}
|
||||
if (markAsVisible)
|
||||
{
|
||||
visibleConvexHulls.Add(p.ConvexHull);
|
||||
visibleConvexHulls.Add(seg1.ConvexHull);
|
||||
visibleConvexHulls.Add(seg2.ConvexHull);
|
||||
}
|
||||
//if neither of the conditions above are met, we just assume
|
||||
//that the raycasts both resulted on the same segment
|
||||
@@ -1396,6 +1395,14 @@ namespace Barotrauma.Lights
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var visibleConvexHull in visibleConvexHulls)
|
||||
{
|
||||
foreach (var convexHullList in convexHullsInRange)
|
||||
{
|
||||
convexHullList.IsHidden.Remove(visibleConvexHull);
|
||||
}
|
||||
}
|
||||
|
||||
CalculateLightVertices(verts);
|
||||
|
||||
LastRecalculationTime = (float)Timing.TotalTime;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>1.0.20.1</Version>
|
||||
<Version>1.0.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>1.0.20.1</Version>
|
||||
<Version>1.0.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>1.0.20.1</Version>
|
||||
<Version>1.0.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>1.0.20.1</Version>
|
||||
<Version>1.0.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>1.0.20.1</Version>
|
||||
<Version>1.0.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -376,10 +376,9 @@ namespace Barotrauma
|
||||
tempBuffer.WriteBoolean(aiming);
|
||||
tempBuffer.WriteBoolean(shoot);
|
||||
tempBuffer.WriteBoolean(use);
|
||||
if (AnimController is HumanoidAnimController)
|
||||
{
|
||||
tempBuffer.WriteBoolean(((HumanoidAnimController)AnimController).Crouching);
|
||||
}
|
||||
|
||||
tempBuffer.WriteBoolean(AnimController is HumanoidAnimController { Crouching: true });
|
||||
|
||||
tempBuffer.WriteBoolean(attack);
|
||||
|
||||
Vector2 relativeCursorPos = cursorPosition - AimRefPosition;
|
||||
@@ -430,7 +429,17 @@ namespace Barotrauma
|
||||
if (writeStatus)
|
||||
{
|
||||
WriteStatus(tempBuffer);
|
||||
AIController?.ServerWrite(tempBuffer);
|
||||
tempBuffer.WriteBoolean(AIController is EnemyAIController);
|
||||
if (AIController is EnemyAIController enemyAi)
|
||||
{
|
||||
tempBuffer.WriteByte((byte)enemyAi.State);
|
||||
tempBuffer.WriteBoolean(enemyAi.PetBehavior is PetBehavior);
|
||||
if (enemyAi.PetBehavior is PetBehavior petBehavior)
|
||||
{
|
||||
tempBuffer.WriteByte((byte)((petBehavior.Happiness / petBehavior.MaxHappiness) * byte.MaxValue));
|
||||
tempBuffer.WriteByte((byte)((petBehavior.Hunger / petBehavior.MaxHunger) * byte.MaxValue));
|
||||
}
|
||||
}
|
||||
HealthUpdatePending = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>1.0.20.1</Version>
|
||||
<Version>1.0.21.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -521,8 +521,5 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void OnStateChanged(AIState from, AIState to) { }
|
||||
protected virtual void OnTargetChanged(AITarget previousTarget, AITarget newTarget) { }
|
||||
|
||||
public virtual void ClientRead(IReadMessage msg) { }
|
||||
public virtual void ServerWrite(IWriteMessage msg) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4055,18 +4055,6 @@ namespace Barotrauma
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void ServerWrite(IWriteMessage msg)
|
||||
{
|
||||
msg.WriteByte((byte)State);
|
||||
PetBehavior?.ServerWrite(msg);
|
||||
}
|
||||
|
||||
public override void ClientRead(IReadMessage msg)
|
||||
{
|
||||
State = (AIState)msg.ReadByte();
|
||||
PetBehavior?.ClientRead(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//the "memory" of the Character
|
||||
|
||||
@@ -200,7 +200,8 @@ namespace Barotrauma
|
||||
Leak.linkedTo.Any(e => e is Hull h && (character.CurrentHull == h || h.linkedTo.Contains(character.CurrentHull))),
|
||||
endNodeFilter = IsSuitableEndNode,
|
||||
// The Go To objective can be abandoned if the leak is fixed (in which case we don't want to use the dialogue)
|
||||
SpeakCannotReachCondition = () => !CheckObjectiveSpecific()
|
||||
// Only report about contextual targets.
|
||||
SpeakCannotReachCondition = () => isPriority && !CheckObjectiveSpecific()
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
|
||||
@@ -223,23 +223,30 @@ namespace Barotrauma
|
||||
Hull targetHull = GetTargetHull();
|
||||
if (!IsFollowOrder)
|
||||
{
|
||||
// Abandon if going through unsafe paths or targeting unsafe hulls.
|
||||
bool isUnreachable = HumanAIController.UnreachableHulls.Contains(targetHull);
|
||||
if (!objectiveManager.CurrentObjective.IgnoreUnsafeHulls)
|
||||
{
|
||||
if (HumanAIController.UnsafeHulls.Contains(targetHull))
|
||||
// Wait orders check this so that the bot temporarily leaves the unsafe hull.
|
||||
// Non-orders (that are not set to ignore the unsafe hulls) abandon. In practice this means e.g. repair and clean up item subobjectives (of the looping parent objective).
|
||||
// Other orders are only abandoned if the hull is unreachable, because the path is invalid or not found at all.
|
||||
if (IsWaitOrder || !objectiveManager.HasOrders())
|
||||
{
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(targetHull);
|
||||
}
|
||||
else if (PathSteering?.CurrentPath != null)
|
||||
{
|
||||
foreach (WayPoint wp in PathSteering.CurrentPath.Nodes)
|
||||
if (HumanAIController.UnsafeHulls.Contains(targetHull))
|
||||
{
|
||||
if (wp.CurrentHull == null) { continue; }
|
||||
if (HumanAIController.UnsafeHulls.Contains(wp.CurrentHull))
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(targetHull);
|
||||
}
|
||||
else if (PathSteering?.CurrentPath != null)
|
||||
{
|
||||
foreach (WayPoint wp in PathSteering.CurrentPath.Nodes)
|
||||
{
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(wp.CurrentHull);
|
||||
if (wp.CurrentHull == null) { continue; }
|
||||
if (HumanAIController.UnsafeHulls.Contains(wp.CurrentHull))
|
||||
{
|
||||
isUnreachable = true;
|
||||
HumanAIController.AskToRecalculateHullSafety(wp.CurrentHull);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,8 @@ namespace Barotrauma
|
||||
{
|
||||
var objective = new AIObjectiveGoTo(Item, character, objectiveManager)
|
||||
{
|
||||
TargetName = Item.Name
|
||||
TargetName = Item.Name,
|
||||
SpeakCannotReachCondition = () => isPriority
|
||||
};
|
||||
if (repairTool != null)
|
||||
{
|
||||
|
||||
@@ -287,7 +287,7 @@ namespace Barotrauma
|
||||
if (affliction.Prefab == null) { throw new Exception("Affliction prefab was null"); }
|
||||
float bestSuitability = 0.0f;
|
||||
Item bestItem = null;
|
||||
foreach (KeyValuePair<Identifier, float> treatmentSuitability in affliction.Prefab.TreatmentSuitability)
|
||||
foreach (KeyValuePair<Identifier, float> treatmentSuitability in affliction.Prefab.TreatmentSuitabilities)
|
||||
{
|
||||
if (currentTreatmentSuitabilities.ContainsKey(treatmentSuitability.Key) &&
|
||||
currentTreatmentSuitabilities[treatmentSuitability.Key] > bestSuitability)
|
||||
|
||||
@@ -109,6 +109,7 @@ namespace Barotrauma
|
||||
foreach (Affliction affliction in allAfflictions)
|
||||
{
|
||||
if (affliction.Prefab.IsBuff) { continue; }
|
||||
if (!affliction.Prefab.HasTreatments) { continue; }
|
||||
if (!ignoreTreatmentThreshold)
|
||||
{
|
||||
//other afflictions of the same type increase the "treatability"
|
||||
@@ -116,7 +117,6 @@ namespace Barotrauma
|
||||
float totalAfflictionStrength = character.CharacterHealth.GetTotalAdjustedAfflictionStrength(affliction);
|
||||
if (totalAfflictionStrength < affliction.Prefab.TreatmentThreshold) { continue; }
|
||||
}
|
||||
if (affliction.Prefab.TreatmentSuitability.None(kvp => kvp.Value > 0)) { continue; }
|
||||
if (allAfflictions.Any(otherAffliction => affliction.Prefab.IgnoreTreatmentIfAfflictedBy.Contains(otherAffliction.Identifier))) { continue; }
|
||||
yield return affliction;
|
||||
}
|
||||
|
||||
@@ -435,37 +435,34 @@ namespace Barotrauma
|
||||
spawnPoint ??= WayPoint.WayPointList.Where(wp => wp.SpawnType == SpawnType.Human && wp.Submarine?.Info.Type == SubmarineType.Player).GetRandomUnsynced();
|
||||
spawnPos = spawnPoint?.WorldPosition ?? Submarine.MainSub.WorldPosition;
|
||||
}
|
||||
var pet = Character.Create(speciesName, spawnPos, seed, spawnInitialItems: false);
|
||||
var petBehavior = (pet?.AIController as EnemyAIController)?.PetBehavior;
|
||||
if (petBehavior != null)
|
||||
|
||||
var characterPrefab = CharacterPrefab.FindBySpeciesName(speciesName.ToIdentifier());
|
||||
if (characterPrefab == null)
|
||||
{
|
||||
petBehavior.Owner = owner;
|
||||
var petBehaviorElement = subElement.Element("petbehavior");
|
||||
if (petBehaviorElement != null)
|
||||
DebugConsole.ThrowError($"Failed to load the pet \"{speciesName}\". Character prefab not found.");
|
||||
continue;
|
||||
}
|
||||
var pet = Character.Create(characterPrefab, spawnPos, seed, spawnInitialItems: false);
|
||||
if (pet != null)
|
||||
{
|
||||
var petBehavior = (pet.AIController as EnemyAIController)?.PetBehavior;
|
||||
if (petBehavior != null)
|
||||
{
|
||||
petBehavior.Hunger = petBehaviorElement.GetAttributeFloat("hunger", 50.0f);
|
||||
petBehavior.Happiness = petBehaviorElement.GetAttributeFloat("happiness", 50.0f);
|
||||
petBehavior.Owner = owner;
|
||||
var petBehaviorElement = subElement.Element("petbehavior");
|
||||
if (petBehaviorElement != null)
|
||||
{
|
||||
petBehavior.Hunger = petBehaviorElement.GetAttributeFloat("hunger", 50.0f);
|
||||
petBehavior.Happiness = petBehaviorElement.GetAttributeFloat("happiness", 50.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inventoryElement = subElement.Element("inventory");
|
||||
if (inventoryElement != null)
|
||||
{
|
||||
pet.SpawnInventoryItems(pet.Inventory, inventoryElement.FromPackage(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(IWriteMessage msg)
|
||||
{
|
||||
msg.WriteRangedSingle(Happiness, 0.0f, MaxHappiness, 8);
|
||||
msg.WriteRangedSingle(Hunger, 0.0f, MaxHunger, 8);
|
||||
}
|
||||
|
||||
public void ClientRead(IReadMessage msg)
|
||||
{
|
||||
Happiness = msg.ReadRangedSingle(0.0f, MaxHappiness, 8);
|
||||
Hunger = msg.ReadRangedSingle(0.0f, MaxHunger, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -841,20 +842,16 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public readonly Sprite AfflictionOverlay;
|
||||
|
||||
public IEnumerable<KeyValuePair<Identifier, float>> TreatmentSuitability
|
||||
public ImmutableDictionary<Identifier, float> TreatmentSuitabilities
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var itemPrefab in ItemPrefab.Prefabs)
|
||||
{
|
||||
float suitability = itemPrefab.GetTreatmentSuitability(Identifier) + itemPrefab.GetTreatmentSuitability(AfflictionType);
|
||||
if (!MathUtils.NearlyEqual(suitability, 0.0f))
|
||||
{
|
||||
yield return new KeyValuePair<Identifier, float>(itemPrefab.Identifier, suitability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
get;
|
||||
private set;
|
||||
} = new Dictionary<Identifier, float>().ToImmutableDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// Can this affliction be treated with some item?
|
||||
/// </summary>
|
||||
public bool HasTreatments { get; private set; }
|
||||
|
||||
public AfflictionPrefab(ContentXElement element, AfflictionsFile file, Type type) : base(file, element.GetAttributeIdentifier("identifier", ""))
|
||||
{
|
||||
@@ -974,6 +971,22 @@ namespace Barotrauma
|
||||
constructor = type.GetConstructor(new[] { typeof(AfflictionPrefab), typeof(float) });
|
||||
}
|
||||
|
||||
private void RefreshTreatmentSuitabilities()
|
||||
{
|
||||
var newTreatmentSuitabilities = new Dictionary<Identifier, float>();
|
||||
|
||||
foreach (var itemPrefab in ItemPrefab.Prefabs)
|
||||
{
|
||||
float suitability = itemPrefab.GetTreatmentSuitability(Identifier) + itemPrefab.GetTreatmentSuitability(AfflictionType);
|
||||
if (!MathUtils.NearlyEqual(suitability, 0.0f))
|
||||
{
|
||||
newTreatmentSuitabilities.TryAdd(itemPrefab.Identifier, suitability);
|
||||
}
|
||||
}
|
||||
HasTreatments = newTreatmentSuitabilities.Any(kvp => kvp.Value > 0);
|
||||
TreatmentSuitabilities = newTreatmentSuitabilities.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public LocalizedString GetDescription(float strength, Description.TargetType targetType)
|
||||
{
|
||||
foreach (var description in Descriptions)
|
||||
@@ -993,9 +1006,16 @@ namespace Barotrauma
|
||||
return defaultDescription;
|
||||
}
|
||||
|
||||
public static void LoadAllEffects()
|
||||
/// <summary>
|
||||
/// Should be called before each round: loads all StatusEffects and refreshes treatment suitabilities.
|
||||
/// </summary>
|
||||
public static void LoadAllEffectsAndTreatmentSuitabilities()
|
||||
{
|
||||
Prefabs.ForEach(p => p.LoadEffects());
|
||||
foreach (var prefab in Prefabs)
|
||||
{
|
||||
prefab.RefreshTreatmentSuitabilities();
|
||||
prefab.LoadEffects();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearAllEffects()
|
||||
@@ -1003,7 +1023,7 @@ namespace Barotrauma
|
||||
Prefabs.ForEach(p => p.ClearEffects());
|
||||
}
|
||||
|
||||
public void LoadEffects()
|
||||
private void LoadEffects()
|
||||
{
|
||||
ClearEffects();
|
||||
foreach (var subElement in configElement.Elements())
|
||||
@@ -1032,7 +1052,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearEffects()
|
||||
private void ClearEffects()
|
||||
{
|
||||
effects.Clear();
|
||||
periodicEffects.Clear();
|
||||
|
||||
@@ -1136,7 +1136,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitability)
|
||||
foreach (KeyValuePair<Identifier, float> treatment in affliction.Prefab.TreatmentSuitabilities)
|
||||
{
|
||||
float suitability = treatment.Value * strength;
|
||||
if (treatment.Value > strength)
|
||||
|
||||
@@ -392,7 +392,7 @@ namespace Barotrauma
|
||||
DateTime startTime = DateTime.Now;
|
||||
#endif
|
||||
RoundDuration = 0.0f;
|
||||
AfflictionPrefab.LoadAllEffects();
|
||||
AfflictionPrefab.LoadAllEffectsAndTreatmentSuitabilities();
|
||||
|
||||
MirrorLevel = mirrorLevel;
|
||||
if (SubmarineInfo == null)
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
private void CreateTriggerBody()
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(trigger == null, "LevelResource trigger already created!");
|
||||
var body = item.body ?? holdable.Body;
|
||||
var body = item.body ?? holdable?.Body;
|
||||
if (body != null && Attached)
|
||||
{
|
||||
trigger = new PhysicsBody(body.Width, body.Height, body.Radius,
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace Barotrauma
|
||||
if (eventSet is null) { continue; }
|
||||
int count = childElement.GetAttributeInt("count", 0);
|
||||
if (count < 1) { continue; }
|
||||
FinishedEvents.Add(eventSet, count);
|
||||
FinishedEvents.TryAdd(eventSet, count);
|
||||
}
|
||||
|
||||
static EventSet FindSetRecursive(EventSet parentSet, Identifier setIdentifier)
|
||||
@@ -365,7 +365,7 @@ namespace Barotrauma
|
||||
if (FinishedEvents.Any())
|
||||
{
|
||||
var finishedEventsElement = new XElement(nameof(FinishedEvents));
|
||||
foreach (var (set, count) in FinishedEvents)
|
||||
foreach (var (set, count) in FinishedEvents.DistinctBy(f => f.Key.Identifier))
|
||||
{
|
||||
var element = new XElement(nameof(FinishedEvents),
|
||||
new XAttribute("set", set.Identifier),
|
||||
|
||||
@@ -1353,44 +1353,38 @@ namespace Barotrauma
|
||||
|
||||
if (startWaypoint.WorldPosition.X > endWaypoint.WorldPosition.X)
|
||||
{
|
||||
var temp = startWaypoint;
|
||||
startWaypoint = endWaypoint;
|
||||
endWaypoint = temp;
|
||||
(endWaypoint, startWaypoint) = (startWaypoint, endWaypoint);
|
||||
}
|
||||
|
||||
if (hallwayLength > 100 && isHorizontal)
|
||||
{
|
||||
//if the hallway is longer than 100 pixels, generate some waypoints inside it
|
||||
//for vertical hallways this isn't necessarily, it's done as a part of the ladder generation in AlignLadders
|
||||
WayPoint prevWayPoint = startWaypoint;
|
||||
WayPoint firstWayPoint = null;
|
||||
for (float x = leftHull.Rect.Right + 50; x < rightHull.Rect.X - 50; x += 100.0f)
|
||||
{
|
||||
var newWayPoint = new WayPoint(new Vector2(x, hullBounds.Y + 110.0f), SpawnType.Path, sub);
|
||||
firstWayPoint ??= newWayPoint;
|
||||
prevWayPoint.linkedTo.Add(newWayPoint);
|
||||
newWayPoint.linkedTo.Add(prevWayPoint);
|
||||
prevWayPoint = newWayPoint;
|
||||
}
|
||||
if (firstWayPoint != null)
|
||||
{
|
||||
firstWayPoint.linkedTo.Add(startWaypoint);
|
||||
startWaypoint.linkedTo.Add(firstWayPoint);
|
||||
}
|
||||
if (prevWayPoint != null)
|
||||
{
|
||||
prevWayPoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(prevWayPoint);
|
||||
}
|
||||
}
|
||||
|
||||
WayPoint closestWaypoint = null;
|
||||
float closestDistSqr = 30.0f * 30.0f;
|
||||
foreach (WayPoint waypoint in WayPoint.WayPointList)
|
||||
else
|
||||
{
|
||||
if (waypoint == startWaypoint) { continue; }
|
||||
float dist = Vector2.DistanceSquared(waypoint.WorldPosition, startWaypoint.WorldPosition);
|
||||
if (dist < closestDistSqr)
|
||||
{
|
||||
closestWaypoint = waypoint;
|
||||
closestDistSqr = dist;
|
||||
}
|
||||
}
|
||||
if (closestWaypoint != null)
|
||||
{
|
||||
startWaypoint.linkedTo.Add(closestWaypoint);
|
||||
closestWaypoint.linkedTo.Add(startWaypoint);
|
||||
startWaypoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(startWaypoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1444,7 +1438,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (MapEntity me in entities[module])
|
||||
{
|
||||
if (!(me is Gap gap)) { continue; }
|
||||
if (me is not Gap gap) { continue; }
|
||||
var door = gap.ConnectedDoor;
|
||||
if (door != null && !door.UseBetweenOutpostModules) { continue; }
|
||||
if (placedModules.Any(m => m.PreviousGap == gap || m.ThisGap == gap))
|
||||
@@ -1524,15 +1518,38 @@ namespace Barotrauma
|
||||
|
||||
static void RemoveLinkedEntity(MapEntity linked)
|
||||
{
|
||||
if (linked is Item linkedItem && linkedItem.Connections != null)
|
||||
if (linked is Item linkedItem)
|
||||
{
|
||||
foreach (Connection connection in linkedItem.Connections)
|
||||
if (linkedItem.Connections != null)
|
||||
{
|
||||
foreach (Wire w in connection.Wires.ToArray())
|
||||
foreach (Connection connection in linkedItem.Connections)
|
||||
{
|
||||
w?.Item.Remove();
|
||||
foreach (Wire w in connection.Wires.ToArray())
|
||||
{
|
||||
w?.Item.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
//if we end up removing a ladder, remove its waypoints too
|
||||
if (linkedItem.GetComponent<Ladder>() is Ladder ladder)
|
||||
{
|
||||
var ladderWaypoints = WayPoint.WayPointList.FindAll(wp => wp.Ladders == ladder);
|
||||
foreach (var ladderWaypoint in ladderWaypoints)
|
||||
{
|
||||
//got through all waypoints linked to the ladder waypoints, and link them together
|
||||
//so we don't end up breaking up any paths by removing the ladder waypoints
|
||||
for (int i = 0; i < ladderWaypoint.linkedTo.Count; i++)
|
||||
{
|
||||
if (ladderWaypoint.linkedTo[i] is not WayPoint waypoint1 || waypoint1.Ladders == ladder) { continue; }
|
||||
for (int j = i + 1; j < ladderWaypoint.linkedTo.Count; j++)
|
||||
{
|
||||
if (ladderWaypoint.linkedTo[j] is not WayPoint waypoint2 || waypoint2.Ladders == ladder) { continue; }
|
||||
waypoint1.ConnectTo(waypoint2);
|
||||
}
|
||||
}
|
||||
}
|
||||
ladderWaypoints.ForEach(wp => wp.Remove());
|
||||
}
|
||||
}
|
||||
linked.Remove();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v1.0.21.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Fixes:
|
||||
- Fixed LOS effect sometimes "lagging behind" when the sub is moving fast.
|
||||
- Fixed some minor visual issues (occasional jitter/flickering) on the LOS effect.
|
||||
- Fixed some issues in the bot AI that we're causing a large performance hit particularly in situations when there's lots of bots in a sub with leaks.
|
||||
- Fixed bots abandoning their orders (such as operating a turret) if the room is unsafe (e.g. flooded).
|
||||
- Fixed an issue in character syncing that occasionally caused disconnects with the error message "Exception thrown while reading segment EntityPosition, tried to read too much data from segment".
|
||||
- Fixed wires set to be hidden in-game (e.g. invisible circuits built outside the sub) being visible on the Electrician's Goggles.
|
||||
- Fixed an issue with level resources that caused crashes with certain mods (e.g. ones that include subs with piezo crystals).
|
||||
- Fixed NPCs waiting on some outpost modules never reaching their targets, causing peculiar behavior.
|
||||
- Fixed waypoints sometimes not getting connected between outpost modules if there's a very short hallway between them. Addresses some cities missing connections between waypoints, causing AI to be unable to navigate through the modules.
|
||||
- Fixed some UI layout issues (most noticeably, ultra-wide crew list) on certain resolutions like 3440x1440.
|
||||
- Fixed campaign saves occasionally failing to load with the error "an item with the same key has already been added". Seemed to only occur when using certain mods.
|
||||
- Fixed crashing when you e.g. use a pet from some mod in the campaign, disable the mod and reload the save.
|
||||
- Waypoint adjustments to most submarines, outposts, wrecks, and beacons. Especially on ladders. Should take care of the remaining AI issues on ladders (the old subs in the saves don't get updated, but the fixes apply to new subs that you don't yet own. And ofc all the subs in a new game!)
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v1.0.20.1
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
@@ -5,7 +24,7 @@ v1.0.20.1
|
||||
Fixes:
|
||||
- Fixed hidden structures not colliding anymore.
|
||||
- Wiring debugger: Fixed tooltip rendering under the outer frame of the connection panel.
|
||||
- Wiring debugger: Fixed the glow sprite on connections having an inconsistent size in different resolutions-
|
||||
- Wiring debugger: Fixed the glow sprite on connections having an inconsistent size in different resolutions.
|
||||
- Fixed jailbreak_sootman event getting stuck at the 1st SpawnAction, preventing most of the event from working at all.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user