(a2943d8b7) Merge branch 'dev' into human-ai

This commit is contained in:
Joonas Rikkonen
2019-05-16 05:04:10 +03:00
parent 60f52375e6
commit 039d07f693
76 changed files with 1407 additions and 856 deletions

View File

@@ -193,6 +193,60 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
<None Include="Barotrauma">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Barotrauma.bin.x86">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Barotrauma.bin.x86_64">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Mono.Posix.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Mono.Security.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="monoconfig">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="monomachineconfig">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="mscorlib.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Configuration.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Core.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Data.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Drawing.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Numerics.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Runtime.Serialization.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Security.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Xml.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="System.Xml.Linq.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup />
<ItemGroup>

View File

@@ -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)

View File

@@ -96,6 +96,11 @@ namespace Barotrauma
private const float UpdateDisplayedAfflictionsInterval = 0.5f;
private List<Affliction> currentDisplayedAfflictions = new List<Affliction>();
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;

View File

@@ -296,6 +296,7 @@ namespace Barotrauma
break;
}
}
SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), WorldPosition);
}
// Always spawn damage particles

View File

@@ -1092,8 +1092,8 @@ namespace Barotrauma
List<string> lines = new List<string>();
foreach (MapEntityPrefab me in MapEntityPrefab.List)
{
lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</" + me.Identifier + ".Name>");
lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</" + me.Identifier + ".Description>");
lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</EntityName." + me.Identifier + ">");
lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</EntityDescription." + me.Identifier + ">");
}
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();
}

View File

@@ -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);

View File

@@ -1568,7 +1568,7 @@ namespace Barotrauma
}
/// <summary>
/// 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).
/// </summary>
public static void AddMessage(string message, Color color, float? lifeTime = null, bool playSound = true, ScalableFont font = null)
{

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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
{

View File

@@ -180,6 +180,10 @@ namespace Barotrauma
GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
PerformanceCounter = new PerformanceCounter();
PerformanceCounter = new PerformanceCounter();

View File

@@ -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
/// <summary>
/// Adds the message to the single player chatbox.
/// </summary>
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<object> KillCharacterAnim(GUIComponent component)
@@ -639,6 +692,12 @@ namespace Barotrauma
{
comp.Color = Color.DarkRed;
}
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
c.AIController is HumanAIController &&
!c.IsDead &&
c.SpeechImpediment <= 100.0f);
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
}
yield return new WaitForSeconds(1.0f);
@@ -750,7 +809,7 @@ namespace Barotrauma
if (IsSinglePlayer)
{
orderGiver.Speak(
order.GetChatMessage("", orderGiver.CurrentHull?.RoomName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
order.GetChatMessage("", orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
}
else
{
@@ -767,7 +826,7 @@ namespace Barotrauma
if (IsSinglePlayer)
{
orderGiver?.Speak(
order.GetChatMessage(character.Name, orderGiver.CurrentHull?.RoomName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
}
else if (orderGiver != null)
{
@@ -841,12 +900,6 @@ namespace Barotrauma
matchingItems.RemoveAll(it => it.Submarine != submarine && !submarine.DockedTo.Contains(it.Submarine));
matchingItems.RemoveAll(it => it.Submarine != null && it.Submarine.IsOutpost);
}
var characterElement = characterListBox.Content.FindChild(character);
GUIButton orderBtn = characterElement.FindChild(order, recursive: true) as GUIButton;
if (orderBtn.Frame.FlashTimer <= 0)
{
orderBtn.Flash(color, 1.5f, false, flashRectInflate);
}
//more than one target item -> create a minimap-like selection with a pic of the sub
if (matchingItems.Count > 1)

View File

@@ -135,6 +135,8 @@ namespace Barotrauma
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
msg.Write(PurchasedHullRepairs);
msg.Write(PurchasedItemRepairs);
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
foreach (PurchasedItem pi in CargoManager.PurchasedItems)

View File

@@ -19,7 +19,7 @@ namespace Barotrauma
Right,
Center
}
private enum QuickUseAction
{
None,
@@ -34,6 +34,8 @@ namespace Barotrauma
}
private static Dictionary<InvSlotType, Sprite> limbSlotIcons;
const InvSlotType PersonalSlots = InvSlotType.Card | InvSlotType.Headset | InvSlotType.InnerClothes | InvSlotType.OuterClothes | InvSlotType.Head;
private Point screenResolution;
@@ -51,11 +53,42 @@ namespace Barotrauma
}
}
public bool Hidden { get; set; }
private bool hidePersonalSlots;
private float hidePersonalSlotsState;
private GUIButton hideButton;
private Rectangle personalSlotArea;
public bool HidePersonalSlots
{
get { return hidePersonalSlots; }
}
public Rectangle PersonalSlotArea
{
get { return personalSlotArea; }
}
partial void InitProjSpecific(XElement element)
{
Hidden = true;
hideButton = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), (int)(60 * GUI.Scale)), GUI.Canvas)
{ AbsoluteOffset = HUDLayoutSettings.CrewArea.Location },
"", style: "UIToggleButton");
hideButton.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipHorizontally);
hideButton.OnClicked += (GUIButton btn, object userdata) =>
{
hidePersonalSlots = !hidePersonalSlots;
foreach (GUIComponent child in btn.Children)
{
child.SpriteEffects = hidePersonalSlots ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
}
return true;
};
hidePersonalSlots = false;
if (limbSlotIcons == null)
{
limbSlotIcons = new Dictionary<InvSlotType, Sprite>();
@@ -68,12 +101,11 @@ namespace Barotrauma
limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/IconAtlas.png", new Rectangle(640 + margin, 383 + margin, 128 - margin * 2, 128 - margin * 2)));
limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/IconAtlas.png", new Rectangle(768 + margin, 383 + margin, 128 - margin * 2, 128 - margin * 2)));
}
SlotPositions = new Vector2[SlotTypes.Length];
CurrentLayout = Layout.Default;
SetSlotPositions(layout);
}
protected override void PutItem(Item item, int i, Character user, bool removeItem = true, bool createNetworkEvent = true)
{
base.PutItem(item, i, user, removeItem, createNetworkEvent);
@@ -159,6 +191,11 @@ namespace Barotrauma
{
if (slots[i].Disabled || (hideEmptySlot[i] && Items[i] == null)) return true;
if (layout == Layout.Default)
{
if (PersonalSlots.HasFlag(SlotTypes[i]) && !personalSlotArea.Contains(slots[i].Rect.Center + slots[i].DrawOffset.ToPoint())) return true;
}
//no need to draw the right hand slot if the item is in both hands
if (Items[i] != null && SlotTypes[i] == InvSlotType.RightHand && IsInLimbSlot(Items[i], InvSlotType.LeftHand))
{
@@ -176,7 +213,6 @@ namespace Barotrauma
return false;
}
private void SetSlotPositions(Layout layout)
{
int spacing = (int)(10 * UIScale);
@@ -185,27 +221,32 @@ namespace Barotrauma
if (slots == null) CreateSlots();
var upperSlots = InvSlotType.Card | InvSlotType.Headset | InvSlotType.InnerClothes | InvSlotType.Head | InvSlotType.OuterClothes;
hideButton.Visible = false;
switch (layout)
{
case Layout.Default:
{
int personalSlotCount = SlotTypes.Count(s => upperSlots.HasFlag(s));
int normalSlotCount = SlotTypes.Count(s => !upperSlots.HasFlag(s));
int personalSlotCount = SlotTypes.Count(s => PersonalSlots.HasFlag(s));
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s));
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (slotSize.X + spacing) / 2;
int upperX = HUDLayoutSettings.PortraitArea.X - slotSize.X;
int upperX = HUDLayoutSettings.PortraitArea.X - slotSize.X * 2;
//make sure the rightmost normal slot doesn't overlap with the personal slots
x -= Math.Max((x + normalSlotCount * (slotSize.X + spacing)) - (upperX - personalSlotCount * (slotSize.X + spacing)), 0);
int hideButtonSlotIndex = -1;
for (int i = 0; i < SlotPositions.Length; i++)
{
if (upperSlots.HasFlag(SlotTypes[i]))
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(upperX, GameMain.GraphicsHeight - bottomOffset);
upperX -= slotSize.X + spacing;
personalSlotArea = (hideButtonSlotIndex == -1) ?
new Rectangle(SlotPositions[i].ToPoint(), slotSize) :
Rectangle.Union(personalSlotArea, new Rectangle(SlotPositions[i].ToPoint(), slotSize));
hideButtonSlotIndex = i;
}
else
{
@@ -213,19 +254,29 @@ namespace Barotrauma
x += slotSize.X + spacing;
}
}
if (hideButtonSlotIndex > -1)
{
hideButton.RectTransform.SetPosition(Anchor.TopLeft, Pivot.TopLeft);
hideButton.RectTransform.NonScaledSize = new Point(slotSize.X / 2, slotSize.Y + slots[hideButtonSlotIndex].EquipButtonRect.Height);
hideButton.RectTransform.AbsoluteOffset = new Point(
personalSlotArea.Right + spacing,
personalSlotArea.Y - slots[hideButtonSlotIndex].EquipButtonRect.Height);
hideButton.Visible = true;
}
}
break;
case Layout.Right:
{
int extraOffset = 0;
int x = HUDLayoutSettings.InventoryAreaLower.Right;
int upperX = HUDLayoutSettings.InventoryAreaLower.Right;
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - slotSize.X - spacing;
for (int i = 0; i < slots.Length; i++)
{
if (HideSlot(i)) continue;
if (upperSlots.HasFlag(SlotTypes[i]))
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
upperX -= slotSize.X + spacing;
//upperX -= slotSize.X + spacing;
}
else
{
@@ -237,10 +288,10 @@ namespace Barotrauma
for (int i = 0; i < SlotPositions.Length; i++)
{
if (HideSlot(i)) continue;
if (upperSlots.HasFlag(SlotTypes[i]))
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(upperX, GameMain.GraphicsHeight - bottomOffset * 2 - extraOffset - spacing * 2);
upperX += slots[i].Rect.Width + spacing;
SlotPositions[i] = new Vector2(personalSlotX, GameMain.GraphicsHeight - bottomOffset * 2 - extraOffset - spacing * 2);
personalSlotX -= slots[i].Rect.Width + spacing;
}
else
{
@@ -261,14 +312,14 @@ namespace Barotrauma
case Layout.Left:
{
int x = HUDLayoutSettings.InventoryAreaLower.X;
int upperX = x;
int personalSlotX = x;
for (int i = 0; i < SlotPositions.Length; i++)
{
if (HideSlot(i)) continue;
if (upperSlots.HasFlag(SlotTypes[i]))
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(upperX, GameMain.GraphicsHeight - bottomOffset * 2 - spacing * 2);
upperX += slots[i].Rect.Width + spacing;
SlotPositions[i] = new Vector2(personalSlotX, GameMain.GraphicsHeight - bottomOffset * 2 - spacing * 2);
personalSlotX += slots[i].Rect.Width + spacing;
}
else
{
@@ -354,6 +405,27 @@ namespace Barotrauma
((selectedSlot != null && selectedSlot.IsSubSlot) || (draggingItem != null && (draggingSlot == null || !draggingSlot.MouseOn())));
if (CharacterHealth.OpenHealthWindow != null) hoverOnInventory = true;
if (layout == Layout.Default && hideButton.Visible)
{
hideButton.AddToGUIUpdateList();
hideButton.UpdateManually(deltaTime, alsoChildren: true);
hidePersonalSlotsState = hidePersonalSlots ?
Math.Min(hidePersonalSlotsState + deltaTime * 5.0f, 1.0f) :
Math.Max(hidePersonalSlotsState - deltaTime * 5.0f, 0.0f);
for (int i = 0; i < slots.Length; i++)
{
if (!PersonalSlots.HasFlag(SlotTypes[i])) { continue; }
if (HidePersonalSlots)
{
if (selectedSlot?.Slot == slots[i]) { selectedSlot = null; }
highlightedSubInventorySlots.RemoveWhere(s => s.Slot == slots[i]);
}
slots[i].DrawOffset = Vector2.Lerp(Vector2.Zero, new Vector2(personalSlotArea.Width, 0.0f), hidePersonalSlotsState);
}
}
if (hoverOnInventory) HideTimer = 0.5f;
if (HideTimer > 0.0f) HideTimer -= deltaTime;
@@ -366,7 +438,34 @@ namespace Barotrauma
QuickUseItem(Items[i], true, false, true);
}
}
}
public override void Update(float deltaTime, Camera cam, bool isSubInventory = false)
{
if (!AccessibleWhenAlive && !character.IsDead)
{
syncItemsDelay = Math.Max(syncItemsDelay - deltaTime, 0.0f);
return;
}
base.Update(deltaTime, cam);
//force personal slots open if an item is running out of battery/fuel/oxygen/etc
if (hidePersonalSlots)
{
for (int i = 0; i < slots.Length; i++)
{
if (Items[i]?.OwnInventory != null && Items[i].OwnInventory.Capacity == 1 && PersonalSlots.HasFlag(SlotTypes[i]))
{
if (Items[i].OwnInventory.Items[0].Condition > 0.0f &&
Items[i].OwnInventory.Items[0].Condition / Items[i].OwnInventory.Items[0].MaxCondition < 0.15f)
{
hidePersonalSlots = false;
}
}
}
}
List<SlotReference> hideSubInventories = new List<SlotReference>();
foreach (var highlightedSubInventorySlot in highlightedSubInventorySlots)
{
@@ -703,7 +802,12 @@ namespace Barotrauma
}
base.Draw(spriteBatch);
if (hideButton != null && hideButton.Visible)
{
hideButton.DrawManually(spriteBatch, alsoChildren: true);
}
InventorySlot highlightedQuickUseSlot = null;
for (int i = 0; i < capacity; i++)
{
@@ -717,7 +821,7 @@ namespace Barotrauma
if (limbSlotIcons.ContainsKey(SlotTypes[i]))
{
var icon = limbSlotIcons[SlotTypes[i]];
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2(), Color.White * 0.3f, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, Color.White * 0.3f, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
}
continue;
}
@@ -727,12 +831,12 @@ namespace Barotrauma
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
{
var icon = limbSlotIcons[InvSlotType.LeftHand];
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.X, slots[i].Rect.Bottom), Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.X, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
}
if (IsInLimbSlot(Items[i], InvSlotType.RightHand))
{
var icon = limbSlotIcons[InvSlotType.RightHand];
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.Right, slots[i].Rect.Bottom), Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.Right, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
}
Color color = slots[i].EquipButtonState == GUIComponent.ComponentState.Pressed ? Color.Gray : Color.White * 0.8f;

View File

@@ -380,9 +380,13 @@ namespace Barotrauma.Items.Components
public virtual void UpdateHUD(Character character, float deltaTime, Camera cam) { }
public ItemComponent GetLinkUIToComponent()
public virtual void CreateEditingHUD(SerializableEntityEditor editor)
{
if (string.IsNullOrEmpty(LinkUIToComponent))
}
private bool LoadElemProjSpecific(XElement subElement)
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "guiframe":
if (subElement.Attribute("rect") != null)

View File

@@ -28,7 +28,7 @@ namespace Barotrauma.Items.Components
}
private string text;
[Serialize("", true), Editable(100)]
[Serialize("", true, translationTextTag: "Label."), Editable(100)]
public string Text
{
get { return text; }
@@ -40,9 +40,10 @@ namespace Barotrauma.Items.Components
{
textBlock = null;
}
text = value;
TextBlock.Text = value;
DisplayText = TextManager.Get(text, returnNull: true) ?? value;
TextBlock.Text = DisplayText;
SetScrollingText();
}
}
@@ -121,7 +122,7 @@ namespace Barotrauma.Items.Components
{
if (!scrollable) return;
float totalWidth = textBlock.Font.MeasureString(text).X;
float totalWidth = textBlock.Font.MeasureString(DisplayText).X;
float textAreaWidth = Math.Max(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z, 0);
if (totalWidth >= textAreaWidth)
{
@@ -129,13 +130,13 @@ namespace Barotrauma.Items.Components
//(so the text can scroll entirely out of view before we reset it back to start)
needsScrolling = true;
float spaceWidth = textBlock.Font.MeasureChar(' ').X;
scrollingText = new string(' ', (int)Math.Ceiling(textAreaWidth / spaceWidth)) + text;
scrollingText = new string(' ', (int)Math.Ceiling(textAreaWidth / spaceWidth)) + DisplayText;
}
else
{
//whole text can fit in the textblock, no need to scroll
needsScrolling = false;
scrollingText = text;
scrollingText = DisplayText;
scrollAmount = 0.0f;
scrollIndex = 0;
return;
@@ -151,7 +152,7 @@ namespace Barotrauma.Items.Components
charWidths[i] = charWidth;
}
scrollIndex = MathHelper.Clamp(scrollIndex, 0, text.Length);
scrollIndex = MathHelper.Clamp(scrollIndex, 0, DisplayText.Length);
}
public override void Update(float deltaTime, Camera cam)

View File

@@ -221,7 +221,7 @@ namespace Barotrauma.Items.Components
{
hullInfoFrame.RectTransform.ScreenSpaceOffset = hullFrame.Rect.Center;
hullInfoFrame.Visible = true;
hullNameText.Text = hull.RoomName;
hullNameText.Text = hull.DisplayName;
foreach (Hull linkedHull in hullData.LinkedHulls)
{

View File

@@ -577,13 +577,6 @@ namespace Barotrauma.Items.Components
}
}
protected override void RemoveComponentSpecific()
{
maintainPosIndicator?.Remove();
maintainPosOriginIndicator?.Remove();
steeringIndicator?.Remove();
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
msg.Write(autoPilot);

View File

@@ -3,6 +3,7 @@ using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
@@ -16,16 +17,22 @@ namespace Barotrauma.Items.Components
{
uiElements.Clear();
var visibleElements = customInterfaceElementList.Where(ciElement => !string.IsNullOrEmpty(ciElement.Label));
GUILayoutGroup paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center),
childAnchor: customInterfaceElementList.Count > 1 ? Anchor.TopCenter : Anchor.Center)
{ RelativeSpacing = 0.05f };
{
RelativeSpacing = 0.05f,
Stretch = visibleElements.Count() > 2
};
float elementSize = Math.Min(1.0f / customInterfaceElementList.Count, 0.5f);
foreach (CustomInterfaceElement ciElement in customInterfaceElementList)
float elementSize = Math.Min(1.0f / visibleElements.Count(), 0.5f);
foreach (CustomInterfaceElement ciElement in visibleElements)
{
if (ciElement.ContinuousSignal)
{
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), paddedFrame.RectTransform), ciElement.Label)
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), paddedFrame.RectTransform),
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label)
{
UserData = ciElement
};
@@ -45,7 +52,8 @@ namespace Barotrauma.Items.Components
}
else
{
var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), paddedFrame.RectTransform), ciElement.Label, style: "GUIButtonLarge")
var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), paddedFrame.RectTransform),
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label, style: "GUIButtonLarge")
{
UserData = ciElement
};
@@ -66,6 +74,24 @@ namespace Barotrauma.Items.Components
}
}
public override void CreateEditingHUD(SerializableEntityEditor editor)
{
base.CreateEditingHUD(editor);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(customInterfaceElementList[0]);
PropertyDescriptor labelProperty = properties.Find("Label", false);
PropertyDescriptor signalProperty = properties.Find("Signal", false);
for (int i = 0; i< customInterfaceElementList.Count; i++)
{
editor.CreateStringField(customInterfaceElementList[i],
new SerializableProperty(labelProperty, customInterfaceElementList[i]),
customInterfaceElementList[i].Label, "Label #" + (i + 1), "");
editor.CreateStringField(customInterfaceElementList[i],
new SerializableProperty(signalProperty, customInterfaceElementList[i]),
customInterfaceElementList[i].Signal, "Signal #" + (i + 1), "");
}
}
partial void UpdateLabelsProjSpecific()
{
for (int i = 0; i < labels.Length && i < uiElements.Count; i++)

View File

@@ -154,8 +154,6 @@ namespace Barotrauma
public SlotReference(Inventory parentInventory, InventorySlot slot, int slotIndex, bool isSubSlot, Inventory subInventory = null)
{
ParentInventory = parentInventory;
Slot = slot;
SlotIndex = slotIndex;
@@ -714,12 +712,15 @@ namespace Barotrauma
float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f);
Vector2 itemPos = PlayerInput.MousePosition;
if (GUI.MouseOn == null && selectedSlot == null)
bool mouseOnHealthInterface = CharacterHealth.OpenHealthWindow != null && CharacterHealth.OpenHealthWindow.MouseOnElement;
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null)
{
var shadowSprite = GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0];
string toolTip = Character.Controlled.FocusedItem != null ?
TextManager.Get("PutItemIn").Replace("[itemname]", Character.Controlled.FocusedItem.Name) :
TextManager.Get("DropItem");
string toolTip = mouseOnHealthInterface ? TextManager.Get("QuickUseAction.UseTreatment") :
Character.Controlled.FocusedItem != null ?
TextManager.Get("PutItemIn").Replace("[itemname]", Character.Controlled.FocusedItem.Name) :
TextManager.Get("DropItem");
int textWidth = (int)Math.Max(GUI.Font.MeasureString(draggingItem.Name).X, GUI.SmallFont.MeasureString(toolTip).X);
int textSpacing = (int)(15 * GUI.Scale);
Point shadowBorders = (new Point(40, 10)).Multiply(GUI.Scale);
@@ -727,7 +728,7 @@ namespace Barotrauma
new Rectangle(itemPos.ToPoint() - new Point(iconSize / 2) - shadowBorders, new Point(iconSize + textWidth + textSpacing, iconSize) + shadowBorders.Multiply(2)), Color.Black * 0.8f);
GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y - iconSize / 2), draggingItem.Name, Color.White);
GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y), toolTip,
color: Character.Controlled.FocusedItem == null ? Color.Red : Color.LightGreen,
color: Character.Controlled.FocusedItem == null && !mouseOnHealthInterface ? Color.Red : Color.LightGreen,
font: GUI.SmallFont);
}
sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black, scale: scale);
@@ -853,7 +854,7 @@ namespace Barotrauma
if (itemContainer.ContainedStateIndicator?.Texture == null)
{
containedIndicatorArea.Inflate(0, -2);
GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.DarkGray * 0.8f, true);
GUI.DrawRectangle(spriteBatch, containedIndicatorArea, Color.DarkGray * 0.9f, true);
GUI.DrawRectangle(spriteBatch,
new Rectangle(containedIndicatorArea.X, containedIndicatorArea.Y, (int)(containedIndicatorArea.Width * containedState), containedIndicatorArea.Height),
Color.Lerp(Color.Red, Color.Green, containedState) * 0.8f, true);
@@ -867,11 +868,11 @@ namespace Barotrauma
if (containedState > 0.0f && containedState < 0.25f)
{
indicatorScale += ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) * 0.1f;
indicatorScale += ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) * 0.25f;
}
indicatorSprite.Draw(spriteBatch, containedIndicatorArea.Center.ToVector2(),
Color.DarkGray * 0.6f,
Color.DarkGray * 0.9f,
origin: indicatorSprite.size / 2,
rotate: 0.0f,
scale: indicatorScale);

View File

@@ -41,8 +41,6 @@ namespace Barotrauma
{
get { return activeSprite; }
}
public float SpriteRotation;
private GUITextBlock itemInUseWarning;
private GUITextBlock ItemInUseWarning
@@ -579,8 +577,13 @@ namespace Barotrauma
}
var componentEditor = new SerializableEntityEditor(listBox.Content.RectTransform, ic, inGame, showName: !inGame);
if (inGame) continue;
if (inGame)
{
ic.CreateEditingHUD(componentEditor);
componentEditor.Recalculate();
continue;
}
foreach (var kvp in ic.requiredItems)
{
@@ -614,6 +617,10 @@ namespace Barotrauma
}
}
ic.CreateEditingHUD(componentEditor);
componentEditor.Recalculate();
}
PositionEditingHUD();
SetHUDLayout();
@@ -830,14 +837,28 @@ namespace Barotrauma
case NetEntityEvent.Type.ComponentState:
{
int componentIndex = msg.ReadRangedInteger(0, components.Count - 1);
(components[componentIndex] as IServerSerializable).ClientRead(type, msg, sendingTime);
if (components[componentIndex] is IServerSerializable serverSerializable)
{
serverSerializable.ClientRead(type, msg, sendingTime);
}
else
{
throw new Exception("Failed to read component state - " + components[componentIndex].GetType() + " is not IServerSerializable.");
}
}
break;
case NetEntityEvent.Type.InventoryState:
{
{
int containerIndex = msg.ReadRangedInteger(0, components.Count - 1);
(components[containerIndex] as ItemContainer).Inventory.ClientRead(type, msg, sendingTime);
if (components[containerIndex] is ItemContainer container)
{
container.Inventory.ClientRead(type, msg, sendingTime);
}
else
{
throw new Exception("Failed to read inventory state - " + components[containerIndex].GetType() + " is not an ItemContainer.");
}
}
break;
case NetEntityEvent.Type.Status:

View File

@@ -353,6 +353,33 @@ namespace Barotrauma
Color.Green, width: 2);
}
}
foreach (MapEntity e in linkedTo)
{
if (e is Hull)
{
Hull linkedHull = (Hull)e;
Rectangle connectedHullRect = e.Submarine == null ?
linkedHull.rect :
new Rectangle(
(int)(Submarine.DrawPosition.X + linkedHull.WorldPosition.X),
(int)(Submarine.DrawPosition.Y + linkedHull.WorldPosition.Y),
linkedHull.WorldRect.Width, linkedHull.WorldRect.Height);
//center of the hull
Rectangle currentHullRect = Submarine == null ?
WorldRect :
new Rectangle(
(int)(Submarine.DrawPosition.X + WorldPosition.X),
(int)(Submarine.DrawPosition.Y + WorldPosition.Y),
WorldRect.Width, WorldRect.Height);
GUI.DrawLine(spriteBatch,
new Vector2(currentHullRect.X, -currentHullRect.Y),
new Vector2(connectedHullRect.X, -connectedHullRect.Y),
Color.Green, width: 2);
}
}
}
public static void UpdateVertices(GraphicsDevice graphicsDevice, Camera cam, WaterRenderer renderer)

View File

@@ -61,7 +61,7 @@ namespace Barotrauma.Networking
{
orderOption = order.Options[optionIndex];
}
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.RoomName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
if (order.TargetAllCharacters)
{

View File

@@ -598,6 +598,8 @@ namespace Barotrauma.Steam
if (!allowFileOverwrite)
{
// TODO: If you create a new mod via the workshop interface and enable it, it will show the error msg, but still allows you to enable the content.
if (File.Exists(newContentPackagePath))
{
errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable")

View File

@@ -20,8 +20,6 @@ namespace Barotrauma
private GUILayoutGroup subPreviewContainer;
private GUILayoutGroup subPreviewContainer;
private GUIButton loadGameButton;
public Action<Submarine, string, string> StartNewGame;

View File

@@ -9,15 +9,11 @@ namespace Barotrauma
{
class CampaignUI
{
public enum Tab { Map, Crew, Store }
public enum Tab { Map, Crew, Store, Repair }
private Tab selectedTab;
private GUIFrame[] tabs;
private GUIFrame topPanel;
private GUIButton startButton;
private GUIFrame topPanel;
private GUIListBox characterList;
private GUIListBox myItemList;
@@ -28,6 +24,8 @@ namespace Barotrauma
private GUIComponent selectedLocationInfo;
private GUIListBox selectedMissionInfo;
private GUIButton repairHullsButton, repairItemsButton;
private GUIFrame characterPreviewFrame;
private List<GUIButton> tabButtons = new List<GUIButton>();
@@ -41,10 +39,7 @@ namespace Barotrauma
public GUIComponent MapContainer { get; private set; }
public GUIButton StartButton
{
get { return startButton; }
}
public GUIButton StartButton { get; private set; }
public CampaignMode Campaign { get; }
@@ -114,7 +109,7 @@ namespace Barotrauma
tabs[(int)Tab.Crew] = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.7f), container.RectTransform, Anchor.TopLeft)
{
RelativeOffset = new Vector2(0.0f, topPanel.RectTransform.RelativeSize.Y)
}, color: Color.Black * 0.7f);
}, color: Color.Black * 0.9f);
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), tabs[(int)Tab.Crew].RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f)
{
CanBeFocused = false
@@ -159,7 +154,7 @@ namespace Barotrauma
tabs[(int)Tab.Store] = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.7f), container.RectTransform, Anchor.TopLeft)
{
RelativeOffset = new Vector2(0.1f, topPanel.RectTransform.RelativeSize.Y)
}, color: Color.Black * 0.7f);
}, color: Color.Black * 0.9f);
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), tabs[(int)Tab.Store].RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f)
{
CanBeFocused = false
@@ -220,6 +215,97 @@ namespace Barotrauma
}
SelectItemCategory(MapEntityCategory.Equipment);
// repair tab -------------------------------------------------------------------------
tabs[(int)Tab.Repair] = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.5f), container.RectTransform, Anchor.TopLeft)
{
RelativeOffset = new Vector2(0.02f, topPanel.RectTransform.RelativeSize.Y)
}, color: Color.Black * 0.9f);
new GUIFrame(new RectTransform(new Vector2(1.25f, 1.25f), tabs[(int)Tab.Repair].RectTransform, Anchor.Center), style: "OuterGlow", color: Color.Black * 0.7f)
{
CanBeFocused = false
};
var repairContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), tabs[(int)Tab.Repair].RectTransform, Anchor.Center))
{
RelativeSpacing = 0.05f,
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), crewContent.RectTransform), "", font: GUI.LargeFont)
{
TextGetter = GetMoney
};
var repairHullsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight)
{
RelativeSpacing = 0.05f,
Stretch = true
};
new GUIImage(new RectTransform(new Vector2(0.3f, 1.0f), repairHullsHolder.RectTransform, Anchor.CenterLeft), "RepairHullButton")
{
IgnoreLayoutGroups = true,
CanBeFocused = false
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("RepairAllWalls"), textAlignment: Alignment.Right, font: GUI.LargeFont)
{
ForceUpperCase = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), "500", textAlignment: Alignment.Right, font: GUI.LargeFont);
repairHullsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("Repair"), style: "GUIButtonLarge")
{
OnClicked = (btn, userdata) =>
{
if (campaign.Money >= CampaignMode.HullRepairCost)
{
campaign.Money -= CampaignMode.HullRepairCost;
campaign.PurchasedHullRepairs = true;
GameMain.Client?.SendCampaignState();
btn.GetChild<GUITickBox>().Selected = true;
}
btn.Enabled = false;
return true;
}
};
new GUITickBox(new RectTransform(new Vector2(0.65f), repairHullsButton.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(10, 0) }, "")
{
CanBeFocused = false
};
var repairItemsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight)
{
RelativeSpacing = 0.05f,
Stretch = true
};
new GUIImage(new RectTransform(new Vector2(0.3f, 1.0f), repairItemsHolder.RectTransform, Anchor.CenterLeft), "RepairItemsButton")
{
IgnoreLayoutGroups = true,
CanBeFocused = false
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("RepairAllItems"), textAlignment: Alignment.Right, font: GUI.LargeFont)
{
ForceUpperCase = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), "500", textAlignment: Alignment.Right, font: GUI.LargeFont);
repairItemsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("Repair"), style: "GUIButtonLarge")
{
OnClicked = (btn, userdata) =>
{
if (campaign.Money >= CampaignMode.ItemRepairCost)
{
campaign.Money -= CampaignMode.ItemRepairCost;
campaign.PurchasedItemRepairs = true;
GameMain.Client?.SendCampaignState();
btn.GetChild<GUITickBox>().Selected = true;
}
btn.Enabled = false;
return true;
}
};
new GUITickBox(new RectTransform(new Vector2(0.65f), repairItemsButton.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(10, 0) }, "")
{
CanBeFocused = false
};
// mission info -------------------------------------------------------------------------
missionPanel = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.5f), container.RectTransform, Anchor.TopRight)
@@ -332,8 +418,7 @@ namespace Barotrauma
bool purchaseableItemsFound = false;
foreach (MapEntityPrefab mapEntityPrefab in MapEntityPrefab.List)
{
var itemPrefab = mapEntityPrefab as ItemPrefab;
if (itemPrefab == null) { continue; }
if (!(mapEntityPrefab is ItemPrefab itemPrefab)) { continue; }
PriceInfo priceInfo = itemPrefab.GetPrice(Campaign.Map.CurrentLocation);
if (priceInfo != null) { purchaseableItemsFound = true; break; }
@@ -351,8 +436,7 @@ namespace Barotrauma
{
//refresh store view
SelectItemCategory(MapEntityCategory.Equipment);
}
}
}
private void DrawMap(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
@@ -454,7 +538,7 @@ namespace Barotrauma
RefreshMissionTab(selectedMission);
startButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.7f), missionContent.RectTransform, Anchor.CenterRight),
StartButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.7f), missionContent.RectTransform, Anchor.CenterRight),
TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
{
IgnoreLayoutGroups = true,
@@ -463,7 +547,7 @@ namespace Barotrauma
};
if (GameMain.Client != null)
{
startButton.Visible = !GameMain.Client.GameStarted &&
StartButton.Visible = !GameMain.Client.GameStarted &&
(GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) ||
GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
}
@@ -510,10 +594,10 @@ namespace Barotrauma
CanBeFocused = false
};
if (startButton != null)
if (StartButton != null)
{
startButton.Enabled = true;
startButton.Visible = GameMain.Client == null ||
StartButton.Enabled = true;
StartButton.Visible = GameMain.Client == null ||
GameMain.Client.HasPermission(Networking.ClientPermissions.ManageRound) ||
GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign);
}
@@ -599,8 +683,7 @@ namespace Barotrauma
private bool BuyItem(GUIComponent component, object obj)
{
PurchasedItem pi = obj as PurchasedItem;
if (pi == null || pi.ItemPrefab == null) return false;
if (!(obj is PurchasedItem pi) || pi.ItemPrefab == null) return false;
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
{
@@ -618,8 +701,7 @@ namespace Barotrauma
private bool SellItem(GUIComponent component, object obj)
{
PurchasedItem pi = obj as PurchasedItem;
if (pi == null || pi.ItemPrefab == null) return false;
if (!(obj is PurchasedItem pi) || pi.ItemPrefab == null) return false;
if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign))
{
@@ -661,6 +743,20 @@ namespace Barotrauma
{
button.Selected = (Tab)button.UserData == tab;
}
switch (selectedTab)
{
case Tab.Repair:
repairHullsButton.Enabled =
!Campaign.PurchasedHullRepairs && Campaign.Money >= CampaignMode.HullRepairCost &&
(GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
repairHullsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedHullRepairs;
repairItemsButton.Enabled =
!Campaign.PurchasedItemRepairs && Campaign.Money >= CampaignMode.ItemRepairCost &&
(GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
repairItemsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedItemRepairs;
break;
}
}
private bool SelectItemCategory(MapEntityCategory category)
@@ -670,8 +766,7 @@ namespace Barotrauma
int width = storeItemList.Rect.Width;
foreach (MapEntityPrefab mapEntityPrefab in MapEntityPrefab.List)
{
var itemPrefab = mapEntityPrefab as ItemPrefab;
if (itemPrefab == null || !itemPrefab.Category.HasFlag(category)) continue;
if (!(mapEntityPrefab is ItemPrefab itemPrefab) || !itemPrefab.Category.HasFlag(category)) continue;
PriceInfo priceInfo = itemPrefab.GetPrice(Campaign.Map.CurrentLocation);
if (priceInfo == null) continue;
@@ -709,9 +804,8 @@ namespace Barotrauma
}
if (prevInfoFrame != null) { tabs[(int)selectedTab].RemoveChild(prevInfoFrame); }
CharacterInfo characterInfo = selection as CharacterInfo;
if (characterInfo == null) { return false; }
if (!(selection is CharacterInfo characterInfo)) { return false; }
if (Character.Controlled != null && characterInfo == Character.Controlled.Info) { return false; }
if (characterPreviewFrame == null || characterPreviewFrame.UserData != characterInfo)
@@ -763,11 +857,9 @@ namespace Barotrauma
private bool HireCharacter(GUIButton button, object selection)
{
CharacterInfo characterInfo = selection as CharacterInfo;
if (characterInfo == null) { return false; }
if (!(selection is CharacterInfo characterInfo)) { return false; }
SinglePlayerCampaign spCampaign = Campaign as SinglePlayerCampaign;
if (spCampaign == null)
if (!(Campaign is SinglePlayerCampaign spCampaign))
{
DebugConsole.ThrowError("Characters can only be hired in the single player campaign.\n" + Environment.StackTrace);
return false;
@@ -786,11 +878,9 @@ namespace Barotrauma
private bool FireCharacter(GUIButton button, object selection)
{
CharacterInfo characterInfo = selection as CharacterInfo;
if (characterInfo == null) return false;
if (!(selection is CharacterInfo characterInfo)) return false;
SinglePlayerCampaign spCampaign = Campaign as SinglePlayerCampaign;
if (spCampaign == null)
if (!(Campaign is SinglePlayerCampaign spCampaign))
{
DebugConsole.ThrowError("Characters can only be fired in the single player campaign.\n" + Environment.StackTrace);
return false;

View File

@@ -42,16 +42,16 @@ namespace Barotrauma
private bool showParamsEditor;
private bool showSpritesheet;
private bool isFreezed;
private bool autoFreeze = true;
private bool limbPairEditing = true;
private bool uniformScaling = true;
private bool lockSpriteOrigin = true;
private bool autoFreeze;
private bool limbPairEditing;
private bool uniformScaling;
private bool lockSpriteOrigin;
private bool lockSpritePosition;
private bool lockSpriteSize;
private bool recalculateCollider;
private bool copyJointSettings;
private bool displayColliders;
private bool displayWearables = true;
private bool displayWearables;
private bool displayBackgroundColor;
private bool ragdollResetRequiresForceLoading;
private bool animationResetRequiresForceLoading;
@@ -89,10 +89,17 @@ namespace Barotrauma
public override void Select()
{
base.Select();
SoundPlayer.OverrideMusicType = "none";
SoundPlayer.OverrideMusicDuration = null;
GameMain.SoundManager.SetCategoryGainMultiplier("default", 0.0f);
GameMain.SoundManager.SetCategoryGainMultiplier("waterambience", 0.0f);
GUI.ForceMouseOn(null);
CalculateSpritesheetPosition();
if (Submarine.MainSub == null)
{
ResetVariables();
Submarine.MainSub = new Submarine("Content/AnimEditor.sub");
Submarine.MainSub.Load(unloadPrevious: false, showWarningMessages: false);
originalWall = new WallGroup(new List<Structure>(Structure.WallList));
@@ -101,6 +108,10 @@ namespace Barotrauma
isEndlessRunner = true;
GameMain.LightManager.LightingEnabled = false;
}
else if (instance == null)
{
ResetVariables();
}
Submarine.MainSub.GodMode = true;
if (Character.Controlled == null)
{
@@ -118,31 +129,65 @@ namespace Barotrauma
instance = this;
}
private void ResetVariables()
{
editAnimations = false;
editLimbs = false;
editJoints = false;
editIK = false;
showRagdoll = false;
showParamsEditor = false;
showSpritesheet = false;
isFreezed = false;
autoFreeze = true;
limbPairEditing = true;
uniformScaling = true;
lockSpriteOrigin = false;
lockSpritePosition = false;
lockSpriteSize = false;
recalculateCollider = false;
copyJointSettings = false;
displayColliders = false;
displayWearables = true;
displayBackgroundColor = false;
ragdollResetRequiresForceLoading = false;
animationResetRequiresForceLoading = false;
isExtrudingJoint = false;
isDrawingJoint = false;
Wizard.instance = null;
}
private void Reset()
{
AnimParams.ForEach(a => a.Reset(true));
RagdollParams.Reset(true);
RagdollParams.ClearHistory();
CurrentAnimation.ClearHistory();
if (!character.Removed)
ResetVariables();
if (character != null)
{
character.Remove();
AnimParams.ForEach(a => a.Reset(true));
RagdollParams.Reset(true);
RagdollParams.ClearHistory();
CurrentAnimation.ClearHistory();
if (!character.Removed)
{
character.Remove();
}
character = null;
}
character = null;
}
public override void Deselect()
{
base.Deselect();
SoundPlayer.OverrideMusicType = null;
GameMain.SoundManager.SetCategoryGainMultiplier("default", GameMain.Config.SoundVolume);
GameMain.SoundManager.SetCategoryGainMultiplier("waterambience", GameMain.Config.SoundVolume);
GUI.ForceMouseOn(null);
if (isEndlessRunner)
{
Submarine.MainSub.Remove();
isEndlessRunner = false;
if (character != null)
{
Reset();
}
Reset();
GameMain.World.ProcessChanges();
}
else
@@ -175,7 +220,7 @@ namespace Barotrauma
{
//base.AddToGUIUpdateList();
rightPanel.AddToGUIUpdateList();
Wizard.Instance.AddToGUIUpdateList();
Wizard.instance?.AddToGUIUpdateList();
if (displayBackgroundColor)
{
backgroundColorPanel.AddToGUIUpdateList();
@@ -207,7 +252,7 @@ namespace Barotrauma
base.Update(deltaTime);
spriteSheetRect = CalculateSpritesheetRectangle();
// Handle shortcut keys
if (GUI.KeyboardDispatcher.Subscriber == null)
if (GUI.KeyboardDispatcher.Subscriber == null && Wizard.instance == null)
{
if (PlayerInput.KeyDown(Keys.LeftControl))
{
@@ -396,7 +441,7 @@ namespace Barotrauma
}
}
}
if (!isFreezed)
if (!isFreezed && Wizard.instance == null)
{
if (character.AnimController.Invalid)
{
@@ -1131,7 +1176,22 @@ namespace Barotrauma
character = Character.Create(configFile, spawnPosition, ToolBox.RandomSeed(8), hasAi: false, ragdoll: ragdoll);
selectedJob = null;
}
character.dontFollowCursor = dontFollowCursor;
if (character != null)
{
character.dontFollowCursor = dontFollowCursor;
}
if (character == null)
{
if (currentCharacterConfig == configFile)
{
return null;
}
else
{
// Respawn the current character;
SpawnCharacter(currentCharacterConfig);
}
}
OnPostSpawn();
return character;
}
@@ -1247,27 +1307,33 @@ namespace Barotrauma
string speciesName = name;
// Config file
string configFilePath = Path.Combine(mainFolder, $"{speciesName}.xml").Replace(@"\", @"/");
if (ContentPackage.GetFilesOfType(GameMain.SelectedPackages, ContentType.Character).None(path => path.Contains(speciesName)))
if (ContentPackage.GetFilesOfType(GameMain.SelectedPackages, ContentType.Character).Any(path => path.Contains(speciesName)))
{
// Create the config file
XElement mainElement = new XElement("Character",
new XAttribute("name", speciesName),
new XAttribute("humanoid", isHumanoid),
new XElement("ragdolls", new XAttribute("folder", Path.Combine(mainFolder, $"Ragdolls/").Replace(@"\", @"/"))),
new XElement("animations", new XAttribute("folder", Path.Combine(mainFolder, $"Animations/").Replace(@"\", @"/"))),
new XElement("health"),
new XElement("ai"));
XDocument doc = new XDocument(mainElement);
if (!Directory.Exists(mainFolder))
{
Directory.CreateDirectory(mainFolder);
}
doc.Save(configFilePath);
// Add to the selected content package
contentPackage.AddFile(configFilePath, ContentType.Character);
contentPackage.Save(contentPackage.Path);
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
GUI.AddMessage(GetCharacterEditorTranslation("ExistingCharacterFound"), Color.Red, font: GUI.LargeFont);
// TODO: add a prompt: "Do you want to replace it?" + functionality
return false;
}
// Create the config file
XElement mainElement = new XElement("Character",
new XAttribute("name", speciesName),
new XAttribute("humanoid", isHumanoid),
new XElement("ragdolls", new XAttribute("folder", Path.Combine(mainFolder, $"Ragdolls/").Replace(@"\", @"/"))),
new XElement("animations", new XAttribute("folder", Path.Combine(mainFolder, $"Animations/").Replace(@"\", @"/"))),
new XElement("health"),
new XElement("ai"));
XDocument doc = new XDocument(mainElement);
if (!Directory.Exists(mainFolder))
{
Directory.CreateDirectory(mainFolder);
}
doc.Save(configFilePath);
// Add to the selected content package
contentPackage.AddFile(configFilePath, ContentType.Character);
contentPackage.Save(contentPackage.Path);
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
// Ragdoll
string ragdollFolder = RagdollParams.GetFolder(speciesName);
string ragdollPath = RagdollParams.GetDefaultFile(speciesName);
@@ -1278,12 +1344,20 @@ namespace Barotrauma
string animFolder = AnimationParams.GetFolder(speciesName);
foreach (AnimationType animType in Enum.GetValues(typeof(AnimationType)))
{
if (animType != AnimationType.NotDefined)
switch (animType)
{
Type type = AnimationParams.GetParamTypeFromAnimType(animType, isHumanoid);
string fullPath = AnimationParams.GetDefaultFile(speciesName, animType);
AnimationParams.Create(fullPath, speciesName, animType, type);
case AnimationType.Walk:
case AnimationType.Run:
if (!ragdollParams.CanEnterSubmarine) { continue; }
break;
case AnimationType.SwimSlow:
case AnimationType.SwimFast:
break;
default: continue;
}
Type type = AnimationParams.GetParamTypeFromAnimType(animType, isHumanoid);
string fullPath = AnimationParams.GetDefaultFile(speciesName, animType);
AnimationParams.Create(fullPath, speciesName, animType, type);
}
if (!AllFiles.Contains(configFilePath))
{
@@ -3764,7 +3838,7 @@ namespace Barotrauma
void RecalculateCollider(Limb l)
{
// We want the collider to be slightly smaller than the source rect, because the source rect is usually a bit bigger than the graphic.
float multiplier = 0.75f;
float multiplier = 0.85f;
l.body.SetSize(new Vector2(ConvertUnits.ToSimUnits(width), ConvertUnits.ToSimUnits(height)) * RagdollParams.LimbScale * RagdollParams.TextureScale * multiplier);
TryUpdateLimbParam(l, "radius", ConvertUnits.ToDisplayUnits(l.body.radius / RagdollParams.LimbScale / RagdollParams.TextureScale));
TryUpdateLimbParam(l, "width", ConvertUnits.ToDisplayUnits(l.body.width / RagdollParams.LimbScale / RagdollParams.TextureScale));
@@ -4283,7 +4357,7 @@ namespace Barotrauma
private List<XElement> jointXElements = new List<XElement>();
private List<GUIComponent> jointGUIElements = new List<GUIComponent>();
private static Wizard instance;
public static Wizard instance;
public static Wizard Instance
{
get
@@ -4314,7 +4388,6 @@ namespace Barotrauma
break;
case Tab.None:
default:
//activeView = null;
instance = null;
break;
}
@@ -4343,7 +4416,7 @@ namespace Barotrauma
GUITextBox xmlPathElement = null;
void UpdatePaths()
{
string pathBase = $"Content/Characters/{Name}/{Name}";
string pathBase = $"Mods/Characters/{Name}/{Name}";
XMLPath = $"{pathBase}.xml";
TexturePath = $"{pathBase}.png";
texturePathElement.Text = TexturePath;
@@ -4422,7 +4495,7 @@ namespace Barotrauma
// Cancel
box.Buttons[0].OnClicked += (b, d) =>
{
Instance.SelectTab(Tab.None);
Wizard.Instance.SelectTab(Tab.None);
return true;
};
// Next
@@ -4434,7 +4507,7 @@ namespace Barotrauma
texturePathElement.Flash(Color.Red);
return false;
}
Instance.SelectTab(Tab.Ragdoll);
Wizard.Instance.SelectTab(Tab.Ragdoll);
return true;
};
return box;
@@ -4575,7 +4648,7 @@ namespace Barotrauma
// Previous
box.Buttons[0].OnClicked += (b, d) =>
{
Instance.SelectTab(Tab.Character);
Wizard.Instance.SelectTab(Tab.Character);
return true;
};
// Parse and create
@@ -4666,7 +4739,7 @@ namespace Barotrauma
{
GUI.AddMessage(GetCharacterEditorTranslation("CharacterCreated").Replace("[name]", Name), Color.Green, font: GUI.Font);
}
Instance.SelectTab(Tab.None);
Wizard.Instance.SelectTab(Tab.None);
return true;
};
return box;
@@ -4846,23 +4919,27 @@ namespace Barotrauma
int width = rectInputs[2].IntValue;
int height = rectInputs[3].IntValue;
var colliderAttributes = new List<XAttribute>();
if (width == height)
{
colliderAttributes.Add(new XAttribute("radius", width / 2));
}
else
{
if (height > width)
{
colliderAttributes.Add(new XAttribute("radius", width / 2));
colliderAttributes.Add(new XAttribute("height", height - width));
}
else
{
colliderAttributes.Add(new XAttribute("radius", height / 2));
colliderAttributes.Add(new XAttribute("width", width - height));
}
}
// Capsules/Circles
//if (width == height)
//{
// colliderAttributes.Add(new XAttribute("radius", (int)(width / 2 * 0.85f)));
//}
//else
//{
// if (height > width)
// {
// colliderAttributes.Add(new XAttribute("radius", (int)(width / 2 * 0.85f)));
// colliderAttributes.Add(new XAttribute("height",(int) (height - width * 0.85f)));
// }
// else
// {
// colliderAttributes.Add(new XAttribute("radius", (int)(height / 2 * 0.85f)));
// colliderAttributes.Add(new XAttribute("width", (int)(width - height * 0.85f)));
// }
//}
// Rectangles
colliderAttributes.Add(new XAttribute("height", (int)(height * 0.85f)));
colliderAttributes.Add(new XAttribute("width", (int)(width * 0.85f)));
idToCodeName.TryGetValue(id, out string notes);
LimbXElements.Add(id.ToString(), new XElement("limb",
new XAttribute("id", id),

View File

@@ -635,21 +635,21 @@ namespace Barotrauma
" -ownerkey " + ownerKey.ToString();
string filename = "DedicatedServer.exe";
#if LINUX || OSX
#if LINUX
filename = "./DedicatedServer";
#elif OSX
filename = "mono";
arguments = "./DedicatedServer.exe " + arguments;
#endif
var processInfo = new ProcessStartInfo
{
FileName = filename,
Arguments = arguments,
Arguments = arguments
#if !DEBUG
WindowStyle = ProcessWindowStyle.Hidden
#endif
};
GameMain.ServerChildProcess = Process.Start(processInfo);
Thread.Sleep(1000); //wait until the server is ready before connecting
GameMain.Client = new GameClient(name, "127.0.0.1:" + port.ToString(),ownerKey);

View File

@@ -312,6 +312,25 @@ namespace Barotrauma
return true;
};
playYourself = new GUITickBox(new RectTransform(new Vector2(0.06f, 0.06f), myCharacterFrame.RectTransform) { RelativeOffset = new Vector2(0.05f,0.05f) },
TextManager.Get("PlayYourself"))
{
Selected = true,
OnSelected = TogglePlayYourself,
UserData = "playyourself"
};
var toggleMyPlayerFrame = new GUIButton(new RectTransform(new Point(25, 70), myCharacterFrame.RectTransform, Anchor.TopLeft, Pivot.TopRight), "", style: "GUIButtonHorizontalArrow");
toggleMyPlayerFrame.OnClicked += (GUIButton btn, object userdata) =>
{
MyCharacterFrameOpen = !MyCharacterFrameOpen;
foreach (GUIComponent child in btn.Children)
{
child.SpriteEffects = MyCharacterFrameOpen ? SpriteEffects.FlipHorizontally : SpriteEffects.None;
}
return true;
};
playYourself = new GUITickBox(new RectTransform(new Vector2(0.06f, 0.06f), myCharacterFrame.RectTransform) { RelativeOffset = new Vector2(0.05f,0.05f) },
TextManager.Get("PlayYourself"))
{
@@ -745,11 +764,15 @@ namespace Barotrauma
spectateButton.Visible = GameMain.Client.GameStarted;
ReadyToStartBox.Visible = !GameMain.Client.GameStarted;
ReadyToStartBox.Selected = false;
if (campaignUI?.StartButton != null)
if (campaignUI != null)
{
campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
(GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign));
//SelectTab(Tab.Map);
if (campaignUI.StartButton != null)
{
campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
(GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign));
}
}
GameMain.Client.SetReadyToStart(ReadyToStartBox);
}

View File

@@ -1025,7 +1025,7 @@ namespace Barotrauma
var previewImageButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), rightColumn.RectTransform), isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageGenerate"))
new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), previewImageButtonHolder.RectTransform), TextManager.Get("SubPreviewImageCreate"))
{
OnClicked = (btn, userdata) =>
{

View File

@@ -277,13 +277,17 @@ namespace Barotrauma
{
component.RectTransform.Parent = layoutGroup.RectTransform;
component.RectTransform.RepositionChildInHierarchy(childIndex);
Recalculate();
}
public void Recalculate()
{
int contentHeight = ContentHeight;
RectTransform.NonScaledSize = new Point(RectTransform.NonScaledSize.X, contentHeight);
layoutGroup.RectTransform.NonScaledSize = new Point(layoutGroup.RectTransform.NonScaledSize.X, contentHeight);
}
private GUIComponent CreateNewField(SerializableProperty property, ISerializableEntity entity)
public GUIComponent CreateNewField(SerializableProperty property, ISerializableEntity entity)
{
object value = property.GetValue(entity);
if (property.PropertyType == typeof(string) && value == null)
@@ -351,7 +355,7 @@ namespace Barotrauma
return propertyField;
}
private GUIComponent CreateBoolField(ISerializableEntity entity, SerializableProperty property, bool value, string displayName, string toolTip)
public GUIComponent CreateBoolField(ISerializableEntity entity, SerializableProperty property, bool value, string displayName, string toolTip)
{
GUITickBox propertyTickBox = new GUITickBox(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), displayName)
{
@@ -367,11 +371,11 @@ namespace Barotrauma
return true;
}
};
Fields.Add(property.Name, new GUIComponent[] { propertyTickBox });
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { propertyTickBox }); }
return propertyTickBox;
}
private GUIComponent CreateIntField(ISerializableEntity entity, SerializableProperty property, int value, string displayName, string toolTip)
public GUIComponent CreateIntField(ISerializableEntity entity, SerializableProperty property, int value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -395,11 +399,11 @@ namespace Barotrauma
TrySendNetworkUpdate(entity, property);
}
};
Fields.Add(property.Name, new GUIComponent[] { numberInput });
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { numberInput }); }
return frame;
}
private GUIComponent CreateFloatField(ISerializableEntity entity, SerializableProperty property, float value, string displayName, string toolTip)
public GUIComponent CreateFloatField(ISerializableEntity entity, SerializableProperty property, float value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -425,11 +429,11 @@ namespace Barotrauma
TrySendNetworkUpdate(entity, property);
}
};
Fields.Add(property.Name, new GUIComponent[] { numberInput });
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { numberInput }); }
return frame;
}
private GUIComponent CreateEnumField(ISerializableEntity entity, SerializableProperty property, object value, string displayName, string toolTip)
public GUIComponent CreateEnumField(ISerializableEntity entity, SerializableProperty property, object value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -454,11 +458,11 @@ namespace Barotrauma
return true;
};
enumDropDown.SelectItem(value);
Fields.Add(property.Name, new GUIComponent[] { enumDropDown });
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { enumDropDown }); }
return frame;
}
private GUIComponent CreateEnumFlagField(ISerializableEntity entity, SerializableProperty property, object value, string displayName, string toolTip)
public GUIComponent CreateEnumFlagField(ISerializableEntity entity, SerializableProperty property, object value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -487,18 +491,21 @@ namespace Barotrauma
return true;
};
Fields.Add(property.Name, new GUIComponent[] { enumDropDown });
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { enumDropDown }); }
return frame;
}
private GUIComponent CreateStringField(ISerializableEntity entity, SerializableProperty property, string value, string displayName, string toolTip)
public GUIComponent CreateStringField(ISerializableEntity entity, SerializableProperty property, string value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), color: Color.Transparent);
var frame = new GUILayoutGroup(new RectTransform(new Point(Rect.Width, elementHeight), layoutGroup.RectTransform), isHorizontal: true)
{
Stretch = true
};
var label = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform), displayName, font: GUI.SmallFont, textAlignment: Alignment.Left)
{
ToolTip = toolTip
};
GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform, Anchor.TopRight))
GUITextBox propertyBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1), frame.RectTransform))
{
ToolTip = toolTip,
Font = GUI.SmallFont,
@@ -514,11 +521,36 @@ namespace Barotrauma
return true;
}
};
Fields.Add(property.Name, new GUIComponent[] { propertyBox });
string translationTextTag = property.GetAttribute<Serialize>()?.translationTextTag;
if (translationTextTag != null)
{
new GUIButton(new RectTransform(new Vector2(0.1f, 1), frame.RectTransform, Anchor.TopRight), "...")
{
OnClicked = (bt, userData) => { CreateTextPicker(translationTextTag, entity, property, propertyBox); return true; }
};
propertyBox.OnTextChanged += (tb, text) =>
{
string translatedText = TextManager.Get(text, returnNull: true);
if (translatedText == null)
{
propertyBox.TextColor = Color.Gray;
propertyBox.ToolTip = TextManager.Get("StringPropertyCannotTranslate").Replace("[tag]", text ?? "");
}
else
{
propertyBox.TextColor = Color.LightGreen;
propertyBox.ToolTip = TextManager.Get("StringPropertyTranslate").Replace("[translation]", translatedText);
}
return true;
};
propertyBox.Text = value;
}
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, new GUIComponent[] { propertyBox }); }
return frame;
}
private GUIComponent CreatePointField(ISerializableEntity entity, SerializableProperty property, Point value, string displayName, string toolTip)
public GUIComponent CreatePointField(ISerializableEntity entity, SerializableProperty property, Point value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -566,11 +598,11 @@ namespace Barotrauma
};
fields[i] = numberInput;
}
Fields.Add(property.Name, fields);
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); }
return frame;
}
private GUIComponent CreateVector2Field(ISerializableEntity entity, SerializableProperty property, Vector2 value, string displayName, string toolTip)
public GUIComponent CreateVector2Field(ISerializableEntity entity, SerializableProperty property, Vector2 value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.4f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -620,11 +652,11 @@ namespace Barotrauma
};
fields[i] = numberInput;
}
Fields.Add(property.Name, fields);
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); }
return frame;
}
private GUIComponent CreateVector3Field(ISerializableEntity entity, SerializableProperty property, Vector3 value, string displayName, string toolTip)
public GUIComponent CreateVector3Field(ISerializableEntity entity, SerializableProperty property, Vector3 value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -678,11 +710,11 @@ namespace Barotrauma
};
fields[i] = numberInput;
}
Fields.Add(property.Name, fields);
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); }
return frame;
}
private GUIComponent CreateVector4Field(ISerializableEntity entity, SerializableProperty property, Vector4 value, string displayName, string toolTip)
public GUIComponent CreateVector4Field(ISerializableEntity entity, SerializableProperty property, Vector4 value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -740,14 +772,14 @@ namespace Barotrauma
};
fields[i] = numberInput;
}
Fields.Add(property.Name, fields);
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); }
return frame;
}
private GUIComponent CreateColorField(ISerializableEntity entity, SerializableProperty property, Color value, string displayName, string toolTip)
public GUIComponent CreateColorField(ISerializableEntity entity, SerializableProperty property, Color value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform) { MinSize = new Point(80, 26)}, displayName, font: GUI.SmallFont)
var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform) { MinSize = new Point(80, 26) }, displayName, font: GUI.SmallFont)
{
ToolTip = toolTip
};
@@ -807,11 +839,11 @@ namespace Barotrauma
colorBox.Color = (Color)property.GetValue(entity);
fields[i] = numberInput;
}
Fields.Add(property.Name, fields);
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); }
return frame;
}
private GUIComponent CreateRectangleField(ISerializableEntity entity, SerializableProperty property, Rectangle value, string displayName, string toolTip)
public GUIComponent CreateRectangleField(ISerializableEntity entity, SerializableProperty property, Rectangle value, string displayName, string toolTip)
{
var frame = new GUIFrame(new RectTransform(new Point(Rect.Width, Math.Max(elementHeight, 26)), layoutGroup.RectTransform), color: Color.Transparent);
var label = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform), displayName, font: GUI.SmallFont)
@@ -867,9 +899,43 @@ namespace Barotrauma
};
fields[i] = numberInput;
}
Fields.Add(property.Name, fields);
if (!Fields.ContainsKey(property.Name)) { Fields.Add(property.Name, fields); }
return frame;
}
public void CreateTextPicker(string textTag, ISerializableEntity entity, SerializableProperty property, GUITextBox textBox)
{
var msgBox = new GUIMessageBox("", "", new string[] { TextManager.Get("Cancel") }, width: 300, height: 400);
msgBox.Buttons[0].OnClicked = msgBox.Close;
var textList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), msgBox.Content.RectTransform, Anchor.TopCenter))
{
OnSelected = (component, userData) =>
{
string text = userData as string ?? "";
if (property.TrySetValue(entity, text))
{
TrySendNetworkUpdate(entity, property);
textBox.Text = (string)property.GetValue(entity);
textBox.Deselect();
}
return true;
}
};
textTag = textTag.ToLowerInvariant();
var tagTextPairs = TextManager.GetAllTagTextPairs();
foreach (KeyValuePair<string, string> tagTextPair in tagTextPairs)
{
if (!tagTextPair.Key.StartsWith(textTag)) { continue; }
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textList.Content.RectTransform) { MinSize = new Point(0, 20) },
ToolBox.LimitString(tagTextPair.Value, GUI.Font, textList.Content.Rect.Width))
{
UserData = tagTextPair.Key
};
}
}
private void TrySendNetworkUpdate(ISerializableEntity entity, SerializableProperty property)
{

View File

@@ -372,167 +372,6 @@ namespace Barotrauma
}
}
private static void UpdateFireSounds(float deltaTime)
{
for (int i = 0; i < fireVolumeLeft.Length; i++)
{
fireVolumeLeft[i] = 0.0f;
fireVolumeRight[i] = 0.0f;
}
Vector2 listenerPos = new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y);
foreach (Hull hull in Hull.hullList)
{
foreach (FireSource fs in hull.FireSources)
{
Vector2 diff = fs.WorldPosition + fs.Size / 2 - listenerPos;
if (Math.Abs(diff.X) < FireSoundRange && Math.Abs(diff.Y) < FireSoundRange)
{
Vector2 diffLeft = (fs.WorldPosition + new Vector2(fs.Size.X, fs.Size.Y / 2)) - listenerPos;
if (diff.X < fs.Size.X / 2.0f) diff.X = 0.0f;
if (diffLeft.X <= 0)
{
float distFallOffLeft = diffLeft.Length() / FireSoundRange;
if (distFallOffLeft < 0.99f)
{
fireVolumeLeft[0] += (1.0f - distFallOffLeft) * (fs.Size.X / FireSoundLargeLimit);
if (fs.Size.X > FireSoundLargeLimit) fireVolumeLeft[1] += (1.0f - distFallOffLeft) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
}
}
Vector2 diffRight = (fs.WorldPosition + new Vector2(0.0f, fs.Size.Y / 2)) - listenerPos;
if (diff.X < fs.Size.X / 2.0f) diff.X = 0.0f;
if (diffRight.X >= 0)
{
float distFallOffRight = diffRight.Length() / FireSoundRange;
if (distFallOffRight < 0.99f)
{
fireVolumeRight[0] += 1.0f - distFallOffRight;
if (fs.Size.X > FireSoundLargeLimit) fireVolumeRight[1] += (1.0f - distFallOffRight) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
}
}
}
}
}
for (int i = 0; i < fireVolumeLeft.Length; i++)
{
if (fireVolumeLeft[i] < 0.05f && fireVolumeRight[i] < 0.05f)
{
if (fireSoundChannels[i] != null)
{
fireSoundChannels[i].FadeOutAndDispose();
fireSoundChannels[i] = null;
}
}
else
{
Vector2 soundPos = new Vector2(GameMain.SoundManager.ListenerPosition.X + (fireVolumeRight[i] - fireVolumeLeft[i]) * 100, GameMain.SoundManager.ListenerPosition.Y);
if (fireSoundChannels[i] == null || !fireSoundChannels[i].IsPlaying)
{
fireSoundChannels[i] = GetSound(i == 0 ? "fire" : "firelarge").Play(1.0f, FlowSoundRange, soundPos);
fireSoundChannels[i].Looping = true;
}
fireSoundChannels[i].Gain = Math.Max(fireVolumeRight[i], fireVolumeLeft[i]);
fireSoundChannels[i].Position = new Vector3(soundPos, 0.0f);
}
}
}
if (waterAmbiences.Count > 1)
{
if (waterAmbienceChannels[0] == null || !waterAmbienceChannels[0].IsPlaying)
{
waterAmbienceChannels[0] = waterAmbiences[0].Play(ambienceVolume * (1.0f - movementSoundVolume),"waterambience");
//waterAmbiences[0].Loop(waterAmbienceIndexes[0], ambienceVolume * (1.0f - movementSoundVolume));
waterAmbienceChannels[0].Looping = true;
}
else
{
waterAmbienceChannels[0].Gain = ambienceVolume * (1.0f - movementSoundVolume);
}
if (waterAmbienceChannels[1] == null || !waterAmbienceChannels[1].IsPlaying)
{
waterAmbienceChannels[1] = waterAmbiences[1].Play(ambienceVolume * movementSoundVolume, "waterambience");
//waterAmbienceIndexes[1] = waterAmbiences[1].Loop(waterAmbienceIndexes[1], ambienceVolume * movementSoundVolume);
waterAmbienceChannels[1].Looping = true;
}
else
{
waterAmbienceChannels[1].Gain = ambienceVolume * movementSoundVolume;
}
}
}
private static void UpdateWaterFlowSounds(float deltaTime)
{
if (FlowSounds.Count == 0) { return; }
float[] targetFlowLeft = new float[FlowSounds.Count];
float[] targetFlowRight = new float[FlowSounds.Count];
Vector2 listenerPos = new Vector2(GameMain.SoundManager.ListenerPosition.X, GameMain.SoundManager.ListenerPosition.Y);
foreach (Gap gap in Gap.GapList)
{
if (gap.Open < 0.01f) continue;
float gapFlow = Math.Abs(gap.LerpedFlowForce.X) + Math.Abs(gap.LerpedFlowForce.Y) * 2.5f;
if (gapFlow < 10.0f) continue;
int flowSoundIndex = (int)Math.Floor(MathHelper.Clamp(gapFlow / MaxFlowStrength, 0, FlowSounds.Count));
flowSoundIndex = Math.Min(flowSoundIndex, FlowSounds.Count - 1);
Vector2 diff = gap.WorldPosition - listenerPos;
if (Math.Abs(diff.X) < FlowSoundRange && Math.Abs(diff.Y) < FlowSoundRange)
{
float dist = diff.Length();
float distFallOff = dist / FlowSoundRange;
if (distFallOff >= 0.99f) continue;
//flow at the left side
if (diff.X < 0)
{
targetFlowLeft[flowSoundIndex] = 1.0f - distFallOff;
}
else
{
targetFlowRight[flowSoundIndex] = 1.0f - distFallOff;
}
}
}
for (int i = 0; i < FlowSounds.Count; i++)
{
flowVolumeLeft[i] = (targetFlowLeft[i] < flowVolumeLeft[i]) ?
Math.Max(targetFlowLeft[i], flowVolumeLeft[i] - deltaTime) :
Math.Min(targetFlowLeft[i], flowVolumeLeft[i] + deltaTime);
flowVolumeRight[i] = (targetFlowRight[i] < flowVolumeRight[i]) ?
Math.Max(targetFlowRight[i], flowVolumeRight[i] - deltaTime) :
Math.Min(targetFlowRight[i], flowVolumeRight[i] + deltaTime);
if (flowVolumeLeft[i] < 0.05f && flowVolumeRight[i] < 0.05f)
{
if (flowSoundChannels[i] != null)
{
flowSoundChannels[i].Dispose();
flowSoundChannels[i] = null;
}
}
else
{
Vector2 soundPos = new Vector2(GameMain.SoundManager.ListenerPosition.X + (flowVolumeRight[i] - flowVolumeLeft[i]) * 100, GameMain.SoundManager.ListenerPosition.Y);
if (flowSoundChannels[i] == null || !flowSoundChannels[i].IsPlaying)
{
flowSoundChannels[i] = FlowSounds[i].Play(1.0f, FlowSoundRange, soundPos);
flowSoundChannels[i].Looping = true;
}
flowSoundChannels[i].Gain = Math.Max(flowVolumeRight[i], flowVolumeLeft[i]);
flowSoundChannels[i].Position = new Vector3(soundPos, 0.0f);
}
}
}
private static void UpdateFireSounds(float deltaTime)
{
for (int i = 0; i < fireVolumeLeft.Length; i++)

View File

@@ -151,6 +151,7 @@ namespace Barotrauma
for (int i = traitStart + NPCPersonalityTrait.List.Count; i < csvContent.Length; i++) // Conversations
{
string[] presplit = csvContent[i].Split(','); // Handling speaker index fetching, somehow doesn't work with the regex
string[] split = SplitCSV(csvContent[i]);
int emptyFields = 0;
@@ -172,20 +173,20 @@ namespace Barotrauma
continue;
}
string speaker = split[1];
int depthIndex = int.Parse(split[2]);
string speaker = presplit[1];
int depthIndex = int.Parse(presplit[2]);
// 3 = original line
string line = split[4].Replace("\"", "");
string flags = split[5].Replace("\"", "");
string allowedJobs = split[6].Replace("\"", "");
string speakerTags = split[7].Replace("\"", "");
string minIntensity = split[8].Replace("\"", "");
string maxIntensity = split[9].Replace("\"", "");
string minIntensity = split[8].Replace("\"", "").Replace(",", ".");
string maxIntensity = split[9].Replace("\"", "").Replace(",", ".");
string element =
$"{GetIndenting(depthIndex)}" +
$"<Conversation line=\"{line}\" " +
$"{GetVariable("speaker" ,speaker)}" +
$"{GetVariable("speaker", speaker)}" +
$"{GetVariable("flags", flags)}" +
$"{GetVariable("allowedjobs", allowedJobs)}" +
$"{GetVariable("speakertags", speakerTags)}" +

View File

@@ -216,13 +216,22 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup Condition="'$(DefineConstants)' == 'LINUX' ">
<ItemGroup Condition="'$(Configuration)|$(Platform)' == 'DebugLinux|x64'">
<None Include="Launch_BarotraumaServer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="DedicatedServer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="DedicatedServer.bin.x86">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="DedicatedServer.bin.x86_64">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="..\BarotraumaShared\SharedCode.projitems" Label="Shared" />
<Import Project="..\BarotraumaShared\SharedContent.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets" Condition="Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets')" />
</Project>
</Project>

View File

@@ -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<Client, Vector2, string[]> onClientRequestExecute)

View File

@@ -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();

View File

@@ -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<PurchasedItem> purchasedItems = new List<PurchasedItem>();
@@ -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)
{

View File

@@ -5,11 +5,14 @@
<Item file="Content/Items/Button/button.xml" />
<Item file="Content/Items/Command/command.xml" />
<Item file="Content/Items/Containers/containers.xml" />
<Item file="Content/Items/Jobgear/captaingear.xml" />
<Item file="Content/Items/Jobgear/doctorgear.xml" />
<Item file="Content/Items/Jobgear/engigear.xml" />
<Item file="Content/Items/Jobgear/Captain/captain_gear.xml" />
<Item file="Content/Items/Jobgear/Medic/medic_gear.xml" />
<Item file="Content/Items/Jobgear/Engineer/engineer_gear.xml" />
<Item file="Content/Items/Jobgear/Mechanic/mechanic_gear.xml" />
<Item file="Content/Items/Jobgear/Assistant/assistant_gear.xml" />
<Item file="Content/Items/Jobgear/Watchman/watchman_gear.xml" />
<Item file="Content/Items/Jobgear/Security/securityofficer_gear.xml" />
<Item file="Content/Items/Jobgear/misc.xml" />
<Item file="Content/Items/Jobgear/securitygear.xml" />
<Item file="Content/Items/CreatureLoot/creatureloot.xml" />
<Item file="Content/Items/Diving/divinggear.xml" />
<Item file="Content/Items/Door/doors.xml" />

View File

@@ -24,6 +24,10 @@
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Tigerthresher\Animations\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Characters\Watcher\Animations\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\BackgroundCreatures\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\" />
<Folder Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\" />
<Folder Include="$(MSBuildThisFileDirectory)Data\Saves\" />
</ItemGroup>
<ItemGroup>
@@ -360,6 +364,78 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\door2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\Lamps.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\LampsAdditive.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\assistant_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_legs_female_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_legs_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_torso_female_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_torso_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_legs_female_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_legs_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_torso_female_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_torso_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_legs_female_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_legs_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_legs_male_3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_torso_female_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_torso_male_2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_torso_male_3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Map\FinsA.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Map\FinsABack.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Map\LabelIcons.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Map\LabelLetters.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\1_CommandReactor\BaroTutorial_CommandReactor.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -594,94 +670,94 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\InventoryIconAtlas.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\assistant_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\assistant_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\assistant_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\assistant_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\assistant_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\assistant_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\assistant_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Assistant\assistant_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\captain_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\captain_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\captain_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\captain_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\captain_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\captain_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\captain_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\captain_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\engineer_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\engineer_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\engineer_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\engineer_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Engineer\engineer_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\mechanic_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\mechanic_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\mechanic_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\mechanic_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Mechanic\mechanic_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\medic_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\medic_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\medic_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\medic_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\medic_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\medic_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\medic_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\medic_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\PortraitClothing.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\securityofficer_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\securityofficer_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\securityofficer_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\securityofficer_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\securityofficer_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\securityofficer_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\securityofficer_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\securityofficer_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\SecurityVest.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\SecurityVest.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\watchman_legs_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_legs_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\watchman_legs_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_legs_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\watchman_torso_female.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_torso_female_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\watchman_torso_male.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Watchman\watchman_torso_male_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Materials\CraftingElements2.png">
@@ -1304,7 +1380,7 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\MachineInterface.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\riotgear.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\riotgear.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Reactor\graphLine.png">
@@ -1571,7 +1647,7 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Labels\labels.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\captaingear.xml">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Captain\captain_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\clownmask.png">
@@ -1583,10 +1659,7 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\clownshirt.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\doctorgear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\engigear.xml">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Medic\medic_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\clothes.png">
@@ -1595,10 +1668,10 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\misc.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\securitygear.png">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\securitygear.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\securitygear.xml">
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Jobgear\Security\securityofficer_gear.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Ladder\ladder.png">
@@ -1913,6 +1986,24 @@
<Content Include="$(MSBuildThisFileDirectory)serversettings.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\alienbutton.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\AlienCoil1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\AlienCoil2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\alienpump.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\AlienTurret1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\AlienTurret2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Misc\GuitarClown.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -1931,6 +2022,27 @@
<None Include="$(MSBuildThisFileDirectory)Content\Items\Weapons\ElectricalDischarger.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore3.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore4.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore5.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore6.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\Gore7.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Impact\MetalImpactHeavy1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -2467,18 +2579,6 @@
<None Include="$(MSBuildThisFileDirectory)Content\Fonts\Exo2-Medium.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\alienbutton.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\aliencoil.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\alienpump.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\alienturret.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Alien\alienweapon.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@@ -14,6 +14,11 @@ namespace Barotrauma
{
public static bool DisableEnemyAI;
/// <summary>
/// Enable the character to attack the outposts and the characters inside them. Disabled by default.
/// </summary>
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;

View File

@@ -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);
}
}

View File

@@ -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<Controller>();
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; }
}
}
}

View File

@@ -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<AIObjectiveFindSafety>().Priority = 0;
findSafety = HumanAIController.ObjectiveManager.GetObjective<AIObjectiveFindSafety>();
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<AIObjectiveFindSafety>().FindBestHull(new List<Hull>() { character.CurrentHull });
retreatTarget = findSafety.FindBestHull(new List<Hull>() { character.CurrentHull });
}
if (retreatTarget != null)
{
@@ -277,7 +280,6 @@ namespace Barotrauma
{
abandon = true;
SteeringManager.Reset();
//HumanAIController.ObjectiveManager.GetObjective<AIObjectiveFindSafety>().Priority = 100;
}
public override bool IsCompleted()

View File

@@ -18,7 +18,7 @@ namespace Barotrauma
const float SearchHullInterval = 3.0f;
const float clearUnreachableInterval = 30;
private List<Hull> unreachable = new List<Hull>();
public readonly List<Hull> unreachable = new List<Hull>();
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));

View File

@@ -26,6 +26,9 @@ namespace Barotrauma
private float standStillTimer;
private float walkDuration;
private readonly List<Hull> targetHulls = new List<Hull>(20);
private readonly List<float> hullWeights = new List<float>(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<Hull> targetHulls = new List<Hull>(20);
private readonly List<float> hullWeights = new List<float>(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)

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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<Limb> connectedLimbs, List<LimbJoint> checkedJoints, Limb limb)
{

View File

@@ -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; }
/// <summary>
/// Legacy support. Use Afflictions.

View File

@@ -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

View File

@@ -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));
/// <summary>
/// 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;

View File

@@ -8,6 +8,22 @@ namespace Barotrauma
{
public static class StringFormatter
{
public static string Replace(this string s, string replacement, Func<char, bool> 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<char, bool> predicate)
{
return new string(s.ToCharArray().Where(c => !predicate(c)).ToArray());

View File

@@ -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<ItemContainer, int> availableContainers = new Dictionary<ItemContainer, int>();

View File

@@ -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<string, double> dialogLastSpoken = new Dictionary<string, double>();
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<Items.Components.Repairable>() != null)
{
item.Condition = item.Health;
}
}
}
PurchasedItemRepairs = false;
}
}
public override void Update(float deltaTime)

View File

@@ -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> { 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)

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
get { return name; }
}
[Editable, Serialize("", true)]
[Editable, Serialize("", true, translationTextTag: "ItemMsg")]
public string Msg
{
get;

View File

@@ -185,6 +185,19 @@ namespace Barotrauma.Items.Components
return true;
}
public override void OnItemLoaded()
{
sonar = item.GetComponent<Sonar>();
}
public override bool Select(Character character)
{
if (!CanBeSelected) return false;
user = character;
return true;
}
public override void Update(float deltaTime, Camera cam)
{
networkUpdateTimer -= deltaTime;

View File

@@ -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<string, SerializableProperty> SerializableProperties { get; set; }
public List<StatusEffect> StatusEffects = new List<StatusEffect>();
@@ -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)

View File

@@ -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;
/// <summary>
/// None = Any/Not Defined -> no effect.
@@ -112,30 +115,65 @@ namespace Barotrauma
/// <summary>
/// Note: this constructor cannot initialize automatically, because the gender is unknown at this point. We only know it when the item is equipped.
/// </summary>
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())
{

View File

@@ -144,18 +144,6 @@ namespace Barotrauma
private List<XElement> fabricationRecipeElements = new List<XElement>();
private bool canSpriteFlipX, canSpriteFlipY;
private Dictionary<string, PriceInfo> prices;
/// <summary>
/// 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.
/// </summary>
public List<Rectangle> Triggers;
private List<XElement> fabricationRecipeElements = new List<XElement>();
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<string>(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true));
if (Tags.None())
{
Tags = new HashSet<string>(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<AfflictionPrefab> 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;
}

View File

@@ -25,6 +25,8 @@ namespace Barotrauma
private bool removed;
private bool removed;
#if CLIENT
private List<Decal> burnDecals = new List<Decal>();
#endif

View File

@@ -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)

View File

@@ -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;

View File

@@ -417,7 +417,10 @@ namespace Barotrauma
if (me.Submarine != this) { continue; }
if (me is Item item)
{
item.Indestructible = true;
if (item.GetComponent<Repairable>() != 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)

View File

@@ -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)
{
}

View File

@@ -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();

View File

@@ -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;
}
}
}

View File

@@ -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<string> 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<string> 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<KeyValuePair<string, string>> GetAllTagTextPairs()
{
if (!textPacks.ContainsKey(Language))

View File

@@ -37,6 +37,7 @@ namespace Barotrauma
text = text.Replace("&amp;", "&");
text = text.Replace("&lt;", "<");
text = text.Replace("&gt;", ">");
text = text.Replace("&quot;", "\"");
infoList.Add(text);
}
}
@@ -62,6 +63,20 @@ namespace Barotrauma
return textList;
}
public List<KeyValuePair<string, string>> GetAllTagTextPairs()
{
var pairs = new List<KeyValuePair<string, string>>();
foreach (KeyValuePair<string, List<string>> kvp in texts)
{
foreach (string line in kvp.Value)
{
pairs.Add(new KeyValuePair<string, string>(kvp.Key, line));
}
}
return pairs;
}
#if DEBUG
public void CheckForDuplicates(int index)
{

View File

@@ -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");