(ce8e185aa) Merge branch 'dev' of https://github.com/Regalis11/Barotrauma-development into dev

This commit is contained in:
Joonas Rikkonen
2019-04-16 17:12:09 +03:00
parent bd07acf26d
commit 6262b3ea54
96 changed files with 1972 additions and 825 deletions

View File

@@ -393,7 +393,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 })
{
@@ -411,6 +411,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

@@ -555,6 +555,37 @@ namespace Barotrauma
}
}));
commands.Add(new Command("resetselected", "Reset selected items and structures to prefabs. Only applicable in the subeditor.", args =>
{
if (Screen.Selected == GameMain.SubEditorScreen)
{
foreach (MapEntity entity in MapEntity.SelectedList)
{
if (entity is Item item)
{
item.Reset();
}
else if (entity is Structure structure)
{
structure.Reset();
}
}
foreach (MapEntity entity in MapEntity.SelectedList)
{
if (entity is Item item)
{
item.CreateEditingHUD();
break;
}
else if (entity is Structure structure)
{
structure.CreateEditingHUD();
break;
}
}
}
}));
commands.Add(new Command("alpha", "Change the alpha (as bytes from 0 to 255) of the selected item/structure instances. Applied only in the subeditor.", (string[] args) =>
{
if (Screen.Selected == GameMain.SubEditorScreen)
@@ -1051,6 +1082,130 @@ namespace Barotrauma
};
}));
commands.Add(new Command("dumpentitytexts", "dumpentitytexts [filepath]: gets the names and descriptions of all entity prefabs and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EntityTexts.txt", (string[] args) =>
{
string filePath = args.Length > 0 ? args[0] : "Content/Texts/EntityTexts.txt";
List<string> lines = new List<string>();
foreach (MapEntityPrefab me in MapEntityPrefab.List)
{
lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</EntityName." + me.Identifier + ">");
lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</EntityDescription." + me.Identifier + ">");
}
File.WriteAllLines(filePath, lines);
}));
#if DEBUG
commands.Add(new Command("checkduplicates", "Checks the given language for duplicate translation keys and writes to file.", (string[] args) =>
{
if (args.Length != 1) return;
TextManager.CheckForDuplicates(args[0]);
}));
commands.Add(new Command("writetocsv", "Writes the default language (English) to a .csv file.", (string[] args) =>
{
TextManager.WriteToCSV();
NPCConversation.WriteToCSV();
}));
commands.Add(new Command("csvtoxml", "csvtoxml [language] -> Converts .csv localization files in Content/NPCConversations & Content/Texts to .xml for use in-game.", (string[] args) =>
{
if (args.Length == 0) return;
LocalizationCSVtoXML.Convert(args[0]);
}));
#endif
commands.Add(new Command("cleanbuild", "", (string[] args) =>
{
GameMain.Config.MusicVolume = 0.5f;
GameMain.Config.SoundVolume = 0.5f;
NewMessage("Music and sound volume set to 0.5", Color.Green);
GameMain.Config.GraphicsWidth = 0;
GameMain.Config.GraphicsHeight = 0;
GameMain.Config.WindowMode = WindowMode.Fullscreen;
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
NewMessage("Fullscreen enabled", Color.Green);
GameSettings.ShowUserStatisticsPrompt = true;
GameSettings.VerboseLogging = false;
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
{
ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!");
}
GameMain.Config.SaveNewPlayerConfig();
var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder);
foreach (string saveFile in saveFiles)
{
System.IO.File.Delete(saveFile);
NewMessage("Deleted " + saveFile, Color.Green);
}
if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp")))
{
ThrowError("Reading the file \"" + sourcePath + "\" failed.", e);
return;
}
var doc = XMLExtensions.TryLoadXml(destinationPath);
int i = 0;
foreach (XElement element in doc.Root.Elements())
{
if (i >= lines.Length)
{
ThrowError("Error while loading texts to the xml file. The xml has more elements than the number of lines in the text file.");
return;
}
element.Value = lines[i];
i++;
}
doc.Save(destinationPath);
},
() =>
{
var files = TextManager.GetTextFiles().Select(f => f.Replace("\\", "/"));
return new string[][]
{
files.Where(f => Path.GetExtension(f)==".txt").ToArray(),
files.Where(f => Path.GetExtension(f)==".xml").ToArray()
};
}));
commands.Add(new Command("updatetextfile", "updatetextfile [sourcefile] [destinationfile]: Inserts all the xml elements that are only present in the source file into the destination file. Can be used to update outdated translation files more easily.", (string[] args) =>
{
if (args.Length < 2) return;
string sourcePath = args[0];
string destinationPath = args[1];
var sourceDoc = XMLExtensions.TryLoadXml(sourcePath);
var destinationDoc = XMLExtensions.TryLoadXml(destinationPath);
XElement destinationElement = destinationDoc.Root.Elements().First();
foreach (XElement element in sourceDoc.Root.Elements())
{
if (destinationDoc.Root.Element(element.Name) == null)
{
element.Value = "!!!!!!!!!!!!!" + element.Value;
destinationElement.AddAfterSelf(element);
}
XNode nextNode = destinationElement.NextNode;
while ((!(nextNode is XElement) || nextNode == element) && nextNode != null) nextNode = nextNode.NextNode;
destinationElement = nextNode as XElement;
}
destinationDoc.Save(destinationPath);
},
() =>
{
var files = TextManager.GetTextFiles().Where(f => Path.GetExtension(f) == ".xml").Select(f => f.Replace("\\", "/")).ToArray();
return new string[][]
{
files,
files
};
}));
commands.Add(new Command("dumpentitytexts", "dumpentitytexts [filepath]: gets the names and descriptions of all entity prefabs and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EntityTexts.txt", (string[] args) =>
{
string filePath = args.Length > 0 ? args[0] : "Content/Texts/EntityTexts.txt";
@@ -1694,7 +1849,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)
@@ -1705,6 +1860,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)
@@ -1852,7 +2027,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)
{
@@ -1861,11 +2036,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

@@ -26,7 +26,21 @@ namespace Barotrauma
private bool isSinglePlayer;
public bool IsSinglePlayer => isSinglePlayer;
private bool toggleOpen = true;
private bool _toggleOpen = true;
public bool ToggleOpen
{
get { return _toggleOpen; }
set
{
if (_toggleOpen == value) { return; }
_toggleOpen = GameMain.Config.ChatOpen = value;
foreach (GUIComponent child in ToggleButton.Children)
{
child.SpriteEffects = _toggleOpen == (HUDLayoutSettings.ChatBoxAlignment == Alignment.Right) ?
SpriteEffects.FlipHorizontally : SpriteEffects.None;
}
}
}
private float openState;
private float prevUIScale;
@@ -81,12 +95,7 @@ namespace Barotrauma
toggleButton.OnClicked += (GUIButton btn, object userdata) =>
{
toggleOpen = !toggleOpen;
foreach (GUIComponent child in btn.Children)
{
child.SpriteEffects = toggleOpen == (HUDLayoutSettings.ChatBoxAlignment == Alignment.Right) ?
SpriteEffects.FlipHorizontally : SpriteEffects.None;
}
ToggleOpen = !ToggleOpen;
return true;
};
@@ -124,6 +133,8 @@ namespace Barotrauma
}
return true;
};
ToggleOpen = GameMain.Config.ChatOpen;
}
public bool TypingChatMessage(GUITextBox textBox, string text)
@@ -228,7 +239,7 @@ namespace Barotrauma
chatBox.UpdateScrollBarSize();
if (!toggleOpen)
if (!ToggleOpen)
{
var popupMsg = new GUIFrame(new RectTransform(Vector2.One, guiFrame.RectTransform), style: "GUIToolTip")
{
@@ -313,9 +324,7 @@ namespace Barotrauma
prevUIScale = GUI.Scale;
}
if (toggleOpen || (inputBox != null && inputBox.Selected))
if (ToggleOpen || (inputBox != null && inputBox.Selected))
{
openState += deltaTime * 5.0f;
//delete all popup messages when the chatbox is open

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

@@ -318,8 +318,16 @@ namespace Barotrauma
SoundManager.SetCategoryGainMultiplier("voip", Config.VoiceChatVolume);
if (Config.EnableSplashScreen)
{
(TitleScreen as LoadingScreen).SplashScreen = new Video(base.GraphicsDevice, SoundManager, "Content/splashscreen.mp4", 1280, 720);
}
try
{
(TitleScreen as LoadingScreen).SplashScreen = new Video(base.GraphicsDevice, SoundManager, "Content/splashscreen.mp4", 1280, 720);
}
catch (Exception e)
{
Config.EnableSplashScreen = false;
DebugConsole.ThrowError("Playing the splash screen failed.", e);
}
}
GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
DebugConsole.Init();

View File

@@ -41,7 +41,10 @@ namespace Barotrauma
private bool toggleCrewAreaOpen = true;
private int characterInfoWidth;
private ChatBox chatBox;
/// <summary>
/// Present only in single player games. In multiplayer. The chatbox is found from GameSession.Client.
/// </summary>
public ChatBox ChatBox { get; private set; }
private float prevUIScale;
@@ -50,7 +53,15 @@ namespace Barotrauma
public bool ToggleCrewAreaOpen
{
get { return toggleCrewAreaOpen; }
set { toggleCrewAreaOpen = value; }
set
{
if (toggleCrewAreaOpen == value) { return; }
toggleCrewAreaOpen = GameMain.Config.CrewMenuOpen = value;
foreach (GUIComponent child in toggleCrewButton.Children)
{
child.SpriteEffects = toggleCrewAreaOpen ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
}
}
}
#endregion
@@ -93,11 +104,7 @@ namespace Barotrauma
"", style: "UIToggleButton");
toggleCrewButton.OnClicked += (GUIButton btn, object userdata) =>
{
toggleCrewAreaOpen = !toggleCrewAreaOpen;
foreach (GUIComponent child in btn.Children)
{
child.SpriteEffects = toggleCrewAreaOpen ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
}
ToggleCrewAreaOpen = !ToggleCrewAreaOpen;
return true;
};
@@ -125,7 +132,7 @@ namespace Barotrauma
if (isSinglePlayer)
{
chatBox = new ChatBox(guiFrame, isSinglePlayer: true)
ChatBox = new ChatBox(guiFrame, isSinglePlayer: true)
{
OnEnterMessage = (textbox, text) =>
{
@@ -158,7 +165,7 @@ namespace Barotrauma
}
};
chatBox.InputBox.OnTextChanged += chatBox.TypingChatMessage;
ChatBox.InputBox.OnTextChanged += ChatBox.TypingChatMessage;
}
var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null);
@@ -208,6 +215,8 @@ namespace Barotrauma
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
prevUIScale = GUI.Scale;
ToggleCrewAreaOpen = GameMain.Config.CrewMenuOpen;
}
@@ -271,7 +280,6 @@ namespace Barotrauma
DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace);
return;
}
}
characterInfos.Add(characterInfo);
}
@@ -599,7 +607,20 @@ namespace Barotrauma
characterListBox.BarScroll = roundedPos;
}
return false;
#region Dialog
/// <summary>
/// Adds the message to the single player chatbox.
/// </summary>
public void AddSinglePlayerChatMessage(string senderName, string text, ChatMessageType messageType, Character sender)
{
if (!isSinglePlayer)
{
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
return;
}
if (string.IsNullOrEmpty(text)) { return; }
chatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
}
private IEnumerable<object> KillCharacterAnim(GUIComponent component)
@@ -612,6 +633,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);
@@ -647,7 +674,7 @@ namespace Barotrauma
}
if (string.IsNullOrEmpty(text)) { return; }
chatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
}
private WifiComponent GetHeadset(Character character, bool requireEquipped)
@@ -723,7 +750,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
{
@@ -740,7 +767,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)
{
@@ -1057,24 +1084,24 @@ namespace Barotrauma
}
if (GUI.DisableHUD || GUI.DisableUpperHUD) return;
if (chatBox != null)
if (ChatBox != null)
{
chatBox.Update(deltaTime);
chatBox.InputBox.Visible = Character.Controlled != null;
ChatBox.Update(deltaTime);
ChatBox.InputBox.Visible = Character.Controlled != null;
if (!DebugConsole.IsOpen && chatBox.InputBox.Visible)
if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible)
{
if (PlayerInput.KeyHit(InputType.Chat) && !chatBox.InputBox.Selected)
if (PlayerInput.KeyHit(InputType.Chat) && !ChatBox.InputBox.Selected)
{
chatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
chatBox.InputBox.Select();
ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
ChatBox.InputBox.Select();
}
if (PlayerInput.KeyHit(InputType.RadioChat) && !chatBox.InputBox.Selected)
if (PlayerInput.KeyHit(InputType.RadioChat) && !ChatBox.InputBox.Selected)
{
chatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
chatBox.InputBox.Select();
chatBox.InputBox.Text = "r; ";
ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
ChatBox.InputBox.Select();
ChatBox.InputBox.Text = "r; ";
}
}
}
@@ -1144,7 +1171,7 @@ namespace Barotrauma
crewArea.RectTransform.AbsoluteOffset =
Vector2.SmoothStep(new Vector2(-crewArea.Rect.Width, 0), new Vector2(toggleCrewButton.Rect.Width, 0), crewAreaOpenState).ToPoint();
crewAreaOpenState = toggleCrewAreaOpen ?
crewAreaOpenState = ToggleCrewAreaOpen ?
Math.Min(crewAreaOpenState + deltaTime * 2.0f, 1.0f) :
Math.Max(crewAreaOpenState - deltaTime * 2.0f, 0.0f);
@@ -1157,7 +1184,7 @@ namespace Barotrauma
{
Character.Controlled.SelectedConstruction = null;
}
toggleCrewAreaOpen = !toggleCrewAreaOpen;
ToggleCrewAreaOpen = !ToggleCrewAreaOpen;
}
UpdateReports(deltaTime);
@@ -1285,7 +1312,7 @@ namespace Barotrauma
{
reportButtonFrame.Visible = true;
var reportButtonParent = chatBox ?? GameMain.Client.ChatBox;
var reportButtonParent = ChatBox ?? GameMain.Client.ChatBox;
reportButtonFrame.RectTransform.AbsoluteOffset = new Point(
Math.Min(reportButtonParent.GUIFrame.Rect.X, reportButtonParent.ToggleButton.Rect.X) - reportButtonFrame.Rect.Width - (int)(10 * GUI.Scale),
reportButtonParent.GUIFrame.Rect.Y);

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

@@ -81,7 +81,8 @@ namespace Barotrauma
var leftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), settingsFramePadding.RectTransform, Anchor.TopLeft));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform),
TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont);
TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont)
{ ForceUpperCase = true };
var generalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), leftPanel.RectTransform, Anchor.TopLeft));
@@ -438,6 +439,17 @@ namespace Barotrauma
DebugConsole.NewMessage(name + " " + name.Length.ToString(), Color.Lime);
}
GUITickBox directionalVoiceChat = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get("DirectionalVoiceChat"));
directionalVoiceChat.Selected = UseDirectionalVoiceChat;
directionalVoiceChat.ToolTip = TextManager.Get("DirectionalVoiceChatToolTip");
directionalVoiceChat.OnSelected = (tickBox) =>
{
UseDirectionalVoiceChat = tickBox.Selected;
UnsavedSettings = true;
return true;
};
if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0];
#if (!OSX)
var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), VoiceCaptureDevice, deviceNames.Count);

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;
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,6 +438,32 @@ namespace Barotrauma
QuickUseItem(Items[i], true, false, true);
}
}
}
//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)
{
if (highlightedSubInventorySlot.ParentInventory == this)
{
UpdateSubInventory(deltaTime, highlightedSubInventorySlot.SlotIndex, cam);
}
}
List<SlotReference> hideSubInventories = new List<SlotReference>();
foreach (var highlightedSubInventorySlot in highlightedSubInventorySlots)
@@ -704,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++)
{
@@ -718,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;
}
@@ -728,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

@@ -377,9 +377,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

@@ -785,15 +785,32 @@ namespace Barotrauma.Items.Components
foreach (Character c in Character.CharacterList)
{
if (c.AnimController.CurrentHull != null || !c.Enabled) continue;
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) continue;
if (c.AnimController.CurrentHull != null || !c.Enabled) { continue; }
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) { continue; }
if (c.AnimController.SimplePhysicsEnabled)
{
float pointDist = ((c.WorldPosition - pingSource) * displayScale).LengthSquared();
if (pointDist > DisplayRadius * DisplayRadius) { continue; }
if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr)
{
var blip = new SonarBlip(
c.WorldPosition,
MathHelper.Clamp(c.Mass, 0.1f, pingStrength),
MathHelper.Clamp(c.Mass * 0.03f, 0.1f, 2.0f));
if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; }
sonarBlips.Add(blip);
}
continue;
}
foreach (Limb limb in c.AnimController.Limbs)
{
if (!limb.body.Enabled) { continue; }
float pointDist = ((limb.WorldPosition - pingSource) * displayScale).LengthSquared();
if (limb.SimPosition == Vector2.Zero || pointDist > DisplayRadius * DisplayRadius) continue;
if (limb.SimPosition == Vector2.Zero || pointDist > DisplayRadius * DisplayRadius) { continue; }
if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr)
{
@@ -801,13 +818,13 @@ namespace Barotrauma.Items.Components
limb.WorldPosition + Rand.Vector(limb.Mass / 10.0f),
MathHelper.Clamp(limb.Mass, 0.1f, pingStrength),
MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f));
if (!passive && !CheckBlipVisibility(blip, transducerPos)) continue;
if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; }
sonarBlips.Add(blip);
}
}
}
}
private void CreateBlipsForLine(Vector2 point1, Vector2 point2, Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius,
float lineStep, float zStep, float range, float pingStrength, bool passive)
{

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
@@ -103,9 +101,22 @@ namespace Barotrauma
return color;
}
partial void SetActiveSprite()
partial void SetActiveSpriteProjSpecific()
{
activeSprite = prefab.sprite;
Holdable holdable = GetComponent<Holdable>();
if (holdable != null && holdable.Attached)
{
foreach (ContainedItemSprite containedSprite in Prefab.ContainedSprites)
{
if (containedSprite.UseWhenAttached)
{
activeSprite = containedSprite.Sprite;
return;
}
}
}
if (Container != null)
{
foreach (ContainedItemSprite containedSprite in Prefab.ContainedSprites)
@@ -175,8 +186,7 @@ namespace Barotrauma
Color color = isHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? Color.Orange : GetSpriteColor();
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
Sprite activeSprite = prefab.sprite;
BrokenItemSprite fadeInBrokenSprite = null;
float fadeInBrokenSpriteAlpha = 0.0f;
if (condition < Prefab.Health)
@@ -567,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)
{
@@ -602,6 +617,10 @@ namespace Barotrauma
}
}
ic.CreateEditingHUD(componentEditor);
componentEditor.Recalculate();
}
PositionEditingHUD();
SetHUDLayout();
@@ -784,7 +803,7 @@ namespace Barotrauma
{
if (!ic.CanBeSelected) { continue; }
bool useAlternativeLayout = ic.Item != this;
bool useAlternativeLayout = activeHUDs.Count > 1;
bool wasUsingAlternativeLayout = ic.UseAlternativeLayout;
ic.UseAlternativeLayout = useAlternativeLayout;
needsLayoutUpdate |= ic.UseAlternativeLayout != wasUsingAlternativeLayout;
@@ -818,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

@@ -25,12 +25,14 @@ namespace Barotrauma
class ContainedItemSprite
{
public readonly Sprite Sprite;
public readonly bool UseWhenAttached;
public readonly string[] AllowedContainerIdentifiers;
public readonly string[] AllowedContainerTags;
public ContainedItemSprite(XElement element, string path = "", bool lazyLoad = false)
{
Sprite = new Sprite(element, path, lazyLoad: lazyLoad);
UseWhenAttached = element.GetAttributeBool("usewhenattached", false);
AllowedContainerIdentifiers = element.GetAttributeStringArray("allowedcontaineridentifiers", new string[0], convertToLowerInvariant: true);
AllowedContainerTags = element.GetAttributeStringArray("allowedcontainertags", new string[0], convertToLowerInvariant: true);
}

View File

@@ -217,7 +217,7 @@ namespace Barotrauma
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
SamplerState.LinearClamp, DepthStencilState.Default, null, null,
SamplerState.LinearClamp, DepthStencilState.DepthRead, null, null,
cam.Transform);
if (backgroundSpriteManager != null) backgroundSpriteManager.DrawObjects(spriteBatch, cam, drawFront: true);
spriteBatch.End();

View File

@@ -291,11 +291,6 @@ namespace Barotrauma.Lights
spriteBatch.Draw(HighlightMap, Vector2.Zero, Color.White);
spriteBatch.End();
}
GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive);
spriteBatch.End();
//draw a black rectangle on hulls to hide background lights behind subs
//---------------------------------------------------------------------------------------------------
//draw characters to obstruct the highlighted items/characters and light sprites
//---------------------------------------------------------------------------------------------------
@@ -500,6 +495,8 @@ namespace Barotrauma.Lights
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.White);
}
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, effect: SolidColorEffect, transformMatrix: spriteBatchTransform);
foreach (Character c in Character.CharacterList)
{
if (c.Enabled) { c.Draw(spriteBatch, cam); }

View File

@@ -215,23 +215,24 @@ namespace Barotrauma
{
if (Prefab.BackgroundSprite != null)
{
bool drawDropShadow = Submarine != null && HasBody;
Vector2 dropShadowOffset = Vector2.Zero;
if (drawDropShadow)
if (UseDropShadow)
{
dropShadowOffset = Submarine.HiddenSubPosition - Position;
if (dropShadowOffset != Vector2.Zero)
dropShadowOffset = DropShadowOffset;
if (dropShadowOffset == Vector2.Zero)
{
if (IsHorizontal)
if (Submarine == null)
{
dropShadowOffset = new Vector2(0.0f, Math.Sign(dropShadowOffset.Y) * 10.0f);
dropShadowOffset = Vector2.UnitY * 10.0f;
}
else
{
dropShadowOffset = new Vector2(Math.Sign(dropShadowOffset.X) * 10.0f, 0.0f);
dropShadowOffset = IsHorizontal ?
new Vector2(0.0f, Math.Sign(Submarine.HiddenSubPosition.Y - Position.Y) * 10.0f) :
new Vector2(Math.Sign(Submarine.HiddenSubPosition.X - Position.X) * 10.0f, 0.0f);
}
dropShadowOffset.Y = -dropShadowOffset.Y;
}
dropShadowOffset.Y = -dropShadowOffset.Y;
}
if (DrawTiled)
@@ -251,7 +252,7 @@ namespace Barotrauma
textureScale: TextureScale * Scale,
startOffset: backGroundOffset);
if (drawDropShadow)
if (UseDropShadow)
{
Prefab.BackgroundSprite.DrawTiled(
spriteBatch,
@@ -276,7 +277,7 @@ namespace Barotrauma
rotate: 0,
spriteEffect: SpriteEffects);
if (drawDropShadow)
if (UseDropShadow)
{
Prefab.BackgroundSprite.Draw(
spriteBatch,

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

@@ -39,25 +39,33 @@ namespace Barotrauma.Networking
public void UpdateSoundPosition()
{
if (VoipSound != null)
if (VoipSound == null) { return; }
if (!VoipSound.IsPlaying)
{
if (!VoipSound.IsPlaying)
{
DebugConsole.Log("Destroying voipsound");
VoipSound.Dispose();
VoipSound = null;
return;
}
DebugConsole.Log("Destroying voipsound");
VoipSound.Dispose();
VoipSound = null;
return;
}
if (character != null)
if (character != null)
{
if (GameMain.Config.UseDirectionalVoiceChat)
{
VoipSound.SetPosition(new Vector3(character.WorldPosition.X, character.WorldPosition.Y, 0.0f));
}
else
{
VoipSound.SetPosition(null);
float dist = Vector3.Distance(new Vector3(character.WorldPosition, 0.0f), GameMain.SoundManager.ListenerPosition);
VoipSound.Gain = 1.0f - MathUtils.InverseLerp(VoipSound.Near, VoipSound.Far, dist);
}
}
else
{
VoipSound.SetPosition(null);
}
}
partial void InitProjSpecific()

View File

@@ -1114,7 +1114,9 @@ namespace Barotrauma.Networking
if (campaign == null)
{
GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedSub, "", gameMode, missionIndex < 0 ? null : MissionPrefab.List[missionIndex]);
GameMain.GameSession = missionIndex < 0 ?
new GameSession(GameMain.NetLobbyScreen.SelectedSub, "", gameMode, MissionType.None) :
new GameSession(GameMain.NetLobbyScreen.SelectedSub, "", gameMode, MissionPrefab.List[missionIndex]);
GameMain.GameSession.StartRound(levelSeed, levelDifficulty, loadSecondSub);
}
else
@@ -1126,6 +1128,18 @@ namespace Barotrauma.Networking
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
}
for (int i = 0; i < Submarine.MainSubs.Length; i++)
{
if (!loadSecondSub && i > 0) { break; }
var teamID = i == 0 ? Character.TeamType.Team1 : Character.TeamType.Team2;
Submarine.MainSubs[i].TeamID = teamID;
foreach (Submarine sub in Submarine.MainSubs[i].DockedTo)
{
sub.TeamID = teamID;
}
}
if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
{
string errorMsg = "Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
@@ -2246,7 +2260,47 @@ namespace Barotrauma.Networking
public virtual void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
{
if (!gameStarted || Screen.Selected != GameMain.GameScreen || GUI.DisableHUD || GUI.DisableUpperHUD) return;
if (GUI.DisableHUD || GUI.DisableUpperHUD) return;
if (fileReceiver != null && fileReceiver.ActiveTransfers.Count > 0)
{
Vector2 downloadBarSize = new Vector2(250, 35) * GUI.Scale;
Vector2 pos = new Vector2(GameMain.NetLobbyScreen.InfoFrame.Rect.X, GameMain.GraphicsHeight - downloadBarSize.Y - 5);
GUI.DrawRectangle(spriteBatch, new Rectangle(
(int)pos.X,
(int)pos.Y,
(int)(fileReceiver.ActiveTransfers.Count * (downloadBarSize.X + 10)),
(int)downloadBarSize.Y),
Color.Black * 0.8f, true);
for (int i = 0; i < fileReceiver.ActiveTransfers.Count; i++)
{
var transfer = fileReceiver.ActiveTransfers[i];
GUI.DrawString(spriteBatch,
pos,
ToolBox.LimitString(TextManager.Get("DownloadingFile").Replace("[filename]", transfer.FileName), GUI.SmallFont, (int)downloadBarSize.X),
Color.White, null, 0, GUI.SmallFont);
GUI.DrawProgressBar(spriteBatch, new Vector2(pos.X, -pos.Y - downloadBarSize.Y / 2), new Vector2(downloadBarSize.X * 0.7f, downloadBarSize.Y / 2), transfer.Progress, Color.Green);
GUI.DrawString(spriteBatch, pos + new Vector2(5, downloadBarSize.Y / 2),
MathUtils.GetBytesReadable((long)transfer.Received) + " / " + MathUtils.GetBytesReadable((long)transfer.FileSize),
Color.White, null, 0, GUI.SmallFont);
if (GUI.DrawButton(spriteBatch, new Rectangle(
(int)(pos.X + downloadBarSize.X * 0.7f), (int)(pos.Y + downloadBarSize.Y / 2),
(int)(downloadBarSize.X * 0.3f), (int)(downloadBarSize.Y / 2)),
TextManager.Get("Cancel"), new Color(0.47f, 0.13f, 0.15f, 0.08f)))
{
CancelFileTransfer(transfer);
fileReceiver.StopTransfer(transfer);
}
pos.X += (downloadBarSize.X + 10);
}
}
if (!gameStarted || Screen.Selected != GameMain.GameScreen) return;
inGameHUD.DrawManually(spriteBatch);
@@ -2297,40 +2351,6 @@ namespace Barotrauma.Networking
}
}
if (fileReceiver != null && fileReceiver.ActiveTransfers.Count > 0)
{
Vector2 pos = new Vector2(GameMain.NetLobbyScreen.InfoFrame.Rect.X, GameMain.GraphicsHeight - 35);
GUI.DrawRectangle(spriteBatch, new Rectangle(
(int)pos.X,
(int)pos.Y,
fileReceiver.ActiveTransfers.Count * 210 + 10,
32),
Color.Black * 0.8f, true);
for (int i = 0; i < fileReceiver.ActiveTransfers.Count; i++)
{
var transfer = fileReceiver.ActiveTransfers[i];
GUI.DrawString(spriteBatch,
pos,
ToolBox.LimitString(TextManager.Get("DownloadingFile").Replace("[filename]", transfer.FileName), GUI.SmallFont, 200),
Color.White, null, 0, GUI.SmallFont);
GUI.DrawProgressBar(spriteBatch, new Vector2(pos.X, -pos.Y - 15), new Vector2(135, 15), transfer.Progress, Color.Green);
GUI.DrawString(spriteBatch, pos + new Vector2(5, 15),
MathUtils.GetBytesReadable((long)transfer.Received) + " / " + MathUtils.GetBytesReadable((long)transfer.FileSize),
Color.White, null, 0, GUI.SmallFont);
if (GUI.DrawButton(spriteBatch, new Rectangle((int)pos.X + 140, (int)pos.Y + 18, 60, 15), TextManager.Get("Cancel"), new Color(0.47f, 0.13f, 0.15f, 0.08f)))
{
CancelFileTransfer(transfer);
fileReceiver.StopTransfer(transfer);
}
pos.X += 210;
}
}
if (!ShowNetStats) return;
netStats.Draw(spriteBatch, new Rectangle(300, 10, 300, 150));

View File

@@ -59,17 +59,32 @@ namespace Barotrauma.Networking
return contentPackageHashes.SetEquals(myContentPackageHashes);
}
public void CreatePreviewWindow(GUIMessageBox messageBox)
public void CreatePreviewWindow(GUIListBox listBox)
{
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), messageBox.Content.RectTransform), ServerName, textAlignment: Alignment.Center, font: GUI.LargeFont, wrap: true);
listBox.ClearChildren();
var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), messageBox.Content.RectTransform));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, wrap: true);
if (listBox == null) return;
var columnContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), messageBox.Content.RectTransform), isHorizontal: true)
var previewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), listBox.Content.RectTransform, Anchor.Center))
{
Stretch = true
};
var titleHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.97f, 0.07f), previewContainer.RectTransform))
{
IsHorizontal = true,
Stretch = true
};
var title = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), titleHolder.RectTransform), ServerName, font: GUI.LargeFont, wrap: true);
new GUITextBlock(new RectTransform(Vector2.One, title.RectTransform),
TextManager.Get("ServerListVersion") + ": " + (string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion), textAlignment: Alignment.Right);
var columnContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), previewContainer.RectTransform), isHorizontal: true)
{
Stretch = true,
RelativeSpacing = 0.05f
RelativeSpacing = 0.005f
};
var columnLeft = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), columnContainer.RectTransform))
@@ -88,12 +103,72 @@ namespace Barotrauma.Networking
// left column -----------------------------------------------------------------------------
//new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnLeft.RectTransform), IP + ":" + Port);
new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnLeft.RectTransform),
TextManager.Get("ServerListVersion") + ": " + (string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), columnLeft.RectTransform),
var serverMsg = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), columnLeft.RectTransform)) { ScrollBarVisible = true };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverMsg.Content.RectTransform), ServerMessage, wrap: true) { CanBeFocused = false };
// right column -----------------------------------------------------------------------------
/*var playerCount = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListPlayers"));
new GUITextBlock(new RectTransform(Vector2.One, playerCount.RectTransform), PlayerCount + "/" + MaxPlayers, textAlignment: Alignment.Right);
new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), "Round running")
{
Selected = GameStarted,
CanBeFocused = false
};*/
var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("GameMode"));
new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform), TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : GameMode), textAlignment: Alignment.Right);
var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("Traitors"));
new GUITextBlock(new RectTransform(Vector2.One, traitors.RectTransform), TextManager.Get(!TraitorsEnabled.HasValue ? "Unknown" : TraitorsEnabled.Value.ToString()), textAlignment: Alignment.Right);
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListSubSelection"));
new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListModeSelection"));
new GUITextBlock(new RectTransform(Vector2.One, modeSelection.RectTransform), TextManager.Get(!ModeSelectionMode.HasValue ? "Unknown" : ModeSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListAllowSpectating"))
{
CanBeFocused = false
};
if (!AllowSpectating.HasValue)
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), allowSpectating.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
else
allowSpectating.Selected = AllowSpectating.Value;
var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerSettingsAllowRespawning"))
{
CanBeFocused = false
};
if (!AllowRespawn.HasValue)
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), allowRespawn.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
else
allowRespawn.Selected = AllowRespawn.Value;
/*new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListHasPassword"))
{
Selected = HasPassword,
CanBeFocused = false
};*/
var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListUsingWhitelist"))
{
CanBeFocused = false
};
if (!UsingWhiteList.HasValue)
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), usingWhiteList.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
else
usingWhiteList.Selected = UsingWhiteList.Value;
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), columnRight.RectTransform),
TextManager.Get("ServerListContentPackages"));
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), columnLeft.RectTransform));
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), columnRight.RectTransform));
if (ContentPackageNames.Count == 0)
{
new GUITextBlock(new RectTransform(Vector2.One, contentPackageList.Content.RectTransform), TextManager.Get("Unknown"), textAlignment: Alignment.Center)
@@ -143,7 +218,7 @@ namespace Barotrauma.Networking
}
}
}
if (availableWorkshopUrls.Count > 0 )
if (availableWorkshopUrls.Count > 0)
{
var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.15f), columnLeft.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages"))
{
@@ -159,64 +234,6 @@ namespace Barotrauma.Networking
workshopBtn.TextBlock.AutoScale = true;
}
}
// right column -----------------------------------------------------------------------------
var playerCount = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListPlayers"));
new GUITextBlock(new RectTransform(Vector2.One, playerCount.RectTransform), PlayerCount + "/" + MaxPlayers, textAlignment: Alignment.Right);
new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), "Round running")
{
Selected = GameStarted,
CanBeFocused = false
};
var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("GameMode"));
new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform), string.IsNullOrEmpty(GameMode) ? "Unknown" : GameMode, textAlignment: Alignment.Right);
var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("Traitors"));
new GUITextBlock(new RectTransform(Vector2.One, traitors.RectTransform), !TraitorsEnabled.HasValue ? "Unknown" : TraitorsEnabled.Value.ToString(), textAlignment: Alignment.Right);
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListSubSelection"));
new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), !SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString(), textAlignment: Alignment.Right);
var modeSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListModeSelection"));
new GUITextBlock(new RectTransform(Vector2.One, modeSelection.RectTransform), (!ModeSelectionMode.HasValue ? "Unknown" : ModeSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListAllowSpectating"))
{
CanBeFocused = false
};
if (!AllowSpectating.HasValue)
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), allowSpectating.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
else
allowSpectating.Selected = AllowSpectating.Value;
var allowRespawn = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), "Allow respawn")
{
CanBeFocused = false
};
if (!AllowRespawn.HasValue)
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), allowRespawn.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
else
allowRespawn.Selected = AllowRespawn.Value;
new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListHasPassword"))
{
Selected = HasPassword,
CanBeFocused = false
};
var usingWhiteList = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), columnRight.RectTransform), TextManager.Get("ServerListUsingWhitelist"))
{
CanBeFocused = false
};
if (!UsingWhiteList.HasValue)
new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.8f), usingWhiteList.Box.RectTransform, Anchor.Center), "?", textAlignment: Alignment.Center);
else
usingWhiteList.Selected = UsingWhiteList.Value;
// -----------------------------------------------------------------------------

View File

@@ -107,6 +107,56 @@ namespace Barotrauma.Steam
return true;
}
public static bool GetFavouriteServers(Action<Networking.ServerInfo> onServerFound, Action<Networking.ServerInfo> onServerRulesReceived, Action onFinished)
{
if (instance == null || !instance.isInitialized)
{
return false;
}
var filter = new ServerList.Filter
{
{ "appid", AppID.ToString() },
{ "gamedir", "Barotrauma" },
{ "secure", "1" }
};
//include unresponsive servers in the server list
//the response is queried using the server's query port, not the game port,
//so it may be possible to play on the server even if it doesn't respond to server list queries
var query = instance.client.ServerList.Favourites(filter);
query.OnUpdate += () => { UpdateServerQuery(query, onServerFound, onServerRulesReceived, includeUnresponsive: true); };
query.OnFinished = onFinished;
return true;
}
public static bool GetServersFromHistory(Action<Networking.ServerInfo> onServerFound, Action<Networking.ServerInfo> onServerRulesReceived, Action onFinished)
{
if (instance == null || !instance.isInitialized)
{
return false;
}
var filter = new ServerList.Filter
{
{ "appid", AppID.ToString() },
{ "gamedir", "Barotrauma" },
{ "secure", "1" }
};
//include unresponsive servers in the server list
//the response is queried using the server's query port, not the game port,
//so it may be possible to play on the server even if it doesn't respond to server list queries
var query = instance.client.ServerList.History(filter);
query.OnUpdate += () => { UpdateServerQuery(query, onServerFound, onServerRulesReceived, includeUnresponsive: true); };
query.OnFinished = onFinished;
return true;
}
private static void UpdateServerQuery(ServerList.Request query, Action<Networking.ServerInfo> onServerFound, Action<Networking.ServerInfo> onServerRulesReceived, bool includeUnresponsive)
{
IEnumerable<ServerList.Server> servers = includeUnresponsive ?
@@ -548,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

@@ -9,12 +9,9 @@ namespace Barotrauma
{
class CampaignUI
{
public enum Tab { Map, Crew, Store }
public enum Tab { Map, Crew, Store, Repair }
private Tab selectedTab;
private GUIFrame[] tabs;
private GUIButton startButton;
private GUIFrame topPanel;
private GUIListBox characterList;
@@ -26,6 +23,8 @@ namespace Barotrauma
private GUIComponent selectedLocationInfo;
private GUIListBox selectedMissionInfo;
private GUIButton repairHullsButton, repairItemsButton;
private GUIFrame characterPreviewFrame;
private List<GUIButton> tabButtons = new List<GUIButton>();
@@ -39,10 +38,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; }
@@ -112,7 +108,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
@@ -157,7 +153,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
@@ -218,6 +214,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)
@@ -330,8 +417,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; }
@@ -349,8 +435,7 @@ namespace Barotrauma
{
//refresh store view
SelectItemCategory(MapEntityCategory.Equipment);
}
}
}
private void DrawMap(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
@@ -452,7 +537,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,
@@ -461,7 +546,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));
}
@@ -508,10 +593,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);
}
@@ -597,8 +682,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))
{
@@ -616,8 +700,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))
{
@@ -659,6 +742,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)
@@ -668,8 +765,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;
@@ -707,9 +803,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)
@@ -761,11 +856,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;
@@ -784,11 +877,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

@@ -261,7 +261,7 @@ namespace Barotrauma
public NetLobbyScreen()
{
defaultModeContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), Frame.RectTransform, Anchor.Center), style: null);
defaultModeContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), Frame.RectTransform, Anchor.Center) { MaxSize = new Point(int.MaxValue, GameMain.GraphicsHeight - 100) }, style: null);
campaignContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.75f), Frame.RectTransform, Anchor.TopCenter), style: null)
{
Visible = false
@@ -737,11 +737,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

@@ -57,32 +57,20 @@ namespace Barotrauma
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), paddedFrame.RectTransform, Anchor.CenterLeft)) { Stretch = true, RelativeSpacing = 0.5f };
menu = new GUIFrame(new RectTransform(new Point(width, height), GUI.Canvas, Anchor.Center));
var infoHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), leftColumn.RectTransform)) { RelativeSpacing = 0.05f };
new GUITextBlock(new RectTransform(new Vector2(0.95f, 0.133f), menu.RectTransform, Anchor.TopCenter),
TextManager.Get("JoinServer"), textAlignment: Alignment.Left, font: GUI.LargeFont) { ForceUpperCase = true };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), infoHolder.RectTransform, Anchor.Center), TextManager.Get("JoinServer"), font: GUI.LargeFont)
{ ForceUpperCase = true };
var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), menu.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.03f) }, style: null);
//-------------------------------------------------------------------------------------
//left column
//-------------------------------------------------------------------------------------
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 0.92f), paddedFrame.RectTransform, Anchor.TopLeft));
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("YourName"));
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.045f), leftColumn.RectTransform), "")
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoHolder.RectTransform), TextManager.Get("YourName"));
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), infoHolder.RectTransform), "")
{
Text = GameMain.Config.DefaultPlayerName
};
clientNameBox.OnTextChanged += RefreshJoinButtonState;
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("ServerIP"));
// TODO: Show IP on server info window
ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.045f), leftColumn.RectTransform), "");
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoHolder.RectTransform), TextManager.Get("ServerIP"));
ipBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), infoHolder.RectTransform), "");
ipBox.OnTextChanged += RefreshJoinButtonState;
ipBox.OnSelected += (sender, key) =>
{
@@ -92,31 +80,81 @@ namespace Barotrauma
sender.UserData = null;
}
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.45f), leftColumn.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterServers"));
searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), "");
var filterHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), leftColumn.RectTransform)) { RelativeSpacing = 0.05f };
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), leftColumn.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), filterHolder.RectTransform), TextManager.Get("FilterServers"));
searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.13f), filterHolder.RectTransform), "");
var tickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), filterHolder.RectTransform));
searchBox.OnTextChanged += (txtBox, txt) => { FilterServers(); return true; };
filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterPassword"));
filterPassword = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterPassword"));
filterPassword.OnSelected += (tickBox) => { FilterServers(); return true; };
filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterIncompatibleServers"));
filterIncompatible = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterIncompatibleServers"));
filterIncompatible.OnSelected += (tickBox) => { FilterServers(); return true; };
filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterFullServers"));
filterFull = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterFullServers"));
filterFull.OnSelected += (tickBox) => { FilterServers(); return true; };
filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("FilterEmptyServers"));
filterEmpty = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.27f), tickBoxHolder.RectTransform), TextManager.Get("FilterEmptyServers"));
filterEmpty.OnSelected += (tickBox) => { FilterServers(); return true; };
//-------------------------------------------------------------------------------------
//right column
//-------------------------------------------------------------------------------------
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - leftColumn.RectTransform.RelativeSize.X - 0.017f, 1.0f),
paddedFrame.RectTransform, Anchor.CenterRight))
{
RelativeSpacing = 0.02f,
Stretch = true
};
var serverListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform)) { Stretch = true, RelativeSpacing = 0.02f };
serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform, Anchor.Center))
{
OnSelected = (btn, obj) => {
ServerInfo serverInfo = (ServerInfo)obj;
serverInfo.CreatePreviewWindow(serverPreview);
return true;
}
};
serverList.OnSelected += SelectServer;
serverPreview = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListHolder.RectTransform, Anchor.Center));
columnRelativeWidth = new float[] { 0.04f, 0.02f, 0.044f, 0.77f, 0.02f, 0.075f, 0.06f };
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.075f), rightColumn.RectTransform), style: null);
GUIButton button = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform, Anchor.TopLeft),
TextManager.Get("Back"), style: "GUIButtonLarge")
{
OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu
};
var refreshButton = new GUIButton(new RectTransform(new Vector2(buttonContainer.Rect.Height / (float)buttonContainer.Rect.Width, 0.9f), buttonContainer.RectTransform, Anchor.Center),
"", style: "GUIButtonRefresh") {
ToolTip = TextManager.Get("ServerListRefresh"),
OnClicked = RefreshServers
};
joinButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.9f), buttonContainer.RectTransform, Anchor.TopRight),
TextManager.Get("ServerListJoin"), style: "GUIButtonLarge")
{
OnClicked = JoinServer,
Enabled = false
};
//-------------------------------------------------------------------------------------
//right column
//-------------------------------------------------------------------------------------
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - leftColumn.RectTransform.RelativeSize.X - 0.017f, 0.97f),
paddedFrame.RectTransform, Anchor.TopRight))
{
@@ -360,7 +398,7 @@ namespace Barotrauma
private void AddToServerList(ServerInfo serverInfo)
{
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 20) },
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) },
style: "InnerFrame", color: Color.White * 0.5f)
{
UserData = serverInfo
@@ -398,19 +436,6 @@ namespace Barotrauma
UserData = "password"
};
new GUIButton(new RectTransform(new Vector2(columnRelativeWidth[2], 0.8f), serverContent.RectTransform, Anchor.Center), style: "GUIButtonServerListInfo") {
ToolTip = TextManager.Get("ServerListInfo"),
OnClicked = (btn, obj) => {
SelectServer(null, serverInfo);
var msgBox = new GUIMessageBox("", "", new string[] { TextManager.Get("Cancel"), TextManager.Get("ServerListJoin") }, 550, 400);
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked += JoinServer;
msgBox.Buttons[1].OnClicked += msgBox.Close;
serverInfo.CreatePreviewWindow(msgBox);
return true;
}
};
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[3], 1.0f), serverContent.RectTransform), serverInfo.ServerName, style: "GUIServerListTextBox");
var gameStartedBox = new GUITickBox(new RectTransform(new Vector2(columnRelativeWidth[4], 0.4f), serverContent.RectTransform, Anchor.Center),

View File

@@ -43,6 +43,7 @@ namespace Barotrauma
private ContentPackage itemContentPackage;
private Facepunch.Steamworks.Workshop.Editor itemEditor;
//private Facepunch.Steamworks.Overlay overlay;
public SteamWorkshopScreen()
{
@@ -637,6 +638,12 @@ namespace Barotrauma
OutlineColor = new Color(72, 124, 77, 255),
OnClicked = (btn, userdata) =>
{
// Failed attempt, might have to be activated before accessing because as of now it just throws a null for overlay
/*if (overlay.Enabled)
{
overlay.OpenUrl("steam://url/CommunityFilePage/" + item.Id);
}*/
System.Diagnostics.Process.Start("steam://url/CommunityFilePage/" + item.Id);
return true;
}

View File

@@ -310,6 +310,12 @@ namespace Barotrauma
RelativeSpacing = 0.01f,
Stretch = true
};
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), tabButtonHolder.RectTransform), TextManager.Get("MapEntityCategory.All"), style: "GUITabButton")
{
OnClicked = (btn, userdata) => { ClearFilter(); return true; }
};
foreach (MapEntityCategory category in Enum.GetValues(typeof(MapEntityCategory)))
{
entityCategoryButtons.Add(new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), tabButtonHolder.RectTransform),
@@ -1011,7 +1017,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

@@ -32,6 +32,9 @@ namespace Barotrauma.Sounds
public bool UseRadioFilter;
public bool UseMuffleFilter;
public float Near { get; private set; }
public float Far { get; private set; }
private static BiQuad[] muffleFilters = new BiQuad[]
{
new LowpassFilter(VoipConfig.FREQUENCY, 800)
@@ -41,6 +44,16 @@ namespace Barotrauma.Sounds
new BandpassFilter(VoipConfig.FREQUENCY, 2000)
};
public float Gain
{
get { return soundChannel == null ? 0.0f : soundChannel.Gain; }
set
{
if (soundChannel == null) { return; }
soundChannel.Gain = value;
}
}
public VoipSound(SoundManager owner, VoipQueue q) : base(owner, "voip", true, true)
{
VoipConfig.SetupEncoding();
@@ -64,8 +77,8 @@ namespace Barotrauma.Sounds
public void SetRange(float near, float far)
{
soundChannel.Near = near;
soundChannel.Far = far;
soundChannel.Near = Near = near;
soundChannel.Far = Far = far;
}
public void ApplyFilters(short[] buffer, int readSamples)

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

@@ -360,7 +360,7 @@ namespace Barotrauma
Vector2 relativeCursorPos = cursorPosition - AimRefPosition;
tempBuffer.Write((UInt16)(65535.0 * Math.Atan2(relativeCursorPos.Y, relativeCursorPos.X) / (2.0 * Math.PI)));
}
tempBuffer.Write(IsRagdolled);
tempBuffer.Write(IsRagdolled || IsUnconscious || Stun > 0.0f || IsDead);
tempBuffer.Write(AnimController.Dir > 0.0f);
}

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

@@ -1754,11 +1754,10 @@ namespace Barotrauma.Networking
Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage);
}
}
bool missionAllowRespawn = campaign == null &&
(!(GameMain.GameSession.GameMode is MissionMode) ||
((MissionMode)GameMain.GameSession.GameMode).Mission.AllowRespawn);
MissionMode missionMode = GameMain.GameSession.GameMode as MissionMode;
bool missionAllowRespawn = campaign == null && (missionMode?.Mission == null || missionMode.Mission.AllowRespawn);
if (serverSettings.AllowRespawn && missionAllowRespawn) respawnManager = new RespawnManager(this, usingShuttle ? selectedShuttle : null);
@@ -1767,6 +1766,12 @@ namespace Barotrauma.Networking
{
var teamID = n == 0 ? Character.TeamType.Team1 : Character.TeamType.Team2;
Submarine.MainSubs[n].TeamID = teamID;
foreach (Submarine sub in Submarine.MainSubs[n].DockedTo)
{
sub.TeamID = teamID;
}
//find the clients in this team
List<Client> teamClients = teamCount == 1 ?
new List<Client>(connectedClients) :
@@ -1935,10 +1940,8 @@ namespace Barotrauma.Networking
MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
bool missionAllowRespawn = campaign == null &&
(!(GameMain.GameSession.GameMode is MissionMode) ||
((MissionMode)GameMain.GameSession.GameMode).Mission.AllowRespawn);
MissionMode missionMode = GameMain.GameSession.GameMode as MissionMode;
bool missionAllowRespawn = campaign == null && (missionMode?.Mission == null || missionMode.Mission.AllowRespawn);
msg.Write(serverSettings.AllowRespawn && missionAllowRespawn);
msg.Write(Submarine.MainSubs[1] != null); //loadSecondSub

View File

@@ -10,9 +10,7 @@ namespace Barotrauma.Networking
class ServerEntityEvent : NetEntityEvent
{
private IServerSerializable serializable;
public bool Sent;
#if DEBUG
public string StackTrace;
#endif

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>
@@ -357,6 +361,81 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Effects\waterbump.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<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>
@@ -591,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">
@@ -1301,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">
@@ -1568,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">
@@ -1580,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">
@@ -1592,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">
@@ -1928,6 +2004,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>

View File

@@ -12,6 +12,8 @@ namespace Barotrauma
{
partial class EnemyAIController : AIController
{
public static bool DisableEnemyAI;
class WallTarget
{
public Vector2 Position;
@@ -249,7 +251,7 @@ namespace Barotrauma
}
}
public TargetingPriority GetTargetingPriority(string targetTag)
private TargetingPriority GetTargetingPriority(string targetTag)
{
if (targetingPriorities.TryGetValue(targetTag, out TargetingPriority priority))
{
@@ -485,7 +487,7 @@ namespace Barotrauma
}
else
{
if (!IsProperlyLatched)
if (!IsProperlyLatchedOnSub)
{
UpdateWallTarget();
}
@@ -1001,7 +1003,7 @@ namespace Barotrauma
private void UpdateEating(float deltaTime)
{
if (SelectedAiTarget == null)
if (SelectedAiTarget == null) //SelectedAiTarget.Entity is Character c && !c.IsDead
{
State = AIState.Idle;
return;
@@ -1038,14 +1040,14 @@ namespace Barotrauma
#region Targeting
private bool IsProperlyLatched => LatchOntoAI != null && LatchOntoAI.IsAttached && 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
public AITarget UpdateTargets(Character character, out TargetingPriority priority)
{
if (IsProperlyLatched)
if (IsProperlyLatchedOnSub)
{
// If attached to a valid target, just keep the target.
// Priority not used in this case.

View File

@@ -267,7 +267,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);
}
}
}
@@ -286,7 +286,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;
}
}
}
}
@@ -414,20 +426,12 @@ namespace Barotrauma
if (!nextNode.Waypoint.ConnectedDoor.HasRequiredItems(character, false)) { 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;
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

@@ -54,6 +54,8 @@ namespace Barotrauma
get { return attachJoints.Count > 0; }
}
public bool IsAttachedToSub => IsAttached && attachTargetBody?.UserData is Entity entity && (entity is Submarine sub || entity?.Submarine != null);
public LatchOntoAI(XElement element, EnemyAIController enemyAI)
{
attachToWalls = element.GetAttributeBool("attachtowalls", false);
@@ -207,10 +209,10 @@ namespace Barotrauma
break;
}
if (attachTargetBody != null && deattachTimer < 0.0f)
if (IsAttached && attachTargetBody != null && deattachTimer < 0.0f)
{
Entity entity = attachTargetBody.UserData as Entity;
Submarine attachedSub = entity is Submarine ? (Submarine)entity : entity?.Submarine;
Submarine attachedSub = entity is Submarine sub ? sub : entity?.Submarine;
if (attachedSub != null)
{
float velocity = attachedSub.Velocity == Vector2.Zero ? 0.0f : attachedSub.Velocity.Length();

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)
{
@@ -235,6 +238,7 @@ namespace Barotrauma
{
if (Vector2.DistanceSquared(character.Position, Enemy.Position) <= meleeWeapon.Range * meleeWeapon.Range)
{
character.SetInput(InputType.Shoot, false, true);
Weapon.Use(deltaTime, character);
}
}
@@ -264,6 +268,7 @@ namespace Barotrauma
}
if (target != null && target == Enemy)
{
character.SetInput(InputType.Shoot, false, true);
Weapon.Use(deltaTime, character);
}
}
@@ -275,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

@@ -527,7 +527,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)
{
@@ -556,13 +561,17 @@ 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;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f;
float footMid = colliderPos.X;
if (limpAmount > 0.0f)
{
//make the footpos oscillate when limping
footMid += ((float)Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * 0.3f);
}
movement = overrideTargetMovement == Vector2.Zero ?
MathUtils.SmoothStep(movement, TargetMovement, movementLerp) :
@@ -576,7 +585,7 @@ namespace Barotrauma
movement.Y = 0.0f;
if (torso == null) { return; }
bool isNotRemote = true;
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) isNotRemote = !character.IsRemotePlayer;
@@ -680,7 +689,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

@@ -692,7 +692,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)
{
@@ -721,7 +721,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

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

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.

View File

@@ -255,8 +255,10 @@ namespace Barotrauma
commands.Add(new Command("disablecrewai", "disablecrewai: Disable the AI of the NPCs in the crew.", (string[] args) =>
{
ThrowError("Karma has not been fully implemented yet, and is disabled in this version of Barotrauma.");
return;
HumanAIController.DisableCrewAI = true;
NewMessage("Crew AI disabled", Color.Red);
// This is probably not where it should be?
//ThrowError("Karma has not been fully implemented yet, and is disabled in this version of Barotrauma.");
/*if (GameMain.Server == null) return;
GameMain.Server.KarmaEnabled = !GameMain.Server.KarmaEnabled;*/
}));
@@ -264,7 +266,19 @@ namespace Barotrauma
commands.Add(new Command("enablecrewai", "enablecrewai: Enable the AI of the NPCs in the crew.", (string[] args) =>
{
HumanAIController.DisableCrewAI = false;
NewMessage("Crew AI enabled", Color.White);
NewMessage("Crew AI enabled", Color.Green);
}, isCheat: true));
commands.Add(new Command("disableenemyai", "disableenemyai: Disable the AI of the Enemy characters (monsters).", (string[] args) =>
{
EnemyAIController.DisableEnemyAI = true;
NewMessage("Enemy AI disabled", Color.Red);
}, isCheat: true));
commands.Add(new Command("enableenemyai", "enableenemyai: Enable the AI of the Enemy characters (monsters).", (string[] args) =>
{
EnemyAIController.DisableEnemyAI = false;
NewMessage("Enemy AI enabled", Color.Green);
}, isCheat: true));
commands.Add(new Command("botcount", "botcount [x]: Set the number of bots in the crew in multiplayer.", null));

View File

@@ -209,6 +209,7 @@ namespace Barotrauma
//isActive = false;
bool spawnReady = false;
if (spawnPending)
{
//wait until there are no submarines at the spawnpos
@@ -219,25 +220,31 @@ namespace Barotrauma
if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos) < minDist * minDist) return;
}
spawnPending = false;
//+1 because Range returns an integer less than the max value
int amount = Rand.Range(minAmount, maxAmount + 1, Rand.RandSync.Server);
monsters = new Character[amount];
monsters = new List<Character>();
float offsetAmount = spawnPosType == Level.PositionType.MainPath ? 1000 : 100;
for (int i = 0; i < amount; i++)
{
bool isClient = false;
{
CoroutineManager.InvokeAfter(() =>
{
bool isClient = false;
#if CLIENT
isClient = GameMain.Client != null;
isClient = GameMain.Client != null;
#endif
monsters[i] = Character.Create(
characterFile, spawnPos + Rand.Vector(100.0f, Rand.RandSync.Server),
i.ToString(), null, isClient, true, true);
monsters.Add(Character.Create(characterFile, spawnPos + Rand.Vector(offsetAmount, Rand.RandSync.Server), i.ToString(), null, isClient, true, true));
if (monsters.Count == amount)
{
spawnReady = true;
}
}, Rand.Range(0f, amount / 2, Rand.RandSync.Server));
}
spawnPending = false;
}
if (!spawnReady) { return; }
Entity targetEntity = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter);
#if CLIENT
if (Character.Controlled != null) targetEntity = (Entity)Character.Controlled;

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

@@ -44,6 +44,7 @@ namespace Barotrauma
public bool ChromaticAberrationEnabled { get; set; }
public bool MuteOnFocusLost { get; set; }
public bool UseDirectionalVoiceChat { get; set; }
public enum VoiceMode
{
@@ -149,6 +150,9 @@ namespace Barotrauma
public bool EnableMouseLook { get; set; } = true;
public bool CrewMenuOpen { get; set; } = true;
public bool ChatOpen { get; set; } = true;
private bool unsavedSettings;
public bool UnsavedSettings
{
@@ -826,6 +830,8 @@ namespace Barotrauma
SoundVolume = audioSettings.GetAttributeFloat("soundvolume", SoundVolume);
MusicVolume = audioSettings.GetAttributeFloat("musicvolume", MusicVolume);
VoiceChatVolume = audioSettings.GetAttributeFloat("voicechatvolume", VoiceChatVolume);
MuteOnFocusLost = audioSettings.GetAttributeBool("muteonfocuslost", false);
UseDirectionalVoiceChat = audioSettings.GetAttributeBool("usedirectionalvoicechat", true);
string voiceSettingStr = audioSettings.GetAttributeString("voicesetting", "Disabled");
VoiceCaptureDevice = audioSettings.GetAttributeString("voicecapturedevice", "");
NoiseGateThreshold = audioSettings.GetAttributeFloat("noisegatethreshold", -45);
@@ -844,6 +850,9 @@ namespace Barotrauma
AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", AimAssistAmount);
EnableMouseLook = doc.Root.GetAttributeBool("enablemouselook", EnableMouseLook);
CrewMenuOpen = doc.Root.GetAttributeBool("crewmenuopen", CrewMenuOpen);
ChatOpen = doc.Root.GetAttributeBool("chatopen", ChatOpen);
foreach (XElement subElement in doc.Root.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -1019,7 +1028,9 @@ namespace Barotrauma
new XAttribute("requiresteamauthentication", requireSteamAuthentication),
new XAttribute("autoupdateworkshopitems", AutoUpdateWorkshopItems),
new XAttribute("aimassistamount", aimAssistAmount),
new XAttribute("enablemouselook", EnableMouseLook));
new XAttribute("enablemouselook", EnableMouseLook),
new XAttribute("chatopen", ChatOpen),
new XAttribute("crewmenuopen", CrewMenuOpen));
if (!ShowUserStatisticsPrompt)
{
@@ -1055,6 +1066,8 @@ namespace Barotrauma
audio.ReplaceAttributes(
new XAttribute("musicvolume", musicVolume),
new XAttribute("soundvolume", soundVolume),
new XAttribute("muteonfocuslost", MuteOnFocusLost),
new XAttribute("usedirectionalvoicechat", UseDirectionalVoiceChat),
new XAttribute("voicesetting", VoiceSetting),
new XAttribute("voicecapturedevice", VoiceCaptureDevice ?? ""),
new XAttribute("noisegatethreshold", NoiseGateThreshold));

View File

@@ -56,7 +56,7 @@ namespace Barotrauma
switch (SlotTypes[i])
{
//case InvSlotType.Head:
case InvSlotType.OuterClothes:
//case InvSlotType.OuterClothes:
case InvSlotType.LeftHand:
case InvSlotType.RightHand:
hideEmptySlot[i] = true;
@@ -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

@@ -221,29 +221,64 @@ namespace Barotrauma.Items.Components
{
if (item.Condition <= RepairThreshold) return true; //For repairing
var idCard = character.Inventory.FindItemByIdentifier("idcard");
hasValidIdCard = requiredItems.Any(ri => ri.Value.Any(r => r.MatchesItem(idCard)));
Msg = requiredItems.None() || hasValidIdCard ? "ItemMsgOpen" : "ItemMsgForceOpenCrowbar";
ParseMsg();
if (addMessage)
{
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.
return requiredItems.Any() ? base.HasRequiredItems(character, addMessage, msg) : canBePicked;
}
public override bool Pick(Character picker)
{
return item.Condition <= RepairThreshold ? true : base.Pick(picker);
if (item.Condition <= RepairThreshold) { return true; }
if (requiredItems.None()) { return false; }
if (HasRequiredItems(picker, false) && hasValidIdCard) { return false; }
return base.Pick(picker);
}
public override bool OnPicked(Character picker)
{
if (item.Condition <= RepairThreshold) return true; //repairs
if (requiredItems.Any() && !hasValidIdCard)
{
ForceOpen(ActionType.OnPicked);
}
return false;
}
private void ForceOpen(ActionType actionType)
{
SetState(PredictedState == null ? !isOpen : !PredictedState.Value, false, true); //crowbar function
#if CLIENT
PlaySound(ActionType.OnPicked, item.WorldPosition, picker);
PlaySound(actionType, item.WorldPosition, picker);
#endif
}
public override bool Select(Character character)
{
//can only be selected if the item is broken
return item.Condition <= RepairThreshold;
if (item.Condition <= RepairThreshold) return true; //repairs
bool hasRequiredItems = HasRequiredItems(character, false);
if (requiredItems.None() || hasRequiredItems && hasValidIdCard)
{
float originalPickingTime = PickingTime;
PickingTime = 0;
ForceOpen(ActionType.OnUse);
PickingTime = originalPickingTime;
}
else if (hasRequiredItems)
{
#if CLIENT
GUI.AddMessage(accessDeniedTxt, Color.Red);
#endif
}
return false;
}
public override void Update(float deltaTime, Camera cam)

View File

@@ -34,6 +34,20 @@ namespace Barotrauma.Items.Components
}
}
public override bool IsActive
{
get { return base.IsActive; }
set
{
base.IsActive = value;
if (!value)
{
nodes.Clear();
charactersInRange.Clear();
}
}
}
[Serialize(100.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 5000.0f)]
public float Range
{
@@ -126,14 +140,19 @@ namespace Barotrauma.Items.Components
}
else
{
nodes.Clear();
charactersInRange.Clear();
IsActive = false;
}
voltage = 0.0f;
}
public override void UpdateBroken(float deltaTime, Camera cam)
{
base.UpdateBroken(deltaTime, cam);
nodes.Clear();
charactersInRange.Clear();
}
private void Discharge()
{
ApplyStatusEffects(ActionType.OnUse, 1.0f);

View File

@@ -58,13 +58,6 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(true, true)]
public bool Aimable
{
get;
set;
}
[Serialize(false, false)]
public bool ControlPose
{

View File

@@ -11,6 +11,12 @@ namespace Barotrauma.Items.Components
{
private float lastSentDeattachTimer;
private PhysicsBody trigger;
private Holdable holdable;
private float deattachTimer;
[Serialize(1.0f, false)]
public float DeattachDuration
{
@@ -49,13 +55,7 @@ namespace Barotrauma.Items.Components
#endif
}
}
private PhysicsBody trigger;
private Holdable holdable;
private float deattachTimer;
public LevelResource(Item item, XElement element) : base(item, element)
{
IsActive = true;

View File

@@ -142,8 +142,6 @@ namespace Barotrauma.Items.Components
pickTimer / requiredTime,
Color.Red, Color.Green);
#endif
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
picker.AnimController.UpdateUseItem(true, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
pickTimer += CoroutineManager.DeltaTime;

View File

@@ -322,6 +322,7 @@ namespace Barotrauma.Items.Components
// If the character is climbing, ignore the check, because we cannot aim while climbing.
if (VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak) < MathHelper.PiOver4)
{
character.SetInput(InputType.Shoot, false, true);
Use(deltaTime, character);
}
else
@@ -337,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;
@@ -538,7 +538,6 @@ namespace Barotrauma.Items.Components
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
return 0.0f;
}
float average = skillSuccessSum / requiredSkills.Count;
float skillSuccessSum = 0.0f;
for (int i = 0; i < requiredSkills.Count; i++)
@@ -555,7 +554,7 @@ namespace Barotrauma.Items.Components
public virtual void FlipY(bool relativeToSub) { }
public bool HasRequiredContainedItems(bool addMessage)
public bool HasRequiredContainedItems(bool addMessage, string msg = null)
{
if (!requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) return true;
if (item.OwnInventory == null) return false;
@@ -582,33 +581,52 @@ namespace Barotrauma.Items.Components
{
if (!requiredItems.Any()) return true;
if (character.Inventory == null) return false;
bool hasRequiredItems = false;
bool canContinue = true;
if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped))
{
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Equipped])
{
if (character.SelectedItems.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null)
canContinue = CheckItems(ri, character.SelectedItems);
if (!canContinue) { break; }
}
}
if (canContinue)
{
if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked))
{
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked])
{
#if CLIENT
if (addMessage && !string.IsNullOrEmpty(ri.Msg)) GUI.AddMessage(ri.Msg, Color.Red);
#endif
return false;
if (!CheckItems(ri, character.Inventory.Items)) { break; }
}
}
}
if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked))
{
foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked])
{
if (character.Inventory.Items.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null)
{
#if CLIENT
if (!hasRequiredItems && addMessage && !string.IsNullOrEmpty(msg))
{
GUI.AddMessage(msg, Color.Red);
}
#endif
return false;
return hasRequiredItems;
bool CheckItems(RelatedItem relatedItem, IEnumerable<Item> itemList)
{
bool Predicate(Item it) => it != null && it.Condition > 0.0f && relatedItem.MatchesItem(it);
bool shouldBreak = false;
if (relatedItem.IsOptional)
{
if (!hasRequiredItems)
{
hasRequiredItems = itemList.Any(Predicate);
}
}
else
{
hasRequiredItems = itemList.Any(Predicate);
if (!hasRequiredItems)
{
shouldBreak = true;
}
}
if (!hasRequiredItems)
@@ -620,8 +638,6 @@ namespace Barotrauma.Items.Components
}
return !shouldBreak;
}
return true;
}
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Character user = null)
@@ -766,6 +782,7 @@ namespace Barotrauma.Items.Components
{
newRequiredItem.statusEffects = prevRequiredItem.statusEffects;
newRequiredItem.Msg = prevRequiredItem.Msg;
newRequiredItem.IsOptional = prevRequiredItem.IsOptional;
}
if (!requiredItems.ContainsKey(newRequiredItem.Type))

View File

@@ -343,5 +343,7 @@ namespace Barotrauma.Items.Components
limbPositions[i] = new LimbPos(limbPositions[i].limbType, flippedPos);
}
}
partial void HideHUDs(bool value);
}
}

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

@@ -801,7 +801,12 @@ namespace Barotrauma
if (findNewHull) FindHull();
}
partial void SetActiveSprite();
public void SetActiveSprite()
{
SetActiveSpriteProjSpecific();
}
partial void SetActiveSpriteProjSpecific();
public override void Move(Vector2 amount)
{
@@ -1432,13 +1437,13 @@ namespace Barotrauma
selectHit = picker.IsKeyHit(ic.SelectKey);
#if CLIENT
//if the cursor is on a UI component, disable interaction with the left mouse button
//to prevent accidentally selecting items when clicking UI elements
if (picker == Character.Controlled && GUI.MouseOn != null)
{
if (GameMain.Config.KeyBind(ic.PickKey).MouseButton == 0) pickHit = false;
if (GameMain.Config.KeyBind(ic.SelectKey).MouseButton == 0) selectHit = false;
}
//if the cursor is on a UI component, disable interaction with the left mouse button
//to prevent accidentally selecting items when clicking UI elements
if (picker == Character.Controlled && GUI.MouseOn != null)
{
if (GameMain.Config.KeyBind(ic.PickKey).MouseButton == 0) pickHit = false;
if (GameMain.Config.KeyBind(ic.SelectKey).MouseButton == 0) selectHit = false;
}
#endif
}
}
@@ -1608,6 +1613,7 @@ namespace Barotrauma
if (remove) { Spawner?.AddToRemoveQueue(this); }
}
List<ColoredText> texts = new List<ColoredText>();
public List<ColoredText> GetHUDTexts(Character character)
{
texts.Clear();
@@ -1617,6 +1623,13 @@ namespace Barotrauma
if (!ic.CanBePicked && !ic.CanBeSelected) continue;
if (ic is Holdable holdable && !holdable.CanBeDeattached()) continue;
Color color = Color.Gray;
bool hasRequiredSkillsAndItems = ic.HasRequiredSkills(character) && ic.HasRequiredItems(character, false);
if (hasRequiredSkillsAndItems)
{
color = Color.Cyan;
}
texts.Add(new ColoredText(ic.DisplayMsg, color, false));
}
@@ -2054,6 +2067,8 @@ namespace Barotrauma
public virtual void Reset()
{
SerializableProperties = SerializableProperty.DeserializeProperties(this, Prefab.ConfigElement);
Sprite.ReloadXML();
SpriteDepth = Sprite.Depth;
components.ForEach(c => c.Reset());
}

View File

@@ -621,10 +621,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

@@ -16,6 +16,8 @@ namespace Barotrauma
Container
}
public bool IsOptional { get; set; }
private string[] identifiers;
private string[] excludedIdentifiers;
@@ -138,7 +140,8 @@ namespace Barotrauma
{
element.Add(
new XAttribute("identifiers", JoinedIdentifiers),
new XAttribute("type", type.ToString()));
new XAttribute("type", type.ToString()),
new XAttribute("optional", IsOptional));
if (excludedIdentifiers.Length > 0)
{

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

@@ -144,6 +144,20 @@ namespace Barotrauma
get { return spriteColor; }
set { spriteColor = value; }
}
[Editable, Serialize(false, true)]
public bool UseDropShadow
{
get;
private set;
}
[Serialize("0,0", true), Editable(ToolTip = "The position of the drop shadow relative to the structure. If set to zero, the shadow is positioned automatically so that it points towards the sub's center of mass.")]
public Vector2 DropShadowOffset
{
get;
private set;
}
public override Rectangle Rect
{
@@ -299,8 +313,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);
}
@@ -1139,6 +1153,13 @@ namespace Barotrauma
if (element.GetAttributeBool("flippedx", false)) s.FlipX(false);
if (element.GetAttributeBool("flippedy", false)) s.FlipY(false);
SerializableProperty.DeserializeProperties(s, element);
//structures with a body drop a shadow by default
if (element.Attribute("usedropshadow") == null)
{
s.UseDropShadow = prefab.Body;
}
return s;
}

View File

@@ -194,7 +194,14 @@ namespace Barotrauma
break;
case "backgroundsprite":
sp.BackgroundSprite = new Sprite(subElement, lazyLoad: true);
if (subElement.Attribute("sourcerect") == null && sp.sprite != null)
{
sp.BackgroundSprite.SourceRect = sp.sprite.SourceRect;
sp.BackgroundSprite.size = sp.sprite.size;
sp.BackgroundSprite.size.X *= sp.sprite.SourceRect.Width;
sp.BackgroundSprite.size.Y *= sp.sprite.SourceRect.Height;
sp.BackgroundSprite.RelativeOrigin = subElement.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f));
}
if (subElement.GetAttributeBool("fliphorizontal", false))
sp.BackgroundSprite.effects = SpriteEffects.FlipHorizontally;
if (subElement.GetAttributeBool("flipvertical", false))

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)

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

@@ -44,6 +44,7 @@ namespace Barotrauma
base.Deselect();
#if CLIENT
GameMain.Config.SaveNewPlayerConfig();
GameMain.SoundManager.SetCategoryMuffle("default", false);
GUI.ClearMessages();
#endif

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,6 +252,28 @@ namespace Barotrauma
return null;
}
public static List<KeyValuePair<string, string>> GetAllTagTextPairs()
{
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<KeyValuePair<string, string>> allText = new List<KeyValuePair<string, string>>();
foreach (TextPack textPack in textPacks[Language])
{
allText.AddRange(textPack.GetAllTagTextPairs());
}
return allText;
}
public static string ReplaceGenderPronouns(string text, Gender gender)
{
if (gender == Gender.Male)

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