Unstable 1.2.1.0

This commit is contained in:
Markus Isberg
2023-11-10 17:45:19 +02:00
parent 2ea58c58a7
commit 8a2e2ea0ae
268 changed files with 4076 additions and 1843 deletions
@@ -336,7 +336,10 @@ namespace Barotrauma
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
if (pressure > 0.0f)
{
float zoomInEffectStrength = MathHelper.Clamp(pressure / 100.0f, 0.1f, 1.0f);
//lerp in during the 1st second of the pressure timer so the zoom doesn't
//"flicker" in and out if the pressure fluctuates around the minimum threshold
float timerMultiplier = (PressureTimer / 100.0f);
float zoomInEffectStrength = MathHelper.Clamp(pressure / 100.0f * timerMultiplier, 0.0f, 1.0f);
cam.Zoom = MathHelper.Lerp(cam.Zoom,
cam.DefaultZoom + (Math.Max(pressure, 10) / 150.0f) * Rand.Range(0.9f, 1.1f),
zoomInEffectStrength);
@@ -8,24 +8,25 @@ namespace Barotrauma
{
internal abstract partial class CircuitBoxConnection
{
public string Name => Label.Value.Value;
public string Name => Connection.Name;
public CircuitBoxLabel Label { get; private set; }
private Sprite? knobSprite,
screwSprite,
connectorSprite;
private static int padding => GUI.IntScale(8);
private static int Padding => GUI.IntScale(8);
private Option<LocalizedString> tooltip = Option.None;
private partial void InitProjSpecific(CircuitBox circuitBox)
{
Label = new CircuitBoxLabel(Connection.Name, GUIStyle.SubHeadingFont);
Label = new CircuitBoxLabel(Connection.DisplayName, GUIStyle.SubHeadingFont);
knobSprite = circuitBox.ConnectionSprite;
screwSprite = circuitBox.ConnectionScrewSprite;
connectorSprite = circuitBox.WireConnectorSprite;
Length = Rect.Width + padding + Label.Size.X;
Length = Rect.Width + Padding + Label.Size.X;
}
public void Draw(SpriteBatch spriteBatch, Vector2 drawPos, Vector2 parentPos, Color color)
@@ -41,11 +42,11 @@ namespace Barotrauma
float xPos;
if (IsOutput)
{
xPos = drawRect.Left - padding - Label.Size.X;
xPos = drawRect.Left - Padding - Label.Size.X;
}
else
{
xPos = drawRect.Right + padding;
xPos = drawRect.Right + Padding;
}
Vector2 stringPos = new Vector2(xPos, drawRect.Center.Y - Label.Size.Y / 2f);
@@ -34,7 +34,7 @@ namespace Barotrauma
bool allowCheats = GameMain.NetworkMember == null && (GameMain.GameSession?.GameMode is TestGameMode || Screen.Selected is { IsEditor: true });
if (!allowCheats && !CheatsEnabled && IsCheat)
{
NewMessage("You need to enable cheats using the command \"enablecheats\" before you can use the command \"" + names[0] + "\".", Color.Red);
NewMessage("You need to enable cheats using the command \"enablecheats\" before you can use the command \"" + Names[0] + "\".", Color.Red);
#if USE_STEAM
NewMessage("Enabling cheats will disable Steam achievements during this play session.", Color.Red);
#endif
@@ -215,9 +215,9 @@ namespace Barotrauma
SoundPlayer.PlayUISound(GUISoundType.Select);
}
private static bool IsCommandPermitted(string command, GameClient client)
private static bool IsCommandPermitted(Identifier command, GameClient client)
{
switch (command)
switch (command.Value.ToLowerInvariant())
{
case "kick":
return client.HasPermission(ClientPermissions.Kick);
@@ -304,7 +304,7 @@ namespace Barotrauma
}
};
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 5, 0), textContainer.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(2, 2) },
msg.Text, textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
RichString.Rich(msg.Text), textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
{
CanBeFocused = false,
TextColor = msg.Color
@@ -346,7 +346,7 @@ namespace Barotrauma
CanBeFocused = false
};
var textBlock = new GUITextBlock(new RectTransform(new Point(listBox.Content.Rect.Width - 170, 0), textContainer.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(20, 0) },
command.help, textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
command.Help, textAlignment: Alignment.TopLeft, font: GUIStyle.SmallFont, wrap: true)
{
CanBeFocused = false,
TextColor = Color.White
@@ -354,7 +354,7 @@ namespace Barotrauma
textContainer.RectTransform.NonScaledSize = new Point(textContainer.RectTransform.NonScaledSize.X, textBlock.RectTransform.NonScaledSize.Y + 5);
textBlock.SetTextPos();
new GUITextBlock(new RectTransform(new Point(150, textContainer.Rect.Height), textContainer.RectTransform),
command.names[0], textAlignment: Alignment.TopLeft);
command.Names[0].Value, textAlignment: Alignment.TopLeft);
listBox.UpdateScrollBarSize();
listBox.BarScroll = 1.0f;
@@ -364,7 +364,7 @@ namespace Barotrauma
private static void AssignOnClientExecute(string names, Action<string[]> onClientExecute)
{
Command command = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
Command command = commands.Find(c => c.Names.Intersect(names.Split('|').ToIdentifiers()).Any());
if (command == null)
{
throw new Exception("AssignOnClientExecute failed. Command matching the name(s) \"" + names + "\" not found.");
@@ -378,7 +378,7 @@ namespace Barotrauma
private static void AssignRelayToServer(string names, bool relay)
{
Command command = commands.Find(c => c.names.Intersect(names.Split('|')).Count() > 0);
Command command = commands.Find(c => c.Names.Intersect(names.Split('|').ToIdentifiers()).Any());
if (command == null)
{
DebugConsole.Log("Could not assign to relay to server: " + names);
@@ -706,6 +706,8 @@ namespace Barotrauma
AssignRelayToServer("showmoney", true);
AssignRelayToServer("setskill", true);
AssignRelayToServer("readycheck", true);
commands.Add(new Command("debugjobassignment", "", (string[] args) => { }));
AssignRelayToServer("debugjobassignment", true);
AssignRelayToServer("givetalent", true);
AssignRelayToServer("unlocktalents", true);
@@ -374,13 +374,12 @@ namespace Barotrauma
btn.RectTransform.MinSize = new Point(0, (int)(btn.TextBlock.Rect.Height * 1.2f));
}
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height) + GUI.IntScale(16));
textContent.RectTransform.MinSize = new Point(0, textContent.Children.Sum(c => c.Rect.Height + textContent.AbsoluteSpacing) + GUI.IntScale(16));
content.RectTransform.MinSize = new Point(0, content.Children.Sum(c => c.Rect.Height));
// Recalculate the text size as it is scaled up and no longer matching the text height due to the textContent's minSize increasing
textBlock.CalculateHeightFromText();
textBlock.TextAlignment = Alignment.TopLeft;
//content.RectTransform.MinSize = new Point(0, textContent.Rect.Height);
return buttons;
}
@@ -47,7 +47,7 @@ namespace Barotrauma
}
float theoreticalMaxMonsterStrength = 10000;
float relativeMaxMonsterStrength = theoreticalMaxMonsterStrength * (GameMain.GameSession?.LevelData?.Difficulty ?? 0f) / 100;
float relativeMaxMonsterStrength = theoreticalMaxMonsterStrength * (GameMain.GameSession?.Level?.Difficulty ?? 0f) / 100;
float absoluteMonsterStrength = monsterStrength / theoreticalMaxMonsterStrength;
float relativeMonsterStrength = monsterStrength / relativeMaxMonsterStrength;
@@ -51,7 +51,8 @@ namespace Barotrauma
if (requiredDeliveryAmount == 0) { requiredDeliveryAmount = items.Count; }
if (requiredDeliveryAmount > items.Count)
{
DebugConsole.AddWarning($"Error in mission \"{Prefab.Identifier}\". Required delivery amount is {requiredDeliveryAmount} but there's only {items.Count} items to deliver.");
DebugConsole.AddWarning($"Error in mission \"{Prefab.Identifier}\". Required delivery amount is {requiredDeliveryAmount} but there's only {items.Count} items to deliver.",
contentPackage: Prefab.ContentPackage);
requiredDeliveryAmount = items.Count;
}
}
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Barotrauma.Extensions;
using Microsoft.Xna.Framework.Input;
namespace Barotrauma
{
@@ -81,6 +82,8 @@ namespace Barotrauma
public bool FlashOnAutoCloseCondition { get; set; }
public Action OnEnterPressed { get; set; }
public Type MessageBoxType => type;
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
@@ -89,6 +92,10 @@ namespace Barotrauma
: this(headerText, text, new LocalizedString[] { "OK" }, relativeSize, minSize, type: type)
{
this.Buttons[0].OnClicked = Close;
OnEnterPressed = () =>
{
Buttons[0].OnClicked(Buttons[0], Buttons[0].UserData);
};
}
public GUIMessageBox(RichString headerText, RichString text, LocalizedString[] buttons,
@@ -516,6 +523,11 @@ namespace Barotrauma
protected override void Update(float deltaTime)
{
if (PlayerInput.KeyHit(Keys.Enter))
{
OnEnterPressed?.Invoke();
}
if (Draggable)
{
GUIComponent parent = GUI.MouseOn?.Parent?.Parent;
@@ -18,6 +18,20 @@ namespace Barotrauma
public GUIButton PlusButton { get; private set; }
public GUIButton MinusButton { get; private set; }
private void UpdatePlusMinusButtonVisibility()
{
if (ForceShowPlusMinusButtons
|| inputType == NumberType.Int
|| (inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
{
ShowPlusMinusButtons();
}
else
{
HidePlusMinusButtons();
}
}
private NumberType inputType;
public NumberType InputType
{
@@ -26,15 +40,7 @@ namespace Barotrauma
{
if (inputType == value) { return; }
inputType = value;
if (inputType == NumberType.Int ||
(inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
{
ShowPlusMinusButtons();
}
else
{
HidePlusMinusButtons();
}
UpdatePlusMinusButtonVisibility();
}
}
@@ -46,15 +52,7 @@ namespace Barotrauma
{
minValueFloat = value;
ClampFloatValue();
if (inputType == NumberType.Int ||
(inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
{
ShowPlusMinusButtons();
}
else
{
HidePlusMinusButtons();
}
UpdatePlusMinusButtonVisibility();
}
}
public float? MaxValueFloat
@@ -64,15 +62,7 @@ namespace Barotrauma
{
maxValueFloat = value;
ClampFloatValue();
if (inputType == NumberType.Int ||
(inputType == NumberType.Float && MinValueFloat > float.MinValue && MaxValueFloat < float.MaxValue))
{
ShowPlusMinusButtons();
}
else
{
HidePlusMinusButtons();
}
UpdatePlusMinusButtonVisibility();
}
}
@@ -96,6 +86,19 @@ namespace Barotrauma
}
}
private bool forceShowPlusMinusButtons;
public bool ForceShowPlusMinusButtons
{
get { return forceShowPlusMinusButtons; }
set
{
if (forceShowPlusMinusButtons == value) { return; }
forceShowPlusMinusButtons = value;
UpdatePlusMinusButtonVisibility();
}
}
private int decimalsToDisplay = 1;
public int DecimalsToDisplay
{
@@ -184,7 +187,7 @@ namespace Barotrauma
/// </summary>
public bool WrapAround;
public float valueStep;
public float ValueStep;
private float pressedTimer;
private readonly float pressedDelay = 0.5f;
@@ -339,12 +342,12 @@ namespace Barotrauma
{
if (inputType == NumberType.Int)
{
IntValue -= valueStep > 0 ? (int)valueStep : 1;
IntValue -= ValueStep > 0 ? (int)ValueStep : 1;
ClampIntValue();
}
else if (maxValueFloat.HasValue && minValueFloat.HasValue)
{
FloatValue -= valueStep > 0 ? valueStep : Round();
FloatValue -= ValueStep > 0 ? ValueStep : Round();
ClampFloatValue();
}
}
@@ -353,12 +356,12 @@ namespace Barotrauma
{
if (inputType == NumberType.Int)
{
IntValue += valueStep > 0 ? (int)valueStep : 1;
IntValue += ValueStep > 0 ? (int)ValueStep : 1;
ClampIntValue();
}
else if (inputType == NumberType.Float)
{
FloatValue += valueStep > 0 ? valueStep : Round();
FloatValue += ValueStep > 0 ? ValueStep : Round();
ClampFloatValue();
}
}
@@ -341,9 +341,9 @@ namespace Barotrauma
};
var panelMaxWidth = (int)(GUI.xScale * (GUI.HorizontalAspectRatio < 1.4f ? 650 : 560));
var storeContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform)
var storeContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, Anchor.BottomLeft)
{
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height)
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height - HUDLayoutSettings.ButtonAreaTop.Bottom)
})
{
Stretch = true,
@@ -583,9 +583,9 @@ namespace Barotrauma
// Shopping Crate ------------------------------------------------------------------------------------------------------------------------------------------
var shoppingCrateContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, anchor: Anchor.TopRight)
var shoppingCrateContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, anchor: Anchor.BottomRight)
{
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height)
MaxSize = new Point(panelMaxWidth, campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).Rect.Height - HUDLayoutSettings.ButtonAreaTop.Bottom)
})
{
Stretch = true,
@@ -922,15 +922,12 @@ namespace Barotrauma
{
if (itemPrefab.CanBeBoughtFrom(ActiveStore, out PriceInfo priceInfo) && itemPrefab.CanCharacterBuy())
{
bool isDailySpecial = ActiveStore.DailySpecials.Contains(itemPrefab);
var itemFrame = isDailySpecial ?
storeDailySpecialsGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
storeBuyList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
if (CargoManager.GetPurchasedItem(ActiveStore, itemPrefab) is { } purchasedItem)
{
quantity = Math.Max(quantity - purchasedItem.Quantity, 0);
}
quantity = Math.Max(quantity - CargoManager.GetPurchasedItemCount(ActiveStore, itemPrefab), 0);
if (CargoManager.GetBuyCrateItem(ActiveStore, itemPrefab) is { } buyCrateItem)
{
quantity = Math.Max(quantity - buyCrateItem.Quantity, 0);
@@ -1245,9 +1242,9 @@ namespace Barotrauma
int totalPrice = 0;
if (ActiveStore != null)
{
foreach (PurchasedItem item in items)
foreach (PurchasedItem item in items.ToList())
{
if (!(item.ItemPrefab.GetPriceInfo(ActiveStore) is { } priceInfo)) { continue; }
if (item.ItemPrefab.GetPriceInfo(ActiveStore) is not { } priceInfo) { continue; }
GUINumberInput numInput = null;
if (!(listBox.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab.Identifier == item.ItemPrefab.Identifier) is { } itemFrame))
{
@@ -1749,7 +1746,7 @@ namespace Barotrauma
}
// Add items already purchased
CargoManager?.GetPurchasedItems(ActiveStore).ForEach(pi => AddNonEmptyOwnedItems(pi));
CargoManager?.GetPurchasedItems(ActiveStore).Where(pi => !pi.DeliverImmediately).ForEach(pi => AddNonEmptyOwnedItems(pi));
ownedItemsUpdateTimer = 0.0f;
@@ -1959,14 +1956,13 @@ namespace Barotrauma
}
catch (NotImplementedException e)
{
DebugConsole.LogError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
DebugConsole.LogError($"Error getting item availability: Unknown store tab type. {e.StackTrace.CleanupStackTrace()}");
}
if (list != null && list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
{
if (mode == StoreTab.Buy)
{
var purchasedItem = CargoManager.GetPurchasedItem(ActiveStore, item.ItemPrefab);
if (purchasedItem != null) { return Math.Max(item.Quantity - purchasedItem.Quantity, 0); }
return Math.Max(item.Quantity - CargoManager.GetPurchasedItemCount(ActiveStore, item.ItemPrefab), 0);
}
return item.Quantity;
}
@@ -2093,13 +2089,49 @@ namespace Barotrauma
}
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
if (itemsToPurchase.None() || Balance < totalPrice) { return false; }
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, true);
GameMain.Client?.SendCampaignState();
var dialog = new GUIMessageBox(
TextManager.Get("newsupplies"),
TextManager.GetWithVariable("suppliespurchasedmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
new LocalizedString[] { TextManager.Get("Ok") });
dialog.Buttons[0].OnClicked += dialog.Close;
if (CampaignMode.AllowImmediateItemDelivery())
{
var deliveryPrompt = new GUIMessageBox(
TextManager.Get("newsupplies"),
TextManager.Get("suppliespurchased.deliverymethod"),
new LocalizedString[]
{
TextManager.Get("suppliespurchased.deliverymethod.deliverimmediately"),
TextManager.Get("suppliespurchased.deliverymethod.delivertosub")
});
deliveryPrompt.Buttons[0].OnClicked = (btn, userdata) =>
{
ConfirmPurchase(deliverImmediately: true);
deliveryPrompt.Close();
return true;
};
deliveryPrompt.Buttons[1].OnClicked = (btn, userdata) =>
{
ConfirmPurchase(deliverImmediately: false);
deliveryPrompt.Close();
return true;
};
}
else
{
ConfirmPurchase(deliverImmediately: false);
}
void ConfirmPurchase(bool deliverImmediately)
{
itemsToPurchase.ForEach(it => it.DeliverImmediately = deliverImmediately);
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, removeFromCrate: true);
GameMain.Client?.SendCampaignState();
if (!deliverImmediately)
{
var dialog = new GUIMessageBox(
TextManager.Get("newsupplies"),
TextManager.GetWithVariable("suppliespurchasedmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name));
dialog.Buttons[0].OnClicked += dialog.Close;
}
}
return false;
}
@@ -163,7 +163,7 @@ namespace Barotrauma
else if (Tile)
{
Vector2 startPos = new Vector2(rect.X, rect.Y);
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color, startOffset: uvOffset);
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color: color, startOffset: uvOffset);
}
else
{
@@ -1110,7 +1110,7 @@ namespace Barotrauma
public static UpgradeFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
{
int price = prefab.Price.GetBuyPrice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
int price = prefab.Price.GetBuyPrice(prefab, campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
}
@@ -1267,7 +1267,7 @@ namespace Barotrauma
{
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
("[upgradename]", prefab.Name),
("[amount]", prefab.Price.GetBuyPrice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation, characterList).ToString()));
("[amount]", prefab.Price.GetBuyPrice(prefab, Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation, characterList).ToString()));
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
{
if (GameMain.NetworkMember != null)
@@ -1682,7 +1682,7 @@ namespace Barotrauma
GUITextBlock priceLabel = (GUITextBlock)buttonParent.FindChild(UpgradeStoreUserData.PriceLabel, recursive: true);
priceLabel.Visible = true;
int price = prefab.Price.GetBuyPrice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
int price = prefab.Price.GetBuyPrice(prefab, campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation, characterList);
if (!WaitForServerUpdate)
{
@@ -147,7 +147,7 @@ namespace Barotrauma
}
catch (NotImplementedException e)
{
DebugConsole.LogError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
DebugConsole.LogError($"Error selling items: unknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
return;
}
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
@@ -121,6 +121,16 @@ namespace Barotrauma
{
return AllowedToManageCampaign(ClientPermissions.ManageMoney);
}
public static bool AllowImmediateItemDelivery()
{
if (GameMain.Client == null) { return true; }
return
GameMain.Client.ServerSettings.AllowImmediateItemDelivery ||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
GameMain.Client.IsServerOwner;
}
protected GUIButton CreateEndRoundButton()
{
int buttonWidth = (int)(450 * GUI.xScale * (GUI.IsUltrawide ? 3.0f : 1.0f));
@@ -535,7 +535,7 @@ namespace Barotrauma
bool refreshCampaignUI = false;
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
if (GameMain.GameSession?.GameMode is not MultiPlayerCampaign campaign || campaignID != campaign.CampaignID)
{
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
@@ -98,7 +98,7 @@ namespace Barotrauma
if (gameSession.Missions.Any(m => m is CombatMission))
{
crewHeader.Text = CombatMission.GetTeamName(CharacterTeamType.Team1);
GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.45f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
GUIFrame crewFrame2 = new GUIFrame(new RectTransform(crewFrame.RectTransform.RelativeSize, background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
rightPanels.Add(crewFrame2);
GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame");
var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center))
@@ -54,7 +54,9 @@ namespace Barotrauma.Items.Components
{
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
{
if (!deconstructor.InputContainer.Inventory.AllItems.All(it => it.Prefab == item.Prefab))
var otherGeneticMaterial =
deconstructor.InputContainer.Inventory.AllItems.FirstOrDefault(it => it != item && it.Prefab == item.Prefab)?.GetComponent<GeneticMaterial>();
if (otherGeneticMaterial == null)
{
buttonText = TextManager.Get("researchstation.combine");
infoText = TextManager.Get("researchstation.combine.infotext");
@@ -62,7 +64,7 @@ namespace Barotrauma.Items.Components
else
{
buttonText = TextManager.Get("researchstation.refine");
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(Character.Controlled) * 100);
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(otherGeneticMaterial, Character.Controlled) * 100);
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
}
}
@@ -497,7 +497,8 @@ namespace Barotrauma.Items.Components
case "guiframe":
if (subElement.GetAttribute("rect") != null)
{
DebugConsole.ThrowError($"Error in item config \"{item.ConfigFilePath}\" - GUIFrame defined as rect, use RectTransform instead.");
DebugConsole.ThrowError($"Error in item config \"{item.ConfigFilePath}\" - GUIFrame defined as rect, use RectTransform instead.",
contentPackage: subElement.ContentPackage);
break;
}
GuiFrameSource = subElement;
@@ -516,7 +517,8 @@ namespace Barotrauma.Items.Components
if (filePath.IsNullOrEmpty())
{
DebugConsole.ThrowError(
$"Error when instantiating item \"{item.Name}\" - sound with no file path set");
$"Error when instantiating item \"{item.Name}\" - sound with no file path set",
contentPackage: subElement.ContentPackage);
break;
}
@@ -528,7 +530,8 @@ namespace Barotrauma.Items.Components
}
catch (Exception e)
{
DebugConsole.ThrowError($"Invalid sound type \"{typeStr}\" in item \"{item.Prefab.Identifier}\"!", e);
DebugConsole.ThrowError($"Invalid sound type \"{typeStr}\" in item \"{item.Prefab.Identifier}\"!", e,
contentPackage: subElement.ContentPackage);
break;
}
@@ -158,7 +158,8 @@ namespace Barotrauma.Items.Components
IndicatorStyle = GUIStyle.GetComponentStyle("ContainedStateIndicator." + ContainedStateIndicatorStyle);
if (ContainedStateIndicator != null || ContainedStateIndicatorEmpty != null)
{
DebugConsole.AddWarning($"Item \"{item.Name}\" defines both a contained state indicator style and a custom indicator sprite. Will use the custom sprite...");
DebugConsole.AddWarning($"Item \"{item.Name}\" defines both a contained state indicator style and a custom indicator sprite. Will use the custom sprite...",
contentPackage: item.Prefab.ContentPackage);
}
}
if (GuiFrame == null)
@@ -393,6 +393,8 @@ namespace Barotrauma.Items.Components
partial void SelectProjSpecific(Character character)
{
if (character != Character.Controlled) { return; }
var nonItems = itemList.Content.Children.Where(c => c.UserData is not FabricationRecipe).ToList();
nonItems.ForEach(i => itemList.Content.RemoveChild(i));
@@ -784,6 +786,7 @@ namespace Barotrauma.Items.Components
private void HideEmptyItemListCategories()
{
bool visibleElementsChanged = false;
//go through the elements backwards, and disable the labels ("insufficient skills to fabricate", "recipe required...") if there's no items below them
bool recipeVisible = false;
foreach (GUIComponent child in itemList.Content.Children.Reverse())
@@ -792,7 +795,11 @@ namespace Barotrauma.Items.Components
{
if (child.Enabled)
{
child.Visible = recipeVisible;
if (child.Visible != recipeVisible)
{
child.Visible = recipeVisible;
visibleElementsChanged = true;
}
}
recipeVisible = false;
}
@@ -802,8 +809,11 @@ namespace Barotrauma.Items.Components
}
}
itemList.UpdateScrollBarSize();
itemList.BarScroll = 0.0f;
if (visibleElementsChanged)
{
itemList.UpdateScrollBarSize();
itemList.BarScroll = 0.0f;
}
}
public bool ClearFilter()
@@ -66,7 +66,15 @@ namespace Barotrauma.Items.Components
private float prevPassivePingRadius;
private Vector2 center;
private float displayScale;
/// <summary>
/// Current scale of the display, taking zoom into account. In other words, the scaling factor of world coordinates to coordinates on the display.
/// </summary>
public float DisplayScale
{
get;
private set;
} = 1.0f;
private const float DisruptionUpdateInterval = 0.2f;
private float disruptionUpdateTimer;
@@ -751,9 +759,9 @@ namespace Barotrauma.Items.Components
{
var activePing = activePings[pingIndex];
float pingRadius = DisplayRadius * activePing.State / zoom;
if (disruptionUpdateTimer <= 0.0f) { UpdateDisruptions(transducerCenter, pingRadius / displayScale); }
if (disruptionUpdateTimer <= 0.0f) { UpdateDisruptions(transducerCenter, pingRadius / DisplayScale); }
Ping(transducerCenter, transducerCenter,
pingRadius, activePing.PrevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f);
pingRadius, activePing.PrevPingRadius, DisplayScale, range / zoom, passive: false, pingStrength: 2.0f);
activePing.PrevPingRadius = pingRadius;
}
if (disruptionUpdateTimer <= 0.0f)
@@ -770,7 +778,7 @@ namespace Barotrauma.Items.Components
if (c.Params.HideInSonar) { continue; }
if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f &&
((c.WorldPosition - transducerCenter) * displayScale).LengthSquared() > DisplayRadius * DisplayRadius)
((c.WorldPosition - transducerCenter) * DisplayScale).LengthSquared() > DisplayRadius * DisplayRadius)
{
Vector2 targetVector = c.WorldPosition - transducerCenter;
if (targetVector.LengthSquared() > MathUtils.Pow2(c.Params.DistantSonarRange)) { continue; }
@@ -818,7 +826,7 @@ namespace Barotrauma.Items.Components
if (dist > prevPassivePingRadius * Range && dist <= passivePingRadius * Range && Rand.Int(sonarBlips.Count) < 500)
{
Ping(t.WorldPosition, transducerCenter,
t.SoundRange * displayScale, 0, displayScale, range,
t.SoundRange * DisplayScale, 0, DisplayScale, range,
passive: true, pingStrength: 0.5f, needsToBeInSector: t);
if (t.IsWithinSector(transducerCenter))
{
@@ -857,7 +865,7 @@ namespace Barotrauma.Items.Components
displayBorderSize = 0.2f;
center = rect.Center.ToVector2();
DisplayRadius = (rect.Width / 2.0f) * (1.0f - displayBorderSize);
displayScale = DisplayRadius / range * zoom;
DisplayScale = DisplayRadius / range * zoom;
screenBackground?.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
@@ -972,7 +980,7 @@ namespace Barotrauma.Items.Components
aiTarget.SonarIconIdentifier,
aiTarget,
aiTarget.WorldPosition, transducerCenter,
displayScale, center, DisplayRadius * 0.975f);
DisplayScale, center, DisplayRadius * 0.975f);
}
}
@@ -987,7 +995,7 @@ namespace Barotrauma.Items.Components
(Level.Loaded.StartOutpost != null ? "outpost" : "location").ToIdentifier(),
"startlocation",
Level.Loaded.StartExitPosition, transducerCenter,
displayScale, center, DisplayRadius);
DisplayScale, center, DisplayRadius);
}
if (Level.Loaded is { EndLocation.Type.ShowSonarMarker: true, Type: LevelData.LevelType.LocationConnection })
@@ -997,7 +1005,7 @@ namespace Barotrauma.Items.Components
(Level.Loaded.EndOutpost != null ? "outpost" : "location").ToIdentifier(),
"endlocation",
Level.Loaded.EndExitPosition, transducerCenter,
displayScale, center, DisplayRadius);
DisplayScale, center, DisplayRadius);
}
for (int i = 0; i < Level.Loaded.Caves.Count; i++)
@@ -1009,7 +1017,7 @@ namespace Barotrauma.Items.Components
"cave".ToIdentifier(),
"cave" + i,
cave.StartPos.ToVector2(), transducerCenter,
displayScale, center, DisplayRadius);
DisplayScale, center, DisplayRadius);
}
}
@@ -1026,7 +1034,7 @@ namespace Barotrauma.Items.Components
mission.SonarIconIdentifier,
"mission" + missionIndex + ":" + i,
position, transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
DisplayScale, center, DisplayRadius * 0.95f);
}
i++;
}
@@ -1059,7 +1067,7 @@ namespace Barotrauma.Items.Components
DrawMarker(spriteBatch,
i.Name, "mineral".ToIdentifier(), "mineralcluster" + i,
c.center, transducerCenter,
displayScale, center, DisplayRadius * 0.95f,
DisplayScale, center, DisplayRadius * 0.95f,
onlyShowTextOnMouseOver: true);
}
}
@@ -1088,19 +1096,19 @@ namespace Barotrauma.Items.Components
(sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine").ToIdentifier(),
sub,
sub.WorldPosition, transducerCenter,
displayScale, center, DisplayRadius * 0.95f);
DisplayScale, center, DisplayRadius * 0.95f);
}
if (GameMain.DebugDraw)
{
var steering = item.GetComponent<Steering>();
steering?.DebugDrawHUD(spriteBatch, transducerCenter, displayScale, DisplayRadius, center);
steering?.DebugDrawHUD(spriteBatch, transducerCenter, DisplayScale, DisplayRadius, center);
}
}
private void DrawOwnSubmarineBorders(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
{
float simScale = displayScale * Physics.DisplayToSimRation * zoom;
float simScale = DisplayScale * Physics.DisplayToSimRation;
foreach (Submarine submarine in Submarine.Loaded)
{
@@ -1167,7 +1175,7 @@ namespace Barotrauma.Items.Components
private void DrawDockingPorts(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength)
{
float scale = displayScale * zoom;
float scale = DisplayScale;
Steering steering = item.GetComponent<Steering>();
if (steering != null && steering.DockingModeEnabled && steering.ActiveDockingSource != null)
@@ -1219,7 +1227,7 @@ namespace Barotrauma.Items.Components
private void DrawDockingIndicator(SpriteBatch spriteBatch, Steering steering, ref Vector2 transducerCenter)
{
float scale = displayScale * zoom;
float scale = DisplayScale;
Vector2 worldFocusPos = (steering.ActiveDockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f;
worldFocusPos.X = steering.DockingTarget.Item.WorldPosition.X;
@@ -1591,7 +1599,7 @@ namespace Barotrauma.Items.Components
{
lineStep /= zoom;
zStep /= zoom;
range *= displayScale;
range *= DisplayScale;
float length = (point1 - point2).Length();
Vector2 lineDir = (point2 - point1) / length;
for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
@@ -1602,12 +1610,12 @@ namespace Barotrauma.Items.Components
//ignore if outside the display
Vector2 transducerDiff = point - transducerPos;
Vector2 transducerDisplayDiff = transducerDiff * displayScale;
Vector2 transducerDisplayDiff = transducerDiff * DisplayScale / zoom;
if (transducerDisplayDiff.LengthSquared() > DisplayRadius * DisplayRadius) { continue; }
//ignore if the point is not within the ping
Vector2 pointDiff = point - pingSource;
Vector2 displayPointDiff = pointDiff * displayScale;
Vector2 displayPointDiff = pointDiff * DisplayScale / zoom;
float displayPointDistSqr = displayPointDiff.LengthSquared();
if (displayPointDistSqr < prevPingRadius * prevPingRadius || displayPointDistSqr > pingRadius * pingRadius) { continue; }
@@ -1628,9 +1636,9 @@ namespace Barotrauma.Items.Components
float displayPointDist = (float)Math.Sqrt(displayPointDistSqr);
float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
for (float z = 0; z < DisplayRadius - transducerDist * displayScale; z += zStep)
for (float z = 0; z < DisplayRadius - transducerDist * DisplayScale; z += zStep)
{
Vector2 pos = point + Rand.Vector(150.0f / zoom) + pingDirection * z / displayScale;
Vector2 pos = point + Rand.Vector(150.0f / zoom) + pingDirection * z / DisplayScale;
float fadeTimer = alpha * (1.0f - displayPointDist / range);
if (needsToBeInSector != null)
@@ -1697,7 +1705,7 @@ namespace Barotrauma.Items.Components
private bool CheckBlipVisibility(SonarBlip blip, Vector2 transducerPos)
{
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
Vector2 pos = (blip.Position - transducerPos) * DisplayScale;
pos.Y = -pos.Y;
float posDistSqr = pos.LengthSquared();
@@ -1731,7 +1739,7 @@ namespace Barotrauma.Items.Components
}
if (currentPingIndex != -1 && activePings[currentPingIndex].IsDirectional)
{
var pos = (resourcePos - transducerPos) * displayScale * zoom;
var pos = (resourcePos - transducerPos) * DisplayScale;
pos.Y = -pos.Y;
var length = pos.Length();
var dir = pos / length;
@@ -1749,7 +1757,7 @@ namespace Barotrauma.Items.Components
float distort = 1.0f - item.Condition / item.MaxCondition;
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
Vector2 pos = (blip.Position - transducerPos) * DisplayScale;
pos.Y = -pos.Y;
if (Rand.Range(0.5f, 2.0f) < distort) { pos.X = -pos.X; }
@@ -1825,14 +1833,13 @@ namespace Barotrauma.Items.Components
Vector2 position = worldPosition - transducerPosition;
position *= zoom;
position *= scale;
position.Y = -position.Y;
float textAlpha = MathHelper.Clamp(1.5f - dist / 50000.0f, 0.5f, 1.0f);
Vector2 dir = Vector2.Normalize(position);
Vector2 markerPos = (linearDist * zoom * scale > radius) ? dir * radius : position;
Vector2 markerPos = (linearDist * scale > radius) ? dir * radius : position;
markerPos += center;
markerPos.X = (int)markerPos.X;
@@ -589,7 +589,8 @@ namespace Barotrauma.Items.Components
Sonar sonar = item.GetComponent<Sonar>();
if (sonar != null && controlledSub != null)
{
Vector2 displayPosToMaintain = ((posToMaintain.Value - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom;
Vector2 displayPosToMaintain = ((posToMaintain.Value - controlledSub.WorldPosition)) * sonar.DisplayScale;
displayPosToMaintain.Y = -displayPosToMaintain.Y;
displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2);
displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain;
@@ -670,14 +671,14 @@ namespace Barotrauma.Items.Components
pos2.Y = -pos2.Y;
pos2 += center;
GUI.DrawLine(spriteBatch,
pos1,
GUI.DrawLine(spriteBatch,
pos1,
pos2,
GUIStyle.Red * 0.6f, width: 3);
if (obstacle.Intersection.HasValue)
{
Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) *displayScale;
Vector2 intersectionPos = (obstacle.Intersection.Value - transducerCenter) * displayScale;
intersectionPos.Y = -intersectionPos.Y;
intersectionPos += center;
GUI.DrawRectangle(spriteBatch, intersectionPos - Vector2.One * 2, Vector2.One * 4, GUIStyle.Red);
@@ -151,7 +151,7 @@ namespace Barotrauma.Items.Components
GUI.DrawLine(spriteBatch,
new Vector2(debugRayStartPos.X, -debugRayStartPos.Y),
new Vector2(debugRayEndPos.X, -debugRayEndPos.Y),
Color.Yellow);
Color.Yellow, width: 3f);
}
}
#endif
@@ -269,7 +269,7 @@ namespace Barotrauma.Items.Components
resource = ItemPrefab.Prefabs[Tags.FPGACircuit];
}
AddComponentInternal(ICircuitBoxIdentifiable.FindFreeID(Components), prefab, resource, pos, static delegate { });
AddComponentInternal(ICircuitBoxIdentifiable.FindFreeID(Components), prefab, resource, pos, Character.Controlled, onItemSpawned: null);
return;
}
@@ -95,7 +95,7 @@ namespace Barotrauma.Items.Components
MaxValueFloat = numberInputMax,
FloatValue = Math.Clamp(floatSignal, numberInputMin, numberInputMax),
DecimalsToDisplay = ciElement.NumberInputDecimalPlaces,
valueStep = numberInputStep,
ValueStep = numberInputStep,
OnValueChanged = (ni) =>
{
if (GameMain.Client == null)
@@ -121,7 +121,7 @@ namespace Barotrauma.Items.Components
MinValueInt = numberInputMin,
MaxValueInt = numberInputMax,
IntValue = Math.Clamp(intSignal, numberInputMin, numberInputMax),
valueStep = numberInputStep,
ValueStep = numberInputStep,
OnValueChanged = (ni) =>
{
if (GameMain.Client == null)
@@ -137,7 +137,8 @@ namespace Barotrauma.Items.Components
}
else
{
DebugConsole.LogError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\"");
DebugConsole.LogError($"Error creating a CustomInterface component: unexpected NumberType \"{(ciElement.NumberType.HasValue ? ciElement.NumberType.Value.ToString() : "none")}\"",
contentPackage: item.Prefab.ContentPackage);
}
if (numberInput != null)
{
@@ -349,8 +349,8 @@ namespace Barotrauma.Items.Components
}
GUI.DrawString(spriteBatch, hudPos, texts[0].Value, textColors[0] * alpha, Color.Black * 0.7f * alpha, 2, GUIStyle.SubHeadingFont, ForceUpperCase.No);
hudPos.X += 5.0f;
hudPos.Y += 24.0f * GameSettings.CurrentConfig.Graphics.TextScale;
hudPos.X += 5.0f * GUI.Scale;
hudPos.Y += GUIStyle.SubHeadingFont.MeasureString(texts[0].Value).Y;
hudPos.X = (int)hudPos.X;
hudPos.Y = (int)hudPos.Y;
@@ -358,7 +358,7 @@ namespace Barotrauma.Items.Components
for (int i = 1; i < texts.Count; i++)
{
GUI.DrawString(spriteBatch, hudPos, texts[i], textColors[i] * alpha, Color.Black * 0.7f * alpha, 2, GUIStyle.SmallFont);
hudPos.Y += (int)(18.0f * GameSettings.CurrentConfig.Graphics.TextScale);
hudPos.Y += (int)(GUIStyle.SubHeadingFont.MeasureString(texts[i].Value).Y);
}
}
}
@@ -258,7 +258,7 @@ namespace Barotrauma
else
{
LocalizedString description = item.Description;
if (item.HasTag(Tags.IdCard) || item.HasTag(Tags.DespawnContainer))
if (item.HasTag(Tags.IdCardTag) || item.HasTag(Tags.DespawnContainer))
{
string[] readTags = item.Tags.Split(',');
string idName = null;
@@ -1505,14 +1505,28 @@ namespace Barotrauma
int stackAmount = DraggingItems.Count;
if (selectedSlot?.ParentInventory != null)
{
stackAmount = Math.Min(
stackAmount,
selectedSlot.ParentInventory.HowManyCanBePut(draggedItem.Prefab, selectedSlot.SlotIndex, draggedItem.Condition));
if (selectedSlot.Item?.OwnInventory != null)
{
int maxAmountPerSlot = 0;
for (int i = 0; i < SelectedSlot.Item.OwnInventory.Capacity; i++)
{
maxAmountPerSlot = Math.Max(
maxAmountPerSlot,
selectedSlot.Item.OwnInventory.HowManyCanBePut(draggedItem.Prefab, i, draggedItem.Condition, ignoreItemsInSlot: true));
}
stackAmount = Math.Min(stackAmount, maxAmountPerSlot);
}
else
{
stackAmount = Math.Min(
stackAmount,
selectedSlot.ParentInventory.HowManyCanBePut(draggedItem.Prefab, selectedSlot.SlotIndex, draggedItem.Condition, ignoreItemsInSlot: true));
}
}
Vector2 stackCountPos = itemPos + Vector2.One * iconSize * 0.25f;
string stackCountText = "x" + stackAmount;
GUIStyle.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos + Vector2.One, Color.Black);
GUIStyle.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos, GUIStyle.TextColorBright);
GUIStyle.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos, GUIStyle.TextColorBright);
}
}
}
@@ -1908,6 +1922,15 @@ namespace Barotrauma
foreach (UInt16 id in receivedItemIDs[i])
{
if (Entity.FindEntityByID(id) is not Item item || slots[i].Contains(item)) { continue; }
if (Owner is Item thisItem && thisItem.Container == item)
{
//if this item is inside the item we're trying to contain inside it, we need to drop it (both items can't be inside each other!)
//can happen when a player swaps the items to be "the other way around", and we receive a message about the contained item
//before the message about the "parent item" being placed in some other inventory (like the player's inventory)
thisItem.Drop(null);
}
if (!TryPutItem(item, i, false, false, null, false))
{
ForceToSlot(item, i);
@@ -132,9 +132,9 @@ namespace Barotrauma
return GetDrawDepth(SpriteDepth + DrawDepthOffset, Sprite);
}
public Color GetSpriteColor(bool withHighlight = false)
public Color GetSpriteColor(Color? defaultColor = null, bool withHighlight = false)
{
Color color = spriteColor;
Color color = defaultColor ?? spriteColor;
if (Prefab.UseContainedSpriteColor && ownInventory != null)
{
foreach (Item item in ContainedItems)
@@ -333,9 +333,7 @@ namespace Barotrauma
else if (!ShowItems) { return; }
}
Color color =
overrideColor ??
(IsIncludedInSelection && editing ? GUIStyle.Blue : GetSpriteColor(withHighlight: true));
Color color = GetSpriteColor(spriteColor);
bool isWiringMode = editing && SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode() && !isWire && parentInventory == null;
bool renderTransparent = isWiringMode && GetComponent<ConnectionPanel>() == null;
@@ -406,12 +404,14 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
Color decorativeSpriteColor = GetSpriteColor(decorativeSprite.Color);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flippedX && Prefab.CanSpriteFlipX ? RotationRad : -RotationRad) * Scale;
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
decorativeSprite.Sprite.DrawTiled(spriteBatch,
new Vector2(DrawPosition.X + offset.X - rect.Width / 2, -(DrawPosition.Y + offset.Y + rect.Height / 2)),
size, color: color,
size, color: decorativeSpriteColor,
textureScale: Vector2.One * Scale,
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
}
@@ -437,13 +437,15 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
Color decorativeSpriteColor = GetSpriteColor(decorativeSprite.Color);
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
bool flipX = flippedX && Prefab.CanSpriteFlipX;
bool flipY = flippedY && Prefab.CanSpriteFlipY;
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, flipX ^ flipY ? RotationRad : -RotationRad) * Scale;
if (flipX) { offset.X = -offset.X; }
if (flipY) { offset.Y = -offset.Y; }
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), decorativeSpriteColor,
RotationRad + rot, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
}
@@ -618,6 +620,13 @@ namespace Barotrauma
}
return origin;
}
Color GetSpriteColor(Color defaultColor)
{
return
overrideColor ??
(IsIncludedInSelection && editing ? GUIStyle.Blue : this.GetSpriteColor(defaultColor: defaultColor, withHighlight: true));
}
}
partial void OnCollisionProjSpecific(float impact)
@@ -852,7 +861,7 @@ namespace Barotrauma
CanBeFocused = true
};
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
var mirrorX = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
{
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
Enabled = Prefab.CanFlipX,
@@ -863,10 +872,12 @@ namespace Barotrauma
me.FlipX(relativeToSub: false);
}
if (!SelectedList.Contains(this)) { FlipX(relativeToSub: false); }
ColorFlipButton(button, FlippedX);
return true;
}
};
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
ColorFlipButton(mirrorX, FlippedX);
var mirrorY = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
{
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
Enabled = Prefab.CanFlipY,
@@ -877,9 +888,11 @@ namespace Barotrauma
me.FlipY(relativeToSub: false);
}
if (!SelectedList.Contains(this)) { FlipY(relativeToSub: false); }
ColorFlipButton(button, FlippedY);
return true;
}
};
ColorFlipButton(mirrorY, FlippedY);
if (Sprite != null)
{
var reloadTextureButton = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall");
@@ -321,10 +321,8 @@ namespace Barotrauma
}
else
{
if (ResizeHorizontal)
placeSize.X = Math.Max(position.X - placePosition.X, Size.X);
if (ResizeVertical)
placeSize.Y = Math.Max(placePosition.Y - position.Y, Size.Y);
if (ResizeHorizontal) { placeSize.X = Math.Max(position.X - placePosition.X, Size.X); }
if (ResizeVertical) { placeSize.Y = Math.Max(placePosition.Y - position.Y, Size.Y); }
if (PlayerInput.PrimaryMouseButtonReleased())
{
@@ -369,15 +367,23 @@ namespace Barotrauma
}
}
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, SpriteEffects spriteEffects = SpriteEffects.None)
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
{
if (!ResizeHorizontal && !ResizeVertical)
{
Sprite.Draw(spriteBatch, new Vector2(placeRect.Center.X, -(placeRect.Y - placeRect.Height / 2)), SpriteColor * 0.8f, scale: scale);
sprite.Draw(spriteBatch, new Vector2(placeRect.Center.X, -(placeRect.Y - placeRect.Height / 2)), SpriteColor * 0.8f, scale: scale, rotate: rotation);
}
else
{
Sprite.DrawTiled(spriteBatch, new Vector2(placeRect.X, -placeRect.Y), placeRect.Size.ToVector2(), SpriteColor * 0.8f);
Vector2 position = placeRect.Location.ToVector2();
Vector2 placeSize = placeRect.Size.ToVector2();
sprite?.DrawTiled(
spriteBatch,
new Vector2(position.X, -position.Y),
placeSize,
rotation: rotation,
textureScale: Vector2.One * scale,
color: SpriteColor * 0.8f);
}
}
@@ -277,12 +277,21 @@ namespace Barotrauma
Rectangle drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
if ((IsSelected || IsHighlighted) && editing)
if (editing)
{
if (IsSelected || IsHighlighted)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
(IsHighlighted ? Color.LightBlue * 0.8f : GUIStyle.Red * 0.5f) * alpha, false, 0, (int)Math.Max(5.0f / Screen.Selected.Cam.Zoom, 1.0f));
}
float waterHeight = WaterVolume / rect.Width;
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
(IsHighlighted ? Color.LightBlue * 0.8f : GUIStyle.Red * 0.5f) * alpha, false, 0, (int)Math.Max(5.0f / Screen.Selected.Cam.Zoom, 1.0f));
new Vector2(drawRect.X, -drawRect.Y + drawRect.Height - waterHeight),
new Vector2(drawRect.Width, waterHeight),
Color.Blue * 0.25f, isFilled: true);
}
GUI.DrawRectangle(spriteBatch,
@@ -300,13 +309,27 @@ namespace Barotrauma
" - Oxygen: " + ((int)OxygenPercentage), new Vector2(drawRect.X + 5, -drawRect.Y + 5), Color.White);
GUIStyle.SmallFont.DrawString(spriteBatch, waterVolume + " / " + Volume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White);
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * Math.Min(waterVolume / Volume, 1.0f))), Color.Cyan, true);
if (WaterVolume > Volume)
if (WaterVolume > 0)
{
float maxExcessWater = Volume * MaxCompress;
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, (int)(100 * (waterVolume - Volume) / maxExcessWater)), GUIStyle.Red, true);
drawProgressBar(50, new Point(0, 0), Math.Min(waterVolume / Volume, 1.0f), Color.Cyan);
if (WaterVolume > Volume)
{
float maxExcessWater = Volume * MaxCompress;
drawProgressBar(50, new Point(0, 0), (waterVolume - Volume) / maxExcessWater, GUIStyle.Red);
}
}
if (lethalPressure > 0)
{
drawProgressBar(50, new Point(20, 0), lethalPressure / 100.0f, Color.Red);
}
void drawProgressBar(int height, Point offset, float fillAmount, Color color)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X - 2 + offset.X, -drawRect.Y - 2 + drawRect.Height / 2 + offset.Y, 14, height+4), Color.Black * 0.8f, depth: 0.01f, isFilled: true);
int barHeight = (int)(fillAmount * height);
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X + offset.X, -drawRect.Y + drawRect.Height / 2 + height - barHeight + offset.Y, 10, barHeight), color, isFilled: true);
}
GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.Center.X, -drawRect.Y + drawRect.Height / 2, 10, 100), Color.Black);
foreach (FireSource fs in FireSources)
{
@@ -732,7 +755,7 @@ namespace Barotrauma
var newFire = i < FireSources.Count ?
FireSources[i] :
new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
new FireSource(Submarine == null ? pos : pos + Submarine.Position, sourceCharacter: null, isNetworkMessage: true);
newFire.Position = pos;
newFire.Size = new Vector2(size, newFire.Size.Y);
@@ -43,7 +43,7 @@ namespace Barotrauma
{
mainElement = mainElement.FirstElement();
prefabs.Clear();
DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.Yellow);
DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.MediumPurple);
}
else if (prefabs.Any())
{
@@ -53,7 +53,7 @@ namespace Barotrauma
foreach (InterestingPosition pos in PositionsOfInterest)
{
Color color = Color.Yellow;
if (pos.PositionType == PositionType.Cave)
if (pos.PositionType == PositionType.Cave || pos.PositionType == PositionType.AbyssCave)
{
color = Color.DarkOrange;
}
@@ -61,6 +61,10 @@ namespace Barotrauma
{
color = Color.LightGray;
}
if (!pos.IsValid)
{
color = Color.Red;
}
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
}
@@ -1318,7 +1318,7 @@ namespace Barotrauma.Lights
if (LightTextureTargetSize != Vector2.Zero)
{
LightSprite.DrawTiled(spriteBatch, drawPos, LightTextureTargetSize, color, startOffset: LightTextureOffset, textureScale: LightTextureScale);
LightSprite.DrawTiled(spriteBatch, drawPos, LightTextureTargetSize, color: color, startOffset: LightTextureOffset, textureScale: LightTextureScale);
}
else
{
@@ -29,7 +29,7 @@ namespace Barotrauma
Vector2 spriteScale = new Vector2(zoom);
uiSprite.Sprite.DrawTiled(spriteBatch, topLeft, size, Params.RadiationAreaColor, Vector2.Zero, textureScale: spriteScale);
uiSprite.Sprite.DrawTiled(spriteBatch, topLeft, size, color: Params.RadiationAreaColor, startOffset: Vector2.Zero, textureScale: spriteScale);
Vector2 topRight = topLeft + Vector2.UnitX * size.X;
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Barotrauma.Lights;
using Microsoft.Xna.Framework;
namespace Barotrauma
{
@@ -65,9 +66,7 @@ namespace Barotrauma
disableSelect = value;
if (disableSelect)
{
startMovingPos = Vector2.Zero;
selectionSize = Vector2.Zero;
selectionPos = Vector2.Zero;
StopSelection();
}
}
}
@@ -494,6 +493,13 @@ namespace Barotrauma
}
}
public static void StopSelection()
{
startMovingPos = Vector2.Zero;
selectionSize = Vector2.Zero;
selectionPos = Vector2.Zero;
}
public static Vector2 GetNudgeAmount(bool doHold = true)
{
Vector2 nudgeAmount = Vector2.Zero;
@@ -792,12 +798,16 @@ namespace Barotrauma
foreach (MapEntity e in SelectedList)
{
SpriteEffects spriteEffects = SpriteEffects.None;
float spriteRotation = 0.0f;
float rectangleRotation = 0.0f;
switch (e)
{
case Item item:
{
if (item.FlippedX && item.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
if (item.flippedY && item.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
if (item.FlippedY && item.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
spriteRotation = MathHelper.ToRadians(item.Rotation);
rectangleRotation = spriteRotation;
var wire = item.GetComponent<Wire>();
if (wire != null && wire.Item.body != null && !wire.Item.body.Enabled)
{
@@ -809,7 +819,10 @@ namespace Barotrauma
case Structure structure:
{
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
if (structure.flippedY && structure.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
if (structure.FlippedY && structure.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
spriteRotation = MathHelper.ToRadians(structure.Rotation);
rectangleRotation = spriteRotation;
if (structure.FlippedX != structure.FlippedY) { rectangleRotation = -rectangleRotation; }
break;
}
case WayPoint wayPoint:
@@ -831,11 +844,12 @@ namespace Barotrauma
}
}
e.Prefab?.DrawPlacing(spriteBatch,
new Rectangle(e.WorldRect.Location + new Point((int)moveAmount.X, (int)-moveAmount.Y), e.WorldRect.Size), e.Scale, spriteEffects);
new Rectangle(e.WorldRect.Location + new Point((int)moveAmount.X, (int)-moveAmount.Y), e.WorldRect.Size), e.Scale, spriteRotation, spriteEffects: spriteEffects);
GUI.DrawRectangle(spriteBatch,
new Vector2(e.WorldRect.X, -e.WorldRect.Y) + moveAmount,
new Vector2(e.rect.Width, e.rect.Height),
Color.White, false, 0, (int)Math.Max(3.0f / GameScreen.Selected.Cam.Zoom, 2.0f));
center: e.WorldRect.Center.ToVector2().FlipY() + moveAmount + new Vector2(0f, e.WorldRect.Height),
width: e.WorldRect.Width, height: e.WorldRect.Height,
rotation: rectangleRotation, clr: Color.White,
depth: 0f, thickness: Math.Max(3.0f / GameScreen.Selected.Cam.Zoom, 2.0f));
}
//stop dragging the "selection rectangle"
@@ -877,6 +891,23 @@ namespace Barotrauma
spriteBatch.DrawLine(corners[3] + offset, corners[0] - offset, color, thickness);
}
protected static void ColorFlipButton(GUIButton btn, bool flip)
{
var color = flip ? GUIStyle.Green : Color.White;
var hsv = ToolBox.RGBToHSV(color);
// Boost saturation and reduce value a bit because our default colors are too muted for this button's style
var hsvBase = hsv;
hsvBase.Y *= 4f;
hsvBase.Z *= 0.8f;
btn.Color = ToolBox.HSVToRGB(hsvBase.X, hsvBase.Y, hsvBase.Z);
btn.SelectedColor = ToolBox.HSVToRGB(hsvBase.X, hsvBase.Y, hsvBase.Z);
var hsvHover = hsv;
hsvHover.Z *= 1.2f;
btn.HoverColor = ToolBox.HSVToRGB(hsvHover.X, hsvHover.Y, hsvHover.Z);
}
public static List<MapEntity> FilteredSelectedList { get; private set; } = new List<MapEntity>();
public static void UpdateEditor(Camera cam, float deltaTime)
@@ -1105,6 +1136,25 @@ namespace Barotrauma
public virtual void DrawEditing(SpriteBatch spriteBatch, Camera cam) { }
private float RotationRad
=> MathHelper.ToRadians(
this switch
{
Structure s => s.Rotation,
Item it => it.Rotation,
_ => 0.0f
});
private Vector2 GetEditingHandlePos(int x, int y, Camera cam)
{
Vector2 handleDiff = new Vector2(x * (rect.Width * 0.5f), y * (rect.Height * 0.5f));
var rotation = -RotationRad;
handleDiff = MathUtils.RotatePoint(handleDiff, rotation);
if (FlippedX) { handleDiff = handleDiff.FlipX(); }
if (FlippedY) { handleDiff = handleDiff.FlipY(); }
return cam.WorldToScreen(Position + handleDiff);
}
float ResizeHandleSize => 10 * GUI.Scale;
float ResizeHandleHighlightDistance => 8 * GUI.Scale;
@@ -1119,9 +1169,10 @@ namespace Barotrauma
{
for (int y = startY; y < 2; y += 2)
{
Vector2 handlePos = cam.WorldToScreen(Position + new Vector2(x * (rect.Width * 0.5f), y * (rect.Height * 0.5f)));
Vector2 handlePos = GetEditingHandlePos(x, y, cam);
bool highlighted = Vector2.DistanceSquared(PlayerInput.MousePosition, handlePos) < ResizeHandleHighlightDistance * ResizeHandleHighlightDistance;
if (highlighted && PlayerInput.PrimaryMouseButtonDown())
{
selectionPos = Vector2.Zero;
@@ -1138,44 +1189,83 @@ namespace Barotrauma
{
if (prevRect == null)
{
prevRect = new Rectangle(Rect.Location, Rect.Size);
prevRect = Rect;
}
Vector2 placePosition = new Vector2(rect.X, rect.Y);
Vector2 placeSize = new Vector2(rect.Width, rect.Height);
Vector2 placePosition = prevRect.Value.Location.ToVector2();
Vector2 placeSize = prevRect.Value.Size.ToVector2();
Vector2 mousePos = Submarine.MouseToWorldGrid(cam, Submarine.MainSub, round: true);
if (PlayerInput.IsShiftDown())
static Vector2 flipThenRotate(Vector2 point, Vector2 center, float angle, bool flipX, bool flipY)
{
mousePos = cam.ScreenToWorld(PlayerInput.MousePosition);
if (flipX) { point = (point - center).FlipX() + center; }
if (flipY) { point = (point - center).FlipY() + center; }
point = MathUtils.RotatePointAroundTarget(point, center, angle);
return point;
}
static Vector2 rotateThenFlip(Vector2 point, Vector2 center, float angle, bool flipX, bool flipY)
{
point = MathUtils.RotatePointAroundTarget(point, center, angle);
if (flipX) { point = (point - center).FlipX() + center; }
if (flipY) { point = (point - center).FlipY() + center; }
return point;
}
Vector2 mousePos = cam.ScreenToWorld(PlayerInput.MousePosition);
Vector2 prevPos = placePosition;
Vector2 prevOppositeCorner = prevPos + placeSize.FlipY();
Vector2 prevCenter = placePosition + placeSize.FlipY() * 0.5f;
mousePos = flipThenRotate(mousePos, prevCenter, RotationRad, FlippedX, FlippedY);
if (!PlayerInput.IsShiftDown())
{
mousePos = Submarine.VectorToWorldGrid(mousePos, Submarine.MainSub, round: true);
}
if (resizeDirX > 0)
{
mousePos.X = Math.Max(mousePos.X, rect.X + Submarine.GridSize.X);
mousePos.X = Math.Max(mousePos.X, prevRect.Value.X + Submarine.GridSize.X);
placeSize.X = mousePos.X - placePosition.X;
}
else if (resizeDirX < 0)
{
mousePos.X = Math.Min(mousePos.X, rect.Right - Submarine.GridSize.X);
mousePos.X = Math.Min(mousePos.X, prevRect.Value.Right - Submarine.GridSize.X);
placeSize.X = MathF.Round((placePosition.X + placeSize.X) - mousePos.X);
placePosition.X = MathF.Round(mousePos.X);
}
if (resizeDirY < 0)
{
mousePos.Y = Math.Min(mousePos.Y, rect.Y - Submarine.GridSize.Y);
mousePos.Y = Math.Min(mousePos.Y, prevRect.Value.Y - Submarine.GridSize.Y);
placeSize.Y = placePosition.Y - mousePos.Y;
}
else if (resizeDirY > 0)
{
mousePos.Y = Math.Max(mousePos.Y, rect.Y - rect.Height + Submarine.GridSize.X);
mousePos.Y = Math.Max(mousePos.Y, prevRect.Value.Y - prevRect.Value.Height + Submarine.GridSize.Y);
placeSize.Y = mousePos.Y - (rect.Y - rect.Height);
placeSize.Y = mousePos.Y - (prevRect.Value.Y - prevRect.Value.Height);
placePosition.Y = mousePos.Y;
}
Vector2 newPos = placePosition;
Vector2 newOppositeCorner = placePosition + placeSize.FlipY();
Vector2 transformedCornerDiff = rotateThenFlip(newPos-prevPos, Vector2.Zero, -RotationRad, FlippedX, FlippedY);
Vector2 transformedOppositeCornerDiff = rotateThenFlip(newOppositeCorner-prevOppositeCorner, Vector2.Zero, -RotationRad, FlippedX, FlippedY);
Vector2 newPosTransformed = rotateThenFlip(prevPos, prevCenter, -RotationRad, FlippedX, FlippedY)
+ transformedCornerDiff;
Vector2 newOppositeTransformed = rotateThenFlip(prevOppositeCorner, prevCenter, -RotationRad, FlippedX, FlippedY)
+ transformedOppositeCornerDiff;
Vector2 newTransformedCenter = (newPosTransformed + newOppositeTransformed) * 0.5f;
var newDiff = (newOppositeCorner - newPos) * 0.5f;
placePosition = newTransformedCenter - newDiff;
if ((int)placePosition.X != rect.X || (int)placePosition.Y != rect.Y || (int)placeSize.X != rect.Width || (int)placeSize.Y != rect.Height)
{
Rect = new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y);
@@ -1210,15 +1300,16 @@ namespace Barotrauma
IsHighlighted = true;
int startX = ResizeHorizontal ? -1 : 0;
int StartY = ResizeVertical ? -1 : 0;
int startY = ResizeVertical ? -1 : 0;
for (int x = startX; x < 2; x += 2)
{
for (int y = StartY; y < 2; y += 2)
for (int y = startY; y < 2; y += 2)
{
Vector2 handlePos = cam.WorldToScreen(Position + new Vector2(x * (rect.Width * 0.5f), y * (rect.Height * 0.5f)));
Vector2 handlePos = GetEditingHandlePos(x, y, cam);
bool highlighted = Vector2.DistanceSquared(PlayerInput.MousePosition, handlePos) < ResizeHandleHighlightDistance * ResizeHandleHighlightDistance;
var color = Color.White * (highlighted ? 1.0f : 0.6f);
if (highlighted && !PlayerInput.PrimaryMouseButtonHeld())
{
GUI.MouseCursor = CursorState.Hand;
@@ -1226,7 +1317,7 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch,
handlePos - new Vector2(ResizeHandleSize / 2),
new Vector2(ResizeHandleSize),
Color.White * (highlighted ? 1.0f : 0.6f),
color,
true, 0,
(int)Math.Max(1.5f / GameScreen.Selected.Cam.Zoom, 1.0f));
}
@@ -84,7 +84,7 @@ namespace Barotrauma
}
}
public virtual void DrawPlacing(SpriteBatch spriteBatch, Rectangle drawRect, float scale = 1.0f, SpriteEffects spriteEffects = SpriteEffects.None)
public virtual void DrawPlacing(SpriteBatch spriteBatch, Rectangle drawRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
{
if (Submarine.MainSub != null)
{
@@ -1,10 +1,9 @@
#nullable enable
using Barotrauma.Sounds;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
using Barotrauma.Sounds;
using Microsoft.Xna.Framework;
namespace Barotrauma
{
@@ -45,7 +44,8 @@ namespace Barotrauma
}
if (FrequencyMultiplierRange.Y > 4.0f)
{
DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")");
DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")",
contentPackage: element.ContentPackage);
}
IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
}
@@ -65,7 +65,8 @@ namespace Barotrauma
if (filename is null)
{
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
DebugConsole.ThrowError(errorMsg);
DebugConsole.ThrowError(errorMsg,
contentPackage: element.ContentPackage);
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FilePathEmpty" + element.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
return null;
}
@@ -86,7 +87,8 @@ namespace Barotrauma
catch (System.IO.FileNotFoundException e)
{
string errorMsg = "Failed to load sound file \"" + filename + "\" (file not found).";
DebugConsole.ThrowError(errorMsg, e);
DebugConsole.ThrowError(errorMsg, e,
contentPackage: element.ContentPackage);
if (!ContentPackageManager.ModsEnabled)
{
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
@@ -96,7 +98,8 @@ namespace Barotrauma
catch (System.IO.InvalidDataException e)
{
string errorMsg = "Failed to load sound file \"" + filename + "\" (invalid data).";
DebugConsole.ThrowError(errorMsg, e);
DebugConsole.ThrowError(errorMsg, e,
contentPackage: element.ContentPackage);
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:InvalidData" + filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
return null;
}
@@ -123,7 +126,8 @@ namespace Barotrauma
catch (System.IO.FileNotFoundException e)
{
string errorMsg = "Failed to load sound file \"" + roundSound.Filename + "\".";
DebugConsole.ThrowError(errorMsg, e);
DebugConsole.ThrowError(errorMsg, e,
contentPackage: roundSound.Sound?.XElement?.ContentPackage);
GameAnalyticsManager.AddErrorEventOnce("RoundSound.LoadRoundSound:FileNotFound" + roundSound.Filename, GameAnalyticsManager.ErrorSeverity.Error, errorMsg + "\n" + Environment.StackTrace.CleanupStackTrace());
return;
}
@@ -150,7 +150,8 @@ namespace Barotrauma
Stretch = true,
RelativeSpacing = 0.01f
};
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
var mirrorX = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityX"), style: "GUIButtonSmall")
{
ToolTip = TextManager.Get("MirrorEntityXToolTip"),
OnClicked = (button, data) =>
@@ -160,10 +161,12 @@ namespace Barotrauma
me.FlipX(relativeToSub: false);
}
if (!SelectedList.Contains(this)) { FlipX(relativeToSub: false); }
ColorFlipButton(button, FlippedX);
return true;
}
};
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
ColorFlipButton(mirrorX, FlippedX);
var mirrorY = new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("MirrorEntityY"), style: "GUIButtonSmall")
{
ToolTip = TextManager.Get("MirrorEntityYToolTip"),
OnClicked = (button, data) =>
@@ -173,9 +176,11 @@ namespace Barotrauma
me.FlipY(relativeToSub: false);
}
if (!SelectedList.Contains(this)) { FlipY(relativeToSub: false); }
ColorFlipButton(button, FlippedY);
return true;
}
};
ColorFlipButton(mirrorY, FlippedY);
new GUIButton(new RectTransform(new Vector2(0.23f, 1.0f), buttonContainer.RectTransform), TextManager.Get("ReloadSprite"), style: "GUIButtonSmall")
{
OnClicked = (button, data) =>
@@ -357,8 +362,10 @@ namespace Barotrauma
Prefab.BackgroundSprite.DrawTiled(
spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)),
new Vector2(rect.X + rect.Width / 2 + drawOffset.X, -(rect.Y - rect.Height / 2 + drawOffset.Y)),
new Vector2(rect.Width, rect.Height),
rotation: rotationRad,
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
color: Prefab.BackgroundSpriteColor,
textureScale: TextureScale * Scale,
startOffset: backGroundOffset,
@@ -368,8 +375,10 @@ namespace Barotrauma
{
Prefab.BackgroundSprite.DrawTiled(
spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)) + dropShadowOffset,
new Vector2(rect.X + rect.Width / 2 + drawOffset.X, -(rect.Y - rect.Height / 2 + drawOffset.Y)) + dropShadowOffset,
new Vector2(rect.Width, rect.Height),
rotation: rotationRad,
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
color: Color.Black * 0.5f,
textureScale: TextureScale * Scale,
startOffset: backGroundOffset,
@@ -385,6 +394,13 @@ namespace Barotrauma
SpriteEffects oldEffects = Prefab.Sprite.effects;
Prefab.Sprite.effects ^= SpriteEffects;
Vector2 advanceX = MathUtils.RotatedUnitXRadians(this.rotationRad).FlipY();
Vector2 advanceY = advanceX.YX().FlipX();
if (FlippedX != FlippedY)
{
advanceX = advanceX.FlipY();
advanceY = advanceY.FlipX();
}
for (int i = 0; i < Sections.Length; i++)
{
Rectangle drawSection = Sections[i].rect;
@@ -409,7 +425,7 @@ namespace Barotrauma
drawSection = new Rectangle(
drawSection.X,
drawSection.Y,
Sections[Sections.Length -1 ].rect.Right - drawSection.X,
Sections[Sections.Length - 1].rect.Right - drawSection.X,
drawSection.Y - (Sections[Sections.Length - 1].rect.Y - Sections[Sections.Length - 1].rect.Height));
i = Sections.Length;
}
@@ -424,10 +440,18 @@ namespace Barotrauma
sectionOffset.X += MathUtils.PositiveModulo((int)-textureOffset.X, Prefab.Sprite.SourceRect.Width);
sectionOffset.Y += MathUtils.PositiveModulo((int)-textureOffset.Y, Prefab.Sprite.SourceRect.Height);
Vector2 pos = new Vector2(drawSection.X, drawSection.Y);
pos -= rect.Location.ToVector2();
pos = advanceX * pos.X + advanceY * pos.Y;
pos += rect.Location.ToVector2();
pos = new Vector2(pos.X + rect.Width / 2 + drawOffset.X, -(pos.Y - rect.Height / 2 + drawOffset.Y));
Prefab.Sprite.DrawTiled(
spriteBatch,
new Vector2(drawSection.X + drawOffset.X, -(drawSection.Y + drawOffset.Y)),
pos,
new Vector2(drawSection.Width, drawSection.Height),
rotation: rotationRad,
origin: rect.Size.ToVector2() * new Vector2(0.5f, 0.5f),
color: color,
startOffset: sectionOffset,
depth: depth,
@@ -437,7 +461,7 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor) + this.rotationRad;
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier) * Scale;
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, Prefab.Sprite.effects,
@@ -94,16 +94,21 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White);
}
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, SpriteEffects spriteEffects = SpriteEffects.None)
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
{
SpriteEffects oldEffects = Sprite.effects;
Sprite.effects ^= spriteEffects;
var position = placeRect.Location.ToVector2().FlipY();
position += placeRect.Size.ToVector2() * 0.5f;
Sprite.DrawTiled(
spriteBatch,
new Vector2(placeRect.X, -placeRect.Y),
new Vector2(placeRect.Width, placeRect.Height),
color: Color.White * 0.8f,
position,
placeRect.Size.ToVector2(),
color: Color.White * 0.8f,
origin: placeRect.Size.ToVector2() * 0.5f,
rotation: rotation,
textureScale: TextureScale * scale);
Sprite.effects = oldEffects;
@@ -25,7 +25,7 @@ namespace Barotrauma
/// <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;
private const int CullMargin = 50;
/// <summary>
/// Update entity culling when any corner of the view has moved more than this
/// </summary>
@@ -713,18 +713,12 @@ namespace Barotrauma
return GameMain.LightManager.Lights.Count(l => l.CastShadows && !l.IsBackground) - disabledItemLightCount;
}
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub, bool round = false)
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub, Vector2? mousePos = null, bool round = false)
{
Vector2 position = PlayerInput.MousePosition;
Vector2 position = mousePos ?? PlayerInput.MousePosition;
position = cam.ScreenToWorld(position);
Vector2 worldGridPos = VectorToWorldGrid(position, round);
if (sub != null)
{
worldGridPos.X += sub.Position.X % GridSize.X;
worldGridPos.Y += sub.Position.Y % GridSize.Y;
}
Vector2 worldGridPos = VectorToWorldGrid(position, sub, round);
return worldGridPos;
}
@@ -122,12 +122,12 @@ namespace Barotrauma.Networking
VoipSound = null;
}
public void SetPermissions(ClientPermissions permissions, IEnumerable<string> permittedConsoleCommands)
public void SetPermissions(ClientPermissions permissions, IEnumerable<Identifier> permittedConsoleCommands)
{
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
foreach (string commandName in permittedConsoleCommands)
foreach (Identifier commandName in permittedConsoleCommands)
{
var consoleCommand = DebugConsole.Commands.Find(c => c.names.Contains(commandName));
var consoleCommand = DebugConsole.Commands.Find(c => c.Names.Contains(commandName));
if (consoleCommand != null)
{
permittedCommands.Add(consoleCommand);
@@ -65,7 +65,7 @@ namespace Barotrauma.Networking
public bool LateCampaignJoin = false;
private ClientPermissions permissions = ClientPermissions.None;
private List<string> permittedConsoleCommands = new List<string>();
private List<Identifier> permittedConsoleCommands = new List<Identifier>();
private bool connected;
@@ -170,9 +170,9 @@ namespace Barotrauma.Networking
internal readonly struct PermissionChangedEvent
{
public readonly ClientPermissions NewPermissions;
public readonly ImmutableArray<string> NewPermittedConsoleCommands;
public readonly ImmutableArray<Identifier> NewPermittedConsoleCommands;
public PermissionChangedEvent(ClientPermissions newPermissions, IReadOnlyList<string> newPermittedConsoleCommands)
public PermissionChangedEvent(ClientPermissions newPermissions, IReadOnlyList<Identifier> newPermittedConsoleCommands)
{
NewPermissions = newPermissions;
NewPermittedConsoleCommands = newPermittedConsoleCommands.ToImmutableArray();
@@ -1211,11 +1211,11 @@ namespace Barotrauma.Networking
targetClient?.SetPermissions(permissions, permittedCommands);
if (clientId == SessionId)
{
SetMyPermissions(permissions, permittedCommands.Select(command => command.names[0]));
SetMyPermissions(permissions, permittedCommands.Select(command => command.Names[0]));
}
}
private void SetMyPermissions(ClientPermissions newPermissions, IEnumerable<string> permittedConsoleCommands)
private void SetMyPermissions(ClientPermissions newPermissions, IEnumerable<Identifier> permittedConsoleCommands)
{
if (!(this.permittedConsoleCommands.Any(c => !permittedConsoleCommands.Contains(c)) ||
permittedConsoleCommands.Any(c => !this.permittedConsoleCommands.Contains(c))))
@@ -1227,7 +1227,7 @@ namespace Barotrauma.Networking
permissions.HasFlag(ClientPermissions.ManageRound) != newPermissions.HasFlag(ClientPermissions.ManageRound);
permissions = newPermissions;
this.permittedConsoleCommands = new List<string>(permittedConsoleCommands);
this.permittedConsoleCommands = permittedConsoleCommands.ToList();
//don't show the "permissions changed" popup if the client owns the server
if (!IsServerOwner)
{
@@ -1265,10 +1265,10 @@ namespace Barotrauma.Networking
var commandsLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform),
TextManager.Get("PermittedConsoleCommands"), wrap: true, font: GUIStyle.SubHeadingFont);
var commandList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform));
foreach (string permittedCommand in permittedConsoleCommands)
foreach (Identifier permittedCommand in permittedConsoleCommands)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), commandList.Content.RectTransform, minSize: new Point(0, 15)),
permittedCommand, font: GUIStyle.SmallFont)
permittedCommand.Value, font: GUIStyle.SmallFont)
{
CanBeFocused = false
};
@@ -1348,6 +1348,7 @@ namespace Barotrauma.Networking
bool respawnAllowed = inc.ReadBoolean();
ServerSettings.AllowDisguises = inc.ReadBoolean();
ServerSettings.AllowRewiring = inc.ReadBoolean();
ServerSettings.AllowImmediateItemDelivery = inc.ReadBoolean();
ServerSettings.AllowFriendlyFire = inc.ReadBoolean();
ServerSettings.LockAllDefaultWires = inc.ReadBoolean();
ServerSettings.AllowLinkingWifiToChat = inc.ReadBoolean();
@@ -2551,18 +2552,18 @@ namespace Barotrauma.Networking
return permissions.HasFlag(permission);
}
public bool HasConsoleCommandPermission(string commandName)
public bool HasConsoleCommandPermission(Identifier commandName)
{
if (!permissions.HasFlag(ClientPermissions.ConsoleCommands)) { return false; }
if (permittedConsoleCommands.Any(c => c.Equals(commandName, StringComparison.OrdinalIgnoreCase))) { return true; }
if (permittedConsoleCommands.Contains(commandName)) { return true; }
//check aliases
foreach (DebugConsole.Command command in DebugConsole.Commands)
{
if (command.names.Contains(commandName))
if (command.Names.Contains(commandName))
{
if (command.names.Intersect(permittedConsoleCommands).Any()) { return true; }
if (command.Names.Intersect(permittedConsoleCommands).Any()) { return true; }
break;
}
}
@@ -75,6 +75,9 @@ namespace Barotrauma.Networking
[Serialize("", IsPropertySaveable.Yes)]
public LanguageIdentifier Language { get; set; }
[Serialize("", IsPropertySaveable.Yes)]
public string SelectedSub { get; set; } = string.Empty;
public Version GameVersion { get; set; } = new Version(0, 0, 0, 0);
public Option<int> Ping = Option<int>.None();
@@ -104,6 +107,8 @@ namespace Barotrauma.Networking
public ImmutableArray<ContentPackageInfo> ContentPackages;
public int ContentPackageCount;
public bool IsModded => ContentPackages.Any(p => !GameMain.VanillaContent.NameMatches(p.Name));
public ServerInfo(Endpoint endpoint)
@@ -309,6 +314,14 @@ namespace Barotrauma.Networking
TextManager.Get(GameMode.IsEmpty ? "Unknown" : "GameMode." + GameMode).Fallback(GameMode.Value),
textAlignment: Alignment.Right);
if (!string.IsNullOrEmpty(SelectedSub))
{
var submarineText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("Submarine"));
new GUITextBlock(new RectTransform(Vector2.One, submarineText.RectTransform),
SelectedSub,
textAlignment: Alignment.Right);
}
GUITextBlock playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle"));
new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right);
@@ -385,6 +398,15 @@ namespace Barotrauma.Networking
}
}
}
if (ContentPackageCount > ContentPackages.Length)
{
new GUITextBlock(
new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (ContentPackageCount - ContentPackages.Length).ToString()))
{
CanBeFocused = false
};
}
}
// -----------------------------------------------------------------------------
@@ -423,14 +445,16 @@ namespace Barotrauma.Networking
AllowSpectating = getBool("allowspectating");
AllowRespawn = getBool("allowrespawn");
VoipEnabled = getBool("voicechatenabled");
GameMode = valueGetter("gamemode")?.ToIdentifier() ?? Identifier.Empty;
if (float.TryParse(valueGetter("traitors"), NumberStyles.Any, CultureInfo.InvariantCulture, out float traitorProbability)) { TraitorProbability = traitorProbability; }
if (Enum.TryParse(valueGetter("playstyle"), out PlayStyle playStyle)) { PlayStyle = playStyle; }
Language = valueGetter("language")?.ToLanguageIdentifier() ?? LanguageIdentifier.None;
SelectedSub = valueGetter("submarine") ?? string.Empty;
ContentPackages = ExtractContentPackageInfo(ServerName, valueGetter).ToImmutableArray();
ContentPackageCount = ContentPackages.Length;
if (int.TryParse(valueGetter("packagecount"), out int packageCount)) { ContentPackageCount = packageCount; }
bool getBool(string key)
{
string? data = valueGetter(key);
@@ -936,6 +936,10 @@ namespace Barotrauma.Networking
TextManager.Get("ServerSettingsAllowVoteKick"));
GetPropertyData(nameof(AllowVoteKick)).AssignGUIComponent(voteKickBox);
var allowImmediateItemDeliveryBox = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
TextManager.Get("ServerSettingsImmediateItemDelivery"));
GetPropertyData(nameof(AllowImmediateItemDelivery)).AssignGUIComponent(allowImmediateItemDeliveryBox);
GUITextBlock.AutoScaleAndNormalize(tickBoxContainer.Content.Children.Select(c => ((GUITickBox)c).TextBlock));
tickBoxContainer.RectTransform.MinSize = new Point(0, (int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
#nullable enable
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
@@ -148,7 +149,7 @@ namespace Barotrauma.Particles
Prefab = prefab;
}
public void Emit(float deltaTime, Vector2 position, Hull hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2> tracerPoints = null)
public void Emit(float deltaTime, Vector2 position, Hull? hullGuess = null, float angle = 0.0f, float particleRotation = 0.0f, float velocityMultiplier = 1.0f, float sizeMultiplier = 1.0f, float amountMultiplier = 1.0f, Color? colorMultiplier = null, ParticlePrefab? overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2>? tracerPoints = null)
{
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
@@ -191,16 +192,17 @@ namespace Barotrauma.Particles
burstEmitTimer = Prefab.Properties.EmitInterval;
for (int i = 0; i < Prefab.Properties.ParticleAmount * amountMultiplier; i++)
{
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: tracerPoints);
Emit(position, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, mirrorAngle, tracerPoints: tracerPoints);
}
}
private void Emit(Vector2 position, Hull hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2> tracerPoints = null)
private void Emit(Vector2 position, Hull? hullGuess, float angle, float particleRotation, float velocityMultiplier, float sizeMultiplier, Color? colorMultiplier = null, ParticlePrefab? overrideParticle = null, bool mirrorAngle = false, Tuple<Vector2, Vector2>? tracerPoints = null)
{
var particlePrefab = overrideParticle ?? Prefab.ParticlePrefab;
if (particlePrefab == null)
{
DebugConsole.AddWarning($"Could not find the particle prefab \"{Prefab.ParticlePrefabName}\".");
DebugConsole.AddWarning($"Could not find the particle prefab \"{Prefab.ParticlePrefabName}\".",
contentPackage: Prefab.ContentPackage);
return;
}
@@ -271,7 +273,7 @@ namespace Barotrauma.Particles
{
public readonly Identifier ParticlePrefabName;
public ParticlePrefab ParticlePrefab
public ParticlePrefab? ParticlePrefab
{
get
{
@@ -282,12 +284,16 @@ namespace Barotrauma.Particles
public readonly ParticleEmitterProperties Properties;
public bool DrawOnTop => Properties.DrawOnTop || ParticlePrefab.DrawOnTop;
public readonly ContentPackage? ContentPackage;
public bool DrawOnTop => Properties.DrawOnTop || ParticlePrefab is { DrawOnTop: true };
public ParticleEmitterPrefab(ContentXElement element)
{
Properties = new ParticleEmitterProperties(element);
if (element == null) { throw new ArgumentNullException(nameof(element)); }
Properties = new ParticleEmitterProperties(element!);
ParticlePrefabName = element.GetAttributeIdentifier("particle", "");
ContentPackage = element.ContentPackage;
}
public ParticleEmitterPrefab(ParticlePrefab prefab, ParticleEmitterProperties properties)
@@ -244,7 +244,8 @@ namespace Barotrauma.Particles
if (Sprites.Count == 0)
{
DebugConsole.ThrowError($"Particle prefab \"{Name}\" in the file \"{file}\" has no sprites defined!");
DebugConsole.ThrowError($"Particle prefab \"{Name}\" in the file \"{file}\" has no sprites defined!",
contentPackage: element.ContentPackage);
}
//if velocity change in water is not given, it defaults to the normal velocity change
@@ -261,6 +261,9 @@ namespace Barotrauma
{
crashHeader += " " + exception.TargetSite.ToString();
}
//log the message separately, so the same error messages get grouped as the same error in GA
//(the full crash report tends to always have some differences between clients, so they get displayed separately)
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Critical, crashHeader);
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Critical, crashHeader + "\n\n" + sb.ToString());
GameAnalyticsManager.ShutDown();
}
@@ -76,6 +76,8 @@ namespace Barotrauma
private GUITextBlock tutorialHeader, tutorialDescription;
private GUIListBox tutorialList;
private GUIComponent versionMismatchWarning;
#region Creation
public MainMenuScreen(GameMain game)
{
@@ -105,6 +107,28 @@ namespace Barotrauma
}
};
versionMismatchWarning = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.065f), Frame.RectTransform) { AbsoluteOffset = new Point(GUI.IntScale(15)) }, style: "InnerFrame", color: GUIStyle.Red)
{
IgnoreLayoutGroups = true,
Visible = false
};
var versionMismatchContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), versionMismatchWarning.RectTransform, Anchor.Center), isHorizontal: true)
{
RelativeSpacing = 0.05f,
};
new GUIImage(new RectTransform(new Vector2(1.0f), versionMismatchContent.RectTransform, scaleBasis: ScaleBasis.Smallest), style: "GUINotificationButton")
{
Color = GUIStyle.Orange
};
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), versionMismatchContent.RectTransform),
TextManager.GetWithVariables("versionmismatchwarning",
("[gameversion]", GameMain.Version.ToString()),
("[contentversion]", ContentPackageManager.VanillaCorePackage.GameVersion.ToString())),
wrap: true)
{
TextColor = GUIStyle.Orange
};
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
style: "TitleText")
@@ -587,7 +611,9 @@ namespace Barotrauma
GameMain.SubEditorScreen?.ClearBackedUpSubInfo();
Submarine.Unload();
versionMismatchWarning.Visible = GameMain.Version < ContentPackageManager.VanillaCorePackage.GameVersion;
ResetButtonStates(null);
}
@@ -663,7 +689,18 @@ namespace Barotrauma
.ToArray();
foreach (var newServerExe in newServerExes)
{
serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
var serverExeEntry = serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
if (newServerExe.ContentPackage.GameVersion < GameMain.VanillaContent.GameVersion)
{
serverExeEntry.ToolTip =
TextManager.GetWithVariables("versionmismatchwarning",
("[gameversion]", newServerExe.ContentPackage.GameVersion.ToString()),
("[contentversion]", GameMain.VanillaContent.GameVersion.ToString()));
if (serverExeEntry is GUITextBlock serverExeText)
{
serverExeText.TextColor = GUIStyle.Red;
}
}
}
serverExecutableDropdown.ListBox.Content.Children.ForEach(c =>
{
@@ -1472,34 +1509,58 @@ namespace Barotrauma
{
OnClicked = (btn, userdata) =>
{
string name = serverNameBox.Text;
if (string.IsNullOrEmpty(name))
{
serverNameBox.Flash();
return false;
}
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
{
var msgBox = new GUIMessageBox("",
TextManager.GetWithVariables("forbiddenservernameverification", ("[forbiddenword]", forbiddenWord), ("[servername]", name)),
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked += (_, __) =>
{
TryStartServer();
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
}
else
{
TryStartServer();
}
CheckServerName();
return true;
}
};
void CheckServerName()
{
string name = serverNameBox.Text;
if (string.IsNullOrEmpty(name))
{
serverNameBox.Flash();
return;
}
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
{
var msgBox = new GUIMessageBox("",
TextManager.GetWithVariables("forbiddenservernameverification", ("[forbiddenword]", forbiddenWord), ("[servername]", name)),
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked += (_, __) =>
{
CheckServerExe();
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
return;
}
CheckServerExe();
}
void CheckServerExe()
{
if (serverExecutableDropdown?.SelectedData is ServerExecutableFile serverExe &&
serverExe.ContentPackage.GameVersion < GameMain.VanillaContent.GameVersion)
{
var msgBox = new GUIMessageBox(string.Empty,
TextManager.GetWithVariables("versionmismatchwarning",
("[gameversion]", serverExe.ContentPackage.GameVersion.ToString()),
("[contentversion]", GameMain.VanillaContent.GameVersion.ToString())) + "\n\n"+
TextManager.GetWithVariable("versionmismatch.verifylaunch", "[exename]", serverExe.ContentPackage.Name),
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked += (_, __) =>
{
TryStartServer();
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
return;
}
TryStartServer();
}
}
private void SetServerPlayStyle(PlayStyle playStyle)
@@ -2389,10 +2389,20 @@ namespace Barotrauma
options.Add(kickOption);
}
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
if (GameMain.Client?.ServerSettings?.BanList?.BannedPlayers?.Any(bp => bp.MatchesClient(client)) ?? false)
{
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
}));
options.Add(new ContextMenuOption("clientpermission.unban", isEnabled: canBan, onSelected: delegate
{
GameMain.Client?.UnbanPlayer(client.Name);
}));
}
else
{
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
{
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
}));
}
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
}
@@ -2591,11 +2601,11 @@ namespace Barotrauma
foreach (DebugConsole.Command command in DebugConsole.Commands)
{
var commandTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.15f), commandList.Content.RectTransform),
command.names[0], font: GUIStyle.SmallFont)
command.Names[0].Value, font: GUIStyle.SmallFont)
{
Selected = selectedClient.PermittedConsoleCommands.Contains(command),
Enabled = !myClient,
ToolTip = command.help,
ToolTip = command.Help,
UserData = command
};
commandTickBox.OnSelected += (GUITickBox tickBox) =>
@@ -2630,12 +2640,25 @@ namespace Barotrauma
{
if (GameMain.Client.HasPermission(ClientPermissions.Ban))
{
var banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("Ban"))
GUIButton banButton;
if (GameMain.Client?.ServerSettings?.BanList?.BannedPlayers?.Any(bp => bp.MatchesClient(selectedClient)) ?? false)
{
UserData = selectedClient
};
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("clientpermission.unban"))
{
UserData = selectedClient
};
banButton.OnClicked = (bt, userdata) => { GameMain.Client?.UnbanPlayer(selectedClient.Name); return true; };
}
else
{
banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("Ban"))
{
UserData = selectedClient
};
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
}
banButton.OnClicked += ClosePlayerFrame;
}
@@ -3147,12 +3170,12 @@ namespace Barotrauma
GUIButton jobButton = null;
var availableJobs = JobPrefab.Prefabs.Where(jobPrefab =>
jobPrefab.MaxNumber > 0 && JobList.Content.Children.All(c => !(c.UserData is JobVariant prefab) || prefab.Prefab != jobPrefab)
!jobPrefab.HiddenJob && jobPrefab.MaxNumber > 0 && JobList.Content.Children.All(c => c.UserData is not JobVariant prefab || prefab.Prefab != jobPrefab)
).Select(j => new JobVariant(j, 0));
availableJobs = availableJobs.Concat(
JobPrefab.Prefabs.Where(jobPrefab =>
jobPrefab.MaxNumber > 0 && JobList.Content.Children.Any(c => (c.UserData is JobVariant prefab) && prefab.Prefab == jobPrefab)
!jobPrefab.HiddenJob && jobPrefab.MaxNumber > 0 && JobList.Content.Children.Any(c => (c.UserData is JobVariant prefab) && prefab.Prefab == jobPrefab)
).Select(j => (JobVariant)JobList.Content.FindChild(c => (c.UserData is JobVariant prefab) && prefab.Prefab == j).UserData));
availableJobs = availableJobs.ToList();
@@ -655,7 +655,7 @@ namespace Barotrauma
ScrollBarVisible = true,
OnSelected = (btn, obj) =>
{
if (!(obj is ServerInfo serverInfo)) { return false; }
if (obj is not ServerInfo serverInfo) { return false; }
joinButton.Enabled = true;
selectedServer = Option<ServerInfo>.Some(serverInfo);
@@ -1289,7 +1289,8 @@ namespace Barotrauma
if (legacy) { textBlock.TextColor *= 0.6f; }
if (name.IsNullOrEmpty())
{
DebugConsole.AddWarning($"Entity \"{ep.Identifier.Value}\" has no name!");
DebugConsole.AddWarning($"Entity \"{ep.Identifier.Value}\" has no name!",
contentPackage: ep.ContentPackage);
textBlock.Text = frame.ToolTip = ep.Identifier.Value;
textBlock.TextColor = GUIStyle.Red;
}
@@ -2365,49 +2366,58 @@ namespace Barotrauma
//---------------------------------------
var beaconSettingsContainer = new GUILayoutGroup(new RectTransform(Vector2.One, subTypeDependentSettingFrame.RectTransform))
var extraSettingsContainer = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.5f), subTypeDependentSettingFrame.RectTransform))
{
CanBeFocused = true,
Visible = false,
Stretch = true
};
// -------------------
var beaconMinDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
var minDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMinDifficultyGroup.RectTransform),
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), minDifficultyGroup.RectTransform),
TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
var numInput = 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), minDifficultyGroup.RectTransform), NumberType.Int)
{
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MinLevelDifficulty ?? 0),
IntValue = (int)(MainSub?.Info?.GetExtraSubmarineInfo?.MinLevelDifficulty ?? 0),
MinValueInt = 0,
MaxValueInt = 100,
OnValueChanged = (numberInput) =>
{
MainSub.Info.BeaconStationInfo.MinLevelDifficulty = numberInput.IntValue;
MainSub.Info.GetExtraSubmarineInfo.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)
minDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
var maxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMaxDifficultyGroup.RectTransform),
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), maxDifficultyGroup.RectTransform),
TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
numInput = 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), maxDifficultyGroup.RectTransform), NumberType.Int)
{
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MaxLevelDifficulty ?? 100),
IntValue = (int)(MainSub?.Info?.GetExtraSubmarineInfo?.MaxLevelDifficulty ?? 100),
MinValueInt = 0,
MaxValueInt = 100,
OnValueChanged = (numberInput) =>
{
MainSub.Info.BeaconStationInfo.MaxLevelDifficulty = numberInput.IntValue;
MainSub.Info.GetExtraSubmarineInfo.MaxLevelDifficulty = numberInput.IntValue;
}
};
beaconMaxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
maxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
//---------------------------------------
var beaconSettingsContainer = new GUILayoutGroup(new RectTransform(Vector2.One, extraSettingsContainer.RectTransform))
{
CanBeFocused = true,
Visible = false,
Stretch = true
};
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), TextManager.Get("allowdamagedwalls"))
{
Selected = MainSub?.Info?.BeaconStationInfo?.AllowDamagedWalls ?? true,
@@ -2669,8 +2679,13 @@ namespace Barotrauma
{
MainSub.Info.BeaconStationInfo ??= new BeaconStationInfo(MainSub.Info);
}
else if (type == SubmarineType.Wreck)
{
MainSub.Info.WreckInfo ??= new WreckInfo(MainSub.Info);
}
previewImageButtonHolder.Children.ForEach(c => c.Enabled = MainSub.Info.AllowPreviewImage);
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
extraSettingsContainer.Visible = type == SubmarineType.BeaconStation || type == SubmarineType.Wreck;
beaconSettingsContainer.Visible = type == SubmarineType.BeaconStation;
subSettingsContainer.Visible = type == SubmarineType.Player;
return true;
@@ -4439,6 +4454,7 @@ namespace Barotrauma
MapEntity.SelectEntity(itemContainer);
dummyCharacter.SelectedItem = itemContainer;
FilterEntities(entityFilterBox.Text);
MapEntity.StopSelection();
}
/// <summary>
@@ -5556,11 +5572,32 @@ namespace Barotrauma
dummyCharacter.Submarine = MainSub;
}
// Deposit item from our "infinite stack" into inventory slots
var inv = dummyCharacter?.SelectedItem?.OwnInventory;
if (inv?.visualSlots != null && !PlayerInput.IsCtrlDown())
if (dummyCharacter?.SelectedItem != null)
{
var dragginMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
// Deposit item from our "infinite stack" into inventory slots
TryDragItemsToItem(dummyCharacter.SelectedItem);
foreach (Item linkedItem in dummyCharacter.SelectedItem.linkedTo.OfType<Item>())
{
if (linkedItem.OwnInventory?.visualSlots != null)
{
TryDragItemsToItem(linkedItem);
}
}
}
void TryDragItemsToItem(Item item)
{
foreach (ItemContainer ic in item.GetComponents<ItemContainer>())
{
TryDragItemsToInventory(ic.Inventory);
}
}
void TryDragItemsToInventory(Inventory inv)
{
if (PlayerInput.IsCtrlDown()) { return; }
var draggingMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
// So we don't accidentally drag inventory items while doing this
if (DraggedItemPrefab != null) { Inventory.DraggingItems.Clear(); }
@@ -5568,134 +5605,134 @@ namespace Barotrauma
switch (DraggedItemPrefab)
{
// regular item prefabs
case ItemPrefab itemPrefab when PlayerInput.PrimaryMouseButtonClicked() || dragginMouse:
{
bool spawnedItem = false;
for (var i = 0; i < inv.Capacity; i++)
case ItemPrefab itemPrefab when PlayerInput.PrimaryMouseButtonClicked() || draggingMouse:
{
var slot = inv.visualSlots[i];
var itemContainer = inv.GetItemAt(i)?.GetComponent<ItemContainer>();
// check if the slot is empty or if we can place the item into a container, for example an oxygen tank into a diving suit
if (Inventory.IsMouseOnSlot(slot))
bool spawnedItem = false;
for (var i = 0; i < inv.Capacity; i++)
{
var newItem = new Item(itemPrefab, Vector2.Zero, MainSub);
var slot = inv.visualSlots[i];
var itemContainer = inv.GetItemAt(i)?.GetComponent<ItemContainer>();
if (inv.CanBePutInSlot(itemPrefab, i, condition: null))
// check if the slot is empty or if we can place the item into a container, for example an oxygen tank into a diving suit
if (Inventory.IsMouseOnSlot(slot))
{
bool placedItem = inv.TryPutItem(newItem, i, false, true, dummyCharacter);
spawnedItem |= placedItem;
var newItem = new Item(itemPrefab, Vector2.Zero, MainSub);
if (!placedItem)
if (inv.CanBePutInSlot(itemPrefab, i, condition: null))
{
newItem.Remove();
bool placedItem = inv.TryPutItem(newItem, i, false, true, dummyCharacter);
spawnedItem |= placedItem;
if (!placedItem)
{
newItem.Remove();
}
}
}
else if (itemContainer != null && itemContainer.Inventory.CanBePut(itemPrefab))
{
bool placedItem = itemContainer.Inventory.TryPutItem(newItem, dummyCharacter);
spawnedItem |= placedItem;
// try to place the item into the inventory of the item we are hovering over
if (!placedItem)
else if (itemContainer != null && itemContainer.Inventory.CanBePut(itemPrefab))
{
newItem.Remove();
bool placedItem = itemContainer.Inventory.TryPutItem(newItem, dummyCharacter);
spawnedItem |= placedItem;
// try to place the item into the inventory of the item we are hovering over
if (!placedItem)
{
newItem.Remove();
}
else
{
slot.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
}
}
else
{
slot.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
newItem.Remove();
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
}
if (!newItem.Removed)
{
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
}
if (!draggingMouse)
{
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
}
}
else
{
newItem.Remove();
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
}
if (!newItem.Removed)
{
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
}
if (!dragginMouse)
{
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
}
}
break;
}
break;
}
// item assemblies
case ItemAssemblyPrefab assemblyPrefab when PlayerInput.PrimaryMouseButtonClicked():
{
bool spawnedItems = false;
for (var i = 0; i < inv.visualSlots.Length; i++)
{
var slot = inv.visualSlots[i];
var item = inv?.GetItemAt(i);
var itemContainer = item?.GetComponent<ItemContainer>();
if (item == null && Inventory.IsMouseOnSlot(slot))
bool spawnedItems = false;
for (var i = 0; i < inv.visualSlots.Length; i++)
{
// load the items
var itemInstance = LoadItemAssemblyInventorySafe(assemblyPrefab);
// counter for items that failed so we so we known that slot remained empty
var failedCount = 0;
for (var j = 0; j < itemInstance.Count(); j++)
var slot = inv.visualSlots[i];
var item = inv?.GetItemAt(i);
var itemContainer = item?.GetComponent<ItemContainer>();
if (item == null && Inventory.IsMouseOnSlot(slot))
{
var newItem = itemInstance[j];
var newSpot = i + j - failedCount;
// load the items
var itemInstance = LoadItemAssemblyInventorySafe(assemblyPrefab);
// try to find a valid slot to put the items
while (inv.visualSlots.Length > newSpot)
// counter for items that failed so we so we known that slot remained empty
var failedCount = 0;
for (var j = 0; j < itemInstance.Count; j++)
{
if (inv.GetItemAt(newSpot) == null) { break; }
newSpot++;
}
var newItem = itemInstance[j];
var newSpot = i + j - failedCount;
// valid slot found
if (inv.visualSlots.Length > newSpot)
{
var placedItem = inv.TryPutItem(newItem, newSpot, false, true, dummyCharacter);
spawnedItems |= placedItem;
if (!placedItem)
// try to find a valid slot to put the items
while (inv.visualSlots.Length > newSpot)
{
failedCount++;
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
if (inv.GetItemAt(newSpot) == null) { break; }
newSpot++;
}
// valid slot found
if (inv.visualSlots.Length > newSpot)
{
var placedItem = inv.TryPutItem(newItem, newSpot, false, true, dummyCharacter);
spawnedItems |= placedItem;
if (!placedItem)
{
failedCount++;
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
}
}
else
{
var placedItem = inv.TryPutItem(newItem, dummyCharacter);
spawnedItems |= placedItem;
// if our while loop didn't find a valid slot then let the inventory decide where to put it as a last resort
if (!placedItem)
{
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
}
}
}
else
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
if (placedEntities.Any())
{
var placedItem = inv.TryPutItem(newItem, dummyCharacter);
spawnedItems |= placedItem;
// if our while loop didn't find a valid slot then let the inventory decide where to put it as a last resort
if (!placedItem)
{
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
}
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
}
}
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
if (placedEntities.Any())
{
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
}
}
}
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
break;
}
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
break;
}
}
}
@@ -571,16 +571,37 @@ namespace Barotrauma
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
numberInput.valueStep = editableAttribute.ValueStep;
numberInput.ValueStep = editableAttribute.ValueStep;
numberInput.ForceShowPlusMinusButtons = editableAttribute.ForceShowPlusMinusButtons;
numberInput.FloatValue = value;
numberInput.OnValueChanged += (numInput) =>
numberInput.OnValueChanged += numInput =>
{
if (SetPropertyValue(property, entity, numInput.FloatValue))
{
TrySendNetworkUpdate(entity, property);
}
};
// Lots of UI boilerplate to handle all(?) cases where the property's setter may be called
// and modify the input value (e.g. rotation value wrapping)
void HandleSetterModifyingInput(GUINumberInput numInput)
{
var inputFloatValue = numInput.FloatValue;
var resultingFloatValue = property.GetFloatValue(entity);
if (!MathUtils.NearlyEqual(resultingFloatValue, inputFloatValue))
{
numInput.FloatValue = resultingFloatValue;
}
}
bool HandleSetterModifyingInputOnButtonPressed() { HandleSetterModifyingInput(numberInput); return true; }
bool HandleSetterModifyingInputOnButtonClicked(GUIButton _, object __) { HandleSetterModifyingInput(numberInput); return true; }
numberInput.OnValueEntered += HandleSetterModifyingInput;
numberInput.PlusButton.OnPressed += HandleSetterModifyingInputOnButtonPressed;
numberInput.PlusButton.OnClicked += HandleSetterModifyingInputOnButtonClicked;
numberInput.MinusButton.OnPressed += HandleSetterModifyingInputOnButtonPressed;
numberInput.MinusButton.OnClicked += HandleSetterModifyingInputOnButtonClicked;
refresh += () =>
{
if (!numberInput.TextBox.Selected) { numberInput.FloatValue = (float)property.GetValue(entity); }
@@ -859,7 +880,7 @@ namespace Barotrauma
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
numberInput.valueStep = editableAttribute.ValueStep;
numberInput.ValueStep = editableAttribute.ValueStep;
if (i == 0)
numberInput.FloatValue = value.X;
@@ -930,7 +951,7 @@ namespace Barotrauma
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
numberInput.valueStep = editableAttribute.ValueStep;
numberInput.ValueStep = editableAttribute.ValueStep;
if (i == 0)
numberInput.FloatValue = value.X;
@@ -1006,7 +1027,7 @@ namespace Barotrauma
numberInput.MinValueFloat = editableAttribute.MinValueFloat;
numberInput.MaxValueFloat = editableAttribute.MaxValueFloat;
numberInput.DecimalsToDisplay = editableAttribute.DecimalCount;
numberInput.valueStep = editableAttribute.ValueStep;
numberInput.ValueStep = editableAttribute.ValueStep;
if (i == 0)
numberInput.FloatValue = value.X;
@@ -16,7 +16,7 @@ namespace Barotrauma.Sounds
private short[] sampleBuffer = Array.Empty<short>();
private short[] muffleBuffer = Array.Empty<short>();
public OggSound(SoundManager owner, string filename, bool stream, XElement xElement) : base(owner, filename,
public OggSound(SoundManager owner, string filename, bool stream, ContentXElement xElement) : base(owner, filename,
stream, true, xElement)
{
var reader = new VorbisReader(Filename);
@@ -18,7 +18,7 @@ namespace Barotrauma.Sounds
public readonly string Filename;
public readonly XElement XElement;
public readonly ContentXElement XElement;
public readonly bool Stream;
@@ -60,14 +60,14 @@ namespace Barotrauma.Sounds
public float BaseNear;
public float BaseFar;
public Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, XElement xElement = null, bool getFullPath = true)
public Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, ContentXElement xElement = null, bool getFullPath = true)
{
Owner = owner;
Filename = getFullPath ? Path.GetFullPath(filename.CleanUpPath()).CleanUpPath() : filename;
Stream = stream;
StreamsReliably = streamsReliably;
XElement = xElement;
sourcePoolIndex = XElement.GetAttributeEnum("sourcepool", SoundManager.SourcePoolIndex.Default);
sourcePoolIndex = XElement?.GetAttributeEnum("sourcepool", SoundManager.SourcePoolIndex.Default) ?? SoundManager.SourcePoolIndex.Default;
BaseGain = 1.0f;
BaseNear = 100.0f;
@@ -111,7 +111,7 @@ namespace Barotrauma
partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn)
{
texture = LoadTexture(FilePath.Value, Compress);
texture = LoadTexture(FilePath.Value, Compress, contentPackage: SourceElement?.ContentPackage);
if (texture == null)
{
@@ -175,7 +175,7 @@ namespace Barotrauma
return;
}
texture.Dispose();
texture = TextureLoader.FromFile(FilePath.Value, Compress);
texture = TextureLoader.FromFile(FilePath.Value, Compress, contentPackage: SourceElement?.ContentPackage);
Identifier pathKey = FullPath.ToIdentifier();
if (textureRefCounts.ContainsKey(pathKey))
{
@@ -195,7 +195,7 @@ namespace Barotrauma
sourceRect = new Rectangle(0, 0, texture.Width, texture.Height);
}
public static Texture2D LoadTexture(string file, bool compress = true)
public static Texture2D LoadTexture(string file, bool compress = true, ContentPackage contentPackage = null)
{
if (string.IsNullOrWhiteSpace(file))
{
@@ -221,11 +221,11 @@ namespace Barotrauma
if (!ToolBox.IsProperFilenameCase(file))
{
#if DEBUG
DebugConsole.ThrowError("Texture file \"" + file + "\" has incorrect case!");
DebugConsole.ThrowError("Texture file \"" + file + "\" has incorrect case!", contentPackage: contentPackage);
#endif
}
Texture2D newTexture = TextureLoader.FromFile(file, compress);
Texture2D newTexture = TextureLoader.FromFile(file, compress, contentPackage: contentPackage);
lock (list)
{
if (!textureRefCounts.TryAdd(fullPath,
@@ -284,17 +284,35 @@ namespace Barotrauma
}
}
public void DrawTiled(ISpriteBatch spriteBatch, Vector2 position, Vector2 targetSize,
public void DrawTiled(ISpriteBatch spriteBatch, Vector2 position, Vector2 targetSize, float rotation = 0f, Vector2? origin = null,
Color? color = null, Vector2? startOffset = null, Vector2? textureScale = null, float? depth = null)
{
if (Texture == null) { return; }
bool flipHorizontal = (effects & SpriteEffects.FlipHorizontally) != 0;
bool flipVertical = (effects & SpriteEffects.FlipVertically) != 0;
float addedRotation = rotation + this.rotation;
if (flipHorizontal != flipVertical) { addedRotation = -addedRotation; }
Vector2 advanceX = addedRotation == 0.0f ? Vector2.UnitX : new Vector2((float)Math.Cos(addedRotation), (float)Math.Sin(addedRotation));
Vector2 advanceY = new Vector2(-advanceX.Y, advanceX.X);
//Init optional values
Vector2 drawOffset = startOffset ?? Vector2.Zero;
Vector2 scale = textureScale ?? Vector2.One;
Color drawColor = color ?? Color.White;
Vector2 transformedOrigin = origin ?? Vector2.Zero;
bool flipHorizontal = (effects & SpriteEffects.FlipHorizontally) != 0;
bool flipVertical = (effects & SpriteEffects.FlipVertically) != 0;
transformedOrigin = advanceX * transformedOrigin.X + advanceY * transformedOrigin.Y;
void drawSection(Vector2 slicePos, Rectangle sliceRect)
{
Vector2 transformedPos = slicePos - position;
transformedPos = advanceX * transformedPos.X + advanceY * transformedPos.Y;
transformedPos += position - transformedOrigin;
spriteBatch.Draw(texture, transformedPos, sliceRect, drawColor, addedRotation, Vector2.Zero, scale, effects, depth ?? this.depth);
}
//wrap the drawOffset inside the sourceRect
drawOffset.X = (drawOffset.X / scale.X) % sourceRect.Width;
@@ -368,8 +386,8 @@ namespace Barotrauma
{
slicePos.Y += flippedDrawOffset.Y;
}
spriteBatch.Draw(texture, slicePos, sliceRect, drawColor, rotation, Vector2.Zero, scale, effects, depth ?? this.depth);
drawSection(slicePos, sliceRect);
currDrawPosition.X = slicePos.X + sliceWidth;
}
}
@@ -416,7 +434,7 @@ namespace Barotrauma
sliceRect.Y = SourceRect.Y;
sliceRect.Height = (int)(sliceHeight / scale.Y);
spriteBatch.Draw(texture, slicePos, sliceRect, drawColor, rotation, Vector2.Zero, scale, effects, depth ?? this.depth);
drawSection(slicePos, sliceRect);
currDrawPosition.Y = slicePos.Y + sliceHeight;
}
@@ -433,8 +451,7 @@ namespace Barotrauma
}
}
spriteBatch.Draw(texture, currDrawPosition,
texPerspective, drawColor, rotation, Vector2.Zero, scale, effects, depth ?? this.depth);
drawSection(currDrawPosition, texPerspective);
currDrawPosition.Y += texPerspective.Height * scale.Y;
}
@@ -120,6 +120,10 @@ namespace Barotrauma.Steam
currentLobby?.SetData("playstyle", serverSettings.PlayStyle.ToString());
currentLobby?.SetData("gamemode", GameMain.NetLobbyScreen?.SelectedMode?.Identifier.Value ?? "");
currentLobby?.SetData("language", serverSettings.Language.ToString());
if (GameMain.NetLobbyScreen?.SelectedSub != null)
{
currentLobby?.SetData("submarine", GameMain.NetLobbyScreen.SelectedSub.Name);
}
DebugConsole.Log("Lobby updated!");
}
@@ -151,13 +151,13 @@ namespace Barotrauma
output[outputOffset + 10] = (byte)((g2_565 << 5) | b2_565);
}
public static Texture2D FromFile(string path, bool compress = true, bool mipmap = false)
public static Texture2D FromFile(string path, bool compress = true, bool mipmap = false, ContentPackage contentPackage = null)
{
using FileStream fileStream = File.OpenRead(path);
return FromStream(fileStream, path, compress, mipmap);
return FromStream(fileStream, path, compress, mipmap, contentPackage);
}
public static Texture2D FromStream(System.IO.Stream stream, string path = null, bool compress = true, bool mipmap = false)
public static Texture2D FromStream(System.IO.Stream stream, string path = null, bool compress = true, bool mipmap = false, ContentPackage contentPackage = null)
{
try
{
@@ -176,7 +176,8 @@ namespace Barotrauma
}
else
{
DebugConsole.AddWarning($"Could not compress a texture because the dimensions aren't a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})");
DebugConsole.AddWarning($"Could not compress a texture because the dimensions aren't a multiple of 4 (path: {path ?? "null"}, size: {width}x{height})",
contentPackage);
}
}