diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj
index f0fa4331e..f0d80d9ee 100644
--- a/Barotrauma/BarotraumaClient/LinuxClient.csproj
+++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj
@@ -193,6 +193,60 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
index 69530ef26..847902e84 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs
@@ -415,7 +415,7 @@ namespace Barotrauma
}
}
- partial void SeverLimbJointProjSpecific(LimbJoint limbJoint)
+ partial void SeverLimbJointProjSpecific(LimbJoint limbJoint, bool playSound = true)
{
foreach (Limb limb in new Limb[] { limbJoint.LimbA, limbJoint.LimbB })
{
@@ -433,6 +433,11 @@ namespace Barotrauma
character.CurrentHull?.AddDecal(character.BloodDecalName, limb.WorldPosition, MathHelper.Clamp(limb.Mass, 0.5f, 2.0f));
}
}
+
+ if (playSound)
+ {
+ SoundPlayer.PlayDamageSound("Gore", 1.0f, limbJoint.LimbA.body);
+ }
}
public virtual void Draw(SpriteBatch spriteBatch, Camera cam)
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs
index 777bc7775..2bcb03cb3 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs
@@ -96,6 +96,11 @@ namespace Barotrauma
private const float UpdateDisplayedAfflictionsInterval = 0.5f;
private List currentDisplayedAfflictions = new List();
+ public bool MouseOnElement
+ {
+ get { return highlightedLimbIndex > -1 || GUI.MouseOn == dropItemArea; }
+ }
+
private static CharacterHealth openHealthWindow;
public static CharacterHealth OpenHealthWindow
{
@@ -172,18 +177,16 @@ namespace Barotrauma
afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(0.7f, 0.85f), paddedInfoFrame.RectTransform, Anchor.BottomLeft));
- new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.08f), paddedInfoFrame.RectTransform), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopRight);
- lowSkillIndicator = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.07f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.08f) },
- TextManager.Get("LowMedicalSkillWarning"), Color.Orange, textAlignment: Alignment.Center, font: GUI.SmallFont, wrap: true)
+ lowSkillIndicator = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedInfoFrame.RectTransform, Anchor.TopRight),
+ TextManager.Get("LowMedicalSkillWarning"), Color.Orange, textAlignment: Alignment.TopRight, font: GUI.SmallFont, wrap: true)
{
Visible = false
};
- recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.28f, 0.5f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.15f) })
- {
- Spacing = 10
- };
+ new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedInfoFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.05f) }, TextManager.Get("SuitableTreatments"), textAlignment: Alignment.BottomRight);
+
+ recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.28f, 0.5f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.12f) });
dropItemArea = new GUIFrame(new RectTransform(new Vector2(0.28f, 0.3f), paddedInfoFrame.RectTransform, Anchor.BottomRight)
- { RelativeOffset = new Vector2(0.0f, 0.0f) }, style: null)
+ { RelativeOffset = new Vector2(0.02f, 0.0f) }, style: null)
{
ToolTip = TextManager.Get("HealthItemUseTip")
};
@@ -584,9 +587,18 @@ namespace Barotrauma
var affliction = GetAllAfflictions(a => a.Prefab.IndicatorLimb != LimbType.None)
.OrderByDescending(a => a.DamagePerSecond)
.ThenByDescending(a => a.Strength).FirstOrDefault();
- var limbHealth = GetMathingLimbHealth(affliction);
- if (limbHealth != null)
+ if (affliction.DamagePerSecond > 0 || affliction.Strength > 0)
{
+ var limbHealth = GetMathingLimbHealth(affliction);
+ if (limbHealth != null)
+ {
+ selectedLimbIndex = limbHealths.IndexOf(limbHealth);
+ }
+ }
+ else
+ {
+ // If no affliction is critical, select the limb which has most damage.
+ var limbHealth = limbHealths.OrderByDescending(l => l.TotalDamage).FirstOrDefault();
selectedLimbIndex = limbHealths.IndexOf(limbHealth);
}
}
@@ -928,7 +940,7 @@ namespace Barotrauma
{
afflictionInfoContainer.Content.ClearChildren();
recommendedTreatmentContainer.Content.ClearChildren();
-
+
float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel("medical");
//random variance is 200% when the skill is 0
@@ -1023,14 +1035,15 @@ namespace Barotrauma
{
ItemPrefab item = MapEntityPrefab.Find(name: null, identifier: treatment.Key, showErrorMessages: false) as ItemPrefab;
if (item == null) continue;
- int slotSize = (int)(recommendedTreatmentContainer.Content.Rect.Width * 0.8f);
+ int slotSize = (int)(recommendedTreatmentContainer.Content.Rect.Width * 0.5f);
- var itemSlot = new GUIButton(new RectTransform(new Point(slotSize), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopCenter),
- text: "", style: "InventorySlotSmall")
+ var itemSlot = new GUIFrame(new RectTransform(new Point(recommendedTreatmentContainer.Content.Rect.Width, slotSize), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopCenter),
+ style: "InnerGlow")
{
- UserData = item
+ UserData = item,
+ CanBeFocused = false
};
- itemSlot.Color = ToolBox.GradientLerp(treatment.Value, Color.Red, Color.White, Color.LightGreen);
+ itemSlot.Color = ToolBox.GradientLerp(treatment.Value, Color.Red, Color.Orange, Color.LightGreen);
Sprite itemSprite = item.InventoryIcon ?? item.sprite;
Color itemColor = itemSprite == item.sprite ? item.SpriteColor : item.InventoryIconColor;
diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs b/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs
index 0db66467c..5e2696495 100644
--- a/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs
+++ b/Barotrauma/BarotraumaClient/Source/Characters/Limb.cs
@@ -296,6 +296,7 @@ namespace Barotrauma
break;
}
}
+ SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), WorldPosition);
}
// Always spawn damage particles
diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs
index e1b97e425..d9b25edd0 100644
--- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs
+++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs
@@ -1092,8 +1092,8 @@ namespace Barotrauma
List lines = new List();
foreach (MapEntityPrefab me in MapEntityPrefab.List)
{
- lines.Add("" + me.Name + "" + me.Identifier + ".Name>");
- lines.Add("" + me.Description + "" + me.Identifier + ".Description>");
+ lines.Add("" + me.Name + "");
+ lines.Add("" + me.Description + "");
}
File.WriteAllLines(filePath, lines);
}));
@@ -1523,7 +1523,7 @@ namespace Barotrauma
character.AnimController.ResetRagdoll();
}, isCheat: true));
- commands.Add(new Command("reloadwearables|reloadlimbs", "Reloads the sprites of all limbs and wearable sprites (clothing) of the controlled character. Provide id or name if you want to target another character.", args =>
+ commands.Add(new Command("reloadwearables", "Reloads the sprites of all limbs and wearable sprites (clothing) of the controlled character. Provide id or name if you want to target another character.", args =>
{
var character = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args, true);
if (character == null)
@@ -1534,6 +1534,26 @@ namespace Barotrauma
ReloadWearables(character);
}, isCheat: true));
+ commands.Add(new Command("loadwearable", "Force select certain variant for the selected character.", args =>
+ {
+ var character = Character.Controlled;
+ if (character == null)
+ {
+ ThrowError("Not controlling any character.");
+ return;
+ }
+ if (args.Length == 0)
+ {
+ ThrowError("No arguments provided! Give an index number for the variant starting from 1.");
+ return;
+ }
+ if (int.TryParse(args[0], out int variant))
+ {
+ ReloadWearables(character, variant);
+ }
+
+ }, isCheat: true));
+
commands.Add(new Command("reloadsprite|reloadsprites", "Reloads the sprites of the selected item(s)/structure(s) (hovering over or selecting in the subeditor) or the controlled character. Can also reload sprites by entity id or by the name attribute (sprite element). Example 1: reloadsprite id itemid. Example 2: reloadsprite name \"Sprite name\"", args =>
{
if (Screen.Selected is SpriteEditorScreen)
@@ -1681,7 +1701,7 @@ namespace Barotrauma
}, isCheat: true));
}
- private static void ReloadWearables(Character character)
+ private static void ReloadWearables(Character character, int variant = 0)
{
foreach (var limb in character.AnimController.Limbs)
{
@@ -1690,11 +1710,17 @@ namespace Barotrauma
limb.DeformSprite?.Sprite.ReloadTexture();
foreach (var wearable in limb.WearingItems)
{
+ if (variant > 0 && wearable.Variant > 0)
+ {
+ wearable.Variant = variant;
+ }
+ wearable.RefreshPath();
wearable.Sprite.ReloadXML();
wearable.Sprite.ReloadTexture();
}
foreach (var wearable in limb.OtherWearables)
{
+ wearable.RefreshPath();
wearable.Sprite.ReloadXML();
wearable.Sprite.ReloadTexture();
}
diff --git a/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs b/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs
index a5ef20967..a64d9b6e1 100644
--- a/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs
+++ b/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs
@@ -414,6 +414,17 @@ namespace Barotrauma
return retVal;
}
+ public Vector2 MeasureChar(char c)
+ {
+ Vector2 retVal = Vector2.Zero;
+ retVal.Y = baseHeight * 1.8f;
+ if (texCoords.TryGetValue(c, out GlyphData gd))
+ {
+ retVal.X = gd.advance;
+ }
+ return retVal;
+ }
+
public void Dispose()
{
FontList.Remove(this);
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs
index 53457108e..dddd37a0f 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs
@@ -1568,7 +1568,7 @@ namespace Barotrauma
}
///
- /// Displays a message at the center of the screen, automatically preventing overlapping with other centered messages
+ /// Displays a message at the center of the screen, automatically preventing overlapping with other centered messages. TODO: Allow to show messages at the middle of the screen (instead of the top center).
///
public static void AddMessage(string message, Color color, float? lifeTime = null, bool playSound = true, ScalableFont font = null)
{
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs
index d7fa5f045..61ae5e113 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs
@@ -132,6 +132,8 @@ namespace Barotrauma
public bool IgnoreLayoutGroups;
+ public bool IgnoreLayoutGroups;
+
public virtual ScalableFont Font
{
get;
@@ -513,6 +515,7 @@ namespace Barotrauma
yield return CoroutineStatus.Running;
}
+ toolTipBlock.SetTextPos();
SetAlpha(to);
@@ -538,11 +541,9 @@ namespace Barotrauma
OutlineColor = style.OutlineColor;
- public virtual void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, Vector2? flashRectInflate = null)
+ public virtual void Flash(Color? color = null, float flashDuration = 1.5f)
{
flashTimer = flashDuration;
- this.flashRectInflate = flashRectInflate ?? Vector2.Zero;
- this.useRectangleFlash = useRectangleFlash;
this.flashDuration = flashDuration;
flashColor = (color == null) ? Color.Red : (Color)color;
}
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs
index ec9c026e6..435c43066 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs
@@ -47,6 +47,12 @@ namespace Barotrauma
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
Tag = tag;
+ InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, Anchor.Center) { IsFixedSize = false }, style: null);
+ GUI.Style.Apply(InnerFrame, "", this);
+
+ Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
+ Tag = tag;
+
if (height == 0)
{
string wrappedText = ToolBox.WrapText(text, Content.Rect.Width, GUI.Font);
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs
index f7006dea9..a3b89fd53 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIStyle.cs
@@ -78,85 +78,6 @@ namespace Barotrauma
break;
}
}
- return defaultFont;
- }
-
-
- private void RescaleFonts()
- {
- foreach (XElement subElement in configElement.Elements())
- {
- switch (subElement.Name.ToString().ToLowerInvariant())
- {
- case "font":
- Font.Size = GetFontSize(subElement);
- break;
- case "smallfont":
- SmallFont.Size = GetFontSize(subElement);
- break;
- case "largefont":
- LargeFont.Size = GetFontSize(subElement);
- break;
- case "objectivetitle":
- ObjectiveTitleFont.Size = GetFontSize(subElement);
- break;
- case "objectivename":
- ObjectiveNameFont.Size = GetFontSize(subElement);
- break;
- case "videotitle":
- VideoTitleFont.Size = GetFontSize(subElement);
- break;
- }
- }
- }
-
- private ScalableFont LoadFont(XElement element, GraphicsDevice graphicsDevice)
- {
- string file = GetFontFilePath(element);
- uint size = GetFontSize(element);
- bool dynamicLoading = GetFontDynamicLoading(element);
- return new ScalableFont(file, size, graphicsDevice, dynamicLoading);
- }
-
- private uint GetFontSize(XElement element)
- {
- foreach (XElement subElement in element.Elements())
- {
- if (subElement.Name.ToString().ToLowerInvariant() != "size") { continue; }
- Point maxResolution = subElement.GetAttributePoint("maxresolution", new Point(int.MaxValue, int.MaxValue));
- if (GameMain.GraphicsWidth <= maxResolution.X && GameMain.GraphicsHeight <= maxResolution.Y)
- {
- return (uint)subElement.GetAttributeInt("size", 14);
- }
- }
- return 14;
- }
-
- private string GetFontFilePath(XElement element)
- {
- foreach (XElement subElement in element.Elements())
- {
- if (subElement.Name.ToString().ToLowerInvariant() != "override") { continue; }
- string language = subElement.GetAttributeString("language", "").ToLowerInvariant();
- if (GameMain.Config.Language.ToLowerInvariant() == language)
- {
- return subElement.GetAttributeString("file", "");
- }
- }
- return element.GetAttributeString("file", "");
- }
-
- private bool GetFontDynamicLoading(XElement element)
- {
- foreach (XElement subElement in element.Elements())
- {
- if (subElement.Name.ToString().ToLowerInvariant() != "override") { continue; }
- string language = subElement.GetAttributeString("language", "").ToLowerInvariant();
- if (GameMain.Config.Language.ToLowerInvariant() == language)
- {
- return subElement.GetAttributeBool("dynamicloading", false);
- }
- }
return element.GetAttributeBool("dynamicloading", false);
}
@@ -172,6 +93,12 @@ namespace Barotrauma
return style;
}
+ public GUIComponentStyle GetComponentStyle(string name)
+ {
+ componentStyles.TryGetValue(name.ToLowerInvariant(), out GUIComponentStyle style);
+ return style;
+ }
+
public void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
{
GUIComponentStyle componentStyle = null;
diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs
index 913914243..889628213 100644
--- a/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs
+++ b/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs
@@ -44,10 +44,11 @@ namespace Barotrauma
public Color TextColor
{
- get { return box; }
+ get { return text.TextColor; }
+ set { text.TextColor = value; }
}
- public GUITextBlock TextBlock
+ public override Rectangle MouseRect
{
get
{
diff --git a/Barotrauma/BarotraumaClient/Source/GameMain.cs b/Barotrauma/BarotraumaClient/Source/GameMain.cs
index 96409dd29..12f296bf5 100644
--- a/Barotrauma/BarotraumaClient/Source/GameMain.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameMain.cs
@@ -180,6 +180,10 @@ namespace Barotrauma
GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
+ GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
+
+
+ PerformanceCounter = new PerformanceCounter();
PerformanceCounter = new PerformanceCounter();
diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs
index 9f8baaf79..2a0aa2f37 100644
--- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs
+++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs
@@ -83,6 +83,66 @@ namespace Barotrauma
break;
}
}
+
+ var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null);
+ reportButtonFrame = new GUILayoutGroup(new RectTransform(
+ new Point((HUDLayoutSettings.CrewArea.Height - (int)((reports.Count - 1) * 5 * GUI.Scale)) / reports.Count, HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform))
+ {
+ AbsoluteSpacing = (int)(5 * GUI.Scale),
+ UserData = "reportbuttons",
+ CanBeFocused = false
+ };
+
+ //report buttons
+ foreach (Order order in reports)
+ {
+ if (!order.TargetAllCharacters || order.SymbolSprite == null) continue;
+ var btn = new GUIButton(new RectTransform(new Point(reportButtonFrame.Rect.Width), reportButtonFrame.RectTransform), style: null)
+ {
+ OnClicked = (GUIButton button, object userData) =>
+ {
+ if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false;
+ SetCharacterOrder(null, order, null, Character.Controlled);
+ HumanAIController.PropagateHullSafety(Character.Controlled, Character.Controlled.CurrentHull);
+ return true;
+ },
+ UserData = order,
+ ToolTip = order.Name
+ };
+
+ new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow")
+ {
+ Color = Color.Red * 0.8f,
+ HoverColor = Color.Red * 1.0f,
+ PressedColor = Color.Red * 0.6f,
+ UserData = "highlighted",
+ CanBeFocused = false,
+ Visible = false
+ };
+
+ var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite, scaleToFit: true)
+ {
+ Color = order.Color,
+ HoverColor = Color.Lerp(order.Color, Color.White, 0.5f),
+ ToolTip = order.Name
+ };
+ }
+
+ screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
+
+ prevUIScale = GUI.Scale;
+
+ ToggleCrewAreaOpen = GameMain.Config.CrewMenuOpen;
+ }
+
+
+ #endregion
+
+ #region Character list management
+
+ public Rectangle GetCharacterListArea()
+ {
+ return characterListBox.Rect;
}
partial void InitProjectSpecific()
@@ -606,27 +666,20 @@ namespace Barotrauma
characterListBox.BarScroll = roundedPos;
}
- #endregion
-
-
- #region Voice chat
-
- public void SetPlayerVoiceIconState(Client client, bool muted, bool mutedLocally)
+ #region Dialog
+ ///
+ /// Adds the message to the single player chatbox.
+ ///
+ public void AddSinglePlayerChatMessage(string senderName, string text, ChatMessageType messageType, Character sender)
{
- if (client?.Character == null) { return; }
-
- var playerFrame = characterListBox.Content.FindChild(client.Character)?.FindChild(client.Character);
- if (playerFrame == null) { return; }
- var soundIcon = playerFrame.FindChild("soundicon");
- var soundIconDisabled = playerFrame.FindChild("soundicondisabled");
-
- if (!soundIcon.Visible)
+ if (!isSinglePlayer)
{
- soundIcon.Color = new Color(soundIcon.Color, 0.0f);
+ DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
+ return;
}
- soundIcon.Visible = !muted && !mutedLocally;
- soundIconDisabled.Visible = muted || mutedLocally;
- soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally");
+ if (string.IsNullOrEmpty(text)) { return; }
+
+ ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
}
private IEnumerable
-
+
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
-
\ No newline at end of file
+
diff --git a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs
index 1dd05bae8..a7d06ffa1 100644
--- a/Barotrauma/BarotraumaServer/Source/DebugConsole.cs
+++ b/Barotrauma/BarotraumaServer/Source/DebugConsole.cs
@@ -193,7 +193,7 @@ namespace Barotrauma
Console.CursorLeft = 0;
Console.CursorTop -= cursorLine;
Console.Write(input);
- Console.CursorLeft = input.Length % Console.WindowWidth;
+ Console.CursorLeft = input.Length % consoleWidth;
}
private static void AssignOnClientRequestExecute(string names, Action onClientRequestExecute)
diff --git a/Barotrauma/BarotraumaServer/Source/GameMain.cs b/Barotrauma/BarotraumaServer/Source/GameMain.cs
index 6d44fd936..53e3623d6 100644
--- a/Barotrauma/BarotraumaServer/Source/GameMain.cs
+++ b/Barotrauma/BarotraumaServer/Source/GameMain.cs
@@ -83,6 +83,7 @@ namespace Barotrauma
LevelGenerationParams.LoadPresets();
ScriptedEventSet.LoadPrefabs();
+ AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
@@ -90,7 +91,6 @@ namespace Barotrauma
NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
ItemAssemblyPrefab.LoadAll();
LevelObjectPrefab.LoadAll();
- AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
GameModePreset.Init();
LocationType.Init();
diff --git a/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs
index 0e1667db4..7cacaa130 100644
--- a/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs
+++ b/Barotrauma/BarotraumaServer/Source/GameSession/GameModes/MultiPlayerCampaign.cs
@@ -168,6 +168,8 @@ namespace Barotrauma
msg.Write(isRunning && endWatchman != null ? endWatchman.ID : (UInt16)0);
msg.Write(Money);
+ msg.Write(PurchasedHullRepairs);
+ msg.Write(PurchasedItemRepairs);
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
@@ -192,6 +194,8 @@ namespace Barotrauma
{
UInt16 selectedLocIndex = msg.ReadUInt16();
byte selectedMissionIndex = msg.ReadByte();
+ bool purchasedHullRepairs = msg.ReadBoolean();
+ bool purchasedItemRepairs = msg.ReadBoolean();
UInt16 purchasedItemCount = msg.ReadUInt16();
List purchasedItems = new List();
@@ -208,6 +212,17 @@ namespace Barotrauma
return;
}
+ if (purchasedHullRepairs && !this.PurchasedHullRepairs && Money >= HullRepairCost)
+ {
+ this.PurchasedHullRepairs = true;
+ Money -= HullRepairCost;
+ }
+ if (purchasedItemRepairs && !this.PurchasedItemRepairs && Money >= ItemRepairCost)
+ {
+ this.PurchasedItemRepairs = true;
+ Money -= ItemRepairCost;
+ }
+
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
if (Map.SelectedConnection != null)
{
diff --git a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml
index 529a93864..5d1bf37a2 100644
--- a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml
+++ b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml
@@ -5,11 +5,14 @@
-
-
-
+
+
+
+
+
+
+
-
diff --git a/Barotrauma/BarotraumaShared/SharedContent.projitems b/Barotrauma/BarotraumaShared/SharedContent.projitems
index bd71d9c68..e95896c42 100644
--- a/Barotrauma/BarotraumaShared/SharedContent.projitems
+++ b/Barotrauma/BarotraumaShared/SharedContent.projitems
@@ -24,6 +24,10 @@
+
+
+
+
@@ -360,6 +364,78 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -594,94 +670,94 @@
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
@@ -1304,7 +1380,7 @@
PreserveNewest
-
+
PreserveNewest
@@ -1571,7 +1647,7 @@
PreserveNewest
-
+
PreserveNewest
@@ -1583,10 +1659,7 @@
PreserveNewest
-
- PreserveNewest
-
-
+
PreserveNewest
@@ -1595,10 +1668,10 @@
PreserveNewest
-
+
PreserveNewest
-
+
PreserveNewest
@@ -1913,6 +1986,24 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -1931,6 +2022,27 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -2467,18 +2579,6 @@
PreserveNewest
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
PreserveNewest
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
index 9cc8fc1ff..364acaaae 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
@@ -14,6 +14,11 @@ namespace Barotrauma
{
public static bool DisableEnemyAI;
+ ///
+ /// Enable the character to attack the outposts and the characters inside them. Disabled by default.
+ ///
+ public bool TargetOutposts;
+
class WallTarget
{
public Vector2 Position;
@@ -1043,6 +1048,8 @@ namespace Barotrauma
private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
+ private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure;
+
//goes through all the AItargets, evaluates how preferable it is to attack the target,
//whether the Character can see/hear the target and chooses the most preferable target within
//sight/hearing range
@@ -1068,9 +1075,10 @@ namespace Barotrauma
continue;
}
if (target.Type == AITarget.TargetType.HumanOnly) { continue; }
- // Don't attack outposts.
- if (target.Entity.Submarine != null && target.Entity.Submarine.IsOutpost) { continue; }
-
+ if (!TargetOutposts)
+ {
+ if (target.Entity.Submarine != null && target.Entity.Submarine.IsOutpost) { continue; }
+ }
Character targetCharacter = target.Entity as Character;
//ignore the aitarget if it is the Character itself
if (targetCharacter == character) continue;
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs
index e759548fa..2237d4a0b 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs
@@ -290,7 +290,7 @@ namespace Barotrauma
if (GameMain.GameSession?.CrewManager != null && GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime))
{
Character.Speak(
- newOrder.GetChatMessage("", Character.CurrentHull?.RoomName, givingOrderToSelf: false), ChatMessageType.Order);
+ newOrder.GetChatMessage("", Character.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order);
}
}
}
@@ -309,7 +309,7 @@ namespace Barotrauma
if (Character.PressureTimer > 50.0f && Character.CurrentHull != null)
{
- Character.Speak(TextManager.Get("DialogPressure").Replace("[roomname]", Character.CurrentHull.RoomName), null, 0, "pressure", 30.0f);
+ Character.Speak(TextManager.Get("DialogPressure").Replace("[roomname]", Character.CurrentHull.DisplayName), null, 0, "pressure", 30.0f);
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs
index 794dd8443..2d3de2875 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs
@@ -388,6 +388,18 @@ namespace Barotrauma
buttonPressCooldown = ButtonPressInterval;
break;
}
+ else
+ {
+ if (!door.HasRequiredItems(character, false) && shouldBeOpen)
+ {
+ currentPath.Unreachable = true;
+ return;
+ }
+
+ door.Item.TryInteract(character, false, true, true);
+ buttonPressCooldown = ButtonPressInterval;
+ break;
+ }
}
}
}
@@ -408,20 +420,18 @@ namespace Barotrauma
//door closed and the character can't open doors -> node can't be traversed
if (!canOpenDoors || character.LockHands) { return null; }
- if (!canBreakDoors)
- {
- //door closed and the character can't open doors -> node can't be traversed
- if (!canOpenDoors || character.LockHands) return null;
-
var doorButtons = nextNode.Waypoint.ConnectedDoor.Item.GetConnectedComponents();
- if (!doorButtons.Any()) return null;
+ if (!doorButtons.Any())
+ {
+ if (!nextNode.Waypoint.ConnectedDoor.HasRequiredItems(character, false)) { return null; }
+ }
foreach (Controller button in doorButtons)
{
if (Math.Sign(button.Item.Position.X - nextNode.Waypoint.Position.X) !=
- Math.Sign(node.Position.X - nextNode.Position.X)) continue;
+ Math.Sign(node.Position.X - nextNode.Position.X)) { continue; }
- if (!button.HasRequiredItems(character, false)) return null;
+ if (!button.HasRequiredItems(character, false)) { return null; }
}
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs
index 128992a3e..9acf4bc99 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs
@@ -44,6 +44,7 @@ namespace Barotrauma
private AIObjectiveContainItem reloadWeaponObjective;
private Hull retreatTarget;
private AIObjectiveGoTo retreatObjective;
+ private AIObjectiveFindSafety findSafety;
private float coolDownTimer;
@@ -60,7 +61,9 @@ namespace Barotrauma
{
Enemy = enemy;
coolDownTimer = CoolDown;
- HumanAIController.ObjectiveManager.GetObjective().Priority = 0;
+ findSafety = HumanAIController.ObjectiveManager.GetObjective();
+ findSafety.Priority = 0;
+ findSafety.unreachable.Clear();
Mode = mode;
if (Enemy == null)
{
@@ -175,7 +178,7 @@ namespace Barotrauma
{
if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted))
{
- retreatTarget = HumanAIController.ObjectiveManager.GetObjective().FindBestHull(new List() { character.CurrentHull });
+ retreatTarget = findSafety.FindBestHull(new List() { character.CurrentHull });
}
if (retreatTarget != null)
{
@@ -277,7 +280,6 @@ namespace Barotrauma
{
abandon = true;
SteeringManager.Reset();
- //HumanAIController.ObjectiveManager.GetObjective().Priority = 100;
}
public override bool IsCompleted()
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs
index 2ac3ef0ce..6b735f0f5 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs
@@ -18,7 +18,7 @@ namespace Barotrauma
const float SearchHullInterval = 3.0f;
const float clearUnreachableInterval = 30;
- private List unreachable = new List();
+ public readonly List unreachable = new List();
private float currenthullSafety;
private float unreachableClearTimer;
@@ -60,11 +60,16 @@ namespace Barotrauma
else
{
divingGearObjective = null;
- // Reset the timer so that we get a safe hull target.
- searchHullTimer = 0;
+ // Reduce the timer so that we get a safe hull target faster.
+ searchHullTimer = Math.Min(1, searchHullTimer);
}
}
+ if (currenthullSafety < HumanAIController.HULL_SAFETY_THRESHOLD)
+ {
+ searchHullTimer = Math.Min(1, searchHullTimer);
+ }
+
if (unreachableClearTimer > 0)
{
unreachableClearTimer -= deltaTime;
@@ -188,10 +193,17 @@ namespace Barotrauma
float dist = Math.Abs(character.WorldPosition.X - hull.WorldPosition.X) + Math.Abs(character.WorldPosition.Y - hull.WorldPosition.Y) * 2.0f;
float distanceFactor = MathHelper.Lerp(1, 0.9f, MathUtils.InverseLerp(0, 10000, dist));
hullSafety *= distanceFactor;
+ //skip the hull if the safety is already less than the best hull
+ //(no need to do the expensive pathfinding if we already know we're not going to choose this hull)
+ if (hullSafety < bestValue) { continue; }
// Each unsafe node reduces the hull safety value.
// Ignore current hull, because otherwise the would block all paths from the current hull to the target hull.
var path = PathSteering.PathFinder.FindPath(character.SimPosition, hull.SimPosition);
- if (path.Unreachable) { continue; }
+ if (path.Unreachable)
+ {
+ unreachable.Add(hull);
+ continue;
+ }
int unsafeNodes = path.Nodes.Count(n => n.CurrentHull != character.CurrentHull && HumanAIController.UnsafeHulls.Contains(n.CurrentHull));
hullSafety /= 1 + unsafeNodes;
// If the target is not inside a friendly submarine, considerably reduce the hull safety.
@@ -219,7 +231,6 @@ namespace Barotrauma
}
}
}
-
// Huge preference for closer targets
float distance = Vector2.DistanceSquared(character.WorldPosition, hull.WorldPosition);
float distanceFactor = MathHelper.Lerp(1, 0.2f, MathUtils.InverseLerp(0, MathUtils.Pow(100000, 2), distance));
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs
index 865f18203..c03fbef43 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs
@@ -26,6 +26,9 @@ namespace Barotrauma
private float standStillTimer;
private float walkDuration;
+ private readonly List targetHulls = new List(20);
+ private readonly List hullWeights = new List(20);
+
public AIObjectiveIdle(Character character) : base(character, "")
{
standStillTimer = Rand.Range(-10.0f, 10.0f);
@@ -106,7 +109,7 @@ namespace Barotrauma
if (isCurrentHullOK)
{
// Check that there is no unsafe or forbidden hulls on the way to the target
- // Only do this when the current hull is ok, because otherwise the would block all paths from the current hull to the target hull.
+ // Only do this when the current hull is ok, because otherwise would block all paths from the current hull to the target hull.
var path = PathSteering.PathFinder.FindPath(character.SimPosition, randomHull.SimPosition);
if (path.Unreachable ||
path.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull) || IsForbidden(n.CurrentHull)))
@@ -128,8 +131,8 @@ namespace Barotrauma
character.AIController.SelectTarget(currentTarget.AiTarget);
string errorMsg = null;
#if DEBUG
- bool isRoomNameFound = currentTarget.RoomName != null;
- errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.RoomName : currentTarget.ToString()) + ")";
+ bool isRoomNameFound = currentTarget.DisplayName != null;
+ errorMsg = "(Character " + character.Name + " idling, target " + (isRoomNameFound ? currentTarget.DisplayName : currentTarget.ToString()) + ")";
#endif
var path = PathSteering.PathFinder.FindPath(character.SimPosition, currentTarget.SimPosition, errorMsg);
PathSteering.SetPath(path);
@@ -230,13 +233,9 @@ namespace Barotrauma
}
}
- private readonly List targetHulls = new List(20);
- private readonly List hullWeights = new List(20);
-
private void FindTargetHulls()
{
bool isCurrentHullOK = !HumanAIController.UnsafeHulls.Contains(character.CurrentHull) && !IsForbidden(character.CurrentHull);
-
targetHulls.Clear();
hullWeights.Clear();
foreach (var hull in Hull.hullList)
@@ -266,7 +265,6 @@ namespace Barotrauma
hullWeights.Add(weight);
}
}
-
}
private bool IsForbidden(Hull hull)
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs
index 943d7110d..72004ee14 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs
@@ -83,7 +83,7 @@ namespace Barotrauma
if (character.SelectedCharacter == null)
{
character?.Speak(TextManager.Get("DialogFoundUnconsciousTarget")
- .Replace("[targetname]", targetCharacter.Name).Replace("[roomname]", character.CurrentHull.RoomName),
+ .Replace("[targetname]", targetCharacter.Name).Replace("[roomname]", character.CurrentHull.DisplayName),
null, 1.0f,
"foundunconscioustarget" + targetCharacter.Name, 60.0f);
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs
index 6ccd779c1..2839536b5 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs
@@ -717,22 +717,6 @@ namespace Barotrauma
limb?.body.SmoothRotate(angle, torque, wrapAngle: false);
}
- private void SmoothRotateWithoutWrapping(Limb limb, float angle, Limb referenceLimb, float torque)
- {
- //make sure the angle "has the same number of revolutions" as the reference limb
- //(e.g. we don't want to rotate the legs to 0 if the torso is at 360, because that'd blow up the hip joints)
- while (referenceLimb.Rotation - angle > MathHelper.TwoPi)
- {
- angle += MathHelper.TwoPi;
- }
- while (referenceLimb.Rotation - angle < -MathHelper.TwoPi)
- {
- angle -= MathHelper.TwoPi;
- }
-
- limb?.body.SmoothRotate(angle, torque, wrapAngle: false);
- }
-
public override void Flip()
{
base.Flip();
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs
index 138cc61d7..da531aed0 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs
@@ -534,7 +534,12 @@ namespace Barotrauma
Limb leftLeg = GetLimb(LimbType.LeftLeg);
Limb rightLeg = GetLimb(LimbType.RightLeg);
-
+
+ float limpAmount =
+ character.CharacterHealth.GetAfflictionStrength("damage", leftFoot, true) +
+ character.CharacterHealth.GetAfflictionStrength("damage", rightFoot, true);
+ limpAmount = MathHelper.Clamp(limpAmount / 100.0f, 0.0f, 1.0f);
+
float walkCycleMultiplier = 1.0f;
if (Stairs != null)
{
@@ -564,17 +569,16 @@ namespace Barotrauma
float walkPosX = (float)Math.Cos(WalkPos);
float walkPosY = (float)Math.Sin(WalkPos);
-
-
+
Vector2 stepSize = StepSize.Value;
stepSize.X *= walkPosX;
- stepSize.Y *= walkPosY;
+ stepSize.Y *= walkPosY;
float footMid = colliderPos.X;
if (limpAmount > 0.0f)
{
//make the footpos oscillate when limping
- footMid += (Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * Math.Min(Math.Abs(TargetMovement.X), 0.3f));
+ footMid += ((float)Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * 0.3f);
}
movement = overrideTargetMovement == Vector2.Zero ?
@@ -589,7 +593,7 @@ namespace Barotrauma
movement.Y = 0.0f;
if (torso == null) { return; }
-
+
bool isNotRemote = true;
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) isNotRemote = !character.IsRemotePlayer;
@@ -693,7 +697,7 @@ namespace Barotrauma
//make the character limp if the feet are damaged
float footAfflictionStrength = character.CharacterHealth.GetAfflictionStrength("damage", foot, true);
- footPos *= MathHelper.Lerp(1.0f, 0.5f, MathHelper.Clamp(footAfflictionStrength / 100.0f, 0.0f, 1.0f));
+ footPos.X *= MathHelper.Lerp(1.0f, 0.75f, MathHelper.Clamp(footAfflictionStrength / 50.0f, 0.0f, 1.0f));
if (onSlope && Stairs == null)
{
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs
index 3f32ca43d..81677d50f 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Params/Ragdoll/RagdollParams.cs
@@ -84,6 +84,7 @@ namespace Barotrauma
var folder = XMLExtensions.TryLoadXml(Character.GetConfigFile(speciesName))?.Root?.Element("ragdolls")?.GetAttributeString("folder", string.Empty);
if (string.IsNullOrEmpty(folder) || folder.ToLowerInvariant() == "default")
{
+ //DebugConsole.NewMessage("[RagollParams] Using the default folder.");
folder = GetDefaultFolder(speciesName);
}
return folder;
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
index 934e0bd3a..3d57328e5 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
@@ -701,7 +701,7 @@ namespace Barotrauma
ImpactProjSpecific(impact, f1.Body);
}
- public void SeverLimbJoint(LimbJoint limbJoint)
+ public void SeverLimbJoint(LimbJoint limbJoint, bool playSound = true)
{
if (!limbJoint.CanBeSevered || limbJoint.IsSevered)
{
@@ -730,7 +730,7 @@ namespace Barotrauma
}
}
- partial void SeverLimbJointProjSpecific(LimbJoint limbJoint);
+ partial void SeverLimbJointProjSpecific(LimbJoint limbJoint, bool playSound = true);
private void GetConnectedLimbs(List connectedLimbs, List checkedJoints, Limb limb)
{
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
index 0e84aa580..8e0c79593 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
@@ -80,13 +80,13 @@ namespace Barotrauma
public HitDetection HitDetectionType { get; private set; }
[Serialize(AIBehaviorAfterAttack.FallBack, true), Editable(ToolTip = "The preferred AI behavior after the attack.")]
- public AIBehaviorAfterAttack AfterAttack { get; private set; }
+ public AIBehaviorAfterAttack AfterAttack { get; set; }
[Serialize(false, true), Editable(ToolTip = "Should the ai try to reverse when aiming with this attack?")]
public bool Reverse { get; private set; }
[Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 2000.0f, ToolTip = "Min distance from the attack limb to the target before the AI tries to attack.")]
- public float Range { get; private set; }
+ public float Range { get; set; }
[Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 2000.0f, ToolTip = "Min distance from the attack limb to the target to do damage. In distance based hit detection, the hit will be registered as soon as the target is within the damage range, unless the attack duration has expired.")]
public float DamageRange { get; set; }
@@ -95,19 +95,19 @@ namespace Barotrauma
public float Duration { get; private set; }
[Serialize(5f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ToolTip = "How long the AI waits between the attacks.")]
- public float CoolDown { get; private set; } = 5;
+ public float CoolDown { get; set; } = 5;
[Serialize(0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 2, ToolTip = "Used as the attack cooldown between different kind of attacks. Does not have effect, if set to 0.")]
- public float SecondaryCoolDown { get; private set; } = 0;
+ public float SecondaryCoolDown { get; set; } = 0;
[Serialize(0f, true), Editable(MinValueFloat = 0, MaxValueFloat = 1, DecimalCount = 2, ToolTip = "Random factor applied to all cooldowns. Example: 0.1 -> adds a random value between -10% and 10% of the cooldown. Min 0 (default), Max 1 (could disable or double the cooldown in extreme cases).")]
public float CoolDownRandomFactor { get; private set; } = 0;
[Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10000.0f)]
- public float StructureDamage { get; private set; }
+ public float StructureDamage { get; set; }
[Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
- public float ItemDamage { get; private set; }
+ public float ItemDamage { get; set; }
///
/// Legacy support. Use Afflictions.
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
index 720372de4..7257b4c18 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs
@@ -1103,14 +1103,14 @@ namespace Barotrauma
if (leftFoot != null)
{
float footAfflictionStrength = CharacterHealth.GetAfflictionStrength("damage", leftFoot, true);
- speed *= MathHelper.Lerp(1.0f, 0.25f, MathHelper.Clamp(footAfflictionStrength / 100.0f, 0.0f, 1.0f));
+ speed *= MathHelper.Lerp(1.0f, 0.4f, MathHelper.Clamp(footAfflictionStrength / 80.0f, 0.0f, 1.0f));
}
var rightFoot = AnimController.GetLimb(LimbType.RightFoot);
if (rightFoot != null)
{
float footAfflictionStrength = CharacterHealth.GetAfflictionStrength("damage", rightFoot, true);
- speed *= MathHelper.Lerp(1.0f, 0.25f, MathHelper.Clamp(footAfflictionStrength / 100.0f, 0.0f, 1.0f));
+ speed *= MathHelper.Lerp(1.0f, 0.4f, MathHelper.Clamp(footAfflictionStrength / 80.0f, 0.0f, 1.0f));
}
return speed;
@@ -2598,6 +2598,10 @@ namespace Barotrauma
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
+#if CLIENT
+ GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
+#endif
+
#if CLIENT
GameMain.GameSession?.CrewManager?.RemoveCharacter(this);
#endif
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs
index 9a25fcd52..8a2aa9ca9 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs
@@ -231,7 +231,8 @@ namespace Barotrauma
: afflictions.Concat(limbHealths.SelectMany(lh => lh.Afflictions.Where(limbHealthFilter)));
}
- private LimbHealth GetMathingLimbHealth(Affliction affliction) => limbHealths[Character.AnimController.GetLimb(affliction.Prefab.IndicatorLimb).HealthIndex];
+ private LimbHealth GetMatchingLimbHealth(Limb limb) => limbHealths[limb.HealthIndex];
+ private LimbHealth GetMathingLimbHealth(Affliction affliction) => GetMatchingLimbHealth(Character.AnimController.GetLimb(affliction.Prefab.IndicatorLimb));
///
/// Returns the limb afflictions and non-limbspecific afflictions that are set to be displayed on this limb.
@@ -611,6 +612,12 @@ namespace Barotrauma
partial void UpdateBleedingProjSpecific(AfflictionBleeding affliction, Limb targetLimb, float deltaTime);
+ public void SetVitality(float newVitality)
+ {
+ maxVitality = newVitality;
+ CalculateVitality();
+ }
+
public void CalculateVitality()
{
Vitality = MaxVitality;
diff --git a/Barotrauma/BarotraumaShared/Source/Extensions/StringFormatter.cs b/Barotrauma/BarotraumaShared/Source/Extensions/StringFormatter.cs
index 541879e2d..9aa6cdada 100644
--- a/Barotrauma/BarotraumaShared/Source/Extensions/StringFormatter.cs
+++ b/Barotrauma/BarotraumaShared/Source/Extensions/StringFormatter.cs
@@ -8,6 +8,22 @@ namespace Barotrauma
{
public static class StringFormatter
{
+ public static string Replace(this string s, string replacement, Func predicate)
+ {
+ var newString = new string[s.Length];
+ for (int i = 0; i < s.Length; i++)
+ {
+ char letter = s[i];
+ string newLetter = letter.ToString();
+ if (predicate(letter))
+ {
+ newLetter = replacement;
+ }
+ newString[i] = newLetter;
+ }
+ return new string(newString.SelectMany(str => str.ToCharArray()).ToArray());
+ }
+
public static string Remove(this string s, Func predicate)
{
return new string(s.ToCharArray().Where(c => !predicate(c)).ToArray());
diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs b/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs
index aa0aa8fda..271dd6dc1 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs
@@ -108,7 +108,7 @@ namespace Barotrauma
}
#if CLIENT
- new GUIMessageBox("", TextManager.Get("CargoSpawnNotification").Replace("[roomname]", cargoRoom.RoomName));
+ new GUIMessageBox("", TextManager.Get("CargoSpawnNotification").Replace("[roomname]", cargoRoom.DisplayName));
#endif
Dictionary availableContainers = new Dictionary();
diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/CampaignMode.cs
index 220e756cd..f081d1c0e 100644
--- a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/CampaignMode.cs
+++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/CampaignMode.cs
@@ -13,6 +13,7 @@ namespace Barotrauma
public bool CheatsEnabled;
const int InitialMoney = 4700;
+ public const int HullRepairCost = 500, ItemRepairCost = 500;
protected bool watchmenSpawned;
protected Character startWatchman, endWatchman;
@@ -20,6 +21,8 @@ namespace Barotrauma
//key = dialog flag, double = Timing.TotalTime when the line was last said
private Dictionary dialogLastSpoken = new Dictionary();
+ public bool PurchasedHullRepairs, PurchasedItemRepairs;
+
protected Map map;
public Map Map
{
@@ -70,6 +73,37 @@ namespace Barotrauma
watchmenSpawned = false;
startWatchman = null;
endWatchman = null;
+
+ if (PurchasedHullRepairs)
+ {
+ foreach (Structure wall in Structure.WallList)
+ {
+ if (wall.Submarine == null || wall.Submarine.IsOutpost) { continue; }
+ if (wall.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(wall.Submarine))
+ {
+ for (int i = 0; i < wall.SectionCount; i++)
+ {
+ wall.AddDamage(i, -100000.0f);
+ }
+ }
+ }
+ PurchasedHullRepairs = false;
+ }
+ if (PurchasedItemRepairs)
+ {
+ foreach (Item item in Item.ItemList)
+ {
+ if (item.Submarine == null || item.Submarine.IsOutpost) { continue; }
+ if (item.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(item.Submarine))
+ {
+ if (item.GetComponent() != null)
+ {
+ item.Condition = item.Health;
+ }
+ }
+ }
+ PurchasedItemRepairs = false;
+ }
}
public override void Update(float deltaTime)
diff --git a/Barotrauma/BarotraumaShared/Source/Items/CharacterInventory.cs b/Barotrauma/BarotraumaShared/Source/Items/CharacterInventory.cs
index 12434a1be..4b8d00255 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/CharacterInventory.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/CharacterInventory.cs
@@ -176,6 +176,9 @@ namespace Barotrauma
{
if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] != null && Items[i] != item)
{
+#if CLIENT
+ if (PersonalSlots.HasFlag(SlotTypes[i])) { hidePersonalSlots = false; }
+#endif
if (!Items[i].AllowedSlots.Contains(InvSlotType.Any) || !TryPutItem(Items[i], character, new List { InvSlotType.Any }, true))
{
free = false;
@@ -195,6 +198,9 @@ namespace Barotrauma
{
if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] == null)
{
+#if CLIENT
+ if (PersonalSlots.HasFlag(SlotTypes[i])) { hidePersonalSlots = false; }
+#endif
bool removeFromOtherSlots = item.ParentInventory != this;
if (placedInSlot == -1 && inWrongSlot)
{
@@ -248,7 +254,9 @@ namespace Barotrauma
GameAnalyticsManager.AddErrorEventOnce("CharacterInventory.TryPutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return false;
}
-
+#if CLIENT
+ if (PersonalSlots.HasFlag(SlotTypes[index])) { hidePersonalSlots = false; }
+#endif
//there's already an item in the slot
if (Items[index] != null)
{
@@ -273,7 +281,9 @@ namespace Barotrauma
foreach (InvSlotType allowedSlot in allowedSlots)
{
if (!allowedSlot.HasFlag(SlotTypes[index])) continue;
-
+#if CLIENT
+ if (PersonalSlots.HasFlag(allowedSlot)) { hidePersonalSlots = false; }
+#endif
for (int i = 0; i < capacity; i++)
{
if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] != null && Items[i] != item)
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs
index 8e632707b..973b7e655 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs
@@ -223,11 +223,11 @@ namespace Barotrauma.Items.Components
var idCard = character.Inventory.FindItemByIdentifier("idcard");
hasValidIdCard = requiredItems.Any(ri => ri.Value.Any(r => r.MatchesItem(idCard)));
- Msg = hasValidIdCard ? "ItemMsgOpen" : "ItemMsgForceOpenCrowbar";
+ Msg = requiredItems.None() || hasValidIdCard ? "ItemMsgOpen" : "ItemMsgForceOpenCrowbar";
ParseMsg();
if (addMessage)
{
- msg = msg ?? (requiredItems.Any(ri => ri.Value.Any(r => r.Identifiers.Contains("idcard"))) ? accessDeniedTxt : cannotOpenText);
+ msg = msg ?? (HasIntegratedButtons ? accessDeniedTxt : cannotOpenText);
}
//this is a bit pointless atm because if canBePicked is false it won't allow you to do Pick() anyway, however it's still good for future-proofing.
@@ -237,6 +237,7 @@ namespace Barotrauma.Items.Components
public override bool Pick(Character picker)
{
if (item.Condition <= RepairThreshold) { return true; }
+ if (requiredItems.None()) { return false; }
if (HasRequiredItems(picker, false) && hasValidIdCard) { return false; }
return base.Pick(picker);
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs
index 36e56362a..38953e28a 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs
@@ -338,11 +338,11 @@ namespace Barotrauma.Items.Components
sinTime = 0;
if (!leak.FlowTargetHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f))
{
- character.Speak(TextManager.Get("DialogLeaksFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leaksfixed", 10.0f);
+ character.Speak(TextManager.Get("DialogLeaksFixed").Replace("[roomname]", leak.FlowTargetHull.DisplayName), null, 0.0f, "leaksfixed", 10.0f);
}
else
{
- character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.RoomName), null, 0.0f, "leakfixed", 10.0f);
+ character.Speak(TextManager.Get("DialogLeakFixed").Replace("[roomname]", leak.FlowTargetHull.DisplayName), null, 0.0f, "leakfixed", 10.0f);
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
index 6f0ace085..831c07c39 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs
@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
get { return name; }
}
- [Editable, Serialize("", true)]
+ [Editable, Serialize("", true, translationTextTag: "ItemMsg")]
public string Msg
{
get;
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs
index c090837a7..c59d6bce6 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs
@@ -185,6 +185,19 @@ namespace Barotrauma.Items.Components
return true;
}
+ public override void OnItemLoaded()
+ {
+ sonar = item.GetComponent();
+ }
+
+ public override bool Select(Character character)
+ {
+ if (!CanBeSelected) return false;
+
+ user = character;
+ return true;
+ }
+
public override void Update(float deltaTime, Camera cam)
{
networkUpdateTimer -= deltaTime;
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs
index 1fd9ca9e6..48b98b710 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs
@@ -8,11 +8,19 @@ namespace Barotrauma.Items.Components
{
partial class CustomInterface : ItemComponent, IClientSerializable, IServerSerializable
{
- class CustomInterfaceElement
+ class CustomInterfaceElement : ISerializableEntity
{
public bool ContinuousSignal;
public bool State;
- public string Label, Connection, Signal;
+ public string Connection;
+ [Serialize("", false, translationTextTag = "Label.")]
+ public string Label { get; set; }
+ [Serialize("1", false)]
+ public string Signal { get; set; }
+
+ public string Name => "CustomInterfaceElement";
+
+ public Dictionary SerializableProperties { get; set; }
public List StatusEffects = new List();
@@ -33,7 +41,7 @@ namespace Barotrauma.Items.Components
}
private string[] labels;
- [Serialize("", true), Editable()]
+ [Serialize("", true)]
public string Labels
{
get { return string.Join(",", labels); }
@@ -48,7 +56,7 @@ namespace Barotrauma.Items.Components
}
}
private string[] signals;
- [Serialize("", true), Editable()]
+ [Serialize("", true)]
public string Signals
{
//use semicolon as a separator because comma may be needed in the signals (for color or vector values for example)
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs
index 4bee0e644..1befb10a5 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Wearable.cs
@@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
+using Barotrauma.Extensions;
namespace Barotrauma
{
@@ -66,6 +67,8 @@ namespace Barotrauma
public LightComponent LightComponent { get; set; }
+ public int Variant { get; set; }
+
private Gender _gender;
///
/// None = Any/Not Defined -> no effect.
@@ -112,30 +115,65 @@ namespace Barotrauma
///
/// Note: this constructor cannot initialize automatically, because the gender is unknown at this point. We only know it when the item is equipped.
///
- public WearableSprite(XElement subElement, Wearable wearable)
+ public WearableSprite(XElement subElement, Wearable wearable, int variant = 0)
{
Type = WearableType.Item;
WearableComponent = wearable;
+ Variant = Math.Max(variant, 0);
SpritePath = ParseSpritePath(subElement.GetAttributeString("texture", string.Empty));
SourceElement = subElement;
}
private string ParseSpritePath(string texturePath) => texturePath.Contains("/") ? texturePath : $"{Path.GetDirectoryName(WearableComponent.Item.Prefab.ConfigFile)}/{texturePath}";
+ public void RefreshPath()
+ {
+ if (Variant > 0)
+ {
+ // Restore the tag so that we can parse it again.
+ ReplaceNumbersWith("[VARIANT]");
+ }
+ ParsePath(true);
+ }
+
+ private void ReplaceNumbersWith(string replacement)
+ {
+ var fileName = Path.GetFileName(SpritePath);
+ var path = Path.GetDirectoryName(SpritePath);
+ fileName = fileName.Replace(replacement, c => char.IsNumber(c));
+ SpritePath = Path.Combine(path, fileName);
+ }
+
+ private void ParsePath(bool parseSpritePath)
+ {
+ if (_gender != Gender.None)
+ {
+ SpritePath = SpritePath.Replace("[GENDER]", (_gender == Gender.Female) ? "female" : "male");
+ }
+ SpritePath = SpritePath.Replace("[VARIANT]", Variant.ToString());
+ if (!File.Exists(SpritePath))
+ {
+ // If the variant does not exist, parse the path so that it uses first variant.
+ Variant = 1;
+ ReplaceNumbersWith(Variant.ToString());
+ }
+ if (parseSpritePath)
+ {
+ Sprite.ParseTexturePath(file: SpritePath);
+ }
+ }
+
public bool IsInitialized { get; private set; }
public void Init(Gender gender = Gender.None)
{
if (IsInitialized) { return; }
_gender = SpritePath.Contains("[GENDER]") ? gender : Gender.None;
- if (_gender != Gender.None)
- {
- SpritePath = SpritePath.Replace("[GENDER]", (_gender == Gender.Female) ? "female" : "male");
- }
+ ParsePath(false);
if (Sprite != null)
{
Sprite.Remove();
}
- Sprite = new Sprite(SourceElement, "", SpritePath);
+ Sprite = new Sprite(SourceElement, file: SpritePath);
Limb = (LimbType)Enum.Parse(typeof(LimbType), SourceElement.GetAttributeString("limb", "Head"), true);
HideLimb = SourceElement.GetAttributeBool("hidelimb", false);
HideOtherWearables = SourceElement.GetAttributeBool("hideotherwearables", false);
@@ -170,7 +208,7 @@ namespace Barotrauma.Items.Components
get { return damageModifiers; }
}
- public Wearable (Item item, XElement element) : base(item, element)
+ public Wearable(Item item, XElement element) : base(item, element)
{
this.item = item;
@@ -197,7 +235,7 @@ namespace Barotrauma.Items.Components
limbType[i] = (LimbType)Enum.Parse(typeof(LimbType),
subElement.GetAttributeString("limb", "Head"), true);
- wearableSprites[i] = new WearableSprite(subElement, this);
+ wearableSprites[i] = new WearableSprite(subElement, this, variant);
foreach (XElement lightElement in subElement.Elements())
{
diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs
index e6ff07bc4..0c5ee8062 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs
@@ -144,18 +144,6 @@ namespace Barotrauma
private List fabricationRecipeElements = new List();
- private bool canSpriteFlipX, canSpriteFlipY;
-
- private Dictionary prices;
-
- ///
- /// Defines areas where the item can be interacted with. If RequireBodyInsideTrigger is set to true, the character
- /// has to be within the trigger to interact. If it's set to false, having the cursor within the trigger is enough.
- ///
- public List Triggers;
-
- private List fabricationRecipeElements = new List();
-
public string ConfigFile
{
get { return configFile; }
@@ -477,6 +465,12 @@ namespace Barotrauma
Tags = element.GetAttributeStringArray("Tags", new string[0], convertToLowerInvariant: true).ToHashSet();
}
+ Tags = new HashSet(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true));
+ if (Tags.None())
+ {
+ Tags = new HashSet(element.GetAttributeStringArray("Tags", new string[0], convertToLowerInvariant: true));
+ }
+
if (element.Attribute("cargocontainername") != null)
{
DebugConsole.ThrowError("Error in item prefab \"" + name + "\" - cargo container should be configured using the item's identifier, not the name.");
@@ -636,10 +630,25 @@ namespace Barotrauma
string treatmentIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant();
- var matchingAffliction = AfflictionPrefab.List.Find(a => a.Identifier == treatmentIdentifier);
- if (matchingAffliction != null)
+ List matchingAfflictions = AfflictionPrefab.List.FindAll(a => a.Identifier == treatmentIdentifier || a.AfflictionType == treatmentIdentifier);
+ if (matchingAfflictions.Count == 0)
{
- matchingAffliction.TreatmentSuitability.Add(identifier, subElement.GetAttributeFloat("suitability", 0.0f));
+ DebugConsole.ThrowError("Error in item prefab \"" + Name + "\" - couldn't define as a treatment, no treatments with the identifier or type \"" + treatmentIdentifier + "\" were found.");
+ continue;
+ }
+
+ float suitability = subElement.GetAttributeFloat("suitability", 0.0f);
+ foreach (AfflictionPrefab matchingAffliction in matchingAfflictions)
+ {
+ if (matchingAffliction.TreatmentSuitability.ContainsKey(identifier))
+ {
+ matchingAffliction.TreatmentSuitability[identifier] =
+ Math.Max(matchingAffliction.TreatmentSuitability[identifier], suitability);
+ }
+ else
+ {
+ matchingAffliction.TreatmentSuitability.Add(identifier, suitability);
+ }
}
break;
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs
index b87ca0149..0b833e2dd 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs
@@ -25,6 +25,8 @@ namespace Barotrauma
private bool removed;
+ private bool removed;
+
#if CLIENT
private List burnDecals = new List();
#endif
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs
index 798b322b6..3cfbaa599 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs
@@ -90,6 +90,25 @@ namespace Barotrauma
}
}
+ public string DisplayName
+ {
+ get;
+ private set;
+ }
+
+ private string roomName;
+ [Editable, Serialize("", true, translationTextTag: "RoomName.")]
+ public string RoomName
+ {
+ get { return roomName; }
+ set
+ {
+ if (roomName == value) { return; }
+ roomName = value;
+ DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName;
+ }
+ }
+
public override Rectangle Rect
{
get
@@ -817,17 +836,17 @@ namespace Barotrauma
}
if (roomItems.Contains("reactor"))
- return TextManager.Get("ReactorRoom");
+ return "RoomName.ReactorRoom";
else if (roomItems.Contains("engine"))
- return TextManager.Get("EngineRoom");
+ return "RoomName.EngineRoom";
else if (roomItems.Contains("steering") && roomItems.Contains("sonar"))
- return TextManager.Get("CommandRoom");
+ return "RoomName.CommandRoom";
else if (roomItems.Contains("ballast"))
- return TextManager.Get("Ballast");
+ return "RoomName.Ballast";
if (ConnectedGaps.Any(g => !g.IsRoomToRoom && g.ConnectedDoor != null))
{
- return TextManager.Get("Airlock");
+ return "RoomName.Airlock";
}
Rectangle subRect = Submarine.CalculateDimensions();
@@ -847,7 +866,7 @@ namespace Barotrauma
else
roomPos |= Alignment.Right;
- return TextManager.Get("Sub" + roomPos.ToString());
+ return "RoomName.Sub" + roomPos.ToString();
}
public static Hull Load(XElement element, Submarine submarine)
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
index c7704d343..55608b242 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
@@ -314,8 +314,8 @@ namespace Barotrauma
}
}
- // Only add ai targets automatically to walls
- if (aiTarget == null && HasBody && Tags.Contains("wall"))
+ // Only add ai targets automatically to submarine/outpost walls
+ if (aiTarget == null && HasBody && Tags.Contains("wall") && submarine != null)
{
aiTarget = new AITarget(this);
}
@@ -1203,6 +1203,9 @@ namespace Barotrauma
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;
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs
index ada123764..a0fd7465d 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs
@@ -417,7 +417,10 @@ namespace Barotrauma
if (me.Submarine != this) { continue; }
if (me is Item item)
{
- item.Indestructible = true;
+ if (item.GetComponent() != null)
+ {
+ item.Indestructible = true;
+ }
foreach (ItemComponent ic in item.Components)
{
if (ic is ConnectionPanel connectionPanel)
@@ -533,20 +536,6 @@ namespace Barotrauma
{
maxX = Math.Min(maxX, ruin.Area.X - 100.0f);
}
- else
- {
- maxX = Math.Min(maxX, ruin.Area.X - 100.0f);
- }
- }
-
- if (minX < 0.0f && maxX > Level.Loaded.Size.X)
- {
- //no walls found at either side, just use the initial spawnpos and hope for the best
- }
- else if (minX < 0)
- {
- //no wall found at the left side, spawn to the left from the right-side wall
- spawnPos.X = maxX - minWidth - 100.0f + subDockingPortOffset;
}
if (minX < 0.0f && maxX > Level.Loaded.Size.X)
diff --git a/Barotrauma/BarotraumaShared/Source/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaShared/Source/Networking/OrderChatMessage.cs
index 0f8f53bd7..85523d2fa 100644
--- a/Barotrauma/BarotraumaShared/Source/Networking/OrderChatMessage.cs
+++ b/Barotrauma/BarotraumaShared/Source/Networking/OrderChatMessage.cs
@@ -20,7 +20,7 @@ namespace Barotrauma.Networking
public OrderChatMessage(Order order, string orderOption, Entity targetEntity, Character targetCharacter, Character sender)
: this(order, orderOption,
- order.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.RoomName, givingOrderToSelf: targetCharacter == sender, orderOption: orderOption),
+ order.GetChatMessage(targetCharacter?.Name, sender?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == sender, orderOption: orderOption),
targetEntity, targetCharacter, sender)
{
}
diff --git a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs
index 8ad826eea..e13028523 100644
--- a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs
+++ b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs
@@ -162,21 +162,6 @@ namespace Barotrauma
get { return binding; }
}
- public void SetState()
- {
- hit = binding.IsHit();
- if (hit) hitQueue = true;
-
- held = binding.IsDown();
- if (held) heldQueue = true;
- }
-#endif
-
- public KeyOrMouse State
- {
- get { return binding; }
- }
-
public void SetState()
{
hit = binding.IsHit();
diff --git a/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs b/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs
index 0921bd91d..064b5d1e2 100644
--- a/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs
+++ b/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs
@@ -87,7 +87,6 @@ namespace Barotrauma
public string FullPath { get; private set; }
-
public override string ToString()
{
return FilePath + ": " + sourceRect;
@@ -107,25 +106,7 @@ namespace Barotrauma
{
this.lazyLoad = lazyLoad;
SourceElement = element;
- if (file == "")
- {
- file = SourceElement.GetAttributeString("texture", "");
- }
- if (file == "")
- {
- DebugConsole.ThrowError("Sprite " + SourceElement + " doesn't have a texture specified!");
- return;
- }
- if (!string.IsNullOrEmpty(path))
- {
- LoadTexture(ref sourceVector, ref shouldReturn, preMultipliedAlpha);
- }
- FilePath = path + file;
- if (!string.IsNullOrEmpty(FilePath))
- {
- FullPath = Path.GetFullPath(FilePath);
- }
-
+ if (!ParseTexturePath(path, file)) { return; }
Name = SourceElement.GetAttributeString("name", null);
Vector4 sourceVector = SourceElement.GetAttributeVector4("sourcerect", Vector4.Zero);
preMultipliedAlpha = preMultiplyAlpha ?? SourceElement.GetAttributeBool("premultiplyalpha", true);
@@ -269,6 +250,29 @@ namespace Barotrauma
ID = GetID(SourceElement);
}
}
+
+ public bool ParseTexturePath(string path = "", string file = "")
+ {
+ if (file == "")
+ {
+ file = SourceElement.GetAttributeString("texture", "");
+ }
+ if (file == "")
+ {
+ DebugConsole.ThrowError("Sprite " + SourceElement + " doesn't have a texture specified!");
+ return false;
+ }
+ if (!string.IsNullOrEmpty(path))
+ {
+ if (!path.EndsWith("/")) path += "/";
+ }
+ FilePath = path + file;
+ if (!string.IsNullOrEmpty(FilePath))
+ {
+ FullPath = Path.GetFullPath(FilePath);
+ }
+ return true;
+ }
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/TextManager.cs b/Barotrauma/BarotraumaShared/Source/TextManager.cs
index b7a01e523..52df9ac7b 100644
--- a/Barotrauma/BarotraumaShared/Source/TextManager.cs
+++ b/Barotrauma/BarotraumaShared/Source/TextManager.cs
@@ -252,140 +252,6 @@ namespace Barotrauma
return null;
}
- public static string GetFormatted(string textTag, bool returnNull = false, params object[] args)
- {
- string text = Get(textTag, returnNull);
-
- if (text == null || text.Length == 0)
- {
- if (returnNull)
- {
- return null;
- }
- else
- {
- DebugConsole.ThrowError("Text \"" + textTag + "\" not found.");
- return textTag;
- }
- }
-
- return string.Format(text, args);
- }
-
- // Format: ServerMessage.Identifier1/ServerMessage.Indentifier2~[variable1]=value~[variable2]=value
- public static string GetServerMessage(string serverMessage)
- {
- if (!textPacks.ContainsKey(Language))
- {
- DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
- Language = "English";
- if (!textPacks.ContainsKey(Language))
- {
- throw new Exception("No text packs available in English!");
- }
- }
-
- string[] messages = serverMessage.Split('/');
-
- try
- {
- for (int i = 0; i < messages.Length; i++)
- {
- if (!IsServerMessageWithVariables(messages[i])) // No variables, try to translate
- {
- if (messages[i].Contains(" ")) continue; // Spaces found, do not translate
- string msg = Get(messages[i], true);
- if (msg != null) // If a translation was found, otherwise use the original
- {
- messages[i] = msg;
- }
- }
- else
- {
- string[] messageWithVariables = messages[i].Split('~');
- string msg = Get(messageWithVariables[0], true);
-
- if (msg != null) // If a translation was found, otherwise use the original
- {
- messages[i] = msg;
- }
- else
- {
- continue; // No translation found, probably caused by player input -> skip variable handling
- }
-
- // First index is always the message identifier -> start at 1
- for (int j = 1; j < messageWithVariables.Length; j++)
- {
- string[] variableAndValue = messageWithVariables[j].Split('=');
- messages[i] = messages[i].Replace(variableAndValue[0], variableAndValue[1]);
- }
- }
- }
-
- string translatedServerMessage = string.Empty;
- for (int i = 0; i < messages.Length; i++)
- {
- translatedServerMessage += messages[i];
- }
- return translatedServerMessage;
- }
-
- catch (IndexOutOfRangeException exception)
- {
- string errorMsg = "Failed to translate server message \"" + serverMessage + "\".";
-#if DEBUG
- DebugConsole.ThrowError(errorMsg, exception);
-#endif
- GameAnalyticsManager.AddErrorEventOnce("TextManager.GetServerMessage:" + serverMessage, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
- return errorMsg;
- }
- }
-
- public static bool IsServerMessageWithVariables(string message)
- {
- for (int i = 0; i < serverMessageCharacters.Length; i++)
- {
- if (!message.Contains(serverMessageCharacters[i])) return false;
- }
-
- return true;
- }
-
- public static List GetAll(string textTag)
- {
- if (!textPacks.ContainsKey(Language))
- {
- DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English...");
- Language = "English";
- if (!textPacks.ContainsKey(Language))
- {
- throw new Exception("No text packs available in English!");
- }
- }
-
- List allText;
-
- foreach (TextPack textPack in textPacks[Language])
- {
- allText = textPack.GetAll(textTag);
- if (allText != null) return allText;
- }
-
- //if text was not found and we're using a language other than English, see if we can find an English version
- //may happen, for example, if a user has selected another language and using mods that haven't been translated to that language
- if (Language != "English" && textPacks.ContainsKey("English"))
- {
- foreach (TextPack textPack in textPacks["English"])
- {
- allText = textPack.GetAll(textTag);
- if (allText != null) return allText;
- }
- }
-
- return null;
- }
-
public static List> GetAllTagTextPairs()
{
if (!textPacks.ContainsKey(Language))
diff --git a/Barotrauma/BarotraumaShared/Source/TextPack.cs b/Barotrauma/BarotraumaShared/Source/TextPack.cs
index 91366d043..f1c2c3a76 100644
--- a/Barotrauma/BarotraumaShared/Source/TextPack.cs
+++ b/Barotrauma/BarotraumaShared/Source/TextPack.cs
@@ -37,6 +37,7 @@ namespace Barotrauma
text = text.Replace("&", "&");
text = text.Replace("<", "<");
text = text.Replace(">", ">");
+ text = text.Replace(""", "\"");
infoList.Add(text);
}
}
@@ -62,6 +63,20 @@ namespace Barotrauma
return textList;
}
+ public List> GetAllTagTextPairs()
+ {
+ var pairs = new List>();
+ foreach (KeyValuePair> kvp in texts)
+ {
+ foreach (string line in kvp.Value)
+ {
+ pairs.Add(new KeyValuePair(kvp.Key, line));
+ }
+ }
+
+ return pairs;
+ }
+
#if DEBUG
public void CheckForDuplicates(int index)
{
diff --git a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
index e608871a6..8ae39aa56 100644
--- a/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
+++ b/Barotrauma/BarotraumaShared/Source/Utils/SaveUtil.cs
@@ -228,6 +228,12 @@ namespace Barotrauma
if (fileName.Length == 0) fileName = "Save";
}
+ if (fileName == "Save_Default")
+ {
+ fileName = TextManager.Get("SaveFile.DefaultName", true);
+ if (fileName.Length == 0) fileName = "Save";
+ }
+
if (!Directory.Exists(folder))
{
DebugConsole.ThrowError("Save folder \"" + folder + "\" not found. Created new folder");
diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub
index 2cef11b71..6b354c42d 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ