Unstable 0.1400.2.0 (a mimir edition)

This commit is contained in:
Markus Isberg
2021-05-28 19:04:09 +03:00
parent 5bc850cddb
commit 0b3fb5e440
126 changed files with 1623 additions and 787 deletions
@@ -9,7 +9,7 @@ namespace Barotrauma
{
public override void DebugDraw(SpriteBatch spriteBatch)
{
if (Character.IsDead) return;
if (Character.IsUnconscious || !Character.Enabled || !Enabled) { return; }
Vector2 pos = Character.WorldPosition;
pos.Y = -pos.Y;
@@ -38,7 +38,7 @@ namespace Barotrauma
}
targetPos.Y = -targetPos.Y;
GUI.DrawLine(spriteBatch, pos, targetPos, GUI.Style.Red * 0.5f, 0, 4);
if (wallTarget != null && (State == AIState.Attack || State == AIState.Aggressive || State == AIState.PassiveAggressive))
if (wallTarget != null)
{
Vector2 wallTargetPos = wallTarget.Position;
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
@@ -507,9 +507,10 @@ namespace Barotrauma
{
continue;
}
if (item.body != null && !item.body.Enabled) continue;
if (item.ParentInventory != null) continue;
if (ignoredItems != null && ignoredItems.Contains(item)) continue;
if (item.body != null && !item.body.Enabled) { continue; }
if (item.ParentInventory != null) { continue; }
if (ignoredItems != null && ignoredItems.Contains(item)) { continue; }
if (item.Prefab.RequireCampaignInteract && item.CampaignInteractionType == CampaignMode.InteractionType.None) { continue; }
if (Screen.Selected is SubEditorScreen editor && editor.WiringMode && item.GetComponent<ConnectionPanel>() == null) { continue; }
if (draggingItemToWorld)
@@ -400,7 +400,7 @@ namespace Barotrauma
if (Vector2.DistanceSquared(character.Position, item.Position) > 500f*500f) { continue; }
var body = Submarine.CheckVisibility(character.SimPosition, item.SimPosition, ignoreLevel: true);
if (body != null && body.UserData as Item != item) { continue; }
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Vector2(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color);
GUI.DrawIndicator(spriteBatch, item.WorldPosition + new Vector2(0f, item.RectHeight * 0.65f), cam, new Vector2(-100f, 500.0f), item.IconStyle.GetDefaultSprite(), item.IconStyle.Color, createOffset: false);
}
}
@@ -396,7 +396,9 @@ namespace Barotrauma
break;
case 6: //NetEntityEvent.Type.AssignCampaignInteraction
byte campaignInteractionType = msg.ReadByte();
bool requireConsciousness = msg.ReadBoolean();
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
RequireConsciousnessForCustomInteract = requireConsciousness;
break;
case 7: //NetEntityEvent.Type.ObjectiveManagerState
// 1 = order, 2 = objective
@@ -458,7 +460,7 @@ namespace Barotrauma
{
DebugConsole.Log("Reading character spawn data");
if (GameMain.Client == null) return null;
if (GameMain.Client == null) { return null; }
bool noInfo = inc.ReadBoolean();
ushort id = inc.ReadUInt16();
@@ -474,7 +476,15 @@ namespace Barotrauma
Character character = null;
if (noInfo)
{
character = Create(speciesName, position, seed, characterInfo: null, id: id, isRemotePlayer: false);
try
{
character = Create(speciesName, position, seed, characterInfo: null, id: id, isRemotePlayer: false);
}
catch (Exception e)
{
DebugConsole.ThrowError($"Failed to spawn character {speciesName}", e);
throw;
}
bool containsStatusData = inc.ReadBoolean();
if (containsStatusData)
{
@@ -490,8 +500,15 @@ namespace Barotrauma
string infoSpeciesName = inc.ReadString();
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.ID != ownerId, hasAi: hasAi);
try
{
character = Create(speciesName, position, seed, characterInfo: info, id: id, isRemotePlayer: ownerId > 0 && GameMain.Client.ID != ownerId, hasAi: hasAi);
}
catch (Exception e)
{
DebugConsole.ThrowError($"Failed to spawn character {speciesName}", e);
throw;
}
character.TeamID = (CharacterTeamType)teamID;
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
@@ -241,6 +241,7 @@ namespace Barotrauma
case "toggleupperhud":
case "togglecharacternames":
case "fpscounter":
case "showperf":
case "dumptofile":
case "findentityids":
case "setfreecamspeed":
@@ -16,7 +16,6 @@ namespace Barotrauma
for (int j = 0; j < itemCount; j++)
{
Item.ReadSpawnData(msg);
}
}
if (characters.Contains(null))
@@ -239,6 +239,9 @@ namespace Barotrauma
private static SavingIndicatorState savingIndicatorState = SavingIndicatorState.None;
private static float? timeUntilSavingIndicatorDisabled;
private static string loadedSpritesText;
private static DateTime loadedSpritesUpdateTime;
private enum SavingIndicatorState
{
None,
@@ -454,9 +457,12 @@ namespace Barotrauma
"Particle count: " + GameMain.ParticleManager.ParticleCount + "/" + GameMain.ParticleManager.MaxParticles,
Color.Lerp(GUI.Style.Green, GUI.Style.Red, (GameMain.ParticleManager.ParticleCount / (float)GameMain.ParticleManager.MaxParticles)), Color.Black * 0.5f, 0, SmallFont);
DrawString(spriteBatch, new Vector2(10, 115),
"Loaded sprites: " + Sprite.LoadedSprites.Count() + "\n(" + Sprite.LoadedSprites.Select(s => s.FilePath).Distinct().Count() + " unique textures)",
Color.White, Color.Black * 0.5f, 0, SmallFont);
if (loadedSpritesText == null || DateTime.Now > loadedSpritesUpdateTime)
{
loadedSpritesText = "Loaded sprites: " + Sprite.LoadedSprites.Count() + "\n(" + Sprite.LoadedSprites.Select(s => s.FilePath).Distinct().Count() + " unique textures)";
loadedSpritesUpdateTime = DateTime.Now + new TimeSpan(0, 0, seconds: 5);
}
DrawString(spriteBatch, new Vector2(10, 115), loadedSpritesText, Color.White, Color.Black * 0.5f, 0, SmallFont);
if (debugDrawSounds)
{
@@ -1365,8 +1371,9 @@ namespace Barotrauma
float screenDist = Vector2.Distance(cam.WorldToScreen(cam.WorldViewCenter), targetScreenPos);
float angle = MathUtils.VectorToAngle(diff);
float originalAngle = angle;
float minAngleDiff = 0.05f;
const float minAngleDiff = 0.05f;
bool overlapFound = true;
int iterations = 0;
while (overlapFound && iterations < 10)
@@ -1388,18 +1395,24 @@ namespace Barotrauma
usedIndicatorAngles.Add(angle);
Vector2 unclampedDiff = new Vector2(
(float)Math.Cos(angle) * screenDist,
(float)-Math.Sin(angle) * screenDist);
Vector2 iconDiff = new Vector2(
(float)Math.Cos(angle) * Math.Min(GameMain.GraphicsWidth * 0.4f, screenDist + 10),
(float)-Math.Sin(angle) * Math.Min(GameMain.GraphicsHeight * 0.4f, screenDist + 10));
angle = MathHelper.Lerp(originalAngle, angle, MathHelper.Clamp(((screenDist + 10f) - iconDiff.Length()) / 10f, 0f, 1f));
/*Vector2 unclampedDiff = new Vector2(
(float)Math.Cos(angle) * screenDist,
(float)-Math.Sin(angle) * screenDist);*/
iconDiff = new Vector2(
(float)Math.Cos(angle) * Math.Min(GameMain.GraphicsWidth * 0.4f, screenDist),
(float)-Math.Sin(angle) * Math.Min(GameMain.GraphicsHeight * 0.4f, screenDist));
Vector2 iconPos = cam.WorldToScreen(cam.WorldViewCenter) + iconDiff;
sprite.Draw(spriteBatch, iconPos, color * alpha, rotate: 0.0f, scale: symbolScale);
if (unclampedDiff.Length() - 10 > iconDiff.Length())
if (/*unclampedDiff.Length()*/ screenDist - 10 > iconDiff.Length())
{
Vector2 normalizedDiff = Vector2.Normalize(targetScreenPos - iconPos);
Vector2 arrowOffset = normalizedDiff * sprite.size.X * symbolScale * 0.7f;
@@ -838,6 +838,7 @@ namespace Barotrauma
{
bool hasPermissions = HasPermissions;
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
bool refreshingBuyList = listBox == shoppingCrateBuyList;
int totalPrice = 0;
foreach (PurchasedItem item in items)
{
@@ -859,6 +860,7 @@ namespace Barotrauma
{
numInput.UserData = item;
numInput.Enabled = hasPermissions;
numInput.MaxValueInt = GetMaxAvailable(item.ItemPrefab, refreshingBuyList ? StoreTab.Buy : StoreTab.Sell);
}
SetOwnedLabelText(itemFrame);
SetItemFrameStatus(itemFrame, hasPermissions);
@@ -873,7 +875,7 @@ namespace Barotrauma
}
suppressBuySell = false;
var price = listBox == shoppingCrateBuyList ?
var price = refreshingBuyList ?
CurrentLocation.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo) :
CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo);
totalPrice += item.Quantity * price;
@@ -884,7 +886,7 @@ namespace Barotrauma
SortItems(listBox, SortingMethod.CategoryAsc);
listBox.UpdateScrollBarSize();
if (listBox == shoppingCrateBuyList)
if (refreshingBuyList)
{
buyTotal = totalPrice;
if (IsBuying) { SetShoppingCrateTotalText(); }
@@ -12,7 +12,8 @@ namespace Barotrauma
private const int submarinesPerPage = 4;
private int currentPage = 1;
private int pageCount;
private bool transferService, purchaseService, initialized;
private readonly bool transferService, purchaseService;
private bool initialized;
private int deliveryFee;
private string deliveryLocationName;
@@ -27,12 +28,12 @@ namespace Barotrauma
private int selectionIndicatorThickness;
private GUIImage listBackground;
private List<SubmarineInfo> subsToShow;
private SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
private readonly List<SubmarineInfo> subsToShow;
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
private SubmarineInfo selectedSubmarine = null;
private string purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyShorthandText, currencyLongText;
private RectTransform parent;
private Action closeAction;
private readonly RectTransform parent;
private readonly Action closeAction;
private Sprite pageIndicator;
public static readonly string[] DeliveryTextVariables = new string[] { "[submarinename1]", "[location1]", "[location2]", "[submarinename2]", "[amount]", "[currencyname]" };
@@ -42,7 +43,7 @@ namespace Barotrauma
private static readonly string[] notEnoughCreditsDeliveryTextVariables = new string[] { "[currencyname]", "[submarinename]", "[location1]", "[location2]" };
private static readonly string[] notEnoughCreditsPurchaseTextVariables = new string[] { "[currencyname]", "[submarinename]" };
private string[] messageBoxOptions;
private readonly string[] messageBoxOptions;
public const int DeliveryFeePerDistanceTravelled = 1000;
public static bool ContentRefreshRequired = false;
@@ -65,7 +66,7 @@ namespace Barotrauma
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
{
if (GameMain.GameSession.Campaign == null) return;
if (GameMain.GameSession.Campaign == null) { return; }
transferService = transfer;
purchaseService = !transfer;
@@ -83,7 +84,7 @@ namespace Barotrauma
messageBoxOptions = new string[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
}
if (Submarine.MainSub?.Info == null) return;
if (Submarine.MainSub?.Info == null) { return; }
Initialize();
}
@@ -184,8 +185,10 @@ namespace Barotrauma
for (int i = 0; i < submarineDisplays.Length; i++)
{
SubmarineDisplayContent submarineDisplayElement = new SubmarineDisplayContent();
submarineDisplayElement.background = new GUIFrame(new RectTransform(new Vector2(1f / submarinesPerPage, 1f), submarineHorizontalGroup.RectTransform), style: null, new Color(8, 13, 19));
SubmarineDisplayContent submarineDisplayElement = new SubmarineDisplayContent
{
background = new GUIFrame(new RectTransform(new Vector2(1f / submarinesPerPage, 1f), submarineHorizontalGroup.RectTransform), style: null, new Color(8, 13, 19))
};
submarineDisplayElement.submarineImage = new GUIImage(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), null, true);
submarineDisplayElement.middleTextBlock = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), string.Empty, textAlignment: Alignment.Center);
submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
@@ -433,7 +436,7 @@ namespace Barotrauma
private SubmarineInfo GetSubToDisplay(int index)
{
if (subsToShow.Count <= index || index < 0) return null;
if (subsToShow.Count <= index || index < 0) { return null; }
return subsToShow[index];
}
@@ -112,10 +112,10 @@ namespace Barotrauma
{
switch (selectedUpgradeTab)
{
case UpgradeTab.Repairs:
case UpgradeTab.Repairs:
SelectTab(UpgradeTab.Repairs);
break;
case UpgradeTab.Upgrade:
break;
case UpgradeTab.Upgrade:
RefreshUpgradeList();
foreach (var itemPreview in itemPreviews)
{
@@ -123,7 +123,7 @@ namespace Barotrauma
if (!(itemPreview.Value is GUIImage image)) { continue; }
image.Sprite = itemPreview.Key.PendingItemSwap.UpgradePreviewSprite;
}
break;
break;
}
}
@@ -170,6 +170,11 @@ namespace Barotrauma
// ReSharper disable once PossibleMultipleEnumeration
UpdateCategoryIndicators(indicators, component, data.Prefabs, data.Category, campaign, drawnSubmarine, applicableCategories);
}
var customizeButton = component.FindChild("customizebutton", true);
if (customizeButton != null)
{
customizeButton.Visible = HasSwappableItems(data.Category);
}
}
// reset the order first
@@ -625,6 +630,20 @@ namespace Barotrauma
frameChild.DefaultColor = frameChild.Color;
frameChild.Color = Color.Transparent;
var weaponSwitchBg = new GUIButton(new RectTransform(new Vector2(0.65f), frameChild.RectTransform, Anchor.TopRight, scaleBasis: ScaleBasis.Smallest)
{ RelativeOffset = new Vector2(0.04f, 0.0f) }, style: "WeaponSwitchTab")
{
Visible = false,
CanBeSelected = false,
UserData = "customizebutton"
};
weaponSwitchBg.DefaultColor = weaponSwitchBg.Frame.DefaultColor = weaponSwitchBg.Color;
var weaponSwitchImg = new GUIImage(new RectTransform(new Vector2(0.7f), weaponSwitchBg.RectTransform, Anchor.Center), "WeaponSwitchIcon", scaleToFit: true)
{
CanBeFocused = false
};
weaponSwitchImg.DefaultColor = weaponSwitchImg.Color;
/* UPGRADE CATEGORY
* |--------------------------------------------------------|
* | |
@@ -670,6 +689,7 @@ namespace Barotrauma
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = previewWhite;
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
}
return true;
}
@@ -679,6 +699,9 @@ namespace Barotrauma
TrySelectCategory(prefabs, categoryData.Category, sub);
}
var customizeCategoryButton = selectedUpgradeCategoryLayout?.FindChild("customizebutton", recursive: true) as GUIButton;
customizeCategoryButton?.OnClicked(customizeCategoryButton, customizeCategoryButton.UserData);
return true;
};
}
@@ -688,6 +711,16 @@ namespace Barotrauma
private bool customizeTabOpen;
private static bool HasSwappableItems(UpgradeCategory category)
{
if (Submarine.MainSub == null) { return false; }
return Submarine.MainSub.GetItems(true).Any(i =>
i.Prefab.SwappableItem != null &&
!i.HiddenInGame && i.AllowSwapping &&
(i.Prefab.SwappableItem.CanBeBought || ItemPrefab.Prefabs.Any(ip => ip.SwappableItem?.ReplacementOnUninstall == i.Prefab.Identifier)) &&
Submarine.MainSub.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t)));
}
private void SelectUpgradeCategory(List<UpgradePrefab> prefabs, UpgradeCategory category, Submarine submarine)
{
if (selectedUpgradeCategoryLayout == null) { return; }
@@ -698,6 +731,7 @@ namespace Barotrauma
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
}
highlightWalls = category.IsWallUpgrade;
@@ -706,11 +740,7 @@ namespace Barotrauma
GUIFrame frame = new GUIFrame(rectT(1.0f, 0.4f, selectedUpgradeCategoryLayout));
GUIFrame paddedFrame = new GUIFrame(rectT(0.93f, 0.9f, frame, Anchor.Center), style: null);
bool hasSwappableItems = Submarine.MainSub.GetItems(true).Any(i =>
i.Prefab.SwappableItem != null &&
!i.HiddenInGame && i.AllowSwapping &&
(i.Prefab.SwappableItem.CanBeBought || ItemPrefab.Prefabs.Any(ip => ip.SwappableItem?.ReplacementOnUninstall == i.Prefab.Identifier)) &&
Submarine.MainSub.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t)));
bool hasSwappableItems = HasSwappableItems(category);
float listHeight = hasSwappableItems ? 0.9f : 1.0f;
@@ -725,12 +755,19 @@ namespace Barotrauma
{
GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1.0f, 0.1f, paddedFrame, anchor: Anchor.TopLeft), isHorizontal: true);
GUIButton customizeButton = new GUIButton(rectT(0.5f, 1f, buttonLayout), text: TextManager.Get("uicategory.customize"), style: "GUITabButton")
{
UserData = "customizebutton"
};
new GUIImage(new RectTransform(new Vector2(1.0f, 0.75f), customizeButton.RectTransform, Anchor.CenterLeft, scaleBasis: ScaleBasis.Smallest) { RelativeOffset = new Vector2(0.015f, 0.0f) }, "WeaponSwitchIcon", scaleToFit: true);
customizeButton.TextBlock.RectTransform.RelativeSize = new Vector2(0.7f, 1.0f);
GUIButton upgradeButton = new GUIButton(rectT(0.5f, 1f, buttonLayout), text: TextManager.Get("uicategory.upgrades"), style: "GUITabButton")
{
Selected = true
};
GUIButton customizeButton = new GUIButton(rectT(0.5f, 1f, buttonLayout), text: TextManager.Get("uicategory.customize"), style: "GUITabButton");
GUITextBlock.AutoScaleAndNormalize(upgradeButton.TextBlock, customizeButton.TextBlock);
upgradeButton.OnClicked = delegate
{
@@ -742,6 +779,7 @@ namespace Barotrauma
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
itemFrame.Children.ForEach(c => c.Color = itemFrame.Color);
}
return true;
};
@@ -754,7 +792,6 @@ namespace Barotrauma
CreateSwappableItemList(prefabList, category, submarine);
return true;
};
}
CreateUpgradePrefabList(prefabList, category, prefabs, submarine);
@@ -779,23 +816,25 @@ namespace Barotrauma
{
parent.Content.ClearChildren();
currentUpgradeCategory = category;
IEnumerable<ItemPrefab> availableReplacements = MapEntityPrefab.List.Where(p =>
p is ItemPrefab itemPrefab &&
category.ItemTags.Any(t => itemPrefab.Tags.Contains(t)) &&
(itemPrefab.SwappableItem?.CanBeBought ?? false)).Cast<ItemPrefab>();
var entitiesOnSub = submarine.GetItems(true).Where(i => submarine.IsEntityFoundOnThisSub(i, true) && !i.HiddenInGame && i.AllowSwapping && category.ItemTags.Any(t => i.HasTag(t))).ToList();
int slotIndex = 0;
foreach (Item item in entitiesOnSub)
{
slotIndex++;
CreateSwappableItemSlideDown(parent, slotIndex, item, availableReplacements);
CreateSwappableItemSlideDown(parent, slotIndex, item, submarine);
}
}
private void CreateSwappableItemSlideDown(GUIListBox parent, int slotIndex, Item item, IEnumerable<ItemPrefab> availableReplacements)
private void CreateSwappableItemSlideDown(GUIListBox parent, int slotIndex, Item item, Submarine submarine)
{
if (Campaign == null) { return; }
if (Campaign == null || submarine == null) { return; }
IEnumerable<ItemPrefab> availableReplacements = MapEntityPrefab.List.Where(p =>
p is ItemPrefab itemPrefab &&
itemPrefab.SwappableItem != null &&
itemPrefab.SwappableItem.CanBeBought &&
itemPrefab.SwappableItem.SwapIdentifier.Equals(item.Prefab.SwappableItem.SwapIdentifier, StringComparison.OrdinalIgnoreCase)).Cast<ItemPrefab>();
var currentOrPending = item.PendingItemSwap ?? item.Prefab;
@@ -833,7 +872,7 @@ namespace Barotrauma
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), currentOrPending.UpgradePreviewSprite,
TextManager.GetWithVariable(item.PendingItemSwap != null ? "upgrades.pendingitem" : "upgrades.installeditem", "[itemname]", currentOrPending.Name),
currentOrPending.Description,
0, null, addBuyButton: canUninstall, addProgressBar: false, buttonStyle: "StoreRemoveFromCrateButton"));
0, null, addBuyButton: canUninstall, addProgressBar: false, buttonStyle: "WeaponUninstallButton"));
if (canUninstall && frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton refundButton)
{
@@ -876,7 +915,7 @@ namespace Barotrauma
price, replacement,
addBuyButton: true,
addProgressBar: false,
buttonStyle: isPurchased ? "UpgradeBuyButton" : "StoreAddToCrateButton"));
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
if (Campaign.Money >= price)
@@ -1234,9 +1273,11 @@ namespace Barotrauma
{
if (selectedUpgradeCategoryLayout != null)
{
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem, recursive: true) is GUIButton itemElement && !itemElement.Selected)
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem, recursive: true) is GUIButton itemElement)
{
itemElement.OnClicked(itemElement, itemElement.UserData);
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
//TODO: enable this if/when we make ScrollToElement work with child elements of different sizes
//(itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
}
}
}
@@ -1343,6 +1384,15 @@ namespace Barotrauma
HoverCursor = CursorState.Hand,
SpriteEffects = item.Rotation > 90.0f && item.Rotation < 270.0f ? SpriteEffects.FlipVertically : SpriteEffects.None
};
if (item.Prefab.SwappableItem != null)
{
new GUIImage(new RectTransform(new Vector2(0.8f), itemFrame.RectTransform, Anchor.TopLeft) { RelativeOffset = new Vector2(-0.2f) }, "WeaponSwitchIcon.DropShadow", scaleToFit: true)
{
SelectedColor = GUI.Style.Orange,
Color = previewWhite,
CanBeFocused = false
};
}
}
else
{
@@ -1287,18 +1287,28 @@ namespace Barotrauma
private int TryAdjustIndex(int amount)
{
int index = Character.Controlled == null ? 0 :
crewList.Content.GetChildIndex(crewList.Content.GetChildByUserData(Character.Controlled)) + amount;
if (Character.Controlled == null) { return 0; }
int currentIndex = crewList.Content.GetChildIndex(crewList.Content.GetChildByUserData(Character.Controlled));
if (currentIndex == -1) { return 0; }
int lastIndex = crewList.Content.CountChildren - 1;
if (index > lastIndex)
int index = currentIndex + amount;
for (int i = 0; i < crewList.Content.CountChildren; i++)
{
index = 0;
if (index > lastIndex) { index = 0; }
if (index < 0) { index = lastIndex; }
if ((crewList.Content.GetChild(index)?.UserData as Character)?.IsOnPlayerTeam ?? false)
{
return index;
}
index += amount;
}
if (index < 0)
{
index = lastIndex;
}
return index;
return 0;
}
partial void UpdateProjectSpecific(float deltaTime)
@@ -445,9 +445,13 @@ namespace Barotrauma
{
Submarine.MainSub = leavingSub;
GameMain.GameSession.Submarine = leavingSub;
GameMain.GameSession.SubmarineInfo = leavingSub.Info;
leavingSub.Info.FilePath = System.IO.Path.Combine(SaveUtil.TempPath, leavingSub.Info.Name + ".sub");
var subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
GameMain.GameSession.OwnedSubmarines.Add(leavingSub.Info);
foreach (Submarine sub in subsToLeaveBehind)
{
GameMain.GameSession.OwnedSubmarines.RemoveAll(s => s != leavingSub.Info && s.Name == sub.Info.Name);
MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
LinkedSubmarine.CreateDummy(leavingSub, sub);
}
@@ -559,7 +563,7 @@ namespace Barotrauma
}
#if DEBUG
if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.R))
if (GUI.KeyboardDispatcher.Subscriber == null && PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.M))
{
if (GUIMessageBox.MessageBoxes.Any()) { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.MessageBoxes.Last()); }
@@ -537,9 +537,12 @@ namespace Barotrauma
}
List<SlotReference> hideSubInventories = new List<SlotReference>();
//remove highlighted subinventory slots that can no longer be accessed
highlightedSubInventorySlots.RemoveWhere(s =>
s.ParentInventory == this &&
((s.SlotIndex < 0 || s.SlotIndex >= slots.Length || slots[s.SlotIndex] == null) || (Character.Controlled != null && !Character.Controlled.CanAccessInventory(s.Inventory))));
//remove highlighted subinventory slots that refer to items no longer in this inventory
highlightedSubInventorySlots.RemoveWhere(s => s.Item != null && s.ParentInventory == this && s.Item.ParentInventory != this);
foreach (var highlightedSubInventorySlot in highlightedSubInventorySlots)
{
if (highlightedSubInventorySlot.ParentInventory == this)
@@ -611,5 +611,6 @@ namespace Barotrauma.Items.Components
}
OnResolutionChanged();
}
public virtual void AddTooltipInfo(ref string description) { }
}
}
@@ -1094,7 +1094,10 @@ namespace Barotrauma.Items.Components
if (!dockingPort.Item.Submarine.ShowSonarMarker && dockingPort.Item.Submarine != item.Submarine && !dockingPort.Item.Submarine.Info.IsOutpost) { continue; }
//don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null && item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle && dockingPort.Item.Submarine.Info.Type != SubmarineType.Outpost)
if (item.Submarine != null &&
item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
dockingPort.Item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
dockingPort.Item.Submarine.Info.Type != SubmarineType.Outpost)
{
// specifically checking for friendlyNPC seems more logical here
if (dockingPort.Item.Submarine.TeamID != item.Submarine.TeamID && dockingPort.Item.Submarine.TeamID != CharacterTeamType.FriendlyNPC) { continue; }
@@ -367,9 +367,9 @@ namespace Barotrauma.Items.Components
//a wire has been selected -> check if we should start dragging one of the nodes
float nodeSelectDist = 10, sectionSelectDist = 5;
highlightedNodeIndex = null;
if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item)
if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList.FirstOrDefault() is Item selectedItem)
{
Wire selectedWire = ((Item)MapEntity.SelectedList[0]).GetComponent<Wire>();
Wire selectedWire = selectedItem.GetComponent<Wire>();
if (selectedWire != null)
{
@@ -267,7 +267,7 @@ namespace Barotrauma.Items.Components
}
else if (chargeSoundChannel != null)
{
chargeSoundChannel.FrequencyMultiplier = MathHelper.Lerp(1f, 2f, chargeRatio);
chargeSoundChannel.FrequencyMultiplier = MathHelper.Lerp(0.5f, 1.5f, chargeRatio);
}
break;
default:
@@ -363,13 +363,13 @@ namespace Barotrauma.Items.Components
float chargeRatio = currentChargeTime / MaxChargeTime;
foreach (Tuple<Sprite, Vector2> chargeSprite in chargeSprites)
foreach ((Sprite chargeSprite, Vector2 position) in chargeSprites)
{
chargeSprite.Item1?.Draw(spriteBatch,
drawPos - MathUtils.RotatePoint(new Vector2(chargeSprite.Item2.X * chargeRatio, chargeSprite.Item2.Y * chargeRatio) * item.Scale, rotation + MathHelper.PiOver2),
chargeSprite?.Draw(spriteBatch,
drawPos - MathUtils.RotatePoint(new Vector2(position.X * chargeRatio, position.Y * chargeRatio) * item.Scale, rotation + MathHelper.PiOver2),
item.SpriteColor,
rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (chargeSprite.Item1.Depth - item.Sprite.Depth));
SpriteEffects.None, item.SpriteDepth + (chargeSprite.Depth - item.Sprite.Depth));
}
int spinningBarrelCount = spinningBarrelSprites.Count;
@@ -380,7 +380,7 @@ namespace Barotrauma.Items.Components
Sprite spinningBarrel = spinningBarrelSprites[i];
float barrelCirclePosition = (MaxCircle * i / spinningBarrelCount + currentBarrelSpin) % MaxCircle;
float newDepth = spinningBarrel.Depth + (barrelCirclePosition > HalfCircle ? -0.001f : 0.001f);
float newDepth = item.SpriteDepth + (spinningBarrel.Depth - item.Sprite.Depth) + (barrelCirclePosition > HalfCircle ? 0.0f : 0.001f);
float barrelColorPosition = (barrelCirclePosition + QuarterCircle) % MaxCircle;
float colorOffset = Math.Abs(barrelColorPosition - HalfCircle) / HalfCircle;
@@ -0,0 +1,50 @@
using System;
using System.Linq;
namespace Barotrauma.Items.Components
{
partial class Wearable
{
private void GetDamageModifierText(ref string description, float damageMultiplier, string afflictionIdentifier)
{
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
description += $"\n ‖color:{colorStr}‖-{Math.Round((1 - damageMultiplier) * 100)}%‖color:end‖ {TextManager.Get("AfflictionName." + afflictionIdentifier, true) ?? afflictionIdentifier}";
}
public override void AddTooltipInfo(ref string description)
{
if (damageModifiers.Any(d => d.DamageMultiplier != 1f) || SkillModifiers.Any())
{
description += "\n";
}
if (damageModifiers.Any())
{
foreach (DamageModifier damageModifier in damageModifiers)
{
if (damageModifier.DamageMultiplier == 1f)
{
continue;
}
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionIdentifiers)
{
GetDamageModifierText(ref description, damageModifier.DamageMultiplier, afflictionIdentifier);
}
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionTypes)
{
GetDamageModifierText(ref description, damageModifier.DamageMultiplier, afflictionIdentifier);
}
}
}
if (SkillModifiers.Any())
{
foreach (var skillModifier in SkillModifiers)
{
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
description += $"\n ‖color:{colorStr}‖+{skillModifier.Value}‖color:end‖ {TextManager.Get("SkillName." + skillModifier.Key, true) ?? skillModifier.Key}";
}
}
}
}
}
@@ -296,6 +296,12 @@ namespace Barotrauma
}
}
}
foreach (ItemComponent component in item.Components)
{
component.AddTooltipInfo(ref description);
}
if (item.Prefab.ShowContentsInTooltip && item.OwnInventory != null)
{
foreach (string itemName in item.OwnInventory.AllItems.Select(it => it.Name).Distinct())
@@ -950,6 +956,15 @@ namespace Barotrauma
{
return CursorState.Hand;
}
var container = item?.GetComponent<ItemContainer>();
if (container == null) { continue; }
if (container.Inventory.visualSlots != null)
{
if (container.Inventory.visualSlots.Any(slot => slot.IsHighlighted))
{
return CursorState.Hand;
}
}
}
}
@@ -1586,11 +1586,20 @@ namespace Barotrauma
}
}
var item = new Item(itemPrefab, pos, sub, id: itemId)
Item item = null;
try
{
SpawnedInOutpost = spawnedInOutpost,
AllowStealing = allowStealing
};
item = new Item(itemPrefab, pos, sub, id: itemId)
{
SpawnedInOutpost = spawnedInOutpost,
AllowStealing = allowStealing
};
}
catch (Exception e)
{
DebugConsole.ThrowError($"Failed to spawn item {itemPrefab.Name}", e);
throw;
}
if (item.body != null)
{
@@ -71,7 +71,7 @@ namespace Barotrauma
if (sparks)
{
GameMain.ParticleManager.CreateParticle("spark", worldPosition,
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f, hull);
Rand.Vector(Rand.Range(1200.0f, 2400.0f)), 0.0f, hull);
}
}
@@ -29,20 +29,14 @@ namespace Barotrauma
public static bool SelectionChanged;
//which entities have been selected for editing
private static List<MapEntity> selectedList = new List<MapEntity>();
public static List<MapEntity> SelectedList
{
get
{
return selectedList;
}
}
private static List<MapEntity> copiedList = new List<MapEntity>();
public static HashSet<MapEntity> SelectedList { get; private set; } = new HashSet<MapEntity>();
public static List<MapEntity> CopiedList = new List<MapEntity>();
private static List<MapEntity> highlightedList = new List<MapEntity>();
// Test feature. Not yet saved.
public static Dictionary<MapEntity, List<MapEntity>> SelectionGroups { get; private set; } = new Dictionary<MapEntity, List<MapEntity>>();
public static Dictionary<MapEntity, HashSet<MapEntity>> SelectionGroups { get; private set; } = new Dictionary<MapEntity, HashSet<MapEntity>>();
private static float highlightTimer;
@@ -78,26 +72,12 @@ namespace Barotrauma
}
}
public virtual bool SelectableInEditor
{
get { return true; }
}
public virtual bool SelectableInEditor => true;
public static bool SelectedAny
{
get { return selectedList.Count > 0; }
}
public static bool SelectedAny => SelectedList.Count > 0;
public static IEnumerable<MapEntity> CopiedList
{
get { return copiedList; }
}
public bool IsSelected => SelectedList.Contains(this);
public bool IsSelected
{
get { return selectedList.Contains(this); }
}
public bool IsIncludedInSelection { get; set; }
public virtual bool IsVisible(Rectangle worldView)
@@ -131,7 +111,10 @@ namespace Barotrauma
{
if (resizing)
{
if (selectedList.Count == 0) resizing = false;
if (!SelectedAny)
{
resizing = false;
}
return;
}
@@ -159,19 +142,19 @@ namespace Barotrauma
if (MapEntityPrefab.Selected != null)
{
selectionPos = Vector2.Zero;
selectedList.Clear();
SelectedList.Clear();
return;
}
if (GUI.KeyboardDispatcher.Subscriber == null)
{
if (PlayerInput.KeyHit(Keys.Delete))
{
if (selectedList.Any())
if (SelectedAny)
{
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(selectedList, true));
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(SelectedList), true));
}
selectedList.ForEach(e => { if (!e.Removed) { e.Remove(); } });
selectedList.Clear();
SelectedList.ForEach(e => { if (!e.Removed) { e.Remove(); } });
SelectedList.Clear();
}
if (PlayerInput.IsCtrlDown())
@@ -180,7 +163,7 @@ namespace Barotrauma
if (PlayerInput.KeyHit(Keys.D))
{
bool terminate = false;
foreach (MapEntity entity in selectedList)
foreach (MapEntity entity in SelectedList)
{
if (entity is Item item && item.GetComponent<Planter>() is { } planter)
{
@@ -203,11 +186,11 @@ namespace Barotrauma
#endif
if (PlayerInput.KeyHit(Keys.C))
{
Copy(selectedList);
Copy(SelectedList.ToList());
}
else if (PlayerInput.KeyHit(Keys.X))
{
Cut(selectedList);
Cut(SelectedList.ToList());
}
else if (PlayerInput.KeyHit(Keys.V))
{
@@ -215,21 +198,21 @@ namespace Barotrauma
}
else if (PlayerInput.KeyHit(Keys.G))
{
if (selectedList.Any())
if (SelectedList.Any())
{
if (SelectionGroups.ContainsKey(selectedList.Last()))
if (SelectionGroups.ContainsKey(SelectedList.Last()))
{
// Ungroup all selected
selectedList.ForEach(e => SelectionGroups.Remove(e));
SelectedList.ForEach(e => SelectionGroups.Remove(e));
}
else
{
foreach (var entity in selectedList)
foreach (var entity in SelectedList)
{
// Remove the old group, if any
SelectionGroups.Remove(entity);
// Create a group that can be accessed with any member
SelectionGroups.Add(entity, selectedList);
SelectionGroups.Add(entity, SelectedList);
}
}
}
@@ -279,7 +262,7 @@ namespace Barotrauma
Vector2 nudge = GetNudgeAmount();
if (nudge != Vector2.Zero)
{
foreach (MapEntity entityToNudge in selectedList) { entityToNudge.Move(nudge); }
foreach (MapEntity entityToNudge in SelectedList) { entityToNudge.Move(nudge); }
}
}
else
@@ -292,7 +275,7 @@ namespace Barotrauma
//started moving selected entities
if (startMovingPos != Vector2.Zero)
{
Item targetContainer = GetPotentialContainer(position, selectedList);
Item targetContainer = GetPotentialContainer(position, SelectedList);
if (targetContainer != null) { targetContainer.IsHighlighted = true; }
@@ -315,16 +298,16 @@ namespace Barotrauma
//clone
if (PlayerInput.IsCtrlDown())
{
var clones = Clone(selectedList).Where(c => c != null).ToList();
selectedList = clones;
selectedList.ForEach(c => c.Move(moveAmount));
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
HashSet<MapEntity> clones = Clone(SelectedList.ToList()).Where(c => c != null).ToHashSet();
SelectedList = clones;
SelectedList.ForEach(c => c.Move(moveAmount));
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(clones), false));
}
else // move
{
var oldRects = selectedList.Select(e => e.Rect).ToList();
var oldRects = SelectedList.Select(e => e.Rect).ToList();
List<MapEntity> deposited = new List<MapEntity>();
foreach (MapEntity e in selectedList)
foreach (MapEntity e in SelectedList)
{
e.Move(moveAmount);
@@ -342,14 +325,14 @@ namespace Barotrauma
}
}
SubEditorScreen.StoreCommand(new TransformCommand(new List<MapEntity>(selectedList),selectedList.Select(entity => entity.Rect).ToList(), oldRects, false));
SubEditorScreen.StoreCommand(new TransformCommand(new List<MapEntity>(SelectedList),SelectedList.Select(entity => entity.Rect).ToList(), oldRects, false));
if (deposited.Any() && deposited.Any(entity => entity is Item))
{
var depositedItems = deposited.Where(entity => entity is Item).Cast<Item>().ToList();
SubEditorScreen.StoreCommand(new InventoryPlaceCommand(targetContainer.OwnInventory, depositedItems, false));
}
deposited.ForEach(entity => { selectedList.Remove(entity); });
deposited.ForEach(entity => { SelectedList.Remove(entity); });
}
}
startMovingPos = Vector2.Zero;
@@ -367,7 +350,7 @@ namespace Barotrauma
entity.IsIncludedInSelection = false;
}
List<MapEntity> newSelection = new List<MapEntity>();// FindSelectedEntities(selectionPos, selectionSize);
HashSet<MapEntity> newSelection = new HashSet<MapEntity>();// FindSelectedEntities(selectionPos, selectionSize);
if (Math.Abs(selectionSize.X) > Submarine.GridSize.X || Math.Abs(selectionSize.Y) > Submarine.GridSize.Y)
{
newSelection = FindSelectedEntities(selectionPos, selectionSize);
@@ -376,9 +359,13 @@ namespace Barotrauma
{
if (highLightedEntity != null)
{
if (SelectionGroups.TryGetValue(highLightedEntity, out List<MapEntity> group))
if (SelectionGroups.TryGetValue(highLightedEntity, out HashSet<MapEntity> group))
{
newSelection.AddRange(group);
foreach (MapEntity entity in group.Where(e => !newSelection.Contains(e)))
{
newSelection.Add(entity);
}
foreach (MapEntity entity in group)
{
entity.IsIncludedInSelection = true;
@@ -398,7 +385,7 @@ namespace Barotrauma
{
foreach (MapEntity e in newSelection)
{
if (selectedList.Contains(e))
if (SelectedList.Contains(e))
{
RemoveSelection(e);
}
@@ -410,7 +397,7 @@ namespace Barotrauma
}
else
{
selectedList = new List<MapEntity>(newSelection);
SelectedList = new HashSet<MapEntity>(newSelection);
//selectedList.Clear();
//newSelection.ForEach(e => AddSelection(e));
foreach (var entity in newSelection)
@@ -419,23 +406,23 @@ namespace Barotrauma
onGapFound: (door, gap) =>
{
door.RefreshLinkedGap();
if (!selectedList.Contains(gap))
if (!SelectedList.Contains(gap))
{
selectedList.Add(gap);
SelectedList.Add(gap);
}
},
onDoorFound: (door, gap) =>
{
if (!selectedList.Contains(door.Item))
if (!SelectedList.Contains(door.Item))
{
selectedList.Add(door.Item);
SelectedList.Add(door.Item);
}
});
}
}
//select wire if both items it's connected to are selected
var selectedItems = selectedList.Where(e => e is Item).Cast<Item>().ToList();
var selectedItems = SelectedList.Where(e => e is Item).Cast<Item>().ToList();
foreach (Item item in selectedItems)
{
if (item.Connections == null) continue;
@@ -443,11 +430,11 @@ namespace Barotrauma
{
foreach (Wire w in c.Wires)
{
if (w == null || selectedList.Contains(w.Item)) continue;
if (w == null || SelectedList.Contains(w.Item)) continue;
if (w.OtherConnection(c) != null && selectedList.Contains(w.OtherConnection(c).Item))
if (w.OtherConnection(c) != null && SelectedList.Contains(w.OtherConnection(c).Item))
{
selectedList.Add(w.Item);
SelectedList.Add(w.Item);
}
}
}
@@ -471,7 +458,7 @@ namespace Barotrauma
(highlightedListBox == null || (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn))))
{
//if clicking a selected entity, start moving it
foreach (MapEntity e in selectedList)
foreach (MapEntity e in SelectedList)
{
if (e.IsMouseOn(position)) startMovingPos = position;
}
@@ -519,7 +506,7 @@ namespace Barotrauma
return ReplacedBy?.GetReplacementOrThis() ?? this;
}
public static Item GetPotentialContainer(Vector2 position, List<MapEntity> entities = null)
public static Item GetPotentialContainer(Vector2 position, HashSet<MapEntity> entities = null)
{
Item targetContainer = null;
bool isShiftDown = PlayerInput.IsShiftDown();
@@ -654,7 +641,7 @@ namespace Barotrauma
if (PlayerInput.IsCtrlDown() && !wiringMode)
{
if (selectedList.Contains(entity))
if (SelectedList.Contains(entity))
{
RemoveSelection(entity);
}
@@ -673,56 +660,60 @@ namespace Barotrauma
public static void AddSelection(MapEntity entity)
{
if (selectedList.Contains(entity)) { return; }
selectedList.Add(entity);
if (SelectedList.Contains(entity)) { return; }
SelectedList.Add(entity);
HandleDoorGapLinks(entity,
onGapFound: (door, gap) =>
{
door.RefreshLinkedGap();
if (!selectedList.Contains(gap))
if (!SelectedList.Contains(gap))
{
selectedList.Add(gap);
SelectedList.Add(gap);
}
},
onDoorFound: (door, gap) =>
{
if (!selectedList.Contains(door.Item))
if (!SelectedList.Contains(door.Item))
{
selectedList.Add(door.Item);
SelectedList.Add(door.Item);
}
});
}
private static void HandleDoorGapLinks(MapEntity entity, Action<Door, Gap> onGapFound, Action<Door, Gap> onDoorFound)
{
if (entity is Item i)
switch (entity)
{
var door = i.GetComponent<Door>();
if (door != null)
case Item i:
{
var gap = door.LinkedGap;
var door = i.GetComponent<Door>();
var gap = door?.LinkedGap;
if (gap != null)
{
onGapFound(door, gap);
}
break;
}
}
else if (entity is Gap gap)
{
var door = gap.ConnectedDoor;
if (door != null)
case Gap gap:
{
onDoorFound(door, gap);
var door = gap.ConnectedDoor;
if (door != null)
{
onDoorFound(door, gap);
}
break;
}
}
}
public static void RemoveSelection(MapEntity entity)
{
selectedList.Remove(entity);
SelectedList.Remove(entity);
HandleDoorGapLinks(entity,
onGapFound: (door, gap) => selectedList.Remove(gap),
onDoorFound: (door, gap) => selectedList.Remove(door.Item));
onGapFound: (door, gap) => SelectedList.Remove(gap),
onDoorFound: (door, gap) => SelectedList.Remove(door.Item));
}
static partial void UpdateAllProjSpecific(float deltaTime)
@@ -767,7 +758,7 @@ namespace Barotrauma
//started moving the selected entities
if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y || isShiftDown)
{
foreach (MapEntity e in selectedList)
foreach (MapEntity e in SelectedList)
{
SpriteEffects spriteEffects = SpriteEffects.None;
switch (e)
@@ -865,8 +856,8 @@ namespace Barotrauma
}
}
FilteredSelectedList.Clear();
if (selectedList.Count == 0) return;
foreach (var e in selectedList)
if (SelectedList.Count == 0) return;
foreach (var e in SelectedList)
{
if (e is Gap gap && gap.ConnectedDoor != null) { continue; }
FilteredSelectedList.Add(e);
@@ -885,15 +876,19 @@ namespace Barotrauma
{
if (PlayerInput.KeyHit(Keys.N))
{
float minX = selectedList[0].WorldRect.X, maxX = selectedList[0].WorldRect.Right;
for (int i = 0; i < selectedList.Count; i++)
MapEntity firstSelected = SelectedList.First();
float minX = firstSelected.WorldRect.X,
maxX = firstSelected.WorldRect.Right;
foreach (MapEntity entity in SelectedList)
{
minX = Math.Min(minX, selectedList[i].WorldRect.X);
maxX = Math.Max(maxX, selectedList[i].WorldRect.Right);
minX = Math.Min(minX, entity.WorldRect.X);
maxX = Math.Max(maxX, entity.WorldRect.Right);
}
float centerX = (minX + maxX) / 2.0f;
foreach (MapEntity me in selectedList)
foreach (MapEntity me in SelectedList)
{
me.FlipX(false);
me.Move(new Vector2((centerX - me.WorldPosition.X) * 2.0f, 0.0f));
@@ -901,15 +896,20 @@ namespace Barotrauma
}
else if (PlayerInput.KeyHit(Keys.M))
{
float minY = selectedList[0].WorldRect.Y - selectedList[0].WorldRect.Height, maxY = selectedList[0].WorldRect.Y;
for (int i = 0; i < selectedList.Count; i++)
MapEntity firstSelected = SelectedList.First();
float minY = firstSelected.WorldRect.Y - firstSelected.WorldRect.Height,
maxY = firstSelected.WorldRect.Y;
foreach (MapEntity entity in SelectedList)
{
minY = Math.Min(minY, selectedList[i].WorldRect.Y - selectedList[i].WorldRect.Height);
maxY = Math.Max(maxY, selectedList[i].WorldRect.Y);
minY = Math.Min(minY, entity.WorldRect.Y - entity.WorldRect.Height);
maxY = Math.Max(maxY, entity.WorldRect.Y);
}
float centerY = (minY + maxY) / 2.0f;
foreach (MapEntity me in selectedList)
foreach (MapEntity me in SelectedList)
{
me.FlipY(false);
me.Move(new Vector2(0.0f, (centerY - me.WorldPosition.Y) * 2.0f));
@@ -920,19 +920,20 @@ namespace Barotrauma
public static void DrawEditor(SpriteBatch spriteBatch, Camera cam)
{
if (selectedList.Count == 1)
if (SelectedList.Count == 1)
{
selectedList[0].DrawEditing(spriteBatch, cam);
if (selectedList[0].ResizeHorizontal || selectedList[0].ResizeVertical)
MapEntity firstSelected = SelectedList.First();
firstSelected.DrawEditing(spriteBatch, cam);
if (firstSelected.ResizeHorizontal || firstSelected.ResizeVertical)
{
selectedList[0].DrawResizing(spriteBatch, cam);
firstSelected.DrawResizing(spriteBatch, cam);
}
}
}
public static void DeselectAll()
{
selectedList.Clear();
SelectedList.Clear();
}
public static void SelectEntity(MapEntity entity)
@@ -967,10 +968,10 @@ namespace Barotrauma
public static void Paste(Vector2 position)
{
if (copiedList.Count == 0) { return; }
if (CopiedList.Count == 0) { return; }
List<MapEntity> prevEntities = new List<MapEntity>(mapEntityList);
Clone(copiedList);
Clone(CopiedList);
var clones = mapEntityList.Except(prevEntities).ToList();
var nonWireClones = clones.Where(c => !(c is Item item) || item.GetComponent<Wire>() == null);
@@ -982,8 +983,8 @@ namespace Barotrauma
Vector2 moveAmount = Submarine.VectorToWorldGrid(position - center);
selectedList = new List<MapEntity>(clones);
foreach (MapEntity clone in selectedList)
SelectedList = new HashSet<MapEntity>(clones);
foreach (MapEntity clone in SelectedList)
{
clone.Move(moveAmount);
clone.Submarine = Submarine.MainSub;
@@ -999,7 +1000,7 @@ namespace Barotrauma
{
List<MapEntity> prevEntities = new List<MapEntity>(mapEntityList);
copiedList = Clone(entities);
CopiedList = Clone(entities);
//find all new entities created during cloning
var newEntities = mapEntityList.Except(prevEntities).ToList();
@@ -1172,9 +1173,9 @@ namespace Barotrauma
/// <summary>
/// Find entities whose rect intersects with the "selection rect"
/// </summary>
public static List<MapEntity> FindSelectedEntities(Vector2 pos, Vector2 size)
public static HashSet<MapEntity> FindSelectedEntities(Vector2 pos, Vector2 size)
{
List<MapEntity> foundEntities = new List<MapEntity>();
HashSet<MapEntity> foundEntities = new HashSet<MapEntity>();
Rectangle selectionRect = Submarine.AbsRect(pos, size);
@@ -26,8 +26,6 @@ namespace Barotrauma.Particles
private float angularVelocity;
private Vector2 dragVec = Vector2.Zero;
private float dragWait = 0;
private float collisionIgnoreTimer = 0;
private Vector2 size;
@@ -35,6 +33,7 @@ namespace Barotrauma.Particles
private Color color;
private bool changeColor;
private bool UseMiddleColor;
private int spriteIndex;
@@ -112,9 +111,7 @@ namespace Barotrauma.Particles
animState = 0;
animFrame = 0;
dragWait = 0;
dragVec = Vector2.Zero;
currentHull = Hull.FindHull(position, hullGuess);
size = prefab.StartSizeMin + (prefab.StartSizeMax - prefab.StartSizeMin) * Rand.Range(0.0f, 1.0f);
@@ -144,10 +141,21 @@ namespace Barotrauma.Particles
angularVelocity = Rand.Range(prefab.AngularVelocityMinRad, prefab.AngularVelocityMaxRad);
totalLifeTime = prefab.LifeTime;
lifeTime = prefab.LifeTime;
if (prefab.LifeTimeMin <= 0.0f)
{
totalLifeTime = prefab.LifeTime;
lifeTime = prefab.LifeTime;
}
else
{
totalLifeTime = Rand.Range(prefab.LifeTimeMin, prefab.LifeTime);
lifeTime = totalLifeTime;
}
startDelay = Rand.Range(prefab.StartDelayMin, prefab.StartDelayMax);
UseMiddleColor = prefab.UseMiddleColor;
color = prefab.StartColor;
changeColor = prefab.StartColor != prefab.EndColor;
ColorMultiplier = Vector4.One;
@@ -243,13 +251,27 @@ namespace Barotrauma.Particles
}
size.X += sizeChange.X * deltaTime;
size.Y += sizeChange.Y * deltaTime;
size.Y += sizeChange.Y * deltaTime;
if (changeColor)
if (UseMiddleColor)
{
color = Color.Lerp(prefab.EndColor, prefab.StartColor, lifeTime / prefab.LifeTime);
if (lifeTime > totalLifeTime * 0.5f)
{
color = Color.Lerp(prefab.MiddleColor, prefab.StartColor, (lifeTime / totalLifeTime - 0.5f) * 2.0f);
}
else
{
color = Color.Lerp(prefab.EndColor, prefab.MiddleColor, lifeTime / totalLifeTime * 2.0f);
}
}
else
{
if (changeColor)
{
color = Color.Lerp(prefab.EndColor, prefab.StartColor, lifeTime / totalLifeTime);
}
}
if (prefab.Sprites[spriteIndex] is SpriteSheet)
{
animState += deltaTime;
@@ -399,29 +421,24 @@ namespace Barotrauma.Particles
private void ApplyDrag(float dragCoefficient, float deltaTime)
{
if (velocity.LengthSquared() < dragVec.LengthSquared())
float speed = velocity.Length();
velocity /= speed;
float drag = speed * speed * dragCoefficient * 0.01f * deltaTime;
if (drag > speed)
{
velocity = Vector2.Zero;
return;
}
if (Math.Abs(velocity.X) < 0.0001f && Math.Abs(velocity.Y) < 0.0001f) return;
//TODO: some better way to handle particle drag
//this doesn't work that well because the drag vector is only updated every 0.5 seconds, allowing the particle to accelerate way more than it should
//(e.g. a falling particle can freely accelerate for 0.5 seconds before the drag takes effect)
dragWait-=deltaTime;
if (dragWait <= 0f)
else
{
dragWait = 0.5f;
float speed = velocity.Length();
dragVec = (velocity / speed) * Math.Min(speed * speed * dragCoefficient * deltaTime, 1.0f);
speed -= drag;
velocity *= speed;
}
velocity -= dragVec;
}
private void OnWallCollisionInside(Hull prevHull, Vector2 collisionNormal)
{
if (prevHull == null) { return; }
@@ -51,25 +51,31 @@ namespace Barotrauma.Particles
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
public float VelocityMax { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(1f, true)]
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 100.0f, MinValueFloat = 0.0f), Serialize(1f, true)]
public float ScaleMin { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(1f, true)]
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 100.0f, MinValueFloat = 0.0f), Serialize(1f, true)]
public float ScaleMax { get; set; }
[Editable(), Serialize("1,1", true)]
public Vector2 ScaleMultiplier { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = MinValue), Serialize(0f, true)]
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 100.0f, MinValueFloat = 0.0f), Serialize(0f, true)]
public float EmitInterval { get; set; }
[Editable, Serialize(0, true)]
[Editable(ValueStep = 1, MinValueInt = 0, MaxValueInt = 1000), Serialize(0, true, description: "The number of particles to spawn per frame, or every x seconds if EmitInterval is set.")]
public int ParticleAmount { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = MaxValue, MinValueFloat = 0), Serialize(0f, true)]
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 1000.0f, MinValueFloat = 0.0f), Serialize(0f, true)]
public float ParticlesPerSecond { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 10.0f, MinValueFloat = 0.0f), Serialize(0f, true, description: "If larger than 0, a particle is spawned every x pixels across the ray cast by a hitscan weapon.")]
public float EmitAcrossRayInterval { get; set; }
[Editable(ValueStep = 1, DecimalCount = 2, MaxValueFloat = 100.0f, MinValueFloat = 0.0f), Serialize(0f, true, description: "Delay before the emitter becomes active after being created.")]
public float InitialDelay { get; set; }
[Editable, Serialize(false, true)]
public bool HighQualityCollisionDetection { get; set; }
@@ -115,6 +121,7 @@ namespace Barotrauma.Particles
{
private float emitTimer;
private float burstEmitTimer;
private float initialDelay;
public readonly ParticleEmitterPrefab Prefab;
@@ -131,9 +138,30 @@ namespace Barotrauma.Particles
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, Tuple<Vector2, Vector2> tracerPoints = null)
{
if (initialDelay < Prefab.Properties.InitialDelay)
{
initialDelay += deltaTime;
return;
}
emitTimer += deltaTime * amountMultiplier;
burstEmitTimer -= deltaTime;
if (Prefab.Properties.EmitAcrossRayInterval > 0.0f && tracerPoints != null)
{
Vector2 dir = tracerPoints.Item2 - tracerPoints.Item1;
if (dir.LengthSquared() > 0.001f)
{
float dist = dir.Length();
dir /= dist;
for (float z = 0.0f; z < dist; z += Prefab.Properties.EmitAcrossRayInterval)
{
Vector2 pos = tracerPoints.Item1 + dir * z;
Emit(pos, hullGuess, angle, particleRotation, velocityMultiplier, sizeMultiplier, colorMultiplier, overrideParticle, tracerPoints: null);
}
}
}
if (Prefab.Properties.ParticlesPerSecond > 0)
{
float emitInterval = 1.0f / Prefab.Properties.ParticlesPerSecond;
@@ -53,6 +53,10 @@ namespace Barotrauma.Particles
[Editable(0.0f, float.MaxValue), Serialize(5.0f, false, description: "How many seconds the particle remains alive.")]
public float LifeTime { get; private set; }
[Editable(0.0f, float.MaxValue), Serialize(0.0f, false, description: "Will randomize lifetime value between lifetime and lifetimeMin. If left to 0 will use only lifetime value.")]
public float LifeTimeMin { get; private set; }
[Editable, Serialize(0.0f, false, description: "How long it takes for the particle to appear after spawning it.")]
public float StartDelayMin { get; private set; }
[Editable, Serialize(0.0f, false, description: "How long it takes for the particle to appear after spawning it.")]
@@ -118,10 +122,10 @@ namespace Barotrauma.Particles
[Editable, Serialize(false, false, description: "Should the particle face the direction it's moving towards.")]
public bool RotateToDirection { get; private set; }
[Editable, Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through air.")]
[Editable(0.0f, float.MaxValue, DecimalCount = 3), Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through air.")]
public float Drag { get; private set; }
[Editable, Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through water.")]
[Editable(0.0f, float.MaxValue, DecimalCount = 3), Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through water.")]
public float WaterDrag { get; private set; }
private Vector2 velocityChange;
@@ -193,8 +197,14 @@ namespace Barotrauma.Particles
[Editable, Serialize("1.0,1.0,1.0,1.0", false, description: "The initial color of the particle.")]
public Color StartColor { get; private set; }
[Editable, Serialize("1.0,1.0,1.0,1.0", false, description: "The initial color of the particle.")]
public Color MiddleColor { get; private set; }
[Editable, Serialize("1.0,1.0,1.0,1.0", false, description: "The color of the particle at the end of its lifetime.")]
public Color EndColor { get; private set; }
[Editable, Serialize(false, false, description: "If true the color will go from StartColor to EndcColor and back to StartColor.")]
public bool UseMiddleColor { get; private set; }
[Editable, Serialize(DrawTargetType.Air, false, description: "Should the particle be rendered in air, water or both.")]
public DrawTargetType DrawTarget { get; private set; }
@@ -289,7 +299,7 @@ namespace Barotrauma.Particles
StartRotationMin = element.GetAttributeFloat("startrotation", 0.0f);
StartRotationMax = StartRotationMin;
}
if (CollisionRadius <= 0.0f) CollisionRadius = Sprites.Count > 0 ? 1 : Sprites[0].SourceRect.Width / 2.0f;
}
@@ -21,6 +21,7 @@ namespace Barotrauma
private GUIComponent locationInfoPanel;
private GUIListBox missionList;
private readonly List<GUITickBox> missionTickBoxes = new List<GUITickBox>();
private GUIButton repairHullsButton, replaceShuttlesButton, repairItemsButton;
@@ -320,6 +321,10 @@ namespace Barotrauma
map.SelectLocation(-1);
}
map.Update(deltaTime, mapContainer);
foreach (GUITickBox tickBox in missionTickBoxes)
{
tickBox.Enabled = Campaign.AllowedToManageCampaign();
}
}
public void Update(float deltaTime)
@@ -350,6 +355,7 @@ namespace Barotrauma
public void SelectLocation(Location location, LocationConnection connection)
{
missionTickBoxes.Clear();
locationInfoPanel.ClearChildren();
//don't select the map panel if we're looking at some other tab
if (selectedTab == CampaignMode.InteractionType.Map)
@@ -451,7 +457,10 @@ namespace Barotrauma
if (GUI.MouseOn == tickBox) { return false; }
if (tickBox != null)
{
tickBox.Selected = !tickBox.Selected;
if (Campaign.AllowedToManageCampaign() && tickBox.Enabled)
{
tickBox.Selected = !tickBox.Selected;
}
}
return true;
};
@@ -489,26 +498,28 @@ namespace Barotrauma
};
tickBox.RectTransform.MinSize = new Point(tickBox.Rect.Height, 0);
tickBox.RectTransform.IsFixedSize = true;
if (Campaign.AllowedToManageCampaign())
tickBox.Box.DisabledColor = tickBox.Box.Color * 0.8f;
tickBox.Enabled = Campaign.AllowedToManageCampaign();
tickBox.OnSelected += (GUITickBox tb) =>
{
tickBox.OnSelected += (GUITickBox tb) =>
if (!Campaign.AllowedToManageCampaign()) { return false; }
if (tb.Selected)
{
if (tb.Selected)
{
Campaign.Map.CurrentLocation.SelectMission(mission);
}
else
{
Campaign.Map.CurrentLocation.DeselectMission(mission);
}
if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
Campaign.AllowedToManageCampaign())
{
GameMain.Client?.SendCampaignState();
}
return true;
};
}
Campaign.Map.CurrentLocation.SelectMission(mission);
}
else
{
Campaign.Map.CurrentLocation.DeselectMission(mission);
}
if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
Campaign.AllowedToManageCampaign())
{
GameMain.Client?.SendCampaignState();
}
return true;
};
missionTickBoxes.Add(tickBox);
GUILayoutGroup difficultyIndicatorGroup = null;
if (mission.Difficulty.HasValue)
@@ -578,6 +589,8 @@ namespace Barotrauma
if (prevSelectedLocation == selectedLocation)
{
missionList.BarScroll = prevMissionListScroll;
missionList.UpdateDimensions();
missionList.UpdateScrollBarSize();
}
}
@@ -615,6 +628,7 @@ namespace Barotrauma
StartButton.Visible = false;
missionList.Enabled = false;
}
//locationInfoPanel?.UpdateAuto(1.0f);
}
public void SelectTab(CampaignMode.InteractionType tab)
@@ -867,9 +867,7 @@ namespace Barotrauma
{
int.TryParse(maxPlayersBox.Text, out int currMaxPlayers);
currMaxPlayers = (int)MathHelper.Clamp(currMaxPlayers + (int)button.UserData, 1, NetConfig.MaxPlayers);
maxPlayersBox.Text = currMaxPlayers.ToString();
return true;
}
@@ -1322,8 +1320,18 @@ namespace Barotrauma
};
maxPlayersBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), textAlignment: Alignment.Center)
{
Text = maxPlayers.ToString(),
CanBeFocused = false
Text = maxPlayers.ToString()
};
maxPlayersBox.OnEnterPressed += (GUITextBox sender, string text) =>
{
maxPlayersBox.Deselect();
return true;
};
maxPlayersBox.OnDeselected += (GUITextBox sender, Microsoft.Xna.Framework.Input.Keys key) =>
{
int.TryParse(maxPlayersBox.Text, out int currMaxPlayers);
currMaxPlayers = (int)MathHelper.Clamp(currMaxPlayers, 1, NetConfig.MaxPlayers);
maxPlayersBox.Text = currMaxPlayers.ToString();
};
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
{
@@ -235,7 +235,7 @@ namespace Barotrauma
element.Add(new XAttribute("particle", prefab.Identifier));
}
SerializableProperty.SerializeProperties(emitterProperties, element, saveIfDefault: false);
SerializableProperty.SerializeProperties(emitterProperties, element, saveIfDefault: false, ignoreEditable: true);
StringBuilder sb = new StringBuilder();
@@ -2373,10 +2373,10 @@ namespace Barotrauma
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, saveFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.25f, 0.3f), saveFrame.RectTransform, Anchor.Center) { MinSize = new Point(400, 300) });
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.25f, 0.35f), saveFrame.RectTransform, Anchor.Center) { MinSize = new Point(400, 350) });
GUILayoutGroup paddedSaveFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), innerFrame.RectTransform, Anchor.Center))
{
AbsoluteSpacing = 5,
AbsoluteSpacing = GUI.IntScale(5),
Stretch = true
};
@@ -2393,15 +2393,22 @@ namespace Barotrauma
};
#endif
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedSaveFrame.RectTransform),
TextManager.Get("SaveItemAssemblyDialogDescription"));
descriptionBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.3f), paddedSaveFrame.RectTransform))
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), paddedSaveFrame.RectTransform));
descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform, Anchor.TopLeft),
font: GUI.SmallFont, style: "GUITextBoxNoBorder", wrap: true, textAlignment: Alignment.TopLeft)
{
UserData = "description",
Wrap = true,
Text = ""
Padding = new Vector4(10 * GUI.Scale)
};
descriptionBox.OnTextChanged += (textBox, text) =>
{
Vector2 textSize = textBox.Font.MeasureString(descriptionBox.WrappedText);
textBox.RectTransform.NonScaledSize = new Point(textBox.RectTransform.NonScaledSize.X, Math.Max(descriptionContainer.Content.Rect.Height, (int)textSize.Y + 10));
descriptionContainer.UpdateScrollBarSize();
descriptionContainer.BarScroll = 1.0f;
return true;
};
var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), paddedSaveFrame.RectTransform), style: null);
new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft),
TextManager.Get("Cancel"))
@@ -2417,6 +2424,7 @@ namespace Barotrauma
{
OnClicked = SaveAssembly
};
buttonArea.RectTransform.MinSize = new Point(0, buttonArea.Children.First().RectTransform.MinSize.Y);
}
/// <summary>
@@ -2460,7 +2468,7 @@ namespace Barotrauma
}
}
bool hideInMenus = !(nameBox.Parent.GetChildByUserData("hideinmenus") is GUITickBox hideInMenusTickBox) ? false : hideInMenusTickBox.Selected;
bool hideInMenus = nameBox.Parent.GetChildByUserData("hideinmenus") is GUITickBox hideInMenusTickBox && hideInMenusTickBox.Selected;
#if DEBUG
string saveFolder = ItemAssemblyPrefab.VanillaSaveFolder;
#else
@@ -2479,7 +2487,6 @@ namespace Barotrauma
}
#endif
string filePath = Path.Combine(saveFolder, nameBox.Text + ".xml");
if (File.Exists(filePath))
{
var msgBox = new GUIMessageBox(TextManager.Get("Warning"), TextManager.Get("ItemAssemblyFileExistsWarning"), new[] { TextManager.Get("Yes"), TextManager.Get("No") });
@@ -2494,18 +2501,27 @@ namespace Barotrauma
}
else
{
Save();
var identifier = nameBox.Text.ToLowerInvariant().Replace(" ", "");
var existingPrefab = MapEntityPrefab.Find(null, identifier, showErrorMessages: false);
if (existingPrefab != null && System.IO.Path.GetDirectoryName(existingPrefab.FilePath) == ItemAssemblyPrefab.VanillaSaveFolder)
{
var msgBox = new GUIMessageBox(TextManager.Get("Warning"), TextManager.Get("ItemAssemblyVanillaFileExistsWarning"));
}
else
{
Save();
}
}
void Save()
{
XDocument doc = new XDocument(ItemAssemblyPrefab.Save(MapEntity.SelectedList, nameBox.Text, descriptionBox.Text, hideInMenus));
XDocument doc = new XDocument(ItemAssemblyPrefab.Save(MapEntity.SelectedList.ToList(), nameBox.Text, descriptionBox.Text, hideInMenus));
#if DEBUG
doc.Save(filePath);
#else
doc.SaveSafe(filePath);
#endif
new ItemAssemblyPrefab(filePath);
new ItemAssemblyPrefab(filePath, allowOverwrite: true);
UpdateEntityList();
}
@@ -3002,8 +3018,11 @@ namespace Barotrauma
new ContextMenuOption("SubEditor.PasteAssembly", isEnabled: true, () => PasteAssembly()),
new ContextMenuOption("Editor.SelectSame", isEnabled: targets.Count > 0, onSelected: delegate
{
IEnumerable<MapEntity> matching = MapEntity.mapEntityList.Where(e => e.prefab != null && targets.Any(t => t.prefab?.Identifier == e.prefab.Identifier) && !MapEntity.SelectedList.Contains(e));
MapEntity.SelectedList.AddRange(matching);
foreach (MapEntity match in MapEntity.mapEntityList.Where(e => e.prefab != null && targets.Any(t => t.prefab?.Identifier == e.prefab.Identifier) && !MapEntity.SelectedList.Contains(e)))
{
if (MapEntity.SelectedList.Contains(match)) { continue; }
MapEntity.SelectedList.Add(match);
}
}),
new ContextMenuOption("SubEditor.AddImage", isEnabled: true, onSelected: ImageManager.CreateImageWizard),
new ContextMenuOption("SubEditor.ToggleImageEditing", isEnabled: true, onSelected: delegate
@@ -4716,9 +4735,9 @@ namespace Barotrauma
CloseItem();
}
}
else if (MapEntity.SelectedList.Count == 1 && WiringMode)
else if (MapEntity.SelectedList.Count == 1 && WiringMode && MapEntity.SelectedList.FirstOrDefault() is Item item)
{
(MapEntity.SelectedList[0] as Item)?.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
item.UpdateHUD(cam, dummyCharacter, (float)deltaTime);
}
CharacterHUD.Update((float)deltaTime, dummyCharacter, cam);