Build 0.18.5.0
This commit is contained in:
@@ -266,7 +266,7 @@ namespace Barotrauma
|
||||
disguisedSkinColor = idCard.StoredOwnerAppearance.SkinColor;
|
||||
}
|
||||
|
||||
partial void LoadAttachmentSprites(bool omitJob)
|
||||
partial void LoadAttachmentSprites()
|
||||
{
|
||||
if (attachmentSprites == null)
|
||||
{
|
||||
@@ -280,14 +280,6 @@ namespace Barotrauma
|
||||
Head.BeardElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Beard)));
|
||||
Head.MoustacheElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Moustache)));
|
||||
Head.HairElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Hair)));
|
||||
if (omitJob)
|
||||
{
|
||||
JobPrefab.NoJobElement?.GetChildElement("PortraitClothing")?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Job?.Prefab.ClothingElement?.GetChildElements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
|
||||
}
|
||||
}
|
||||
|
||||
// Doesn't work if the head's source rect does not start at 0,0.
|
||||
|
||||
@@ -651,6 +651,8 @@ namespace Barotrauma
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
GameMain.LightManager.LosAlpha = 1f;
|
||||
|
||||
GameMain.NetLobbyScreen.CampaignCharacterDiscarded = false;
|
||||
|
||||
character.memInput.Clear();
|
||||
character.memState.Clear();
|
||||
character.memLocalState.Clear();
|
||||
|
||||
@@ -172,6 +172,7 @@ namespace Barotrauma
|
||||
isOpen = false;
|
||||
GUI.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
|
||||
if (isOpen)
|
||||
@@ -209,7 +210,7 @@ namespace Barotrauma
|
||||
isOpen = !isOpen;
|
||||
if (isOpen)
|
||||
{
|
||||
textBox.Select();
|
||||
textBox.Select(ignoreSelectSound: true);
|
||||
AddToGUIUpdateList();
|
||||
}
|
||||
else
|
||||
@@ -217,6 +218,7 @@ namespace Barotrauma
|
||||
GUI.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
}
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
|
||||
private static bool IsCommandPermitted(string command, GameClient client)
|
||||
|
||||
@@ -81,6 +81,8 @@ namespace Barotrauma
|
||||
public const int ToggleButtonWidthRaw = 30;
|
||||
private int popupMessageOffset;
|
||||
|
||||
private GUIDropDown ChatModeDropDown { get; set; }
|
||||
|
||||
public ChatBox(GUIComponent parent, bool isSinglePlayer)
|
||||
{
|
||||
this.IsSinglePlayer = isSinglePlayer;
|
||||
@@ -226,7 +228,53 @@ namespace Barotrauma
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
InputBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft),
|
||||
var bottomContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.125f), hideableElements.RectTransform, Anchor.BottomLeft), isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var dropdownRt = new RectTransform(new Vector2(0.1f, 1.0f), bottomContainer.RectTransform)
|
||||
{
|
||||
// The chat mode selection dropdown will take a maximum of 45% of the horizontal space
|
||||
MaxSize = new Point((int)(0.45f * bottomContainer.RectTransform.NonScaledSize.X), int.MaxValue)
|
||||
};
|
||||
var chatModes = new ChatMode[] { ChatMode.Local, ChatMode.Radio };
|
||||
ChatModeDropDown = new GUIDropDown(dropdownRt, elementCount: chatModes.Length, dropAbove: true)
|
||||
{
|
||||
OnSelected = (component, userdata) =>
|
||||
{
|
||||
GameMain.ActiveChatMode = (ChatMode)userdata;
|
||||
if (InputBox != null && InputBox.Text.StartsWith(RadioChatString) && GameMain.ActiveChatMode == ChatMode.Local)
|
||||
{
|
||||
string text = InputBox.Text;
|
||||
InputBox.Text = text.Remove(0, RadioChatString.Length);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
float longestDropDownOption = 0.0f;
|
||||
foreach (ChatMode mode in chatModes)
|
||||
{
|
||||
var text = TextManager.Get($"chatmode.{mode}");
|
||||
ChatModeDropDown.AddItem(text, userData: mode);
|
||||
if (ChatModeDropDown.ListBox.Content.GetChildByUserData(mode) is GUITextBlock textBlock)
|
||||
{
|
||||
if (textBlock.TextSize.X > longestDropDownOption)
|
||||
{
|
||||
longestDropDownOption = textBlock.TextSize.X;
|
||||
}
|
||||
}
|
||||
}
|
||||
ChatModeDropDown.SelectItem(GameMain.ActiveChatMode);
|
||||
|
||||
float minDropDownWidth = longestDropDownOption + ChatModeDropDown.Padding.X +
|
||||
(ChatModeDropDown.DropDownIcon?.RectTransform.NonScaledSize.X ?? 0) +
|
||||
(ChatModeDropDown.DropDownIcon?.RectTransform.AbsoluteOffset.X ?? 0) * 2;
|
||||
ChatModeDropDown.RectTransform.MinSize = new Point(
|
||||
Math.Max((int)minDropDownWidth, ChatModeDropDown.RectTransform.MinSize.X),
|
||||
ChatModeDropDown.RectTransform.MinSize.Y);
|
||||
|
||||
InputBox = new GUITextBox(new RectTransform(new Vector2(0.9f, 1.0f), bottomContainer.RectTransform),
|
||||
style: "ChatTextBox")
|
||||
{
|
||||
OverflowClip = true,
|
||||
@@ -248,8 +296,6 @@ namespace Barotrauma
|
||||
CloseAfterMessageSent = false;
|
||||
}
|
||||
}
|
||||
|
||||
//gui.Text = "";
|
||||
};
|
||||
|
||||
var chatSendButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.7f), InputBox.RectTransform, Anchor.CenterRight, scaleBasis: ScaleBasis.BothHeight), style: "GUIButtonToggleRight");
|
||||
@@ -306,6 +352,10 @@ namespace Barotrauma
|
||||
{
|
||||
textColor = ChatMessage.MessageColor[(int)ChatMessageType.Private];
|
||||
}
|
||||
else if (GameMain.ActiveChatMode == ChatMode.Radio)
|
||||
{
|
||||
textColor = ChatMessage.MessageColor[(int)ChatMessageType.Radio];
|
||||
}
|
||||
else
|
||||
{
|
||||
textColor = ChatMessage.MessageColor[(int)ChatMessageType.Default];
|
||||
@@ -550,6 +600,25 @@ namespace Barotrauma
|
||||
showNewMessagesButton.Visible = false;
|
||||
}
|
||||
|
||||
if (PlayerInput.KeyHit(InputType.ToggleChatMode) && GUI.KeyboardDispatcher.Subscriber == null && Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mode = GameMain.ActiveChatMode switch
|
||||
{
|
||||
ChatMode.Local => ChatMode.Radio,
|
||||
ChatMode.Radio => ChatMode.Local,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
ChatModeDropDown.SelectItem(mode);
|
||||
// TODO: Play a sound?
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error toggling chat mode: not implemented for current mode \"{GameMain.ActiveChatMode}\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (ToggleButton != null)
|
||||
{
|
||||
ToggleButton.Selected = ToggleOpen;
|
||||
@@ -700,5 +769,70 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplySelectionInputs() => ApplySelectionInputs(InputBox, true, ChatKeyStates.GetChatKeyStates());
|
||||
|
||||
public struct ChatKeyStates
|
||||
{
|
||||
public bool ActiveChatKeyHit { get; set; }
|
||||
public bool LocalChatKeyHit { get; set; }
|
||||
public bool RadioChatKeyHit { get; set; }
|
||||
public bool AnyHit => ActiveChatKeyHit || LocalChatKeyHit || RadioChatKeyHit;
|
||||
|
||||
private ChatKeyStates(bool active, bool local, bool radio)
|
||||
{
|
||||
ActiveChatKeyHit = active;
|
||||
LocalChatKeyHit = local;
|
||||
RadioChatKeyHit = radio;
|
||||
}
|
||||
|
||||
public static ChatKeyStates GetChatKeyStates()
|
||||
{
|
||||
return new ChatKeyStates(PlayerInput.KeyHit(InputType.ActiveChat),
|
||||
PlayerInput.KeyHit(InputType.Chat),
|
||||
PlayerInput.KeyHit(InputType.RadioChat) && (Character.Controlled == null || Character.Controlled.SpeechImpediment < 100));
|
||||
}
|
||||
|
||||
public (bool active, bool local, bool radio) Deconstruct()
|
||||
{
|
||||
return (ActiveChatKeyHit, LocalChatKeyHit, RadioChatKeyHit);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplySelectionInputs(GUITextBox inputBox, bool selectInputBox, ChatKeyStates chatKeyStates)
|
||||
{
|
||||
inputBox ??= InputBox;
|
||||
var (activeChatKeyHit, localChatKeyHit, radioChatKeyHit) = chatKeyStates.Deconstruct();
|
||||
if (localChatKeyHit || (activeChatKeyHit && GameMain.ActiveChatMode == ChatMode.Local))
|
||||
{
|
||||
ChatModeDropDown.SelectItem(ChatMode.Local);
|
||||
inputBox.AddToGUIUpdateList();
|
||||
GUIFrame.Flash(Color.DarkGreen, 0.5f);
|
||||
if (!ToggleOpen)
|
||||
{
|
||||
CloseAfterMessageSent = !ToggleOpen;
|
||||
ToggleOpen = true;
|
||||
}
|
||||
if (selectInputBox)
|
||||
{
|
||||
inputBox.Select(inputBox.Text.Length);
|
||||
}
|
||||
}
|
||||
else if (radioChatKeyHit || (activeChatKeyHit && GameMain.ActiveChatMode == ChatMode.Radio))
|
||||
{
|
||||
ChatModeDropDown.SelectItem(ChatMode.Radio);
|
||||
inputBox.AddToGUIUpdateList();
|
||||
GUIFrame.Flash(Color.YellowGreen, 0.5f);
|
||||
if (!ToggleOpen)
|
||||
{
|
||||
CloseAfterMessageSent = !ToggleOpen;
|
||||
ToggleOpen = true;
|
||||
}
|
||||
if (selectInputBox)
|
||||
{
|
||||
inputBox.Select(inputBox.Text.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,10 @@ namespace Barotrauma
|
||||
Width = null;
|
||||
Height = null;
|
||||
GetSize(Element);
|
||||
foreach (var childStyle in ChildStyles.Values)
|
||||
{
|
||||
childStyle.RefreshSize();
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSize(XElement element)
|
||||
|
||||
@@ -356,7 +356,7 @@ namespace Barotrauma
|
||||
GUIStyle.Green, Color.Black * 0.8f, font: GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
GameMain.PerformanceCounter.DrawTimeGraph.Draw(spriteBatch, new Rectangle((int)x, (int)y, 170, 50), color: GUIStyle.Green);
|
||||
y += yStep * 3;
|
||||
y += yStep * 4;
|
||||
|
||||
DrawString(spriteBatch, new Vector2(x, y),
|
||||
"Update - Avg: " + GameMain.PerformanceCounter.UpdateTimeGraph.Average().ToString("0.00") + " ms" +
|
||||
@@ -364,39 +364,33 @@ namespace Barotrauma
|
||||
Color.LightBlue, Color.Black * 0.8f, font: GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
GameMain.PerformanceCounter.UpdateTimeGraph.Draw(spriteBatch, new Rectangle((int)x, (int)y, 170, 50), color: Color.LightBlue);
|
||||
y += yStep * 3;
|
||||
foreach (string key in GameMain.PerformanceCounter.GetSavedIdentifiers)
|
||||
y += yStep * 4;
|
||||
foreach (string key in GameMain.PerformanceCounter.GetSavedIdentifiers.OrderBy(i => i))
|
||||
{
|
||||
float elapsedMillisecs = GameMain.PerformanceCounter.GetAverageElapsedMillisecs(key);
|
||||
DrawString(spriteBatch, new Vector2(x, y),
|
||||
key + ": " + elapsedMillisecs.ToString("0.00"),
|
||||
Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
foreach (string childKey in GameMain.PerformanceCounter.GetSavedPartialIdentifiers(key))
|
||||
{
|
||||
elapsedMillisecs = GameMain.PerformanceCounter.GetPartialAverageElapsedMillisecs(key, childKey);
|
||||
DrawString(spriteBatch, new Vector2(x + 15, y),
|
||||
childKey + ": " + elapsedMillisecs.ToString("0.00"),
|
||||
Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
}
|
||||
}
|
||||
|
||||
int categoryDepth = key.Count(c => c == ':');
|
||||
//color the more fine-grained counters red more easily (ok for the whole Update to take a longer time than specific part of the update)
|
||||
float runningSlowThreshold = 10.0f / categoryDepth;
|
||||
DrawString(spriteBatch, new Vector2(x + categoryDepth * 15, y),
|
||||
key.Split(':').Last() + ": " + elapsedMillisecs.ToString("0.00"),
|
||||
ToolBox.GradientLerp(elapsedMillisecs / runningSlowThreshold, Color.LightGreen, GUIStyle.Yellow, GUIStyle.Orange, GUIStyle.Red, Color.Magenta), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
}
|
||||
if (Powered.Grids != null)
|
||||
{
|
||||
DrawString(spriteBatch, new Vector2(x, y), "Grids: " + Powered.Grids.Count, Color.LightGreen, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
y += yStep;
|
||||
}
|
||||
|
||||
if (Settings.EnableDiagnostics)
|
||||
{
|
||||
x += yStep * 2;
|
||||
DrawString(spriteBatch, new Vector2(x, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 2), "AddRemoveTime: " + GameMain.World.AddRemoveTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.AddRemoveTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 3), "NewContactsTime: " + GameMain.World.NewContactsTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.NewContactsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 4), "ContactsUpdateTime: " + GameMain.World.ContactsUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContactsUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 5), "SolveUpdateTime: " + GameMain.World.SolveUpdateTime.TotalMilliseconds, Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.SolveUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y), "ContinuousPhysicsTime: " + GameMain.World.ContinuousPhysicsTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContinuousPhysicsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep), "ControllersUpdateTime: " + GameMain.World.ControllersUpdateTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ControllersUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 2), "AddRemoveTime: " + GameMain.World.AddRemoveTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.AddRemoveTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 3), "NewContactsTime: " + GameMain.World.NewContactsTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.NewContactsTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 4), "ContactsUpdateTime: " + GameMain.World.ContactsUpdateTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.ContactsUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
DrawString(spriteBatch, new Vector2(x, y + yStep * 5), "SolveUpdateTime: " + GameMain.World.SolveUpdateTime.TotalMilliseconds.ToString("0.00"), Color.Lerp(Color.LightGreen, GUIStyle.Red, (float)GameMain.World.SolveUpdateTime.TotalMilliseconds / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,11 @@ namespace Barotrauma
|
||||
set { textBlock.SelectedTextColor = value; }
|
||||
}
|
||||
|
||||
public Color DisabledTextColor
|
||||
{
|
||||
get { return textBlock.DisabledTextColor; }
|
||||
}
|
||||
|
||||
public override float FlashTimer
|
||||
{
|
||||
get { return Frame.FlashTimer; }
|
||||
|
||||
@@ -160,6 +160,10 @@ namespace Barotrauma
|
||||
listBox.ToolTip = value;
|
||||
}
|
||||
}
|
||||
|
||||
public GUIImage DropDownIcon => icon;
|
||||
|
||||
public Vector4 Padding => button.TextBlock.Padding;
|
||||
|
||||
public GUIDropDown(RectTransform rectT, LocalizedString text = null, int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false, Alignment textAlignment = Alignment.CenterLeft) : base(style, rectT)
|
||||
{
|
||||
|
||||
@@ -352,7 +352,7 @@ namespace Barotrauma
|
||||
caretPosDirty = false;
|
||||
}
|
||||
|
||||
public void Select(int forcedCaretIndex = -1)
|
||||
public void Select(int forcedCaretIndex = -1, bool ignoreSelectSound = false)
|
||||
{
|
||||
skipUpdate = true;
|
||||
if (memento.Current == null)
|
||||
@@ -362,10 +362,11 @@ namespace Barotrauma
|
||||
CaretIndex = forcedCaretIndex == - 1 ? textBlock.GetCaretIndexFromScreenPos(PlayerInput.MousePosition) : forcedCaretIndex;
|
||||
CalculateCaretPos();
|
||||
ClearSelection();
|
||||
bool wasSelected = selected;
|
||||
selected = true;
|
||||
GUI.KeyboardDispatcher.Subscriber = this;
|
||||
OnSelected?.Invoke(this, Keys.None);
|
||||
if (PlaySoundOnSelect)
|
||||
if (!wasSelected && PlaySoundOnSelect && !ignoreSelectSound)
|
||||
{
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -122,7 +123,17 @@ namespace Barotrauma
|
||||
|
||||
//horizontal slices at the corners of the screen for health bar and affliction icons
|
||||
int afflictionAreaHeight = (int)(50 * GUI.Scale);
|
||||
int healthBarWidth = (int)(BottomRightInfoArea.Width * 1.3f);
|
||||
int healthBarWidth = BottomRightInfoArea.Width;
|
||||
|
||||
var healthBarChildStyles = GUIStyle.GetComponentStyle("CharacterHealthBar")?.ChildStyles;
|
||||
if (healthBarChildStyles!= null && healthBarChildStyles.TryGetValue("GUIFrame".ToIdentifier(), out var style))
|
||||
{
|
||||
if (style.Sprites.TryGetValue(GUIComponent.ComponentState.None, out var uiSprites) && uiSprites.FirstOrDefault() is { } uiSprite)
|
||||
{
|
||||
// The default health bar uses a sliced sprite so let's make sure the health bar area is calculated accordingly
|
||||
healthBarWidth += (int)(uiSprite.NonSliceSize.X * Math.Min(GUI.Scale, 1f));
|
||||
}
|
||||
}
|
||||
int healthBarHeight = (int)(50f * GUI.Scale);
|
||||
HealthBarArea = new Rectangle(BottomRightInfoArea.Right - healthBarWidth + (int)Math.Floor(1 / GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + GUI.IntScale(10), healthBarWidth, healthBarHeight);
|
||||
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
|
||||
|
||||
@@ -2208,7 +2208,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
updateStopwatch.Stop();
|
||||
GameMain.PerformanceCounter.AddPartialElapsedTicks("GameSessionUpdate", "StoreUpdate", updateStopwatch.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:GameSession:Store", updateStopwatch.ElapsedTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1858,14 +1858,18 @@ namespace Barotrauma
|
||||
});
|
||||
|
||||
GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), talentInfoLayoutGroup.RectTransform)) { RelativeSpacing = 0.05f };
|
||||
|
||||
|
||||
Vector2 nameSize = GUIStyle.SubHeadingFont.MeasureString(info.Name);
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUIStyle.SubHeadingFont) { TextColor = job.Prefab.UIColor };
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUIStyle.SubHeadingFont);
|
||||
nameBlock.RectTransform.NonScaledSize = nameSize.Pad(nameBlock.Padding).ToPoint();
|
||||
|
||||
Vector2 jobSize = GUIStyle.SmallFont.MeasureString(job.Name);
|
||||
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUIStyle.SmallFont) { TextColor = job.Prefab.UIColor };
|
||||
jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint();
|
||||
if (!info.OmitJobInMenus)
|
||||
{
|
||||
nameBlock.TextColor = job.Prefab.UIColor;
|
||||
Vector2 jobSize = GUIStyle.SmallFont.MeasureString(job.Name);
|
||||
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUIStyle.SmallFont) { TextColor = job.Prefab.UIColor };
|
||||
jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint();
|
||||
}
|
||||
|
||||
LocalizedString traitString = TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + info.PersonalityTrait.Name.Replace(" ", "")));
|
||||
Vector2 traitSize = GUIStyle.SmallFont.MeasureString(traitString);
|
||||
@@ -1876,7 +1880,8 @@ namespace Barotrauma
|
||||
|
||||
if (!(GameMain.NetworkMember is null))
|
||||
{
|
||||
GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), talentsOutsideTreeFrame.RectTransform, Anchor.TopLeft), text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
|
||||
GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), talentsOutsideTreeFrame.RectTransform, Anchor.TopLeft),
|
||||
text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
|
||||
{
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
@@ -1915,7 +1920,7 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
GameMain.Client?.SendCharacterInfo();
|
||||
GameMain.Client?.SendCharacterInfo(GameMain.Client.PendingName);
|
||||
characterSettingsFrame!.Visible = false;
|
||||
talentFrameMain.Visible = true;
|
||||
return true;
|
||||
|
||||
@@ -27,6 +27,11 @@ namespace Barotrauma
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The size of fixed area around the slice area
|
||||
/// </summary>
|
||||
public Point NonSliceSize { get; set; }
|
||||
|
||||
public bool MaintainAspectRatio
|
||||
{
|
||||
get;
|
||||
@@ -72,6 +77,7 @@ namespace Barotrauma
|
||||
maxBorderScale = element.GetAttributeFloat("minborderscale", 10.0f);
|
||||
|
||||
Rectangle slice = new Rectangle((int)sliceVec.X, (int)sliceVec.Y, (int)(sliceVec.Z - sliceVec.X), (int)(sliceVec.W - sliceVec.Y));
|
||||
NonSliceSize = new Point(Sprite.SourceRect.Width - slice.Width, Sprite.SourceRect.Height - slice.Height);
|
||||
|
||||
Slices = new Rectangle[9];
|
||||
|
||||
|
||||
@@ -202,6 +202,8 @@ namespace Barotrauma
|
||||
public static bool CancelQuickStart;
|
||||
#endif
|
||||
|
||||
public static ChatMode ActiveChatMode { get; set; } = ChatMode.Radio;
|
||||
|
||||
public GameMain(string[] args)
|
||||
{
|
||||
Content.RootDirectory = "Content";
|
||||
@@ -924,7 +926,7 @@ namespace Barotrauma
|
||||
updateCount++;
|
||||
|
||||
sw.Stop();
|
||||
PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks);
|
||||
PerformanceCounter.AddElapsedTicks("Update", sw.ElapsedTicks);
|
||||
PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
|
||||
}
|
||||
|
||||
@@ -1026,7 +1028,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks);
|
||||
PerformanceCounter.AddElapsedTicks("Draw", sw.ElapsedTicks);
|
||||
PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,9 +147,10 @@ namespace Barotrauma
|
||||
string msgCommand = ChatMessage.GetChatMessageCommand(text, out string msg);
|
||||
// add to local history
|
||||
ChatBox.ChatManager.Store(text);
|
||||
WifiComponent headset = null;
|
||||
ChatMessageType messageType =
|
||||
((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled, out headset)) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
bool isUsingRadioMode = GameMain.ActiveChatMode == ChatMode.Radio;
|
||||
bool containsRadioCommand = msgCommand == "r" || msgCommand == "radio";
|
||||
bool canUseRadio = ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent headset);
|
||||
ChatMessageType messageType = ((isUsingRadioMode && msgCommand == "") || containsRadioCommand) && canUseRadio ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
AddSinglePlayerChatMessage(
|
||||
Character.Controlled.Info.Name,
|
||||
msg, messageType,
|
||||
@@ -1553,40 +1554,9 @@ namespace Barotrauma
|
||||
{
|
||||
ChatBox.Update(deltaTime);
|
||||
ChatBox.InputBox.Visible = Character.Controlled != null;
|
||||
|
||||
if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible && GUI.KeyboardDispatcher.Subscriber == null)
|
||||
if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible && GUI.KeyboardDispatcher.Subscriber == null && !ChatBox.InputBox.Selected)
|
||||
{
|
||||
if (PlayerInput.KeyHit(InputType.Chat) && !ChatBox.InputBox.Selected)
|
||||
{
|
||||
ChatBox.InputBox.AddToGUIUpdateList();
|
||||
ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
|
||||
if (!ChatBox.ToggleOpen)
|
||||
{
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
ChatBox.ToggleOpen = true;
|
||||
}
|
||||
ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length);
|
||||
}
|
||||
|
||||
if (PlayerInput.KeyHit(InputType.RadioChat) && !ChatBox.InputBox.Selected)
|
||||
{
|
||||
if (Character.Controlled == null || Character.Controlled.SpeechImpediment < 100)
|
||||
{
|
||||
ChatBox.InputBox.AddToGUIUpdateList();
|
||||
ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
|
||||
if (!ChatBox.ToggleOpen)
|
||||
{
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
ChatBox.ToggleOpen = true;
|
||||
}
|
||||
|
||||
if (!ChatBox.InputBox.Text.StartsWith(ChatBox.RadioChatString))
|
||||
{
|
||||
ChatBox.InputBox.Text = ChatBox.RadioChatString;
|
||||
}
|
||||
ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length);
|
||||
}
|
||||
}
|
||||
ChatBox.ApplySelectionInputs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (CrewManager.ChatBox != null)
|
||||
{
|
||||
CrewManager.ChatBox.Update(deltaTime);
|
||||
}
|
||||
|
||||
CrewManager.ChatBox?.Update(deltaTime);
|
||||
CrewManager.UpdateReports();
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,31 @@ namespace Barotrauma.Items.Components
|
||||
corners[2] = center + new Vector2(shadowSize.X, shadowSize.Y) / 2;
|
||||
corners[3] = center + new Vector2(shadowSize.X, -shadowSize.Y) / 2;
|
||||
|
||||
if (IsHorizontal)
|
||||
{
|
||||
if (item.FlippedX)
|
||||
{
|
||||
Vector2 itemCenter = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2);
|
||||
for (int i = 0; i < corners.Length; i++)
|
||||
{
|
||||
corners[i].X = itemCenter.X * 2 - corners[i].X;
|
||||
}
|
||||
Array.Reverse(corners);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.FlippedY)
|
||||
{
|
||||
Vector2 itemCenter = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2);
|
||||
for (int i = 0; i < corners.Length; i++)
|
||||
{
|
||||
corners[i].Y = itemCenter.Y * 2 - corners[i].Y;
|
||||
}
|
||||
Array.Reverse(corners);
|
||||
}
|
||||
}
|
||||
|
||||
return corners;
|
||||
}
|
||||
|
||||
@@ -163,69 +188,67 @@ namespace Barotrauma.Items.Components
|
||||
if (stuck > 0.0f && weldedSprite != null)
|
||||
{
|
||||
Vector2 weldSpritePos = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2.0f) + shakePos;
|
||||
if (item.Submarine != null) weldSpritePos += item.Submarine.DrawPosition;
|
||||
if (item.Submarine != null) { weldSpritePos += item.Submarine.DrawPosition; }
|
||||
weldSpritePos.Y = -weldSpritePos.Y;
|
||||
|
||||
weldedSprite.Draw(spriteBatch,
|
||||
weldSpritePos, item.SpriteColor * (stuck / 100.0f), scale: item.Scale);
|
||||
}
|
||||
|
||||
if (openState >= 1.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (openState >= 1.0f) { return; }
|
||||
|
||||
Vector2 pos;
|
||||
if (IsHorizontal)
|
||||
{
|
||||
Vector2 pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2) + shakePos;
|
||||
if (item.Submarine != null) pos += item.Submarine.DrawPosition;
|
||||
pos.Y = -pos.Y;
|
||||
|
||||
if (brokenSprite == null || !IsBroken)
|
||||
{
|
||||
spriteBatch.Draw(doorSprite.Texture, pos,
|
||||
new Rectangle((int) (doorSprite.SourceRect.X + doorSprite.size.X * openState),
|
||||
(int) doorSprite.SourceRect.Y,
|
||||
(int) (doorSprite.size.X * (1.0f - openState)), (int) doorSprite.size.Y),
|
||||
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
||||
}
|
||||
|
||||
if (brokenSprite != null && item.Health < item.MaxCondition)
|
||||
{
|
||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.MaxCondition) : Vector2.One;
|
||||
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
|
||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||
new Rectangle((int)(brokenSprite.SourceRect.X + brokenSprite.size.X * openState), brokenSprite.SourceRect.Y,
|
||||
(int)(brokenSprite.size.X * (1.0f - openState)), (int)brokenSprite.size.Y),
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None,
|
||||
brokenSprite.Depth);
|
||||
}
|
||||
pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2);
|
||||
if (item.FlippedX) { pos.X += (int)(doorSprite.size.X * item.Scale * openState); }
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 pos = new Vector2(item.Rect.Center.X, item.Rect.Y) + shakePos;
|
||||
if (item.Submarine != null) pos += item.Submarine.DrawPosition;
|
||||
pos.Y = -pos.Y;
|
||||
|
||||
if (brokenSprite == null || !IsBroken)
|
||||
{
|
||||
spriteBatch.Draw(doorSprite.Texture, pos,
|
||||
new Rectangle(doorSprite.SourceRect.X,
|
||||
(int) (doorSprite.SourceRect.Y + doorSprite.size.Y * openState),
|
||||
(int) doorSprite.size.X, (int) (doorSprite.size.Y * (1.0f - openState))),
|
||||
color, 0.0f, doorSprite.Origin, item.Scale, SpriteEffects.None, doorSprite.Depth);
|
||||
}
|
||||
|
||||
if (brokenSprite != null && item.Health < item.MaxCondition)
|
||||
{
|
||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f - item.Health / item.MaxCondition, 1.0f) : Vector2.One;
|
||||
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
|
||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||
new Rectangle(brokenSprite.SourceRect.X, (int)(brokenSprite.SourceRect.Y + brokenSprite.size.Y * openState),
|
||||
(int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))),
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None, brokenSprite.Depth);
|
||||
}
|
||||
pos = new Vector2(item.Rect.Center.X, item.Rect.Y);
|
||||
if (item.FlippedY) { pos.Y -= (int)(doorSprite.size.Y * item.Scale * openState); }
|
||||
}
|
||||
|
||||
pos += shakePos;
|
||||
if (item.Submarine != null) { pos += item.Submarine.DrawPosition; }
|
||||
pos.Y = -pos.Y;
|
||||
|
||||
if (brokenSprite == null || !IsBroken)
|
||||
{
|
||||
spriteBatch.Draw(doorSprite.Texture, pos,
|
||||
getSourceRect(doorSprite, openState, IsHorizontal),
|
||||
color, 0.0f, doorSprite.Origin, item.Scale, item.SpriteEffects, doorSprite.Depth);
|
||||
}
|
||||
|
||||
if (brokenSprite != null && item.Health < item.MaxCondition)
|
||||
{
|
||||
Vector2 scale = scaleBrokenSprite ? new Vector2(1.0f, 1.0f - item.Health / item.MaxCondition) : Vector2.One;
|
||||
float alpha = fadeBrokenSprite ? 1.0f - item.Health / item.MaxCondition : 1.0f;
|
||||
spriteBatch.Draw(brokenSprite.Texture, pos,
|
||||
getSourceRect(brokenSprite, openState, IsHorizontal),
|
||||
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, item.SpriteEffects,
|
||||
brokenSprite.Depth);
|
||||
}
|
||||
|
||||
static Rectangle getSourceRect(Sprite sprite, float openState, bool horizontal)
|
||||
{
|
||||
if (horizontal)
|
||||
{
|
||||
return new Rectangle(
|
||||
(int)(sprite.SourceRect.X + sprite.size.X * openState),
|
||||
sprite.SourceRect.Y,
|
||||
(int)(sprite.size.X * (1.0f - openState)),
|
||||
(int)sprite.size.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Rectangle(
|
||||
sprite.SourceRect.X,
|
||||
(int)(sprite.SourceRect.Y + sprite.size.Y * openState),
|
||||
(int)sprite.size.X,
|
||||
(int)(sprite.size.Y * (1.0f - openState)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnFailedToOpen()
|
||||
|
||||
@@ -116,12 +116,6 @@ namespace Barotrauma.Items.Components
|
||||
loadAttachments(Attachments, disguisedBeardElement, WearableType.Beard);
|
||||
loadAttachments(Attachments, disguisedMoustacheElement, WearableType.Moustache);
|
||||
loadAttachments(Attachments, disguisedHairElement, WearableType.Hair);
|
||||
|
||||
loadAttachments(Attachments,
|
||||
characterInfo.OmitJobInPortraitClothing
|
||||
? JobPrefab.NoJobElement?.GetChildElement("PortraitClothing")
|
||||
: JobPrefab?.ClothingElement,
|
||||
WearableType.JobIndicator);
|
||||
}
|
||||
|
||||
HairColor = hairColor;
|
||||
|
||||
@@ -1,55 +1,61 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.RuinGeneration;
|
||||
using Barotrauma.Sounds;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class Submarine : Entity, IServerPositionSync
|
||||
{
|
||||
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
|
||||
{
|
||||
Vector2 position = PlayerInput.MousePosition;
|
||||
position = cam.ScreenToWorld(position);
|
||||
|
||||
Vector2 worldGridPos = VectorToWorldGrid(position);
|
||||
|
||||
if (sub != null)
|
||||
{
|
||||
worldGridPos.X += sub.Position.X % GridSize.X;
|
||||
worldGridPos.Y += sub.Position.Y % GridSize.Y;
|
||||
}
|
||||
|
||||
return worldGridPos;
|
||||
}
|
||||
|
||||
//drawing ----------------------------------------------------
|
||||
private static readonly HashSet<Submarine> visibleSubs = new HashSet<Submarine>();
|
||||
|
||||
private static double prevCullTime;
|
||||
private static Rectangle prevCullArea;
|
||||
/// <summary>
|
||||
/// Interval at which we force culled entites to be updated, regardless if the camera has moved
|
||||
/// </summary>
|
||||
private const float CullInterval = 0.25f;
|
||||
/// <summary>
|
||||
/// Margin applied around the view area when culling entities (i.e. entities that are this far outside the view are still considered visible)
|
||||
/// </summary>
|
||||
private const int CullMargin = 500;
|
||||
/// <summary>
|
||||
/// Update entity culling when any corner of the view has moved more than this
|
||||
/// </summary>
|
||||
private const int CullMoveThreshold = 50;
|
||||
|
||||
public static void CullEntities(Camera cam)
|
||||
{
|
||||
Rectangle camView = cam.WorldView;
|
||||
camView = new Rectangle(camView.X - CullMargin, camView.Y + CullMargin, camView.Width + CullMargin * 2, camView.Height + CullMargin * 2);
|
||||
|
||||
if (Math.Abs(camView.X - prevCullArea.X) < CullMoveThreshold &&
|
||||
Math.Abs(camView.Y - prevCullArea.Y) < CullMoveThreshold &&
|
||||
Math.Abs(camView.Right - prevCullArea.Right) < CullMoveThreshold &&
|
||||
Math.Abs(camView.Bottom - prevCullArea.Bottom) < CullMoveThreshold &&
|
||||
prevCullTime > Timing.TotalTime - CullInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
visibleSubs.Clear();
|
||||
foreach (Submarine sub in Loaded)
|
||||
{
|
||||
if (Level.Loaded != null && sub.WorldPosition.Y < Level.MaxEntityDepth) { continue; }
|
||||
|
||||
int margin = 500;
|
||||
Rectangle worldBorders = new Rectangle(
|
||||
sub.VisibleBorders.X + (int)sub.WorldPosition.X - margin,
|
||||
sub.VisibleBorders.Y + (int)sub.WorldPosition.Y + margin,
|
||||
sub.VisibleBorders.Width + margin * 2,
|
||||
sub.VisibleBorders.Height + margin * 2);
|
||||
sub.VisibleBorders.X + (int)sub.WorldPosition.X,
|
||||
sub.VisibleBorders.Y + (int)sub.WorldPosition.Y,
|
||||
sub.VisibleBorders.Width,
|
||||
sub.VisibleBorders.Height);
|
||||
|
||||
if (RectsOverlap(worldBorders, cam.WorldView))
|
||||
if (RectsOverlap(worldBorders, camView))
|
||||
{
|
||||
visibleSubs.Add(sub);
|
||||
}
|
||||
@@ -64,16 +70,22 @@ namespace Barotrauma
|
||||
visibleEntities.Clear();
|
||||
}
|
||||
|
||||
Rectangle worldView = cam.WorldView;
|
||||
foreach (MapEntity entity in MapEntity.mapEntityList)
|
||||
{
|
||||
if (entity.Submarine != null)
|
||||
{
|
||||
if (!visibleSubs.Contains(entity.Submarine)) { continue; }
|
||||
}
|
||||
|
||||
if (entity.IsVisible(worldView)) { visibleEntities.Add(entity); }
|
||||
if (entity.IsVisible(camView)) { visibleEntities.Add(entity); }
|
||||
}
|
||||
|
||||
prevCullArea = camView;
|
||||
prevCullTime = Timing.TotalTime;
|
||||
}
|
||||
|
||||
public static void ForceVisibilityRecheck()
|
||||
{
|
||||
prevCullTime = 0;
|
||||
}
|
||||
|
||||
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
@@ -148,7 +160,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(e)) continue;
|
||||
if (!predicate(e)) { continue; }
|
||||
}
|
||||
float drawDepth = structure.GetDrawDepth();
|
||||
int i = 0;
|
||||
@@ -679,6 +691,22 @@ namespace Barotrauma
|
||||
return GameMain.LightManager.Lights.Count(l => l.CastShadows && !l.IsBackground) - disabledItemLightCount;
|
||||
}
|
||||
|
||||
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
|
||||
{
|
||||
Vector2 position = PlayerInput.MousePosition;
|
||||
position = cam.ScreenToWorld(position);
|
||||
|
||||
Vector2 worldGridPos = VectorToWorldGrid(position);
|
||||
|
||||
if (sub != null)
|
||||
{
|
||||
worldGridPos.X += sub.Position.X % GridSize.X;
|
||||
worldGridPos.Y += sub.Position.Y % GridSize.Y;
|
||||
}
|
||||
|
||||
return worldGridPos;
|
||||
}
|
||||
|
||||
public void ClientReadPosition(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
var posInfo = PhysicsBody.ClientRead(msg, sendingTime, parentDebugName: Info.Name);
|
||||
|
||||
@@ -10,14 +10,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
msg.Write((byte)ClientNetObject.CHAT_MESSAGE);
|
||||
msg.Write(NetStateID);
|
||||
msg.Write((byte)Type);
|
||||
msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
msg.WriteRangedInteger((int)ChatMode, 0, Enum.GetValues(typeof(ChatMode)).Length - 1);
|
||||
msg.Write(Text);
|
||||
}
|
||||
|
||||
public static void ClientRead(IReadMessage msg)
|
||||
{
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
ChatMessageType type = (ChatMessageType)msg.ReadByte();
|
||||
ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None;
|
||||
string txt = "";
|
||||
string styleSetting = string.Empty;
|
||||
|
||||
@@ -1831,7 +1831,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
AddChatMessage($"ServerMessage.HowToCommunicate~[chatbutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Chat)}~[radiobutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.RadioChat)}", ChatMessageType.Server);
|
||||
// TODO: Re-enable the server message once it's been edited and translated
|
||||
//AddChatMessage($"ServerMessage.HowToCommunicate~[chatbutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Chat)}~[radiobutton]={GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.RadioChat)}", ChatMessageType.Server);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
@@ -2503,6 +2504,7 @@ namespace Barotrauma.Networking
|
||||
message,
|
||||
type,
|
||||
gameStarted && myCharacter != null ? myCharacter : null);
|
||||
chatMessage.ChatMode = GameMain.ActiveChatMode;
|
||||
|
||||
lastQueueChatMsgID++;
|
||||
chatMessage.NetStateID = lastQueueChatMsgID;
|
||||
@@ -2788,19 +2790,21 @@ namespace Barotrauma.Networking
|
||||
GameMain.GameSession = null;
|
||||
}
|
||||
|
||||
public void SendCharacterInfo()
|
||||
public void SendCharacterInfo(string newName = null)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ClientPacketHeader.UPDATE_CHARACTERINFO);
|
||||
WriteCharacterInfo(msg);
|
||||
WriteCharacterInfo(msg, newName);
|
||||
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
clientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void WriteCharacterInfo(IWriteMessage msg)
|
||||
public void WriteCharacterInfo(IWriteMessage msg, string newName = null)
|
||||
{
|
||||
msg.Write(characterInfo == null);
|
||||
if (characterInfo == null) return;
|
||||
if (characterInfo == null) { return; }
|
||||
|
||||
msg.Write(newName ?? string.Empty);
|
||||
|
||||
msg.Write((byte)characterInfo.Head.Preset.TagSet.Count);
|
||||
foreach (Identifier tag in characterInfo.Head.Preset.TagSet)
|
||||
@@ -3284,10 +3288,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
bool chatKeyHit = PlayerInput.KeyHit(InputType.Chat);
|
||||
bool radioKeyHit = PlayerInput.KeyHit(InputType.RadioChat) && (Character.Controlled == null || Character.Controlled.SpeechImpediment < 100);
|
||||
|
||||
if (chatKeyHit || radioKeyHit)
|
||||
var chatKeyStates = ChatBox.ChatKeyStates.GetChatKeyStates();
|
||||
if (chatKeyStates.AnyHit)
|
||||
{
|
||||
if (msgBox.Selected)
|
||||
{
|
||||
@@ -3298,34 +3300,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (Screen.Selected == GameMain.GameScreen)
|
||||
{
|
||||
if (chatKeyHit)
|
||||
{
|
||||
msgBox.AddToGUIUpdateList();
|
||||
ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
|
||||
if (!chatBox.ToggleOpen)
|
||||
{
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
ChatBox.ToggleOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (radioKeyHit)
|
||||
{
|
||||
msgBox.AddToGUIUpdateList();
|
||||
ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
|
||||
if (!chatBox.ToggleOpen)
|
||||
{
|
||||
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
|
||||
ChatBox.ToggleOpen = true;
|
||||
}
|
||||
|
||||
if (!msgBox.Text.StartsWith(ChatBox.RadioChatString))
|
||||
{
|
||||
msgBox.Text = ChatBox.RadioChatString;
|
||||
}
|
||||
}
|
||||
ChatBox.ApplySelectionInputs(msgBox, false, chatKeyStates);
|
||||
}
|
||||
|
||||
msgBox.Select(msgBox.Text.Length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Barotrauma.Networking
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class OrderChatMessage : ChatMessage
|
||||
{
|
||||
@@ -6,7 +8,7 @@
|
||||
{
|
||||
msg.Write((byte)ClientNetObject.CHAT_MESSAGE);
|
||||
msg.Write(NetStateID);
|
||||
msg.Write((byte)ChatMessageType.Order);
|
||||
msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
WriteOrder(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,20 +227,10 @@ namespace Barotrauma.Networking
|
||||
bool allowEnqueue = overrideSound != null;
|
||||
if (GameMain.WindowActive && SettingsMenu.Instance is null)
|
||||
{
|
||||
ForceLocal = captureTimer > 0 ? ForceLocal : GameSettings.CurrentConfig.Audio.UseLocalVoiceByDefault;
|
||||
bool pttDown = false;
|
||||
if ((PlayerInput.KeyDown(InputType.Voice) || PlayerInput.KeyDown(InputType.LocalVoice)) &&
|
||||
GUI.KeyboardDispatcher.Subscriber == null)
|
||||
bool pttDown = PlayerInput.KeyDown(InputType.Voice) && GUI.KeyboardDispatcher.Subscriber == null;
|
||||
if (pttDown || captureTimer <= 0)
|
||||
{
|
||||
pttDown = true;
|
||||
if (PlayerInput.KeyDown(InputType.LocalVoice))
|
||||
{
|
||||
ForceLocal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ForceLocal = false;
|
||||
}
|
||||
ForceLocal = GameMain.ActiveChatMode == ChatMode.Local;
|
||||
}
|
||||
if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Activity)
|
||||
{
|
||||
@@ -257,7 +247,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allowEnqueue || captureTimer > 0)
|
||||
{
|
||||
LastEnqueueAudio = DateTime.Now;
|
||||
|
||||
@@ -205,7 +205,10 @@ namespace Barotrauma
|
||||
SettingCarouselElement<GameDifficulty> prevDifficulty = difficultyOptions.FirstOrNull(element => element.Value == prevSettings.Difficulty) ?? difficultyOptions[1];
|
||||
SettingValue<GameDifficulty> difficultyInput = CreateSelectionCarousel(settingsList.Content, TextManager.Get("leveldifficulty"), TextManager.Get("leveldifficultyexplanation"), prevDifficulty, verticalSize, difficultyOptions);
|
||||
|
||||
SettingValue<int> maxMissionCountInput = CreateGUINumberInputCarousel(settingsList.Content, TextManager.Get("maxmissioncount"), TextManager.Get("maxmissioncounttooltip"), prevSettings.MaxMissionCount, valueStep: 1, verticalSize);
|
||||
SettingValue<int> maxMissionCountInput = CreateGUINumberInputCarousel(settingsList.Content, TextManager.Get("maxmissioncount"), TextManager.Get("maxmissioncounttooltip"),
|
||||
prevSettings.MaxMissionCount,
|
||||
valueStep: 1, minValue: CampaignSettings.MinMissionCountLimit, maxValue: CampaignSettings.MaxMissionCountLimit,
|
||||
verticalSize);
|
||||
|
||||
presetDropdown.OnSelected = (selected, o) =>
|
||||
{
|
||||
@@ -231,7 +234,7 @@ namespace Barotrauma
|
||||
};
|
||||
|
||||
// Create a number input with plus and minus buttons because for some reason the default GUINumberInput buttons don't work when in a GUIMessageBox
|
||||
static SettingValue<int> CreateGUINumberInputCarousel(GUIComponent parent, LocalizedString description, LocalizedString tooltip, int defaultValue, int valueStep, float verticalSize)
|
||||
static SettingValue<int> CreateGUINumberInputCarousel(GUIComponent parent, LocalizedString description, LocalizedString tooltip, int defaultValue, int valueStep, int minValue, int maxValue, float verticalSize)
|
||||
{
|
||||
GUILayoutGroup inputContainer = CreateSettingBase(parent, description, tooltip, horizontalSize: 0.55f, verticalSize: verticalSize);
|
||||
|
||||
@@ -243,7 +246,9 @@ namespace Barotrauma
|
||||
GUINumberInput numberInput = new GUINumberInput(new RectTransform(Vector2.One, inputContainer.RectTransform, Anchor.Center), NumberType.Int, textAlignment: Alignment.Center, style: "GUITextBox",
|
||||
hidePlusMinusButtons: true)
|
||||
{
|
||||
IntValue = defaultValue
|
||||
IntValue = defaultValue,
|
||||
MinValueInt = minValue,
|
||||
MaxValueInt = maxValue
|
||||
};
|
||||
inputContainer.RectTransform.Parent.MinSize = new Point(0, numberInput.RectTransform.MinSize.Y);
|
||||
GUIButton plusButton = new GUIButton(new RectTransform(Vector2.One, inputContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Barotrauma
|
||||
DrawMap(graphics, spriteBatch, deltaTime);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("DrawMap", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
|
||||
@@ -165,7 +165,7 @@ namespace Barotrauma
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("DrawHUD", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:HUD", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
}
|
||||
|
||||
@@ -178,6 +178,9 @@ namespace Barotrauma
|
||||
|
||||
GameMain.ParticleManager.UpdateTransforms();
|
||||
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
GameMain.LightManager.ObstructVision =
|
||||
Character.Controlled != null &&
|
||||
Character.Controlled.ObstructVision &&
|
||||
@@ -185,6 +188,10 @@ namespace Barotrauma
|
||||
|
||||
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled?.CursorWorldPosition ?? Vector2.Zero);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:LOS", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
graphics.SetRenderTarget(renderTarget);
|
||||
graphics.Clear(Color.Transparent);
|
||||
@@ -196,9 +203,17 @@ namespace Barotrauma
|
||||
Submarine.DrawPaintedColors(spriteBatch, false);
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:BackStructures", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
graphics.SetRenderTarget(null);
|
||||
GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam, renderTarget);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:Lighting", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
graphics.SetRenderTarget(renderTargetBackground);
|
||||
if (Level.Loaded == null)
|
||||
@@ -228,6 +243,10 @@ namespace Barotrauma
|
||||
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:BackLevel", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//Start drawing to the normal render target (stuff that can't be seen through the LOS effect)
|
||||
@@ -248,6 +267,10 @@ namespace Barotrauma
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:BackCharactersItems", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
DrawDeformed(firstPass: true);
|
||||
DrawDeformed(firstPass: false);
|
||||
@@ -266,8 +289,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:DeformableCharacters", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
Level.Loaded?.DrawFront(spriteBatch, cam);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontLevel", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
|
||||
graphics.SetRenderTarget(renderTargetWater);
|
||||
|
||||
@@ -302,6 +333,10 @@ namespace Barotrauma
|
||||
WaterRenderer.Instance.RenderAir(graphics, cam, renderTarget, Cam.ShaderTransform);
|
||||
graphics.DepthStencilState = DepthStencilState.None;
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontParticles", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate,
|
||||
BlendState.NonPremultiplied, SamplerState.LinearWrap,
|
||||
null, null,
|
||||
@@ -310,10 +345,18 @@ namespace Barotrauma
|
||||
Submarine.DrawDamageable(spriteBatch, damageEffect, false);
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontDamageable", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
Submarine.DrawFront(spriteBatch, false, null);
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontStructuresItems", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
//draw additive particles that are inside a sub
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
|
||||
GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
|
||||
@@ -349,6 +392,10 @@ namespace Barotrauma
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:FrontMisc", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
if (GameMain.LightManager.LosEnabled && GameMain.LightManager.LosMode != LosMode.None && Lights.LightManager.ViewTarget != null)
|
||||
{
|
||||
GameMain.LightManager.LosEffect.CurrentTechnique = GameMain.LightManager.LosEffect.Techniques["LosShader"];
|
||||
@@ -457,6 +504,10 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Lerp(Color.TransparentBlack, Color.Black, fadeToBlackState), isFilled: true);
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Draw:Map:PostProcess", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(double deltaTime)
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Barotrauma
|
||||
public bool CampaignCharacterDiscarded
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
set;
|
||||
}
|
||||
|
||||
//elements that can only be used by the host
|
||||
@@ -1253,9 +1253,6 @@ namespace Barotrauma
|
||||
|
||||
CharacterAppearanceCustomizationMenu?.Dispose();
|
||||
JobSelectionFrame = null;
|
||||
|
||||
/*foreach (Sprite sprite in jobPreferenceSprites) { sprite.Remove(); }
|
||||
jobPreferenceSprites.Clear();*/
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
@@ -1417,7 +1414,7 @@ namespace Barotrauma
|
||||
characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, GameMain.Client.Name, null);
|
||||
characterInfo.RecreateHead(MultiplayerPreferences.Instance);
|
||||
GameMain.Client.CharacterInfo = characterInfo;
|
||||
characterInfo.OmitJobInPortraitClothing = false;
|
||||
characterInfo.OmitJobInMenus = true;
|
||||
}
|
||||
|
||||
parent.ClearChildren();
|
||||
|
||||
@@ -1870,7 +1870,8 @@ namespace Barotrauma
|
||||
}
|
||||
addSubAndSaveModProject(modProject, savePath, fileListPath);
|
||||
}
|
||||
else if (MainSub?.Info != null
|
||||
else if (MainSub?.Info?.FilePath != null
|
||||
&& MainSub.Info.Name != null
|
||||
&& MainSub.Info.FilePath.StartsWith(ContentPackage.LocalModsDir)
|
||||
&& MainSub.Info.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
@@ -2321,7 +2322,7 @@ namespace Barotrauma
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMinDifficultyGroup.RectTransform),
|
||||
TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
|
||||
new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMinDifficultyGroup.RectTransform), NumberType.Int)
|
||||
var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMinDifficultyGroup.RectTransform), NumberType.Int)
|
||||
{
|
||||
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MinLevelDifficulty ?? 0),
|
||||
MinValueInt = 0,
|
||||
@@ -2331,13 +2332,14 @@ namespace Barotrauma
|
||||
MainSub.Info.BeaconStationInfo.MinLevelDifficulty = numberInput.IntValue;
|
||||
}
|
||||
};
|
||||
beaconMinDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
|
||||
var beaconMaxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMaxDifficultyGroup.RectTransform),
|
||||
TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
|
||||
new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMaxDifficultyGroup.RectTransform), NumberType.Int)
|
||||
numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMaxDifficultyGroup.RectTransform), NumberType.Int)
|
||||
{
|
||||
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MaxLevelDifficulty ?? 100),
|
||||
MinValueInt = 0,
|
||||
@@ -2347,7 +2349,7 @@ namespace Barotrauma
|
||||
MainSub.Info.BeaconStationInfo.MaxLevelDifficulty = numberInput.IntValue;
|
||||
}
|
||||
};
|
||||
|
||||
beaconMaxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
|
||||
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), TextManager.Get("allowdamagedwalls"))
|
||||
{
|
||||
Selected = MainSub?.Info?.BeaconStationInfo?.AllowDamagedWalls ?? true,
|
||||
@@ -2545,6 +2547,10 @@ namespace Barotrauma
|
||||
{
|
||||
MainSub.Info.OutpostModuleInfo ??= new OutpostModuleInfo(MainSub.Info);
|
||||
}
|
||||
else if (type == SubmarineType.BeaconStation)
|
||||
{
|
||||
MainSub.Info.BeaconStationInfo ??= new BeaconStationInfo(MainSub.Info);
|
||||
}
|
||||
previewImageButtonHolder.Children.ForEach(c => c.Enabled = type != SubmarineType.OutpostModule);
|
||||
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
@@ -36,6 +37,8 @@ namespace Barotrauma
|
||||
|
||||
public readonly WorkshopMenu WorkshopMenu;
|
||||
|
||||
private static readonly ImmutableHashSet<InputType> LegacyInputTypes = new List<InputType>() { InputType.Chat, InputType.RadioChat }.ToImmutableHashSet();
|
||||
|
||||
public static SettingsMenu Create(RectTransform mainParent)
|
||||
{
|
||||
Instance?.Close();
|
||||
@@ -392,6 +395,9 @@ namespace Barotrauma
|
||||
Label(audio, TextManager.Get("MusicVolume"), GUIStyle.SubHeadingFont);
|
||||
Slider(audio, (0, 1), 101, Percentage, unsavedConfig.Audio.MusicVolume, (v) => unsavedConfig.Audio.MusicVolume = v);
|
||||
|
||||
Label(audio, TextManager.Get("UiSoundVolume"), GUIStyle.SubHeadingFont);
|
||||
Slider(audio, (0, 1), 101, Percentage, unsavedConfig.Audio.UiVolume, (v) => unsavedConfig.Audio.UiVolume = v);
|
||||
|
||||
Tickbox(audio, TextManager.Get("MuteOnFocusLost"), TextManager.Get("MuteOnFocusLostTooltip"), unsavedConfig.Audio.MuteOnFocusLost, (v) => unsavedConfig.Audio.MuteOnFocusLost = v);
|
||||
Tickbox(audio, TextManager.Get("DynamicRangeCompression"), TextManager.Get("DynamicRangeCompressionTooltip"), unsavedConfig.Audio.DynamicRangeCompressionEnabled, (v) => unsavedConfig.Audio.DynamicRangeCompressionEnabled = v);
|
||||
Spacer(audio);
|
||||
@@ -481,10 +487,14 @@ namespace Barotrauma
|
||||
|
||||
HashSet<GUIButton> inputButtons = new HashSet<GUIButton>();
|
||||
Action<KeyOrMouse>? currentSetter = null;
|
||||
void addInputToRow(GUILayoutGroup currRow, LocalizedString labelText, Func<LocalizedString> valueNameGetter, Action<KeyOrMouse> valueSetter)
|
||||
void addInputToRow(GUILayoutGroup currRow, LocalizedString labelText, Func<LocalizedString> valueNameGetter, Action<KeyOrMouse> valueSetter, bool isLegacyBind = false)
|
||||
{
|
||||
var inputFrame = new GUIFrame(new RectTransform((0.5f, 1.0f), currRow.RectTransform),
|
||||
style: null);
|
||||
if (isLegacyBind)
|
||||
{
|
||||
labelText = TextManager.GetWithVariable("legacyitemformat", "[name]", labelText);
|
||||
}
|
||||
var label = new GUITextBlock(new RectTransform((0.6f, 1.0f), inputFrame.RectTransform), labelText,
|
||||
font: GUIStyle.SmallFont) {ForceUpperCase = ForceUpperCase.Yes};
|
||||
var inputBox = new GUIButton(
|
||||
@@ -515,6 +525,12 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
};
|
||||
if (isLegacyBind)
|
||||
{
|
||||
label.TextColor = Color.Lerp(label.TextColor, label.DisabledTextColor, 0.5f);
|
||||
inputBox.Color = Color.Lerp(inputBox.Color, inputBox.DisabledColor, 0.5f);
|
||||
inputBox.TextColor = Color.Lerp(inputBox.TextColor, label.DisabledTextColor, 0.5f);
|
||||
}
|
||||
inputButtons.Add(inputBox);
|
||||
}
|
||||
|
||||
@@ -594,7 +610,8 @@ namespace Barotrauma
|
||||
currRow,
|
||||
TextManager.Get($"InputType.{input}"),
|
||||
() => unsavedConfig.KeyMap.Bindings[input].Name,
|
||||
(v) => unsavedConfig.KeyMap = unsavedConfig.KeyMap.WithBinding(input, v));
|
||||
(v) => unsavedConfig.KeyMap = unsavedConfig.KeyMap.WithBinding(input, v),
|
||||
LegacyInputTypes.Contains(input));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,30 +626,29 @@ namespace Barotrauma
|
||||
var input = unsavedConfig.InventoryKeyMap.Bindings[currIndex];
|
||||
addInputToRow(
|
||||
currRow,
|
||||
TextManager.GetWithVariable("inventoryslotkeybind", "[slotnumber]", (currIndex+1).ToString(CultureInfo.InvariantCulture)),
|
||||
TextManager.GetWithVariable("inventoryslotkeybind", "[slotnumber]", (currIndex + 1).ToString(CultureInfo.InvariantCulture)),
|
||||
() => unsavedConfig.InventoryKeyMap.Bindings[currIndex].Name,
|
||||
(v) => unsavedConfig.InventoryKeyMap = unsavedConfig.InventoryKeyMap.WithBinding(currIndex, v));
|
||||
}
|
||||
}
|
||||
|
||||
GUILayoutGroup resetControlsHolder =
|
||||
new GUILayoutGroup(new RectTransform((1.75f, 0.1f), layout.RectTransform), isHorizontal: true)
|
||||
new GUILayoutGroup(new RectTransform((1.75f, 0.1f), layout.RectTransform), isHorizontal: true, childAnchor: Anchor.Center)
|
||||
{
|
||||
RelativeSpacing = 0.1f
|
||||
};
|
||||
|
||||
var defaultBindingsButton =
|
||||
new GUIButton(new RectTransform(new Vector2(0.45f, 1.0f), resetControlsHolder.RectTransform),
|
||||
TextManager.Get("SetDefaultBindings"), style: "GUIButtonSmall")
|
||||
TextManager.Get("Reset"), style: "GUIButtonSmall")
|
||||
{
|
||||
ToolTip = TextManager.Get("SetDefaultBindingsTooltip")
|
||||
};
|
||||
|
||||
var legacyBindingsButton =
|
||||
new GUIButton(new RectTransform(new Vector2(0.45f, 1.0f), resetControlsHolder.RectTransform),
|
||||
TextManager.Get("SetLegacyBindings"), style: "GUIButtonSmall")
|
||||
{
|
||||
ToolTip = TextManager.Get("SetLegacyBindingsTooltip")
|
||||
ToolTip = TextManager.Get("SetDefaultBindingsTooltip"),
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
unsavedConfig.InventoryKeyMap = GameSettings.Config.InventoryKeyMapping.GetDefault();
|
||||
unsavedConfig.KeyMap = GameSettings.Config.KeyMapping.GetDefault();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -705,7 +705,7 @@ namespace Barotrauma.Sounds
|
||||
public void ApplySettings()
|
||||
{
|
||||
SetCategoryGainMultiplier("default", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
|
||||
SetCategoryGainMultiplier("ui", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
|
||||
SetCategoryGainMultiplier("ui", GameSettings.CurrentConfig.Audio.UiVolume, 0);
|
||||
SetCategoryGainMultiplier("waterambience", GameSettings.CurrentConfig.Audio.SoundVolume, 0);
|
||||
SetCategoryGainMultiplier("music", GameSettings.CurrentConfig.Audio.MusicVolume, 0);
|
||||
SetCategoryGainMultiplier("voip", Math.Min(GameSettings.CurrentConfig.Audio.VoiceChatVolume, 1.0f), 0);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.18.4.0</Version>
|
||||
<Version>0.18.5.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.18.4.0</Version>
|
||||
<Version>0.18.5.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.18.4.0</Version>
|
||||
<Version>0.18.5.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.18.4.0</Version>
|
||||
<Version>0.18.5.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.18.4.0</Version>
|
||||
<Version>0.18.5.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -10,7 +10,8 @@ namespace Barotrauma.Networking
|
||||
c.KickAFKTimer = 0.0f;
|
||||
|
||||
UInt16 ID = msg.ReadUInt16();
|
||||
ChatMessageType type = (ChatMessageType)msg.ReadByte();
|
||||
ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
ChatMode chatMode = (ChatMode)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMode)).Length - 1);
|
||||
string txt;
|
||||
|
||||
Character orderTargetCharacter = null;
|
||||
@@ -172,7 +173,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Server.SendChatMessage(txt, null, c);
|
||||
GameMain.Server.SendChatMessage(txt, senderClient: c, chatMode: chatMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
msg.Write((byte)ServerNetObject.CHAT_MESSAGE);
|
||||
msg.Write(NetStateID);
|
||||
msg.Write((byte)Type);
|
||||
msg.WriteRangedInteger((int)Type, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
msg.Write((byte)ChangeType);
|
||||
msg.Write(Text);
|
||||
|
||||
|
||||
@@ -2696,6 +2696,24 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (newName == c.Name) { return false; }
|
||||
|
||||
if (IsNameValid(c, newName))
|
||||
{
|
||||
string oldName = c.Name;
|
||||
c.Name = newName;
|
||||
c.Connection.Name = newName;
|
||||
SendChatMessage($"ServerMessage.NameChangeSuccessful~[oldname]={oldName}~[newname]={newName}", ChatMessageType.Server);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsNameValid(Client c, string newName)
|
||||
{
|
||||
newName = Client.SanitizeName(newName);
|
||||
|
||||
if (c.Connection != OwnerConnection)
|
||||
{
|
||||
if (!Client.IsValidName(newName, serverSettings))
|
||||
@@ -2723,9 +2741,6 @@ namespace Barotrauma.Networking
|
||||
return false;
|
||||
}
|
||||
|
||||
SendChatMessage($"ServerMessage.NameChangeSuccessful~[oldname]={c.Name}~[newname]={newName}", ChatMessageType.Server);
|
||||
c.Name = newName;
|
||||
c.Connection.Name = newName;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2967,7 +2982,7 @@ namespace Barotrauma.Networking
|
||||
/// <summary>
|
||||
/// Add the message to the chatbox and pass it to all clients who can receive it
|
||||
/// </summary>
|
||||
public void SendChatMessage(string message, ChatMessageType? type = null, Client senderClient = null, Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None)
|
||||
public void SendChatMessage(string message, ChatMessageType? type = null, Client senderClient = null, Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None, ChatMode chatMode = ChatMode.None)
|
||||
{
|
||||
string senderName = "";
|
||||
|
||||
@@ -3023,6 +3038,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
type = ChatMessageType.Private;
|
||||
}
|
||||
else if (chatMode == ChatMode.Radio)
|
||||
{
|
||||
type = ChatMessageType.Radio;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = ChatMessageType.Default;
|
||||
@@ -3051,7 +3070,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
senderCharacter = senderClient.Character;
|
||||
senderName = senderCharacter == null ? senderClient.Name : senderCharacter.Name;
|
||||
|
||||
if (type == ChatMessageType.Private)
|
||||
{
|
||||
if (senderCharacter != null && !senderCharacter.IsDead || targetClient.Character != null && !targetClient.Character.IsDead)
|
||||
@@ -3512,6 +3530,20 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
string newName = message.ReadString();
|
||||
if (string.IsNullOrEmpty(newName))
|
||||
{
|
||||
newName = sender.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
newName = Client.SanitizeName(newName);
|
||||
if (!IsNameValid(sender, newName))
|
||||
{
|
||||
newName = sender.Name;
|
||||
}
|
||||
}
|
||||
|
||||
int tagCount = message.ReadByte();
|
||||
HashSet<Identifier> tagSet = new HashSet<Identifier>();
|
||||
for (int i = 0; i < tagCount; i++)
|
||||
@@ -3539,7 +3571,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
sender.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, sender.Name);
|
||||
sender.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, newName);
|
||||
sender.CharacterInfo.RecreateHead(tagSet.ToImmutableHashSet(), hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
||||
sender.CharacterInfo.Head.SkinColor = skinColor;
|
||||
sender.CharacterInfo.Head.HairColor = hairColor;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Barotrauma.Networking
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class OrderChatMessage : ChatMessage
|
||||
{
|
||||
@@ -6,7 +8,7 @@
|
||||
{
|
||||
msg.Write((byte)ServerNetObject.CHAT_MESSAGE);
|
||||
msg.Write(NetStateID);
|
||||
msg.Write((byte)ChatMessageType.Order);
|
||||
msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
msg.Write(SenderName);
|
||||
msg.Write(SenderClient != null);
|
||||
if (SenderClient != null)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.18.4.0</Version>
|
||||
<Version>0.18.5.0</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<CampaignSettingPresets>
|
||||
<CampaignSettingDefinitions>
|
||||
<StartingBalanceAmount high="10000" medium="8500" low="6000" />
|
||||
<ExtraEventManagerDifficulty easy="-15.0" normal="0.0" hard="20.0" hellish="60.0" />
|
||||
<LevelDifficultyMultiplier easy="0.6" normal="1.0" hard="1.6" hellish="10.0" />
|
||||
<ExtraEventManagerDifficulty easy="-15.0" medium="0.0" hard="20.0" hellish="60.0" />
|
||||
<LevelDifficultyMultiplier easy="0.6" medium="1.0" hard="1.6" hellish="10.0" />
|
||||
</CampaignSettingDefinitions>
|
||||
<CampaignSettings
|
||||
presetname="Easy"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -48,6 +47,9 @@ namespace Barotrauma
|
||||
|
||||
protected override bool Filter(Item target)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(target.GetComponent<Pickable>() is { } pickable && !pickable.IsAttached, "Invalid target in AIObjectiveCleanUpItems - the the objective should only be checking pickable, non-attached items.");
|
||||
System.Diagnostics.Debug.Assert(target.Prefab.PreferredContainers.Any(), "Invalid target in AIObjectiveCleanUpItems - the the objective should only be checking items that have preferred containers defined.");
|
||||
|
||||
// If the target was selected as a valid target, we'll have to accept it so that the objective can be completed.
|
||||
// The validity changes when a character picks the item up.
|
||||
if (!IsValidTarget(target, character, checkInventory: true)) { return Objectives.ContainsKey(target) && IsItemInsideValidSubmarine(target, character); }
|
||||
@@ -57,7 +59,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override IEnumerable<Item> GetList() => Item.ItemList;
|
||||
protected override IEnumerable<Item> GetList() => Item.CleanableItems;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Item item)
|
||||
=> new AIObjectiveCleanupItem(item, character, objectiveManager, priorityModifier: PriorityModifier)
|
||||
@@ -102,9 +104,6 @@ namespace Barotrauma
|
||||
}
|
||||
if (character != null && !IsItemInsideValidSubmarine(item, character)) { return false; }
|
||||
if (item.HasBallastFloraInHull) { return false; }
|
||||
var pickable = item.GetComponent<Pickable>();
|
||||
if (pickable == null) { return false; }
|
||||
if (pickable is Holdable h && h.Attachable && h.Attached) { return false; }
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null)
|
||||
{
|
||||
@@ -118,10 +117,6 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (item.Prefab.PreferredContainers.None())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!checkInventory)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -488,7 +488,7 @@ namespace Barotrauma
|
||||
if (hull != null)
|
||||
{
|
||||
itemsToClean.Clear();
|
||||
foreach (Item item in Item.ItemList)
|
||||
foreach (Item item in Item.CleanableItems)
|
||||
{
|
||||
if (item.CurrentHull != hull) { continue; }
|
||||
if (AIObjectiveCleanupItems.IsValidTarget(item, character, checkInventory: true, allowUnloading: false) && !ignoredItems.Contains(item))
|
||||
|
||||
@@ -39,12 +39,21 @@ namespace Barotrauma
|
||||
{
|
||||
TargetContainers.Add(targetContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!OrderPrefab.TargetItemsMatchItem(TargetContainerTags, item)) { continue; }
|
||||
TargetContainers.Add(item);
|
||||
}
|
||||
}
|
||||
TargetCondition = option == "turretammo" ? ItemCondition.Empty : ItemCondition.Full;
|
||||
}
|
||||
|
||||
protected override bool Filter(Item target)
|
||||
{
|
||||
if (!IsValidTarget(target, character, TargetContainerTags, TargetCondition)) { return false; }
|
||||
//don't pass TargetContainerTags to the method (no need to filter by tags anymore, it's already done when populating TargetContainers)
|
||||
if (!IsValidTarget(target, character, null, TargetCondition)) { return false; }
|
||||
if (target.CurrentHull == null || target.CurrentHull.FireSources.Count > 0) { return false; }
|
||||
if (Character.CharacterList.Any(c => c.CurrentHull == target.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return false; }
|
||||
return true;
|
||||
@@ -52,8 +61,7 @@ namespace Barotrauma
|
||||
|
||||
public static bool IsValidTarget(Item item, Character character, ImmutableArray<Identifier>? targetContainerTags = null, ItemCondition? targetCondition = null)
|
||||
{
|
||||
if (item == null) { return false; }
|
||||
if (item.Removed) { return false; }
|
||||
if (item == null || item.Removed) { return false; }
|
||||
if (targetContainerTags.HasValue && !OrderPrefab.TargetItemsMatchItem(targetContainerTags.Value, item)) { return false; }
|
||||
if (!(item.GetComponent<ItemContainer>() is ItemContainer container)) { return false; }
|
||||
if (container.Inventory == null) { return false; }
|
||||
@@ -88,7 +96,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<Item> GetList() => TargetContainers.Any() ? TargetContainers : Item.ItemList;
|
||||
protected override IEnumerable<Item> GetList() => TargetContainers;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Item target)
|
||||
=> new AIObjectiveLoadItem(target, TargetContainerTags, TargetCondition, Option, character, objectiveManager, PriorityModifier);
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
public override bool KeepDivingGearOn => true;
|
||||
public override bool AllowAutomaticItemUnequipping => true;
|
||||
|
||||
private IEnumerable<Pump> pumpList;
|
||||
private List<Pump> pumpList;
|
||||
|
||||
public AIObjectivePumpWater(Character character, AIObjectiveManager objectiveManager, Identifier option, float priorityModifier = 1)
|
||||
: base(character, objectiveManager, priorityModifier, option) { }
|
||||
@@ -26,13 +26,8 @@ namespace Barotrauma
|
||||
|
||||
protected override bool Filter(Pump pump)
|
||||
{
|
||||
if (pump == null) { return false; }
|
||||
if (pump.Item.IgnoreByAI(character)) { return false; }
|
||||
if (!pump.Item.IsInteractable(character)) { return false; }
|
||||
if (pump.Item.HasTag("ballast")) { return false; }
|
||||
if (pump.Item.Submarine == null) { return false; }
|
||||
if (pump.Item.CurrentHull == null) { return false; }
|
||||
if (pump.Item.Submarine.TeamID != character.TeamID) { return false; }
|
||||
if (pump.IsAutoControlled) { return false; }
|
||||
if (pump.Item.ConditionPercentage <= 0) { return false; }
|
||||
if (pump.Item.CurrentHull.FireSources.Count > 0) { return false; }
|
||||
@@ -50,7 +45,16 @@ namespace Barotrauma
|
||||
if (pumpList == null)
|
||||
{
|
||||
if (character == null || character.Submarine == null) { return Array.Empty<Pump>(); }
|
||||
pumpList = character.Submarine.GetItems(true).Select(i => i.GetComponent<Pump>()).Where(p => p != null);
|
||||
|
||||
pumpList = new List<Pump>();
|
||||
foreach (Item item in character.Submarine.GetItems(true))
|
||||
{
|
||||
var pump = item.GetComponent<Pump>();
|
||||
if (pump == null || pump.Item.Submarine == null || pump.Item.CurrentHull == null) { continue; }
|
||||
if (pump.Item.Submarine.TeamID != character.TeamID) { continue; }
|
||||
if (pump.Item.HasTag("ballast")) { continue; }
|
||||
pumpList.Add(pump);
|
||||
}
|
||||
}
|
||||
return pumpList;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Barotrauma
|
||||
return MathHelper.Lerp(0, 100, MathHelper.Clamp(damagePriority * successFactor, 0, 1));
|
||||
}
|
||||
|
||||
protected override IEnumerable<Item> GetList() => Item.ItemList;
|
||||
protected override IEnumerable<Item> GetList() => Item.RepairableItems;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Item item)
|
||||
=> new AIObjectiveRepairItem(character, item, objectiveManager, priorityModifier: PriorityModifier, isPriority: item == PrioritizedItem);
|
||||
@@ -156,6 +156,9 @@ namespace Barotrauma
|
||||
if (character.IsOnPlayerTeam && item.Submarine.Info.IsOutpost) { return false; }
|
||||
if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { return false; }
|
||||
if (item.Repairables.None()) { return false; }
|
||||
|
||||
System.Diagnostics.Debug.Assert(item.Repairables.Any(), "Invalid target in AIObjectiveRepairItems - the objective should only be checking items that have a Repairable component (Item.RepairableItems)");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +356,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool OmitJobInPortraitClothing;
|
||||
/// <summary>
|
||||
/// Can be used to disable displaying the job in any info panels
|
||||
/// </summary>
|
||||
public bool OmitJobInMenus;
|
||||
|
||||
private Sprite portrait;
|
||||
public Sprite Portrait
|
||||
@@ -434,7 +437,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (attachmentSprites == null)
|
||||
{
|
||||
LoadAttachmentSprites(OmitJobInPortraitClothing);
|
||||
LoadAttachmentSprites();
|
||||
}
|
||||
return attachmentSprites;
|
||||
}
|
||||
@@ -1092,7 +1095,7 @@ namespace Barotrauma
|
||||
|
||||
private static IEnumerable<float> GetWeights(IEnumerable<ContentXElement> elements) => elements.Select(h => h.GetAttributeFloat("commonness", 1f));
|
||||
|
||||
partial void LoadAttachmentSprites(bool omitJob);
|
||||
partial void LoadAttachmentSprites();
|
||||
|
||||
private int CalculateSalary()
|
||||
{
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static IReadOnlyDictionary<Identifier, float> ItemRepairPriorities => _itemRepairPriorities;
|
||||
|
||||
public static ContentXElement NoJobElement;
|
||||
public static JobPrefab Get(string identifier)
|
||||
{
|
||||
if (Prefabs.ContainsKey(identifier))
|
||||
@@ -213,7 +212,7 @@ namespace Barotrauma
|
||||
public SkillPrefab PrimarySkill => Skills?.FirstOrDefault(s => s.IsPrimarySkill);
|
||||
|
||||
public ContentXElement Element { get; private set; }
|
||||
public ContentXElement ClothingElement { get; private set; }
|
||||
|
||||
public int Variants { get; private set; }
|
||||
|
||||
public JobPrefab(ContentXElement element, JobsFile file) : base(file, element.GetAttributeIdentifier("identifier", ""))
|
||||
@@ -288,9 +287,6 @@ namespace Barotrauma
|
||||
Variants = variant;
|
||||
|
||||
Skills.Sort((x,y) => y.LevelRange.Start.CompareTo(x.LevelRange.Start));
|
||||
|
||||
// Disabled on purpose, TODO: remove all references?
|
||||
//ClothingElement = element.GetChildElement("PortraitClothing");
|
||||
}
|
||||
|
||||
public static JobPrefab Random(Rand.RandSync sync, Func<JobPrefab, bool> predicate = null) => Prefabs.GetRandom(p => !p.HiddenJob && (predicate == null || predicate(p)), sync);
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Barotrauma
|
||||
return folder.CleanUpPathCrossPlatform(correctFilenameCase: true);
|
||||
}
|
||||
|
||||
public static T GetDefaultRagdollParams<T>(Identifier speciesName) where T : RagdollParams, new() => GetRagdollParams<T>(speciesName, GetDefaultFileName(speciesName));
|
||||
public static T GetDefaultRagdollParams<T>(Identifier speciesName) where T : RagdollParams, new() => GetRagdollParams<T>(speciesName);
|
||||
|
||||
/// <summary>
|
||||
/// If the file name is left null, default file is selected. If fails, will select the default file. Note: Use the filename without the extensions, don't use the full path!
|
||||
|
||||
@@ -22,11 +22,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var element in mainElement.Elements())
|
||||
{
|
||||
if (element.NameAsIdentifier() == "nojob")
|
||||
{
|
||||
JobPrefab.NoJobElement ??= element;
|
||||
}
|
||||
else if (element.NameAsIdentifier() == "ItemRepairPriorities")
|
||||
if (element.NameAsIdentifier() == "ItemRepairPriorities")
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
|
||||
@@ -177,4 +177,11 @@ namespace Barotrauma
|
||||
Int,
|
||||
Float
|
||||
}
|
||||
|
||||
public enum ChatMode
|
||||
{
|
||||
None,
|
||||
Local,
|
||||
Radio
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1028,13 +1028,14 @@ namespace Barotrauma
|
||||
var itemsToTransfer = new List<(Item item, Item container)>();
|
||||
if (PendingSubmarineSwitch != null)
|
||||
{
|
||||
var connectedSubs = currentSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
|
||||
// Remove items from the old sub
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.Removed) { continue; }
|
||||
if (item.NonInteractable) { continue; }
|
||||
if (item.HiddenInGame) { continue; }
|
||||
if (item.Submarine != currentSub) { continue; }
|
||||
if (!connectedSubs.Contains(item.Submarine)) { continue; }
|
||||
if (item.Prefab.DontTransferBetweenSubs) { continue; }
|
||||
if (item.GetRootInventoryOwner() is Character) { continue; }
|
||||
if (item.GetComponent<Holdable>() == null && item.GetComponent<Wearable>() == null && item.GetComponent<Projectile>() == null) { continue; }
|
||||
@@ -1058,9 +1059,10 @@ namespace Barotrauma
|
||||
{
|
||||
// Load the new sub
|
||||
var newSub = new Submarine(PendingSubmarineSwitch);
|
||||
var connectedSubs = newSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
|
||||
// Move the transferred items
|
||||
List<ItemContainer> availableContainers = Item.ItemList
|
||||
.Where(it => it.Submarine == newSub && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed)
|
||||
.Where(it => connectedSubs.Contains(it.Submarine) && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed)
|
||||
.Select(it => it.GetComponent<ItemContainer>())
|
||||
.Where(c => c != null)
|
||||
.ToList();
|
||||
@@ -1070,7 +1072,7 @@ namespace Barotrauma
|
||||
item.Submarine = newSub;
|
||||
if (item.Container == null)
|
||||
{
|
||||
newContainer = newSub.FindContainerFor(item, onlyPrimary: true, checkTransferConditions: true);
|
||||
newContainer = newSub.FindContainerFor(item, onlyPrimary: true, checkTransferConditions: true, allowConnectedSubs: true);
|
||||
}
|
||||
if (item.Container == null && (newContainer == null || !newContainer.OwnInventory.TryPutItem(item, user: null, createNetworkEvent: false)))
|
||||
{
|
||||
@@ -1086,7 +1088,8 @@ namespace Barotrauma
|
||||
var cargoContainer = CargoManager.GetOrCreateCargoContainerFor(item.Prefab, spawnHull, ref availableContainers);
|
||||
if (cargoContainer == null || !cargoContainer.Inventory.TryPutItem(item, user: null, createNetworkEvent: false))
|
||||
{
|
||||
item.SetTransform(wp.SimPosition, 0.0f, findNewHull: false, setPrevTransform: false);
|
||||
Vector2 simPos = ConvertUnits.ToSimUnits(CargoManager.GetCargoPos(spawnHull, item.Prefab));
|
||||
item.SetTransform(simPos, 0.0f, findNewHull: false, setPrevTransform: false);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -71,12 +71,22 @@ namespace Barotrauma
|
||||
|
||||
public float GetFloat(Identifier identifier)
|
||||
{
|
||||
return values.TryGetValue(identifier, out Either<int, float> value) && value.TryGet(out float range) ? range : 0.0f;
|
||||
float range = 0;
|
||||
if (!values.TryGetValue(identifier, out Either<int, float> value) || !value.TryGet(out range))
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
public int GetInt(Identifier identifier)
|
||||
{
|
||||
return values.TryGetValue(identifier, out Either<int, float> value) && value.TryGet(out int integer) ? integer : 0;
|
||||
int integer = 0;
|
||||
if (!values.TryGetValue(identifier, out Either<int, float> value) || !value.TryGet(out integer))
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
|
||||
}
|
||||
return integer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,14 @@ namespace Barotrauma
|
||||
SelectNextCharacter,
|
||||
SelectPreviousCharacter,
|
||||
Voice,
|
||||
LocalVoice,
|
||||
Deselect,
|
||||
Shoot,
|
||||
Command,
|
||||
TakeOneFromInventorySlot,
|
||||
TakeHalfFromInventorySlot,
|
||||
NextFireMode,
|
||||
PreviousFireMode
|
||||
PreviousFireMode,
|
||||
ActiveChat,
|
||||
ToggleChatMode,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Body?.SetTransform(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
}
|
||||
|
||||
if (linkedGap != null)
|
||||
{
|
||||
RefreshLinkedGap();
|
||||
linkedGap.Rect = item.Rect;
|
||||
}
|
||||
#if CLIENT
|
||||
UpdateConvexHulls();
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private Character prevEquipper;
|
||||
|
||||
public override bool IsAttached => Attached;
|
||||
|
||||
private bool attachable, attached, attachedByDefault;
|
||||
private Voronoi2.VoronoiCell attachTargetCell;
|
||||
private PhysicsBody body;
|
||||
@@ -71,6 +73,7 @@ namespace Barotrauma.Items.Components
|
||||
set
|
||||
{
|
||||
attached = value;
|
||||
item.CheckCleanable();
|
||||
item.SetActiveSprite();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -20,6 +19,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private CoroutineHandle pickingCoroutine;
|
||||
|
||||
public virtual bool IsAttached => false;
|
||||
|
||||
public List<InvSlotType> AllowedSlots
|
||||
{
|
||||
get { return allowedSlots; }
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Barotrauma.Items.Components
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No, description: "Can the item hit broken doors.")]
|
||||
[Serialize(true, IsPropertySaveable.No, description: "Can the item hit doors.")]
|
||||
public bool HitItems { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Can the item hit broken doors.")]
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool RemoveContainedItemsOnDeconstruct { get; set; }
|
||||
|
||||
private readonly ImmutableArray<SlotRestrictions> slotRestrictions;
|
||||
private ImmutableArray<SlotRestrictions> slotRestrictions;
|
||||
|
||||
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
|
||||
|
||||
@@ -215,13 +215,21 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
public List<RelatedItem> ContainableItems { get; }
|
||||
public List<RelatedItem> ContainableItems { get; private set; }
|
||||
|
||||
public ItemContainer(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
LoadContainableRestrictions(element);
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
|
||||
public void LoadContainableRestrictions(ContentXElement element)
|
||||
{
|
||||
int totalCapacity = capacity;
|
||||
|
||||
ContainableItems?.Clear();
|
||||
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -242,7 +250,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
Inventory = new ItemInventory(item, this, totalCapacity, SlotsPerRow);
|
||||
|
||||
|
||||
List<SlotRestrictions> newSlotRestrictions = new List<SlotRestrictions>(totalCapacity);
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
@@ -253,7 +261,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "subcontainer") { continue; }
|
||||
|
||||
|
||||
int subCapacity = subElement.GetAttributeInt("capacity", 1);
|
||||
int subMaxStackSize = subElement.GetAttributeInt("maxstacksize", maxStackSize);
|
||||
|
||||
@@ -281,7 +289,6 @@ namespace Barotrauma.Items.Components
|
||||
capacity = totalCapacity;
|
||||
slotRestrictions = newSlotRestrictions.ToImmutableArray();
|
||||
System.Diagnostics.Debug.Assert(totalCapacity == slotRestrictions.Length);
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
|
||||
public int GetMaxStackSize(int slotIndex)
|
||||
|
||||
@@ -114,6 +114,20 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
} = true;
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool NonInteractableWhenFlippedX
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool NonInteractableWhenFlippedY
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Controller(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -571,6 +585,18 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
if (item.FlippedX && NonInteractableWhenFlippedX)
|
||||
{
|
||||
item.NonInteractable = true;
|
||||
}
|
||||
else if (item.FlippedY && NonInteractableWhenFlippedY)
|
||||
{
|
||||
item.NonInteractable = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
@@ -435,7 +435,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("GridUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Power", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -592,7 +592,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("PowerUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Power", sw.ElapsedTicks);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Barotrauma
|
||||
Beard,
|
||||
Moustache,
|
||||
FaceAttachment,
|
||||
JobIndicator,
|
||||
Husk,
|
||||
Herpes
|
||||
}
|
||||
@@ -128,7 +127,6 @@ namespace Barotrauma
|
||||
case WearableType.Beard:
|
||||
case WearableType.Moustache:
|
||||
case WearableType.FaceAttachment:
|
||||
case WearableType.JobIndicator:
|
||||
case WearableType.Husk:
|
||||
case WearableType.Herpes:
|
||||
Limb = LimbType.Head;
|
||||
|
||||
@@ -29,6 +29,20 @@ namespace Barotrauma
|
||||
|
||||
public static IReadOnlyCollection<Item> DangerousItems { get { return dangerousItems; } }
|
||||
|
||||
private static readonly List<Item> repairableItems = new List<Item>();
|
||||
|
||||
/// <summary>
|
||||
/// Items that have one more more Repairable component
|
||||
/// </summary>
|
||||
public static IReadOnlyCollection<Item> RepairableItems => repairableItems;
|
||||
|
||||
private static readonly List<Item> cleanableItems = new List<Item>();
|
||||
|
||||
/// <summary>
|
||||
/// Items that may potentially need to be cleaned up (pickable, not attached to a wall, and not inside a valid container)
|
||||
/// </summary>
|
||||
public static IReadOnlyCollection<Item> CleanableItems => cleanableItems;
|
||||
|
||||
public new ItemPrefab Prefab => base.Prefab as ItemPrefab;
|
||||
|
||||
public static bool ShowLinks = true;
|
||||
@@ -186,6 +200,7 @@ namespace Barotrauma
|
||||
if (value != container)
|
||||
{
|
||||
container = value;
|
||||
CheckCleanable();
|
||||
SetActiveSprite();
|
||||
}
|
||||
}
|
||||
@@ -1009,10 +1024,9 @@ namespace Barotrauma
|
||||
|
||||
InsertToList();
|
||||
ItemList.Add(this);
|
||||
if (Prefab.IsDangerous)
|
||||
{
|
||||
dangerousItems.Add(this);
|
||||
}
|
||||
if (Prefab.IsDangerous) { dangerousItems.Add(this); }
|
||||
if (Repairables.Any()) { repairableItems.Add(this); }
|
||||
CheckCleanable();
|
||||
|
||||
DebugConsole.Log("Created " + Name + " (" + ID + ")");
|
||||
|
||||
@@ -1022,6 +1036,9 @@ namespace Barotrauma
|
||||
ApplyStatusEffects(ActionType.OnSpawn, 1.0f);
|
||||
Components.ForEach(c => c.ApplyStatusEffects(ActionType.OnSpawn, 1.0f));
|
||||
RecalculateConditionValues();
|
||||
#if CLIENT
|
||||
Submarine.ForceVisibilityRecheck();
|
||||
#endif
|
||||
}
|
||||
|
||||
partial void InitProjSpecific();
|
||||
@@ -1150,6 +1167,7 @@ namespace Barotrauma
|
||||
drawableComponents.Add(drawable);
|
||||
hasComponentsToDraw = true;
|
||||
#if CLIENT
|
||||
Submarine.ForceVisibilityRecheck();
|
||||
cachedVisibleExtents = null;
|
||||
#endif
|
||||
}
|
||||
@@ -1281,6 +1299,27 @@ namespace Barotrauma
|
||||
|
||||
partial void SetActiveSpriteProjSpecific();
|
||||
|
||||
/// <summary>
|
||||
/// Recheck if the item needs to be included in the list of cleanable items
|
||||
/// </summary>
|
||||
public void CheckCleanable()
|
||||
{
|
||||
var pickable = GetComponent<Pickable>();
|
||||
if (pickable != null && !pickable.IsAttached &&
|
||||
Prefab.PreferredContainers.Any() &&
|
||||
(container == null || container.HasTag("allowcleanup")))
|
||||
{
|
||||
if (!cleanableItems.Contains(this))
|
||||
{
|
||||
cleanableItems.Add(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cleanableItems.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
if (!MathUtils.IsValid(amount))
|
||||
@@ -2526,7 +2565,7 @@ namespace Barotrauma
|
||||
ic.WasUsed = true;
|
||||
#if CLIENT
|
||||
ic.PlaySound(ActionType.OnUse, character);
|
||||
#endif
|
||||
#endif
|
||||
ic.ApplyStatusEffects(ActionType.OnUse, deltaTime, character, targetLimb);
|
||||
|
||||
if (ic.DeleteOnUse) { remove = true; }
|
||||
@@ -2704,6 +2743,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SetContainedItemPositions();
|
||||
#if CLIENT
|
||||
Submarine.ForceVisibilityRecheck();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Equip(Character character)
|
||||
@@ -3368,8 +3410,7 @@ namespace Barotrauma
|
||||
{
|
||||
ic.ShallowRemove();
|
||||
}
|
||||
ItemList.Remove(this);
|
||||
dangerousItems.Remove(this);
|
||||
RemoveFromLists();
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
@@ -3427,8 +3468,8 @@ namespace Barotrauma
|
||||
ic.GuiFrame = null;
|
||||
#endif
|
||||
}
|
||||
ItemList.Remove(this);
|
||||
dangerousItems.Remove(this);
|
||||
|
||||
RemoveFromLists();
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
@@ -3461,6 +3502,14 @@ namespace Barotrauma
|
||||
RemoveProjSpecific();
|
||||
}
|
||||
|
||||
private void RemoveFromLists()
|
||||
{
|
||||
ItemList.Remove(this);
|
||||
dangerousItems.Remove(this);
|
||||
repairableItems.Remove(this);
|
||||
cleanableItems.Remove(this);
|
||||
}
|
||||
|
||||
partial void RemoveProjSpecific();
|
||||
|
||||
public static void RemoveByPrefab(ItemPrefab prefab)
|
||||
|
||||
@@ -463,6 +463,15 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
}
|
||||
}
|
||||
|
||||
if (root == null)
|
||||
{
|
||||
Branches.ForEach(b => b.DisconnectedFromRoot = true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDisconnectedFromRoot();
|
||||
}
|
||||
|
||||
void LoadBranch(XElement branchElement, IdRemap idRemap)
|
||||
{
|
||||
Vector2 pos = branchElement.GetAttributeVector2("pos", Vector2.Zero);
|
||||
@@ -649,9 +658,10 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
toBeRemoved.Clear();
|
||||
foreach (BallastFloraBranch branch in Branches)
|
||||
{
|
||||
if (branch.ParentBranch != null && (branch.ParentBranch.DisconnectedFromRoot || branch.ParentBranch.Health <= 0.0f))
|
||||
if (branch.ParentBranch == null || branch.ParentBranch.DisconnectedFromRoot || branch.ParentBranch.Health <= 0.0f)
|
||||
{
|
||||
float speed = MathHelper.Lerp(5.0f, 0.1f, branch.ParentBranch.Health / branch.ParentBranch.MaxHealth);
|
||||
float parentHealth = branch.ParentBranch == null ? 0.0f : branch.ParentBranch.Health / branch.ParentBranch.MaxHealth;
|
||||
float speed = MathHelper.Lerp(5.0f, 0.1f, parentHealth);
|
||||
DamageBranch(branch, speed * speed * deltaTime, AttackType.CutFromRoot);
|
||||
}
|
||||
if (branch.Health <= 0.0f)
|
||||
@@ -1071,6 +1081,25 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckDisconnectedFromRoot()
|
||||
{
|
||||
bool foundDisconnected;
|
||||
do
|
||||
{
|
||||
foundDisconnected = false;
|
||||
foreach (BallastFloraBranch branch in Branches)
|
||||
{
|
||||
if (branch.ParentBranch == null || branch.DisconnectedFromRoot) { continue; }
|
||||
if (branch.ParentBranch.Removed || branch.ParentBranch.DisconnectedFromRoot)
|
||||
{
|
||||
branch.DisconnectedFromRoot = true;
|
||||
foundDisconnected = true;
|
||||
}
|
||||
}
|
||||
} while (foundDisconnected);
|
||||
|
||||
}
|
||||
|
||||
public void RemoveBranch(BallastFloraBranch branch)
|
||||
{
|
||||
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
|
||||
@@ -1081,20 +1110,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
Branches.Remove(branch);
|
||||
branch.Removed = true;
|
||||
|
||||
bool foundDisconnected = false;
|
||||
do
|
||||
{
|
||||
foundDisconnected = false;
|
||||
foreach (BallastFloraBranch otherBranch in Branches)
|
||||
{
|
||||
if (otherBranch.ParentBranch == null || otherBranch.DisconnectedFromRoot) { continue; }
|
||||
if (otherBranch.ParentBranch.Removed || otherBranch.ParentBranch.DisconnectedFromRoot)
|
||||
{
|
||||
otherBranch.DisconnectedFromRoot = true;
|
||||
foundDisconnected = true;
|
||||
}
|
||||
}
|
||||
} while (foundDisconnected);
|
||||
CheckDisconnectedFromRoot();
|
||||
|
||||
bodies.ForEachMod(body =>
|
||||
{
|
||||
|
||||
@@ -4056,7 +4056,11 @@ namespace Barotrauma
|
||||
string beaconStationName = System.IO.Path.GetFileNameWithoutExtension(contentFile.Path.Value);
|
||||
|
||||
BeaconStation = SpawnSubOnPath(beaconStationName, contentFile, SubmarineType.BeaconStation);
|
||||
if (BeaconStation == null) { return; }
|
||||
if (BeaconStation == null)
|
||||
{
|
||||
LevelData.HasBeaconStation = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Item sonarItem = Item.ItemList.Find(it => it.Submarine == BeaconStation && it.GetComponent<Sonar>() != null);
|
||||
if (sonarItem == null)
|
||||
@@ -4072,6 +4076,11 @@ namespace Barotrauma
|
||||
if (!LevelData.HasBeaconStation) { return; }
|
||||
if (GameMain.NetworkMember?.IsClient ?? false) { return; }
|
||||
|
||||
if (BeaconStation == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to prepare beacon station (no beacon station in the level).");
|
||||
}
|
||||
|
||||
List<Item> beaconItems = Item.ItemList.FindAll(it => it.Submarine == BeaconStation);
|
||||
|
||||
Item reactorItem = beaconItems.Find(it => it.GetComponent<Reactor>() != null);
|
||||
|
||||
@@ -567,6 +567,10 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static void UpdateAll(float deltaTime, Camera cam)
|
||||
{
|
||||
#if CLIENT
|
||||
var sw = new System.Diagnostics.Stopwatch();
|
||||
sw.Start();
|
||||
#endif
|
||||
foreach (Hull hull in Hull.HullList)
|
||||
{
|
||||
hull.Update(deltaTime, cam);
|
||||
@@ -594,6 +598,11 @@ namespace Barotrauma
|
||||
gapUpdateTimer = 0;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity:Misc", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
Powered.UpdatePower(deltaTime);
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
@@ -602,6 +611,11 @@ namespace Barotrauma
|
||||
|
||||
UpdateAllProjSpecific(deltaTime);
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity:Items", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
Spawner?.Update();
|
||||
}
|
||||
|
||||
|
||||
@@ -1857,15 +1857,23 @@ namespace Barotrauma
|
||||
|
||||
public void RefreshOutdoorNodes() => OutdoorNodes.ForEach(n => n?.Waypoint?.FindHull());
|
||||
|
||||
public Item FindContainerFor(Item item, bool onlyPrimary, bool checkTransferConditions = false)
|
||||
public Item FindContainerFor(Item item, bool onlyPrimary, bool checkTransferConditions = false, bool allowConnectedSubs = false)
|
||||
{
|
||||
var potentialContainers = new List<Item>();
|
||||
var connectedSubs = GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
|
||||
Item selectedContainer = null;
|
||||
foreach (Item potentialContainer in Item.ItemList)
|
||||
{
|
||||
if (potentialContainer.Removed) { continue; }
|
||||
if (potentialContainer.NonInteractable) { continue; }
|
||||
if (potentialContainer.HiddenInGame) { continue; }
|
||||
if (potentialContainer.Submarine != this) { continue; }
|
||||
if (allowConnectedSubs)
|
||||
{
|
||||
if (!connectedSubs.Contains(potentialContainer.Submarine)) { continue; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (potentialContainer.Submarine != this) { continue; }
|
||||
}
|
||||
if (potentialContainer == item) { continue; }
|
||||
if (potentialContainer.Condition <= 0) { continue; }
|
||||
if (potentialContainer.OwnInventory == null) { continue; }
|
||||
@@ -1875,13 +1883,15 @@ namespace Barotrauma
|
||||
if (!potentialContainer.OwnInventory.CanBePut(item)) { continue; }
|
||||
if (!container.ShouldBeContained(item, out _)) { continue; }
|
||||
if (!item.Prefab.IsContainerPreferred(item, container, out bool isPreferencesDefined, out bool isSecondary, checkTransferConditions: checkTransferConditions) || !isPreferencesDefined || onlyPrimary && isSecondary) { continue; }
|
||||
potentialContainers.Add(potentialContainer);
|
||||
if (!isSecondary)
|
||||
if (potentialContainer.Submarine == this && !isSecondary)
|
||||
{
|
||||
break;
|
||||
//valid primary container in the same sub -> perfect, let's use that one
|
||||
return potentialContainer;
|
||||
}
|
||||
selectedContainer = potentialContainer;
|
||||
|
||||
}
|
||||
return potentialContainers.LastOrDefault();
|
||||
return selectedContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@ namespace Barotrauma.Networking
|
||||
set;
|
||||
}
|
||||
|
||||
public ChatMode ChatMode { get; set; } = ChatMode.None;
|
||||
|
||||
protected ChatMessage(string senderName, string text, ChatMessageType type, Character sender, Client client, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None, Color? textColor = null)
|
||||
{
|
||||
Text = text;
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace Barotrauma
|
||||
|
||||
private readonly Dictionary<string, Queue<long>> elapsedTicks = new Dictionary<string, Queue<long>>();
|
||||
private readonly Dictionary<string, long> avgTicksPerFrame = new Dictionary<string, long>();
|
||||
private readonly Dictionary<string, Dictionary<string, TickInfo>> partialTickInfos = new Dictionary<string, Dictionary<string, TickInfo>>();
|
||||
|
||||
#if CLIENT
|
||||
internal Graph UpdateTimeGraph = new Graph(500), DrawTimeGraph = new Graph(500);
|
||||
@@ -43,20 +42,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<string> tempSavedPartialIdentifiers = new List<string>();
|
||||
public IReadOnlyList<string> GetSavedPartialIdentifiers(string parentIdentifier)
|
||||
{
|
||||
lock (mutex)
|
||||
{
|
||||
tempSavedPartialIdentifiers.Clear();
|
||||
if (partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos))
|
||||
{
|
||||
tempSavedPartialIdentifiers.AddRange(tickInfos.Keys);
|
||||
}
|
||||
}
|
||||
return tempSavedPartialIdentifiers;
|
||||
}
|
||||
|
||||
public void AddElapsedTicks(string identifier, long ticks)
|
||||
{
|
||||
lock (mutex)
|
||||
@@ -72,29 +57,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPartialElapsedTicks(string parentIdentifier, string identifier, long ticks)
|
||||
{
|
||||
lock (mutex)
|
||||
{
|
||||
if (!partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos))
|
||||
{
|
||||
tickInfos = new Dictionary<string, TickInfo>();
|
||||
partialTickInfos.Add(parentIdentifier, tickInfos);
|
||||
}
|
||||
if (!tickInfos.TryGetValue(identifier, out var tickInfo))
|
||||
{
|
||||
tickInfo = new TickInfo();
|
||||
tickInfos.Add(identifier, tickInfo);
|
||||
}
|
||||
tickInfo.ElapsedTicks.Enqueue(ticks);
|
||||
if (tickInfo.ElapsedTicks.Count > MaximumSamples)
|
||||
{
|
||||
tickInfo.ElapsedTicks.Dequeue();
|
||||
tickInfo.AvgTicksPerFrame = (long)tickInfo.ElapsedTicks.Average(i => i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float GetAverageElapsedMillisecs(string identifier)
|
||||
{
|
||||
long ticksPerFrame = 0;
|
||||
@@ -105,18 +67,6 @@ namespace Barotrauma
|
||||
return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
|
||||
}
|
||||
|
||||
public float GetPartialAverageElapsedMillisecs(string parentIdentifier, string identifier)
|
||||
{
|
||||
long ticksPerFrame = 0;
|
||||
lock (mutex)
|
||||
{
|
||||
if (!partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos)) { return 0.0f; }
|
||||
if (!tickInfos.TryGetValue(identifier, out var tickInfo)) { return 0.0f; }
|
||||
ticksPerFrame = tickInfo.AvgTicksPerFrame;
|
||||
}
|
||||
return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
|
||||
}
|
||||
|
||||
public bool Update(double deltaTime)
|
||||
{
|
||||
if (deltaTime == 0.0f) { return false; }
|
||||
|
||||
@@ -149,19 +149,19 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("GameSessionUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:GameSession", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
GameMain.ParticleManager.Update((float)deltaTime);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("ParticleUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Particles", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, cam);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Level", sw.ElapsedTicks);
|
||||
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
@@ -193,7 +193,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("CharacterUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Character", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("StatusEffectUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:StatusEffects", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
if (Character.Controlled != null &&
|
||||
@@ -253,7 +253,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("MapEntityUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
Character.UpdateAnimAll((float)deltaTime);
|
||||
@@ -266,7 +266,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("AnimUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Ragdolls", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("SubmarineUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Submarine", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Physics", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Physics", sw.ElapsedTicks);
|
||||
#endif
|
||||
UpdateProjSpecific(deltaTime);
|
||||
|
||||
|
||||
@@ -1119,7 +1119,12 @@ namespace Barotrauma
|
||||
itemComponent.SetRequiredItems(element, allowEmpty: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemComponent is ItemContainer itemContainer &&
|
||||
(componentElement.GetChildElement("containable") != null || componentElement.GetChildElement("subcontainer") != null))
|
||||
{
|
||||
itemContainer.LoadContainableRestrictions(componentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ namespace Barotrauma
|
||||
{
|
||||
MusicVolume = 0.3f,
|
||||
SoundVolume = 0.5f,
|
||||
UiVolume = 0.3f,
|
||||
VoiceChatVolume = 0.5f,
|
||||
VoiceChatCutoffPrevention = 0,
|
||||
MicrophoneVolume = 5,
|
||||
@@ -234,7 +235,6 @@ namespace Barotrauma
|
||||
UseDirectionalVoiceChat = true,
|
||||
VoipAttenuationEnabled = true,
|
||||
VoiceSetting = VoiceMode.PushToTalk,
|
||||
UseLocalVoiceByDefault = false,
|
||||
DisableVoiceChatFilters = false
|
||||
};
|
||||
return audioSettings;
|
||||
@@ -249,6 +249,7 @@ namespace Barotrauma
|
||||
|
||||
public float MusicVolume;
|
||||
public float SoundVolume;
|
||||
public float UiVolume;
|
||||
public float VoiceChatVolume;
|
||||
public int VoiceChatCutoffPrevention;
|
||||
public float MicrophoneVolume;
|
||||
@@ -264,7 +265,6 @@ namespace Barotrauma
|
||||
public string VoiceCaptureDevice;
|
||||
|
||||
public float NoiseGateThreshold;
|
||||
public bool UseLocalVoiceByDefault;
|
||||
public bool DisableVoiceChatFilters;
|
||||
}
|
||||
|
||||
@@ -286,12 +286,13 @@ namespace Barotrauma
|
||||
{ InputType.Aim, MouseButton.SecondaryMouse },
|
||||
|
||||
{ InputType.InfoTab, Keys.Tab },
|
||||
{ InputType.Chat, Keys.T },
|
||||
{ InputType.RadioChat, Keys.R },
|
||||
{ InputType.Chat, Keys.None },
|
||||
{ InputType.RadioChat, Keys.None },
|
||||
{ InputType.ActiveChat, Keys.T },
|
||||
{ InputType.CrewOrders, Keys.C },
|
||||
|
||||
{ InputType.Voice, Keys.V },
|
||||
{ InputType.LocalVoice, Keys.B },
|
||||
{ InputType.ToggleChatMode, Keys.R },
|
||||
{ InputType.Command, MouseButton.MiddleMouse },
|
||||
{ InputType.PreviousFireMode, MouseButton.MouseWheelDown },
|
||||
{ InputType.NextFireMode, MouseButton.MouseWheelUp },
|
||||
@@ -332,17 +333,35 @@ namespace Barotrauma
|
||||
if (!bindings.ContainsKey(inputType)) { bindings.Add(inputType, defaultBindings[inputType]); }
|
||||
}
|
||||
|
||||
bool playerConfigContainsNewChatBinds = false;
|
||||
foreach (XElement element in elements)
|
||||
{
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
if (Enum.TryParse(attribute.Name.LocalName, out InputType result))
|
||||
{
|
||||
if (!playerConfigContainsNewChatBinds)
|
||||
{
|
||||
playerConfigContainsNewChatBinds = result == InputType.ActiveChat;
|
||||
}
|
||||
bindings[result] = element.GetAttributeKeyOrMouse(attribute.Name.LocalName, bindings[result]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the old chat binds for configs saved before the introduction of the new chat binds
|
||||
if (!playerConfigContainsNewChatBinds)
|
||||
{
|
||||
if (bindings.ContainsKey(InputType.Chat))
|
||||
{
|
||||
bindings[InputType.Chat] = Keys.None;
|
||||
}
|
||||
if (bindings.ContainsKey(InputType.RadioChat))
|
||||
{
|
||||
bindings[InputType.RadioChat] = Keys.None;
|
||||
}
|
||||
}
|
||||
|
||||
Bindings = bindings.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Barotrauma
|
||||
/// Should the item spawn even if the container can't contain items of this type
|
||||
/// </summary>
|
||||
public readonly bool SpawnIfCantBeContained;
|
||||
public readonly float Speed;
|
||||
public readonly float Impulse;
|
||||
public readonly float Rotation;
|
||||
public readonly int Count;
|
||||
public readonly float Spread;
|
||||
@@ -198,7 +198,7 @@ namespace Barotrauma
|
||||
|
||||
SpawnIfInventoryFull = element.GetAttributeBool("spawnifinventoryfull", false);
|
||||
SpawnIfCantBeContained = element.GetAttributeBool("spawnifcantbecontained", true);
|
||||
Speed = element.GetAttributeFloat("speed", 0.0f);
|
||||
Impulse = element.GetAttributeFloat("impulse", element.GetAttributeFloat("speed", 0.0f));
|
||||
|
||||
Condition = MathHelper.Clamp(element.GetAttributeFloat("condition", 1.0f), 0.0f, 1.0f);
|
||||
|
||||
@@ -1708,7 +1708,7 @@ namespace Barotrauma
|
||||
throw new NotImplementedException("Spawn rotation type not implemented: " + chosenItemSpawnInfo.RotationType);
|
||||
}
|
||||
body.SetTransform(newItem.SimPosition, rotation);
|
||||
body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Speed);
|
||||
body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Impulse);
|
||||
}
|
||||
}
|
||||
newItem.Condition = newItem.MaxCondition * chosenItemSpawnInfo.Condition;
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.18.5.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Chat improvements:
|
||||
- Chat mode (radio/local) can be toggled using a dropdown next to the chat box or with a dedicated "ToggleChatMode" keybind (R by default).
|
||||
- Voice chat now has only one push-to-talk keybind (V by default) which respects the selected chat mode.
|
||||
- There's now a dedicated "ActiveChat" keybind (T by default) to open the chat using the currently active chat mode.
|
||||
- If you want to keep the chat keybinds the way they were (separate keybinds for local and radio), you can rebind the "Chat" and "RadioChat" inputs back to T and R and the new "ToggleChatMode" and "ActiveChat" inputs to something else.
|
||||
|
||||
Changes:
|
||||
- Optimized bot AIs: in particular, the cleanup, repair, pump water and load items objectives. Should significantly improve performance when the bots are doing these objectives when there's a large number of items in the sub.
|
||||
- Optimized entity culling logic (determines which items/structures are currently visible in the screen).
|
||||
- Optimized a bunch of textures.
|
||||
- Improved the performance statistics view that's enabled with the "showperf" console command: more fine-grained stats and easier-to-read visuals.
|
||||
- Added UI volume slider.
|
||||
- Depth charges can be stored in coilgun ammo shelves.
|
||||
|
||||
Fixes:
|
||||
- Fixed ballast flora branches that have been disconnected from the root not being considered disconnected after a level transition (allowing them to keep growing).
|
||||
- Fixed "set default bindings" not doing anything in the settings menu.
|
||||
- Fixed door/hatch gaps not getting moved when snapping to grid in the sub editor.
|
||||
- Vertically mirrored beds can't be laid on.
|
||||
- Fixed wrecked reactors being forced to non-interactable even if made interactable in the sub editor.
|
||||
|
||||
Unstable only:
|
||||
- Fixed crashing when you try to edit beacon station settings on a station you haven't saved yet.
|
||||
- Fixed level difficulties being incorrect in the "normal" difficulty setting (levels were set to the minimum difficulty of the biome, instead of a linear increase across the biome).
|
||||
- Misc fixes and improvements to the new beacon stations.
|
||||
- Fixed "max missions per round" value not being restricted in the UI.
|
||||
- Fixed items not getting transferred to/from linked subs.
|
||||
|
||||
Modding:
|
||||
- Doors and hatches can now be mirrored in the sub editor (making them open from top to bottom, or from right to left).
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.18.4.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
@@ -12,6 +47,7 @@ Unstable only:
|
||||
- Fixed sprite editor crashing if you try to reload a texture twice.
|
||||
- Fixed drone/shuttles getting left behind in the outpost when you buy and switch to a sub that has a one.
|
||||
- Fixed crashing when closing the submarine preview window.
|
||||
- Disallowed mirroring beds vertically.
|
||||
|
||||
Changes:
|
||||
- Added some new campaign settings: starting balance, amount of starting items and difficulty.
|
||||
@@ -19,13 +55,17 @@ Changes:
|
||||
- Made the descriptions of some materials (that used to just say "useful for crafting") more descriptive.
|
||||
- Increased oxygen generator output in some vanilla subs.
|
||||
- Made handheld sonar beacon sound less grating.
|
||||
- Disallowed mirroring beds vertically.
|
||||
- The client who initiated a vote cannot take part in that vote (except if they're the only client who can vote, in which case the vote automatically passes).
|
||||
- Made flashlight flicker before the battery runs out.
|
||||
- Added some lootable money to corpses found in wrecks.
|
||||
- Removed the small equipment indicators next to the character portrait.
|
||||
- Added a bunch of new UI sounds (tickbox toggling, confirming transactions, increase/decrease sounds for number inputs, cart sound for adding/removing items in store interfaces, selecting/clicking components, sliders and modlist).
|
||||
|
||||
- Optimized many status effects by making them only execute once per second instead of every frame (most importantly, diving suits and volatile fuel rods).
|
||||
- Optimized talents: buffs are applied to characters periodically instead of every frame.
|
||||
- Optimized the logic that bots use to determine the safety of hulls.
|
||||
- Optimized items: stop updating items that don't need to be updated more aggressively.
|
||||
- Weapon holders now use the tag "mountableweapon" instead of "weapon" to determine which items can be placed in them. Allows tagging non-weapon items as mountable in the holder, without making bots consider it a weapon due to the "weapon" tag. Also allows to keep some weapons not-mountable.
|
||||
- Ammunition Shelf can now also store Depth Charges ("depthchargeammo" tag added)
|
||||
|
||||
Fixes:
|
||||
- Split campaign state networking messages into multiple ones. Previously all the campaign-related data (map state, reputation, upgrades, purchased items, selected missions) was included in the same message, and whenever anything in the data changed, the server would send all of it to clients. This would cause performance and bandwidth issues in some situations, for example when reputation was changing rapidly.
|
||||
|
||||
Reference in New Issue
Block a user