v0.12.0.2

This commit is contained in:
Joonas Rikkonen
2021-02-10 17:08:21 +02:00
parent 5c80a59bdd
commit 694cdfee7b
353 changed files with 12897 additions and 5028 deletions
@@ -94,8 +94,8 @@ namespace Barotrauma
get { return personalSlotArea; }
}
private GUIImage[] indicators = new GUIImage[5];
private int[] indicatorIndexes = new int[5];
private readonly GUIImage[] indicators = new GUIImage[5];
private readonly int[] indicatorIndices = new int[5];
private Vector2 indicatorSpriteSize;
private GUILayoutGroup indicatorGroup;
@@ -117,11 +117,11 @@ namespace Barotrauma
indicators[3] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorHeadwear");
indicators[4] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorHeadphones");
indicatorIndexes[0] = FindLimbSlot(InvSlotType.OuterClothes);
indicatorIndexes[1] = FindLimbSlot(InvSlotType.Card);
indicatorIndexes[2] = FindLimbSlot(InvSlotType.InnerClothes);
indicatorIndexes[3] = FindLimbSlot(InvSlotType.Head);
indicatorIndexes[4] = FindLimbSlot(InvSlotType.Headset);
indicatorIndices[0] = FindLimbSlot(InvSlotType.OuterClothes);
indicatorIndices[1] = FindLimbSlot(InvSlotType.Card);
indicatorIndices[2] = FindLimbSlot(InvSlotType.InnerClothes);
indicatorIndices[3] = FindLimbSlot(InvSlotType.Head);
indicatorIndices[4] = FindLimbSlot(InvSlotType.Headset);
for (int i = 0; i < indicators.Length; i++)
{
@@ -143,7 +143,7 @@ namespace Barotrauma
protected override ItemInventory GetActiveEquippedSubInventory(int slotIndex)
{
var item = Items[slotIndex];
Item item = slots[slotIndex].FirstOrDefault();
if (item == null) { return null; }
var container = item.GetComponent<ItemContainer>();
@@ -162,38 +162,35 @@ namespace Barotrauma
public override void RemoveItem(Item item)
{
if (!Items.Contains(item)) { return; }
if (!Contains(item)) { return; }
base.RemoveItem(item);
CreateSlots();
}
public override void CreateSlots()
{
if (slots == null) { slots = new InventorySlot[capacity]; }
if (visualSlots == null) { visualSlots = new VisualSlot[capacity]; }
float multiplier = !GUI.IsFourByThree() ? UIScale : UIScale * 0.925f;
for (int i = 0; i < capacity; i++)
{
InventorySlot prevSlot = slots[i];
VisualSlot prevSlot = visualSlots[i];
Sprite slotSprite = SlotSpriteSmall;
Rectangle slotRect = new Rectangle(
(int)(SlotPositions[i].X),
(int)(SlotPositions[i].Y),
(int)SlotPositions[i].X,
(int)SlotPositions[i].Y,
(int)(slotSprite.size.X * multiplier), (int)(slotSprite.size.Y * multiplier));
if (Items[i] != null)
ItemContainer itemContainer = slots[i].FirstOrDefault()?.GetComponent<ItemContainer>();
if (itemContainer != null)
{
ItemContainer itemContainer = Items[i].GetComponent<ItemContainer>();
if (itemContainer != null)
{
if (itemContainer.InventoryTopSprite != null) slotRect.Width = Math.Max(slotRect.Width, (int)(itemContainer.InventoryTopSprite.size.X * UIScale));
if (itemContainer.InventoryBottomSprite != null) slotRect.Width = Math.Max(slotRect.Width, (int)(itemContainer.InventoryBottomSprite.size.X * UIScale));
}
}
if (itemContainer.InventoryTopSprite != null) slotRect.Width = Math.Max(slotRect.Width, (int)(itemContainer.InventoryTopSprite.size.X * UIScale));
if (itemContainer.InventoryBottomSprite != null) slotRect.Width = Math.Max(slotRect.Width, (int)(itemContainer.InventoryBottomSprite.size.X * UIScale));
}
slots[i] = new InventorySlot(slotRect)
visualSlots[i] = new VisualSlot(slotRect)
{
SubInventoryDir = Math.Sign(GameMain.GraphicsHeight / 2 - slotRect.Center.Y),
Disabled = false,
@@ -202,13 +199,13 @@ namespace Barotrauma
};
if (prevSlot != null)
{
slots[i].DrawOffset = prevSlot.DrawOffset;
slots[i].Color = prevSlot.Color;
visualSlots[i].DrawOffset = prevSlot.DrawOffset;
visualSlots[i].Color = prevSlot.Color;
prevSlot.MoveBorderHighlight(visualSlots[i]);
}
if (selectedSlot?.ParentInventory == this && selectedSlot.SlotIndex == i)
{
selectedSlot = new SlotReference(this, slots[i], i, selectedSlot.IsSubSlot, selectedSlot.Inventory);
selectedSlot = new SlotReference(this, visualSlots[i], i, selectedSlot.IsSubSlot, selectedSlot.Inventory);
}
}
@@ -217,9 +214,9 @@ namespace Barotrauma
highlightedSubInventorySlots.RemoveWhere(s => s.Inventory.OpenState <= 0.0f);
foreach (var subSlot in highlightedSubInventorySlots)
{
if (subSlot.ParentInventory == this && subSlot.SlotIndex > 0 && subSlot.SlotIndex < slots.Length)
if (subSlot.ParentInventory == this && subSlot.SlotIndex > 0 && subSlot.SlotIndex < visualSlots.Length)
{
subSlot.Slot = slots[subSlot.SlotIndex];
subSlot.Slot = visualSlots[subSlot.SlotIndex];
}
}
@@ -235,10 +232,10 @@ namespace Barotrauma
if (HideSlot(i)) continue;
if (frame == Rectangle.Empty)
{
frame = slots[i].Rect;
frame = visualSlots[i].Rect;
continue;
}
frame = Rectangle.Union(frame, slots[i].Rect);
frame = Rectangle.Union(frame, visualSlots[i].Rect);
}
frame.Inflate(10, 30);
frame.Location -= new Point(0, 25);
@@ -247,26 +244,25 @@ namespace Barotrauma
protected override bool HideSlot(int i)
{
if (slots[i].Disabled || (hideEmptySlot[i] && Items[i] == null)) return true;
if (visualSlots[i].Disabled || (slots[i].HideIfEmpty && slots[i].Empty())) { return true; }
if (layout == Layout.Default)
{
if (PersonalSlots.HasFlag(SlotTypes[i]) && !personalSlotArea.Contains(slots[i].Rect.Center + slots[i].DrawOffset.ToPoint())) return true;
if (PersonalSlots.HasFlag(SlotTypes[i]) && !personalSlotArea.Contains(visualSlots[i].Rect.Center + visualSlots[i].DrawOffset.ToPoint())) { return true; }
}
Item item = slots[i].FirstOrDefault();
//no need to draw the right hand slot if the item is in both hands
if (Items[i] != null && SlotTypes[i] == InvSlotType.RightHand && IsInLimbSlot(Items[i], InvSlotType.LeftHand))
if (item != null && SlotTypes[i] == InvSlotType.RightHand && IsInLimbSlot(item, InvSlotType.LeftHand))
{
return true;
}
//don't show the equip slot if the item is also in the default inventory
if (SlotTypes[i] != InvSlotType.Any && Items[i] != null)
//don't show the limb-specific slot if the item is also in an Any slot
if (item != null && SlotTypes[i] != InvSlotType.Any)
{
for (int j = 0; j < capacity; j++)
{
if (SlotTypes[j] == InvSlotType.Any && Items[j] == Items[i]) return true;
}
if (IsInLimbSlot(item, InvSlotType.Any)) { return true; }
}
return false;
@@ -308,7 +304,8 @@ namespace Barotrauma
SlotSize = !isFourByThree ? (SlotSpriteSmall.size * UIScale).ToPoint() : (SlotSpriteSmall.size * UIScale * .925f).ToPoint();
int bottomOffset = SlotSize.Y + Spacing * 2 + ContainedIndicatorHeight;
if (slots == null) { CreateSlots(); }
if (visualSlots == null) { CreateSlots(); }
if (visualSlots.None()) { return; }
hideButton.Visible = false;
@@ -359,7 +356,7 @@ namespace Barotrauma
{
int x = HUDLayoutSettings.InventoryAreaLower.Right;
int personalSlotX = HUDLayoutSettings.InventoryAreaLower.Right - SlotSize.X - Spacing;
for (int i = 0; i < slots.Length; i++)
for (int i = 0; i < visualSlots.Length; i++)
{
if (HideSlot(i)) continue;
if (PersonalSlots.HasFlag(SlotTypes[i]))
@@ -380,12 +377,12 @@ namespace Barotrauma
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
personalSlotX -= slots[i].Rect.Width + Spacing;
personalSlotX -= visualSlots[i].Rect.Width + Spacing;
}
else
{
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
x += slots[i].Rect.Width + Spacing;
x += visualSlots[i].Rect.Width + Spacing;
}
}
@@ -393,7 +390,7 @@ namespace Barotrauma
for (int i = 0; i < SlotPositions.Length; i++)
{
if (!HideSlot(i)) continue;
x -= slots[i].Rect.Width + Spacing;
x -= visualSlots[i].Rect.Width + Spacing;
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
}
}
@@ -410,19 +407,19 @@ namespace Barotrauma
if (PersonalSlots.HasFlag(SlotTypes[i]))
{
SlotPositions[i] = new Vector2(personalSlotX, personalSlotY);
personalSlotX += slots[i].Rect.Width + Spacing;
personalSlotX += visualSlots[i].Rect.Width + Spacing;
}
else
{
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
x += slots[i].Rect.Width + Spacing;
x += visualSlots[i].Rect.Width + Spacing;
}
}
for (int i = 0; i < SlotPositions.Length; i++)
{
if (!HideSlot(i)) continue;
SlotPositions[i] = new Vector2(x, GameMain.GraphicsHeight - bottomOffset);
x += slots[i].Rect.Width + Spacing;
x += visualSlots[i].Rect.Width + Spacing;
}
}
break;
@@ -438,10 +435,10 @@ namespace Barotrauma
if (SlotTypes[i] == InvSlotType.Card || SlotTypes[i] == InvSlotType.Headset || SlotTypes[i] == InvSlotType.InnerClothes)
{
SlotPositions[i] = new Vector2(x, y);
x += slots[i].Rect.Width + Spacing;
x += visualSlots[i].Rect.Width + Spacing;
}
}
y += slots[0].Rect.Height + Spacing + ContainedIndicatorHeight + slots[0].EquipButtonRect.Height;
y += visualSlots[0].Rect.Height + Spacing + ContainedIndicatorHeight + visualSlots[0].EquipButtonRect.Height;
x = startX;
int n = 0;
for (int i = 0; i < SlotPositions.Length; i++)
@@ -450,12 +447,12 @@ namespace Barotrauma
if (SlotTypes[i] != InvSlotType.Card && SlotTypes[i] != InvSlotType.Headset && SlotTypes[i] != InvSlotType.InnerClothes)
{
SlotPositions[i] = new Vector2(x, y);
x += slots[i].Rect.Width + Spacing;
x += visualSlots[i].Rect.Width + Spacing;
n++;
if (n >= columns)
{
x = startX;
y += slots[i].Rect.Height + Spacing + ContainedIndicatorHeight + slots[i].EquipButtonRect.Height;
y += visualSlots[i].Rect.Height + Spacing + ContainedIndicatorHeight + visualSlots[i].EquipButtonRect.Height;
n = 0;
}
}
@@ -467,7 +464,7 @@ namespace Barotrauma
CreateSlots();
if (layout == Layout.Default)
{
HUDLayoutSettings.InventoryTopY = slots[0].EquipButtonRect.Y - (int)(15 * GUI.Scale);
HUDLayoutSettings.InventoryTopY = visualSlots[0].EquipButtonRect.Y - (int)(15 * GUI.Scale);
}
}
@@ -484,7 +481,8 @@ namespace Barotrauma
public override void Update(float deltaTime, Camera cam, bool isSubInventory = false)
{
if (!AccessibleWhenAlive && !character.IsDead)
// Need to update the infiltrator's inventory because they use id cards to access the sub. TODO: We don't probably need to update everything.
if (!AccessibleWhenAlive && !character.IsDead && (character.Params.AI == null || !character.Params.AI.Infiltrate))
{
syncItemsDelay = Math.Max(syncItemsDelay - deltaTime, 0.0f);
return;
@@ -493,7 +491,7 @@ namespace Barotrauma
base.Update(deltaTime, cam);
bool hoverOnInventory = GUI.MouseOn == null &&
((selectedSlot != null && selectedSlot.IsSubSlot) || (draggingItem != null && (draggingSlot == null || !draggingSlot.MouseOn())));
((selectedSlot != null && selectedSlot.IsSubSlot) || (DraggingItems.Any() && (DraggingSlot == null || !DraggingSlot.MouseOn())));
if (CharacterHealth.OpenHealthWindow != null) hoverOnInventory = true;
if (layout == Layout.Default && (Screen.Selected != GameMain.SubEditorScreen || Screen.Selected is SubEditorScreen editor && editor.WiringMode))
@@ -508,16 +506,16 @@ namespace Barotrauma
Math.Max(hidePersonalSlotsState - deltaTime * 5.0f, 0.0f);
bool personalSlotsMoving = hidePersonalSlotsState > 0 && hidePersonalSlotsState < 1f;
for (int i = 0; i < slots.Length; i++)
for (int i = 0; i < visualSlots.Length; i++)
{
if (!PersonalSlots.HasFlag(SlotTypes[i])) { continue; }
if (HidePersonalSlots)
{
if (selectedSlot?.Slot == slots[i]) { selectedSlot = null; }
highlightedSubInventorySlots.RemoveWhere(s => s.Slot == slots[i]);
if (selectedSlot?.Slot == visualSlots[i]) { selectedSlot = null; }
highlightedSubInventorySlots.RemoveWhere(s => s.Slot == visualSlots[i]);
}
slots[i].IsMoving = personalSlotsMoving;
slots[i].DrawOffset = Vector2.Lerp(Vector2.Zero, new Vector2(personalSlotArea.Width, 0.0f), hidePersonalSlotsState);
visualSlots[i].IsMoving = personalSlotsMoving;
visualSlots[i].DrawOffset = Vector2.Lerp(Vector2.Zero, new Vector2(personalSlotArea.Width, 0.0f), hidePersonalSlotsState);
}
}
}
@@ -530,13 +528,15 @@ namespace Barotrauma
//force personal slots open if an item is running out of battery/fuel/oxygen/etc
if (hidePersonalSlots)
{
for (int i = 0; i < slots.Length; i++)
for (int i = 0; i < visualSlots.Length; i++)
{
if (Items[i]?.OwnInventory != null && Items[i].OwnInventory.Capacity == 1 && PersonalSlots.HasFlag(SlotTypes[i]))
var item = slots[i].FirstOrDefault();
if (item?.OwnInventory != null && item.OwnInventory.Capacity == 1 && PersonalSlots.HasFlag(SlotTypes[i]))
{
if (Items[i].OwnInventory.Items[0] != null &&
Items[i].OwnInventory.Items[0].Condition > 0.0f &&
Items[i].OwnInventory.Items[0].Condition / Items[i].OwnInventory.Items[0].MaxCondition < 0.15f)
var containedItem = item.OwnInventory.AllItems.FirstOrDefault();
if (containedItem != null &&
containedItem.Condition > 0.0f &&
containedItem.Condition / containedItem.MaxCondition < 0.15f)
{
hidePersonalSlots = false;
}
@@ -547,7 +547,7 @@ namespace Barotrauma
List<SlotReference> hideSubInventories = new List<SlotReference>();
highlightedSubInventorySlots.RemoveWhere(s =>
s.ParentInventory == this &&
((s.SlotIndex < 0 || s.SlotIndex >= Items.Length || Items[s.SlotIndex] == null) || (Character.Controlled != null && !Character.Controlled.CanAccessInventory(s.Inventory))));
((s.SlotIndex < 0 || s.SlotIndex >= slots.Length || slots[s.SlotIndex] == null) || (Character.Controlled != null && !Character.Controlled.CanAccessInventory(s.Inventory))));
foreach (var highlightedSubInventorySlot in highlightedSubInventorySlots)
{
if (highlightedSubInventorySlot.ParentInventory == this)
@@ -558,7 +558,7 @@ namespace Barotrauma
if (!highlightedSubInventorySlot.Inventory.IsInventoryHoverAvailable(character, null)) continue;
Rectangle hoverArea = GetSubInventoryHoverArea(highlightedSubInventorySlot);
if (highlightedSubInventorySlot.Inventory?.slots == null || (!hoverArea.Contains(PlayerInput.MousePosition)))
if (highlightedSubInventorySlot.Inventory?.visualSlots == null || (!hoverArea.Contains(PlayerInput.MousePosition)))
{
hideSubInventories.Add(highlightedSubInventorySlot);
}
@@ -585,19 +585,19 @@ namespace Barotrauma
// In sub editor we cannot hover over the slot because they are not rendered so we override it here
if (Screen.Selected is SubEditorScreen subEditor && !subEditor.WiringMode)
{
for (int i = 0; i < slots.Length; i++)
for (int i = 0; i < visualSlots.Length; i++)
{
var subInventory = GetSubInventory(i);
if (subInventory != null)
{
ShowSubInventory(new SlotReference(this, slots[i], i, false, Items[i].GetComponent<ItemContainer>().Inventory), deltaTime, cam, hideSubInventories, true);
ShowSubInventory(new SlotReference(this, visualSlots[i], i, false, subInventory), deltaTime, cam, hideSubInventories, true);
}
}
}
foreach (var subInventorySlot in hideSubInventories)
{
if (subInventorySlot.Inventory == null) continue;
if (subInventorySlot.Inventory == null) { continue; }
subInventorySlot.Inventory.HideTimer -= deltaTime;
if (subInventorySlot.Inventory.HideTimer < 0.25f)
{
@@ -614,10 +614,10 @@ namespace Barotrauma
for (int i = 0; i < capacity; i++)
{
var item = Items[i];
var item = slots[i].FirstOrDefault();
if (item != null)
{
if (HideSlot(i)) continue;
if (HideSlot(i)) { continue; }
if (character.HasEquippedItem(item)) // Keep a subinventory display open permanently when the container is equipped
{
var itemContainer = item.GetComponent<ItemContainer>();
@@ -626,24 +626,32 @@ namespace Barotrauma
character.CanAccessInventory(itemContainer.Inventory) &&
!highlightedSubInventorySlots.Any(s => s.Inventory == itemContainer.Inventory))
{
ShowSubInventory(new SlotReference(this, slots[i], i, false, itemContainer.Inventory), deltaTime, cam, hideSubInventories, true);
ShowSubInventory(new SlotReference(this, visualSlots[i], i, false, itemContainer.Inventory), deltaTime, cam, hideSubInventories, true);
}
}
}
}
}
if (doubleClickedItem != null)
if (doubleClickedItems.Any())
{
QuickUseItem(doubleClickedItem, true, true, true);
var quickUseAction = GetQuickUseAction(doubleClickedItems.First(), true, true, true);
foreach (Item doubleClickedItem in doubleClickedItems)
{
QuickUseItem(doubleClickedItem, true, true, true, quickUseAction, playSound: doubleClickedItem == doubleClickedItems.First());
if (quickUseAction == QuickUseAction.Equip || quickUseAction == QuickUseAction.UseTreatment)
{
break;
}
}
}
for (int i = 0; i < capacity; i++)
{
var item = Items[i];
var item = slots[i].FirstOrDefault();
if (item != null)
{
var slot = slots[i];
var slot = visualSlots[i];
if (item.AllowedSlots.Any(a => a != InvSlotType.Any))
{
HandleButtonEquipStates(item, slot, deltaTime);
@@ -652,10 +660,10 @@ namespace Barotrauma
}
//cancel dragging if too far away from the container of the dragged item
if (draggingItem != null)
if (DraggingItems.Any())
{
var rootContainer = draggingItem.GetRootContainer();
var rootInventory = draggingItem.ParentInventory;
var rootContainer = DraggingItems.First().GetRootContainer();
var rootInventory = DraggingItems.First().ParentInventory;
if (rootContainer != null)
{
@@ -673,27 +681,39 @@ namespace Barotrauma
Character.Controlled.SelectedConstruction != null &&
rootContainer.linkedTo.Contains(Character.Controlled.SelectedConstruction)))
{
draggingItem = null;
DraggingItems.Clear();
}
}
}
doubleClickedItem = null;
doubleClickedItems.Clear();
}
public void UpdateSlotInput()
{
for (int i = 0; i < capacity; i++)
{
if (Items[i] != null && Items[i] != draggingItem && Character.Controlled?.Inventory == this &&
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(slots[i].InventoryKeyIndex))
var firstItem = slots[i].FirstOrDefault();
if (firstItem != null && !DraggingItems.Contains(firstItem) && Character.Controlled?.Inventory == this &&
GUI.KeyboardDispatcher.Subscriber == null && !CrewManager.IsCommandInterfaceOpen && PlayerInput.InventoryKeyHit(visualSlots[i].InventoryKeyIndex))
{
QuickUseItem(Items[i], true, false, true);
#if LINUX
// some window managers on Linux use windows key + number to change workspaces or perform other actions
if (PlayerInput.KeyDown(Keys.RightWindows) || PlayerInput.KeyDown(Keys.LeftWindows)) { continue; }
#endif
var quickUseAction = GetQuickUseAction(firstItem, true, false, true);
foreach (Item itemToUse in slots[i].Items.ToList())
{
QuickUseItem(itemToUse, true, true, true, quickUseAction, playSound: itemToUse == firstItem);
if (quickUseAction == QuickUseAction.Equip || quickUseAction == QuickUseAction.UseTreatment)
{
break;
}
}
}
}
}
private void HandleButtonEquipStates(Item item, InventorySlot slot, float deltaTime)
private void HandleButtonEquipStates(Item item, VisualSlot slot, float deltaTime)
{
slot.EquipButtonState = slot.EquipButtonRect.Contains(PlayerInput.MousePosition) ?
GUIComponent.ComponentState.Hover : GUIComponent.ComponentState.None;
@@ -713,7 +733,7 @@ namespace Barotrauma
if (quickUseAction != QuickUseAction.Drop)
{
slot.QuickUseButtonToolTip = quickUseAction == QuickUseAction.None ?
"" : TextManager.GetWithVariable("QuickUseAction." + quickUseAction.ToString(), "[equippeditem]", character.SelectedItems.FirstOrDefault(i => i != null)?.Name);
"" : TextManager.GetWithVariable("QuickUseAction." + quickUseAction.ToString(), "[equippeditem]", item?.Name);
if (PlayerInput.PrimaryMouseButtonDown()) { slot.EquipButtonState = GUIComponent.ComponentState.Pressed; }
if (PlayerInput.PrimaryMouseButtonClicked())
{
@@ -726,8 +746,8 @@ namespace Barotrauma
{
for (int i = 0; i < indicators.Length; i++)
{
if (indicatorIndexes[i] < 0) { continue; }
Item item = Items[indicatorIndexes[i]];
if (indicatorIndices[i] < 0) { continue; }
Item item = slots[indicatorIndices[i]].FirstOrDefault();
if (item != null)
{
Wearable wearable = item.GetComponent<Wearable>();
@@ -795,12 +815,12 @@ namespace Barotrauma
public void AssignQuickUseNumKeys()
{
int keyBindIndex = 0;
for (int i = 0; i < slots.Length; i++)
for (int i = 0; i < visualSlots.Length; i++)
{
if (HideSlot(i)) continue;
if (SlotTypes[i] == InvSlotType.Any)
{
slots[i].InventoryKeyIndex = keyBindIndex;
visualSlots[i].InventoryKeyIndex = keyBindIndex;
keyBindIndex++;
}
}
@@ -824,7 +844,7 @@ namespace Barotrauma
{
if (item.Container == null || character.Inventory.FindIndex(item.Container) == -1) // Not a subinventory in the character's inventory
{
if (character.SelectedItems.Any(i => i?.OwnInventory != null && i.OwnInventory.CanBePut(item)))
if (character.HeldItems.Any(i => i.OwnInventory != null && i.OwnInventory.CanBePut(item)))
{
return QuickUseAction.PutToEquippedItem;
}
@@ -875,7 +895,7 @@ namespace Barotrauma
{
return QuickUseAction.TakeFromCharacter;
}
else if (character.SelectedItems.Any(i => i?.OwnInventory != null && i.OwnInventory.CanBePut(item)) && allowInventorySwap)
else if (character.HeldItems.Any(i => i.OwnInventory != null && i.OwnInventory.CanBePut(item)) && allowInventorySwap)
{
return QuickUseAction.PutToEquippedItem;
}
@@ -901,23 +921,20 @@ namespace Barotrauma
return QuickUseAction.None;
}
private void QuickUseItem(Item item, bool allowEquip, bool allowInventorySwap, bool allowApplyTreatment)
private void QuickUseItem(Item item, bool allowEquip, bool allowInventorySwap, bool allowApplyTreatment, QuickUseAction? action = null, bool playSound = true)
{
if (Screen.Selected is SubEditorScreen editor && !editor.WiringMode && !Submarine.Unloading)
{
// Find the slot the item was contained in and flash it
if (item.ParentInventory?.slots != null)
if (item.ParentInventory?.visualSlots != null)
{
var invSlots = item.ParentInventory.slots;
var invItems = item.ParentInventory.Items;
var invSlots = item.ParentInventory.visualSlots;
for (int i = 0; i < invSlots.Length; i++)
{
if (i < 0 || invSlots.Length <= i || i < 0 || invItems.Length <= i) { break; }
if (i < 0 || invSlots.Length <= i || i < 0 || item.ParentInventory.Capacity <= i) { break; }
var slot = invSlots[i];
var slotItem = invItems[i];
if (slotItem == item)
if (item.ParentInventory.GetItemAt(i) == item)
{
slot.ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.4f);
SoundPlayer.PlayUISound(GUISoundType.PickItem);
@@ -931,8 +948,8 @@ namespace Barotrauma
item.Remove();
return;
}
var quickUseAction = GetQuickUseAction(item, allowEquip, allowInventorySwap, allowApplyTreatment);
QuickUseAction quickUseAction = action ?? GetQuickUseAction(item, allowEquip, allowInventorySwap, allowApplyTreatment);
bool success = false;
switch (quickUseAction)
{
@@ -963,7 +980,7 @@ namespace Barotrauma
//attempt to put in a free slot first
for (int i = capacity - 1; i >= 0; i--)
{
if (Items[i] != null) { continue; }
if (!slots[i].Empty()) { continue; }
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
success = TryPutItem(item, i, true, false, Character.Controlled, true);
if (success) { break; }
@@ -975,9 +992,10 @@ namespace Barotrauma
{
if (SlotTypes[i] == InvSlotType.Any || !item.AllowedSlots.Any(a => a.HasFlag(SlotTypes[i]))) { continue; }
// something else already equipped in a hand slot, attempt to unequip it so items aren't unnecessarily swapped to it
if (Items[i] != null && Items[i].AllowedSlots.Contains(InvSlotType.Any) && (SlotTypes[i] == InvSlotType.LeftHand || SlotTypes[i] == InvSlotType.RightHand))
if (!slots[i].Empty() && slots[i].First().AllowedSlots.Contains(InvSlotType.Any) &&
(SlotTypes[i] == InvSlotType.LeftHand || SlotTypes[i] == InvSlotType.RightHand))
{
TryPutItem(Items[i], Character.Controlled, new List<InvSlotType>() { InvSlotType.Any }, true);
TryPutItem(slots[i].First(), Character.Controlled, new List<InvSlotType>() { InvSlotType.Any }, true);
}
success = TryPutItem(item, i, true, false, Character.Controlled, true);
if (success) { break; }
@@ -1040,15 +1058,15 @@ namespace Barotrauma
}
break;
case QuickUseAction.PutToEquippedItem:
for (int i = 0; i < character.SelectedItems.Length; i++)
foreach (Item heldItem in character.HeldItems)
{
if (character.SelectedItems[i]?.OwnInventory != null &&
character.SelectedItems[i].OwnInventory.TryPutItem(item, Character.Controlled))
if (heldItem.OwnInventory != null &&
heldItem.OwnInventory.TryPutItem(item, Character.Controlled))
{
success = true;
for (int j = 0; j < capacity; j++)
{
if (Items[j] == character.SelectedItems[i]) slots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f);
if (slots[j].Contains(heldItem)) { visualSlots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f); }
}
break;
}
@@ -1060,18 +1078,21 @@ namespace Barotrauma
{
for (int i = 0; i < capacity; i++)
{
if (Items[i] == item) slots[i].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f);
if (slots[i].Contains(item)) { visualSlots[i].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.4f); }
}
}
draggingItem = null;
SoundPlayer.PlayUISound(success ? GUISoundType.PickItem : GUISoundType.PickItemFail);
DraggingItems.Clear();
if (playSound)
{
SoundPlayer.PlayUISound(success ? GUISoundType.PickItem : GUISoundType.PickItemFail);
}
}
public void DrawOwn(SpriteBatch spriteBatch)
{
if (!AccessibleWhenAlive && !character.IsDead) { return; }
if (slots == null) { CreateSlots(); }
if (visualSlots == null) { CreateSlots(); }
if (GameMain.GraphicsWidth != screenResolution.X ||
GameMain.GraphicsHeight != screenResolution.Y ||
prevUIScale != UIScale ||
@@ -1096,12 +1117,10 @@ namespace Barotrauma
{
if (HideSlot(i)) { continue; }
Rectangle interactRect = slots[i].InteractRect;
interactRect.Location += slots[i].DrawOffset.ToPoint();
//don't draw the item if it's being dragged out of the slot
bool drawItem = draggingItem == null || draggingItem != Items[i] || interactRect.Contains(PlayerInput.MousePosition);
DrawSlot(spriteBatch, this, slots[i], Items[i], i, drawItem, SlotTypes[i]);
bool drawItem = !DraggingItems.Any() || !slots[i].Items.All(it => DraggingItems.Contains(it)) || visualSlots[i].MouseOn();
DrawSlot(spriteBatch, this, visualSlots[i], slots[i].FirstOrDefault(), i, drawItem, SlotTypes[i]);
}
if (hideButton != null && hideButton.Visible && !Locked)
@@ -1109,48 +1128,48 @@ namespace Barotrauma
hideButton.DrawManually(spriteBatch, alsoChildren: true);
}
InventorySlot highlightedQuickUseSlot = null;
VisualSlot highlightedQuickUseSlot = null;
Rectangle inventoryArea = Rectangle.Empty;
for (int i = 0; i < capacity; i++)
{
if (HideSlot(i)) { continue; }
inventoryArea = inventoryArea == Rectangle.Empty ? slots[i].InteractRect : Rectangle.Union(inventoryArea, slots[i].InteractRect);
inventoryArea = inventoryArea == Rectangle.Empty ? visualSlots[i].InteractRect : Rectangle.Union(inventoryArea, visualSlots[i].InteractRect);
if (Items[i] == null ||
(draggingItem == Items[i] && !slots[i].InteractRect.Contains(PlayerInput.MousePosition)) ||
!Items[i].AllowedSlots.Any(a => a != InvSlotType.Any))
if (slots[i].Empty() ||
(DraggingItems.Any(it => slots[i].Contains(it)) && !visualSlots[i].InteractRect.Contains(PlayerInput.MousePosition)) ||
!slots[i].First().AllowedSlots.Any(a => a != InvSlotType.Any))
{
//draw limb icons on empty slots
if (LimbSlotIcons.ContainsKey(SlotTypes[i]))
{
var icon = LimbSlotIcons[SlotTypes[i]];
icon.Draw(spriteBatch, slots[i].Rect.Center.ToVector2() + slots[i].DrawOffset, GUI.Style.EquipmentSlotIconColor, origin: icon.size / 2, scale: slots[i].Rect.Width / icon.size.X);
icon.Draw(spriteBatch, visualSlots[i].Rect.Center.ToVector2() + visualSlots[i].DrawOffset, GUI.Style.EquipmentSlotIconColor, origin: icon.size / 2, scale: visualSlots[i].Rect.Width / icon.size.X);
}
continue;
}
if (draggingItem == Items[i] && !slots[i].IsHighlighted) { continue; }
if (DraggingItems.Any(it => slots[i].Contains(it)) && !visualSlots[i].IsHighlighted) { continue; }
//draw hand icons if the item is equipped in a hand slot
if (IsInLimbSlot(Items[i], InvSlotType.LeftHand))
if (IsInLimbSlot(slots[i].First(), InvSlotType.LeftHand))
{
var icon = LimbSlotIcons[InvSlotType.LeftHand];
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.X, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
icon.Draw(spriteBatch, new Vector2(visualSlots[i].Rect.X, visualSlots[i].Rect.Bottom) + visualSlots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.35f, icon.size.Y * 0.75f), scale: visualSlots[i].Rect.Width / icon.size.X * 0.7f);
}
if (IsInLimbSlot(Items[i], InvSlotType.RightHand))
if (IsInLimbSlot(slots[i].First(), InvSlotType.RightHand))
{
var icon = LimbSlotIcons[InvSlotType.RightHand];
icon.Draw(spriteBatch, new Vector2(slots[i].Rect.Right, slots[i].Rect.Bottom) + slots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: slots[i].Rect.Width / icon.size.X * 0.7f);
icon.Draw(spriteBatch, new Vector2(visualSlots[i].Rect.Right, visualSlots[i].Rect.Bottom) + visualSlots[i].DrawOffset, Color.White * 0.6f, origin: new Vector2(icon.size.X * 0.65f, icon.size.Y * 0.75f), scale: visualSlots[i].Rect.Width / icon.size.X * 0.7f);
}
GUIComponent.ComponentState state = slots[i].EquipButtonState;
GUIComponent.ComponentState state = visualSlots[i].EquipButtonState;
if (state == GUIComponent.ComponentState.Hover)
{
highlightedQuickUseSlot = slots[i];
highlightedQuickUseSlot = visualSlots[i];
}
if (!Items[i].AllowedSlots.Any(a => a == InvSlotType.Any))
if (!slots[i].First().AllowedSlots.Any(a => a == InvSlotType.Any))
{
continue;
}
@@ -1161,20 +1180,20 @@ namespace Barotrauma
color *= 0.5f;
}
if (character.HasEquippedItem(Items[i]))
if (character.HasEquippedItem(slots[i].First()))
{
switch (state)
{
case GUIComponent.ComponentState.None:
EquippedIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
EquippedIndicator.Draw(spriteBatch, visualSlots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
break;
case GUIComponent.ComponentState.Hover:
EquippedHoverIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
EquippedHoverIndicator.Draw(spriteBatch, visualSlots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
break;
case GUIComponent.ComponentState.Pressed:
case GUIComponent.ComponentState.Selected:
case GUIComponent.ComponentState.HoverSelected:
EquippedClickedIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
EquippedClickedIndicator.Draw(spriteBatch, visualSlots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
break;
}
}
@@ -1183,15 +1202,15 @@ namespace Barotrauma
switch (state)
{
case GUIComponent.ComponentState.None:
UnequippedIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
UnequippedIndicator.Draw(spriteBatch, visualSlots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
break;
case GUIComponent.ComponentState.Hover:
UnequippedHoverIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
UnequippedHoverIndicator.Draw(spriteBatch, visualSlots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
break;
case GUIComponent.ComponentState.Pressed:
case GUIComponent.ComponentState.Selected:
case GUIComponent.ComponentState.HoverSelected:
UnequippedClickedIndicator.Draw(spriteBatch, slots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
UnequippedClickedIndicator.Draw(spriteBatch, visualSlots[i].EquipButtonRect.Center.ToVector2(), color, EquippedIndicator.Origin, 0, UIScale * IndicatorScaleAdjustment);
break;
}
}
@@ -12,16 +12,14 @@ namespace Barotrauma.Items.Components
get { return item.Rect.Size.ToVector2(); }
}
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
if (!IsActive || picker == null || !CanBeAttached(picker) || !picker.IsKeyDown(InputType.Aim) || picker != Character.Controlled)
if (!IsActive || picker == null || !CanBeAttached(picker) || !picker.IsKeyDown(InputType.Aim) || picker != Character.Controlled)
{
Drawable = false;
return;
return;
}
Vector2 gridPos = picker.Position;
Vector2 roundedGridPos = new Vector2(
MathUtils.RoundTowardsClosest(picker.Position.X, Submarine.GridSize.X),
@@ -49,7 +47,7 @@ namespace Barotrauma.Items.Components
attachPos += item.Submarine.Position;
}
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.7f);
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.4f);
item.Sprite.Draw(
spriteBatch,
@@ -130,7 +130,7 @@ namespace Barotrauma.Items.Components
if (body.UserData is Item item)
{
var door = item.GetComponent<Door>();
if (door != null && door.IsOpen || door.IsBroken) continue;
if (door != null && door.CanBeTraversed) { continue; }
}
targetHull = null;
@@ -239,7 +239,7 @@ namespace Barotrauma.Items.Components
{
if (targetSections.Count == 0) { return; }
Item liquidItem = liquidContainer?.Inventory.Items[0];
Item liquidItem = liquidContainer?.Inventory.FirstOrDefault();
if (liquidItem == null) { return; }
bool isCleaning = false;
@@ -15,7 +15,8 @@ namespace Barotrauma.Items.Components
Random,
CharacterSpecific,
ItemSpecific,
All
All,
Manual
}
class ItemSound
@@ -259,6 +260,7 @@ namespace Barotrauma.Items.Components
loopingSoundChannel = null;
loopingSound = null;
}
if (loopingSoundChannel == null || !loopingSoundChannel.IsPlaying)
{
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
@@ -271,6 +273,21 @@ namespace Barotrauma.Items.Components
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
loopingSoundChannel.Far = loopingSound.Range;
}
// Looping sound with manual selection mode should be changed if value of ManuallySelectedSound has changed
// Otherwise the sound won't change until the sound condition (such as being active) is disabled and re-enabled
if (loopingSoundChannel != null && loopingSoundChannel.IsPlaying && soundSelectionModes[type] == SoundSelectionMode.Manual)
{
var playingIndex = sounds[type].IndexOf(loopingSound);
var shouldBePlayingIndex = Math.Clamp(ManuallySelectedSound, 0, sounds[type].Count);
if (playingIndex != shouldBePlayingIndex)
{
loopingSoundChannel.FadeOutAndDispose();
loopingSoundChannel = null;
loopingSound = null;
}
}
return;
}
@@ -295,6 +312,10 @@ namespace Barotrauma.Items.Components
}
return;
}
else if (soundSelectionMode == SoundSelectionMode.Manual)
{
index = Math.Clamp(ManuallySelectedSound, 0, matchingSounds.Count);
}
else
{
index = Rand.Int(matchingSounds.Count);
@@ -335,7 +356,7 @@ namespace Barotrauma.Items.Components
{
float volume = GetSoundVolume(itemSound);
if (volume <= 0.0001f) { return; }
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, itemSound.RoundSound.GetRandomFrequencyMultiplier(), item.CurrentHull);
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, itemSound.RoundSound.GetRandomFrequencyMultiplier(), item.CurrentHull, ignoreMuffling: itemSound.RoundSound.IgnoreMuffling);
if (channel != null) { playingOneshotSoundChannels.Add(channel); }
}
}
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
@@ -32,6 +33,12 @@ namespace Barotrauma.Items.Components
private set;
}
public Sprite ContainedStateIndicatorEmpty
{
get;
private set;
}
#if DEBUG
[Editable]
#endif
@@ -55,6 +62,11 @@ namespace Barotrauma.Items.Components
[Serialize(null, false, description: "An optional text displayed above the item's inventory.")]
public string UILabel { get; set; }
public GUIComponentStyle IndicatorStyle { get; set; }
[Serialize(null, false)]
public string ContainedStateIndicatorStyle { get; set; }
[Serialize(true, false, description: "Should an indicator displaying the state of the contained items be displayed on this item's inventory slot. "+
"If this item can only contain one item, the indicator will display the condition of the contained item, otherwise it will indicate how full the item is.")]
public bool ShowContainedStateIndicator { get; set; }
@@ -98,6 +110,26 @@ namespace Barotrauma.Items.Components
case "containedstateindicator":
ContainedStateIndicator = new Sprite(subElement);
break;
case "containedstateindicatorempty":
ContainedStateIndicatorEmpty = new Sprite(subElement);
break;
}
}
if (string.IsNullOrEmpty(ContainedStateIndicatorStyle))
{
//if neither a style or a custom sprite is defined, use default style
if (ContainedStateIndicator == null)
{
IndicatorStyle = GUI.Style.GetComponentStyle("ContainedStateIndicator.Default");
}
}
else
{
IndicatorStyle = GUI.Style.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...");
}
}
if (GuiFrame == null)
@@ -173,15 +205,9 @@ namespace Barotrauma.Items.Components
}
//if holding 2 different "always open" items in different hands, don't force them to stay open
if (character.SelectedItems[0] != null &&
character.SelectedItems[1] != null &&
character.SelectedItems[0] != character.SelectedItems[1])
if (character.HeldItems.Count() > 1 && character.HeldItems.All(it => it.GetComponent<ItemContainer>()?.KeepOpenWhenEquipped ?? false))
{
if ((character.SelectedItems[0].GetComponent<ItemContainer>()?.KeepOpenWhenEquipped ?? false) &&
(character.SelectedItems[1].GetComponent<ItemContainer>()?.KeepOpenWhenEquipped ?? false))
{
return false;
}
return false;
}
return true;
@@ -260,10 +286,8 @@ namespace Barotrauma.Items.Components
bool isWiringMode = SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode();
int i = 0;
foreach (Item containedItem in Inventory.Items)
foreach (Item containedItem in Inventory.AllItems)
{
if (containedItem == null) continue;
if (AutoInteractWithContained)
{
containedItem.IsHighlighted = item.IsHighlighted;
@@ -313,7 +337,7 @@ namespace Barotrauma.Items.Components
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
if (item.NonInteractable) { return; }
if (!item.IsInteractable(character)) { return; }
if (Inventory.RectTransform != null)
{
guiCustomComponent.RectTransform.Parent = Inventory.RectTransform;
@@ -21,11 +21,17 @@ namespace Barotrauma.Items.Components
private float[] charWidths;
private Vector4 padding;
[Serialize("0,0,0,0", true, description: "The amount of padding around the text in pixels (left,top,right,bottom).")]
public Vector4 Padding
{
get { return TextBlock.Padding; }
set { TextBlock.Padding = value; }
get { return padding; }
set
{
padding = value;
TextBlock.Padding = value * item.Scale;
}
}
private string text;
@@ -41,15 +47,22 @@ namespace Barotrauma.Items.Components
{
textBlock = null;
}
text = value;
DisplayText = TextManager.Get(text, returnNull: true) ?? value;
TextBlock.Text = DisplayText;
if (Screen.Selected == GameMain.SubEditorScreen && Scrollable)
{
TextBlock.Text = ToolBox.LimitString(DisplayText, textBlock.Font, item.Rect.Width);
}
SetScrollingText();
SetDisplayText(value);
}
}
private bool ignoreLocalization;
[Editable, Serialize(false, true, "Whether or not to skip localization and always display the raw value.")]
public bool IgnoreLocalization
{
get => ignoreLocalization;
set
{
ignoreLocalization = value;
SetDisplayText(Text);
}
}
@@ -107,13 +120,7 @@ namespace Barotrauma.Items.Components
{
if (textBlock == null)
{
textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "",
textColor: textColor, font: GUI.UnscaledSmallFont, textAlignment: scrollable ? Alignment.CenterLeft : Alignment.Center, wrap: true, style: null)
{
TextDepth = item.SpriteDepth - 0.00001f,
RoundToNearestPixel = false,
TextScale = TextScale
};
RecreateTextBlock();
}
return textBlock;
}
@@ -126,7 +133,7 @@ namespace Barotrauma.Items.Components
private void SetScrollingText()
{
if (!scrollable) return;
if (!scrollable) { return; }
float totalWidth = textBlock.Font.MeasureString(DisplayText).X;
float textAreaWidth = Math.Max(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z, 0);
@@ -143,6 +150,7 @@ namespace Barotrauma.Items.Components
//whole text can fit in the textblock, no need to scroll
needsScrolling = false;
scrollingText = DisplayText;
scrollPadding = 0;
scrollAmount = 0.0f;
scrollIndex = 0;
return;
@@ -161,16 +169,40 @@ namespace Barotrauma.Items.Components
scrollIndex = MathHelper.Clamp(scrollIndex, 0, DisplayText.Length);
}
private void SetDisplayText(string value)
{
DisplayText = IgnoreLocalization ? value : TextManager.Get(value, returnNull: true) ?? value;
TextBlock.Text = DisplayText;
if (Screen.Selected == GameMain.SubEditorScreen && Scrollable)
{
TextBlock.Text = ToolBox.LimitString(DisplayText, TextBlock.Font, item.Rect.Width);
}
SetScrollingText();
}
private void RecreateTextBlock()
{
textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "",
textColor: textColor, font: GUI.UnscaledSmallFont, textAlignment: scrollable ? Alignment.CenterLeft : Alignment.Center, wrap: !scrollable, style: null)
{
TextDepth = item.SpriteDepth - 0.00001f,
RoundToNearestPixel = false,
TextScale = TextScale,
Padding = padding * item.Scale
};
}
public override void Update(float deltaTime, Camera cam)
{
if (!scrollable) return;
if (!scrollable) { return; }
if (scrollingText == null)
{
SetScrollingText();
}
if (!needsScrolling) return;
if (!needsScrolling) { return; }
scrollAmount -= deltaTime * ScrollSpeed;
@@ -204,11 +236,33 @@ namespace Barotrauma.Items.Components
}
}
TextBlock.Text = sb.ToString();
TextBlock.Text = sb.ToString();
}
public override void OnScaleChanged()
{
RecreateTextBlock();
SetDisplayText(Text);
prevScale = item.Scale;
prevRect = item.Rect;
}
private float prevScale;
private Rectangle prevRect;
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
if (editing)
{
if (!MathUtils.NearlyEqual(prevScale, item.Scale) || prevRect != item.Rect)
{
RecreateTextBlock();
SetDisplayText(Text);
prevScale = item.Scale;
prevRect = item.Rect;
}
}
var drawPos = new Vector2(
item.DrawPosition.X - item.Rect.Width / 2.0f,
-(item.DrawPosition.Y + item.Rect.Height / 2.0f));
@@ -223,7 +277,7 @@ namespace Barotrauma.Items.Components
}
textBlock.TextDepth = item.SpriteDepth - 0.0001f;
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + (editing ? Vector2.Zero : new Vector2(scrollAmount + scrollPadding, 0.0f));
textBlock.DrawManually(spriteBatch);
}
@@ -38,12 +38,6 @@ namespace Barotrauma.Items.Components
light.Color = LightColor.Multiply(brightness);
}
public override void OnItemLoaded()
{
base.OnItemLoaded();
SetLightSourceState(IsActive, lightBrightness);
}
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
@@ -51,7 +45,7 @@ namespace Barotrauma.Items.Components
Vector2 origin = light.LightSprite.Origin;
if ((light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
if ((light.LightSpriteEffect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) { origin.Y = light.LightSprite.SourceRect.Height - origin.Y; }
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, origin, -light.Rotation, item.Scale, light.LightSpriteEffect, item.SpriteDepth - 0.0001f);
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, origin, -light.Rotation, item.Scale, light.LightSpriteEffect, itemDepth - 0.0001f);
}
}
@@ -95,11 +95,11 @@ namespace Barotrauma.Items.Components
// TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental.
// Only do this if there's only one linked component. If you link more containers then may
// GUI.PreventElementOverlap have mercy on your HUD layout
if (GuiFrame != null && item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1)
if (GuiFrame != null && item.linkedTo.Count(entity => entity is Item { DisplaySideBySideWhenLinked: true }) == 1)
{
foreach (MapEntity linkedTo in item.linkedTo)
{
if (!(linkedTo is Item linkedItem) || !linkedItem.DisplaySideBySideWhenLinked) { continue; }
if (!(linkedTo is Item { DisplaySideBySideWhenLinked: true } linkedItem)) { continue; }
if (!linkedItem.Components.Any()) { continue; }
var itemContainer = linkedItem.GetComponent<ItemContainer>();
@@ -108,8 +108,8 @@ namespace Barotrauma.Items.Components
// how much spacing do we want between the components
var padding = (int) (8 * GUI.Scale);
// Move the linked container to the right and move the deconstructor to the left
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(100, 0);
GuiFrame.RectTransform.AbsoluteOffset = new Point(-100, 0);
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(GuiFrame.Rect.Width / -2 - padding, 0);
GuiFrame.RectTransform.AbsoluteOffset = new Point(itemContainer.GuiFrame.Rect.Width / 2 + padding, 0);
}
}
return base.Select(character);
@@ -126,7 +126,7 @@ namespace Barotrauma.Items.Components
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{
overlayComponent.RectTransform.SetAsLastChild();
var lastSlot = inputContainer.Inventory.slots.Last();
var lastSlot = inputContainer.Inventory.visualSlots.Last();
GUI.DrawRectangle(spriteBatch,
new Rectangle(
@@ -144,16 +144,15 @@ namespace Barotrauma.Items.Components
Vector2 drawPos = item.DrawPosition;
drawPos += PropellerPos;
drawPos.Y = -drawPos.Y;
propellerSprite.Draw(spriteBatch, (int)Math.Floor(spriteIndex), drawPos, Color.White, propellerSprite.Origin, 0.0f, Vector2.One);
}
if (editing && !GUI.DisableHUD)
if (editing && !DisablePropellerDamage && propellerDamage != null && !GUI.DisableHUD)
{
Vector2 drawPos = item.DrawPosition;
drawPos += PropellerPos;
drawPos += PropellerPos * item.Scale;
drawPos.Y = -drawPos.Y;
GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, GUI.Style.Red);
spriteBatch.DrawCircle(drawPos, propellerDamage.DamageRange * item.Scale, 16, GUI.Style.Red, thickness: 2);
}
}
@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
};
}
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform), fi.DisplayName)
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform), GetRecipeNameAndAmount(fi))
{
Padding = Vector4.Zero,
AutoScaleVertical = true,
@@ -199,6 +199,21 @@ namespace Barotrauma.Items.Components
}
}
private string GetRecipeNameAndAmount(FabricationRecipe fabricationRecipe)
{
if (fabricationRecipe == null) { return ""; }
if (fabricationRecipe.Amount > 1)
{
return TextManager.GetWithVariables("fabricationrecipenamewithamount",
new string[2] { "[name]", "[amount]" },
new string[2] { fabricationRecipe.DisplayName, fabricationRecipe.Amount.ToString() });
}
else
{
return fabricationRecipe.DisplayName;
}
}
partial void OnItemLoadedProjSpecific()
{
inputContainer.AllowUIOverlap = true;
@@ -212,11 +227,11 @@ namespace Barotrauma.Items.Components
// TODO, This works fine as of now but if GUI.PreventElementOverlap ever gets fixed this block of code may become obsolete or detrimental.
// Only do this if there's only one linked component. If you link more containers then may
// GUI.PreventElementOverlap have mercy on your HUD layout
if (GuiFrame != null && item.linkedTo.Count(entity => entity is Item item && item.DisplaySideBySideWhenLinked) == 1)
if (GuiFrame != null && item.linkedTo.Count(entity => entity is Item { DisplaySideBySideWhenLinked: true }) == 1)
{
foreach (MapEntity linkedTo in item.linkedTo)
{
if (!(linkedTo is Item linkedItem) || !linkedItem.DisplaySideBySideWhenLinked) { continue; }
if (!(linkedTo is Item { DisplaySideBySideWhenLinked: true } linkedItem)) { continue; }
if (!linkedItem.Components.Any()) { continue; }
var itemContainer = linkedItem.GetComponent<ItemContainer>();
@@ -225,8 +240,8 @@ namespace Barotrauma.Items.Components
// how much spacing do we want between the components
var padding = (int) (8 * GUI.Scale);
// Move the linked container to the right and move the fabricator to the left
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(-100, 0);
GuiFrame.RectTransform.AbsoluteOffset = new Point(100, 0);
itemContainer.GuiFrame.RectTransform.AbsoluteOffset = new Point(GuiFrame.Rect.Width / -2 - padding, 0);
GuiFrame.RectTransform.AbsoluteOffset = new Point(itemContainer.GuiFrame.Rect.Width / 2 + padding, 0);
}
}
@@ -287,9 +302,8 @@ namespace Barotrauma.Items.Components
missingItems.Add(requiredItem);
}
}
foreach (Item item in inputContainer.Inventory.Items)
foreach (Item item in inputContainer.Inventory.AllItems)
{
if (item == null) { continue; }
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
}
@@ -297,7 +311,7 @@ namespace Barotrauma.Items.Components
foreach (FabricationRecipe.RequiredItem requiredItem in missingItems)
{
while (slotIndex < inputContainer.Capacity && inputContainer.Inventory.Items[slotIndex] != null)
while (slotIndex < inputContainer.Capacity && inputContainer.Inventory.GetItemAt(slotIndex) != null)
{
slotIndex++;
}
@@ -307,17 +321,17 @@ namespace Barotrauma.Items.Components
{
if (item.ParentInventory != inputContainer.Inventory && IsItemValidIngredient(item, requiredItem))
{
int availableSlotIndex = Array.IndexOf(item.ParentInventory.Items, item);
int availableSlotIndex = item.ParentInventory.FindIndex(item);
//slots are null if the inventory has never been displayed
//(linked item, but the UI is not set to be displayed at the same time)
if (item.ParentInventory.slots != null)
if (item.ParentInventory.visualSlots != null)
{
if (item.ParentInventory.slots[availableSlotIndex].HighlightTimer <= 0.0f)
if (item.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
{
item.ParentInventory.slots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
item.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
if (slotIndex < inputContainer.Capacity)
{
inputContainer.Inventory.slots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
}
}
}
@@ -327,7 +341,7 @@ namespace Barotrauma.Items.Components
if (slotIndex >= inputContainer.Capacity) { break; }
var itemIcon = requiredItem.ItemPrefabs.First().InventoryIcon ?? requiredItem.ItemPrefabs.First().sprite;
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect;
Rectangle slotRect = inputContainer.Inventory.visualSlots[slotIndex].Rect;
itemIcon.Draw(
spriteBatch,
slotRect.Center.ToVector2(),
@@ -367,14 +381,12 @@ namespace Barotrauma.Items.Components
{
overlayComponent.RectTransform.SetAsLastChild();
if (outputContainer.Inventory.Items.First() != null) { return; }
FabricationRecipe targetItem = fabricatedItem ?? selectedItem;
if (targetItem != null)
{
var itemIcon = targetItem.TargetItem.InventoryIcon ?? targetItem.TargetItem.sprite;
Rectangle slotRect = outputContainer.Inventory.slots[0].Rect;
Rectangle slotRect = outputContainer.Inventory.visualSlots[0].Rect;
if (fabricatedItem != null)
{
@@ -449,8 +461,10 @@ namespace Barotrauma.Items.Components
Color = selectedItem.TargetItem.InventoryIconColor
};
}*/
var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
selectedItem.TargetItem.Name, textAlignment: Alignment.CenterLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont)
GetRecipeNameAndAmount(selectedItem), textAlignment: Alignment.CenterLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont)
{
AutoScaleHorizontal = true
};
@@ -539,7 +553,7 @@ namespace Barotrauma.Items.Components
private bool StartButtonClicked(GUIButton button, object obj)
{
if (selectedItem == null) { return false; }
if (!outputContainer.Inventory.IsEmpty())
if (fabricatedItem == null && !outputContainer.Inventory.CanBePut(selectedItem.TargetItem))
{
outputSlot.Flash(GUI.Style.Red);
return false;
@@ -71,10 +71,14 @@ namespace Barotrauma.Items.Components
private float showDirectionalIndicatorTimer;
private List<LevelObject> nearbyObjects = new List<LevelObject>();
private readonly List<LevelObject> nearbyObjects = new List<LevelObject>();
private const float NearbyObjectUpdateInterval = 1.0f;
float nearbyObjectUpdateTimer;
private List<Submarine> connectedSubs = new List<Submarine>();
private const float ConnectedSubUpdateInterval = 1.0f;
float connectedSubUpdateTimer;
//Vector2 = vector from the ping source to the position of the disruption
//float = strength of the disruption, between 0-1
private readonly List<Pair<Vector2, float>> disruptedDirections = new List<Pair<Vector2, float>>();
@@ -135,6 +139,8 @@ namespace Barotrauma.Items.Components
private bool isConnectedToSteering;
private static string caveLabel;
private bool AllowUsingMineralScanner =>
HasMineralScanner && !isConnectedToSteering;
@@ -143,6 +149,10 @@ namespace Barotrauma.Items.Components
System.Diagnostics.Debug.Assert(Enum.GetValues(typeof(BlipType)).Cast<BlipType>().All(t => blipColorGradient.ContainsKey(t)));
sonarBlips = new List<SonarBlip>();
caveLabel =
TextManager.Get("cave", returnNull: true) ??
TextManager.Get("missiontype.nest");
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -413,6 +423,26 @@ namespace Barotrauma.Items.Components
networkUpdateTimer -= deltaTime;
}
connectedSubUpdateTimer -= deltaTime;
if (connectedSubUpdateTimer <= 0.0f)
{
connectedSubs.Clear();
if (UseTransducers)
{
foreach (var transducer in connectedTransducers)
{
if (transducer.Transducer.Item.Submarine == null) { continue; }
if (connectedSubs.Contains(transducer.Transducer.Item.Submarine)) { continue; }
connectedSubs = transducer.Transducer.Item.Submarine?.GetConnectedSubs();
}
}
else if (item.Submarine != null)
{
connectedSubs = item.Submarine?.GetConnectedSubs();
}
connectedSubUpdateTimer = ConnectedSubUpdateInterval;
}
if (sonarView.Rect.Contains(PlayerInput.MousePosition))
{
float scrollSpeed = PlayerInput.ScrollWheelSpeed / 1000.0f;
@@ -848,10 +878,22 @@ namespace Barotrauma.Items.Components
displayScale, center, DisplayRadius);
}
for (int i = 0; i < Level.Loaded.Caves.Count; i++)
{
var cave = Level.Loaded.Caves[i];
if (!cave.DisplayOnSonar) { continue; }
DrawMarker(spriteBatch,
caveLabel,
"cave",
"cave" + i,
cave.StartPos.ToVector2(), transducerCenter,
displayScale, center, DisplayRadius);
}
foreach (AITarget aiTarget in AITarget.List)
{
if (!aiTarget.Enabled) continue;
if (string.IsNullOrEmpty(aiTarget.SonarLabel) || aiTarget.SoundRange <= 0.0f) continue;
if (!aiTarget.Enabled) { continue; }
if (string.IsNullOrEmpty(aiTarget.SonarLabel) || aiTarget.SoundRange <= 0.0f) { continue; }
if (Vector2.DistanceSquared(aiTarget.WorldPosition, transducerCenter) < aiTarget.SoundRange * aiTarget.SoundRange)
{
@@ -902,16 +944,11 @@ namespace Barotrauma.Items.Components
foreach (Submarine sub in Submarine.Loaded)
{
if (!sub.ShowSonarMarker) { continue; }
if (UseTransducers ?
connectedTransducers.Any(t => sub == t.Transducer.Item.Submarine || sub.DockedTo.Contains(t.Transducer.Item.Submarine)) :
(sub == item.Submarine || sub.DockedTo.Contains(item.Submarine)))
{
continue;
}
if (connectedSubs.Contains(sub)) { continue; }
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
DrawMarker(spriteBatch,
sub.Info.DisplayName,
DrawMarker(spriteBatch,
sub.Info.DisplayName,
sub.Info.HasTag(SubmarineTag.Shuttle) ? "shuttle" : "submarine",
sub,
sub.WorldPosition, transducerCenter,
@@ -931,10 +968,8 @@ namespace Barotrauma.Items.Components
foreach (Submarine submarine in Submarine.Loaded)
{
if (UseTransducers ?
!connectedTransducers.Any(t => submarine == t.Transducer.Item.Submarine || submarine.DockedTo.Contains(t.Transducer.Item.Submarine)) :
submarine != item.Submarine && !submarine.DockedTo.Contains(item.Submarine)) continue;
if (submarine.HullVertices == null) continue;
if (!connectedSubs.Contains(submarine)) { continue; }
if (submarine.HullVertices == null) { continue; }
Vector2 offset = ConvertUnits.ToSimUnits(submarine.WorldPosition - transducerCenter);
@@ -1018,8 +1053,8 @@ namespace Barotrauma.Items.Components
//don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null)
{
if ((dockingPort.Item.Submarine.TeamID == Character.TeamType.Team1 && item.Submarine.TeamID == Character.TeamType.Team2) ||
(dockingPort.Item.Submarine.TeamID == Character.TeamType.Team2 && item.Submarine.TeamID == Character.TeamType.Team1))
if ((dockingPort.Item.Submarine.TeamID == CharacterTeamType.Team1 && item.Submarine.TeamID == CharacterTeamType.Team2) ||
(dockingPort.Item.Submarine.TeamID == CharacterTeamType.Team2 && item.Submarine.TeamID == CharacterTeamType.Team1))
{
continue;
}
@@ -1226,19 +1261,10 @@ namespace Barotrauma.Items.Components
foreach (Submarine submarine in Submarine.Loaded)
{
if (submarine.HullVertices == null) continue;
if (submarine.HullVertices == null) { continue; }
if (!DetectSubmarineWalls)
{
if (UseTransducers)
{
if (connectedTransducers.Any(t => submarine == t.Transducer.Item.Submarine ||
submarine.DockedTo.Contains(t.Transducer.Item.Submarine))) continue;
}
else
{
if (item.Submarine == submarine) continue;
if (item.Submarine != null && item.Submarine.DockedTo.Contains(submarine)) continue;
}
if (connectedSubs.Contains(submarine)) { continue; }
}
for (int i = 0; i < submarine.HullVertices.Count; i++)
@@ -34,7 +34,7 @@ namespace Barotrauma.Items.Components
private GUIComponent steerArea;
private GUITextBlock pressureWarningText;
private GUITextBlock pressureWarningText, iceSpireWarningText;
private GUITextBlock tipContainer;
@@ -311,6 +311,7 @@ namespace Barotrauma.Items.Components
{
Vector2 vel = controlledSub == null ? Vector2.Zero : controlledSub.Velocity;
var realWorldVel = ConvertUnits.ToDisplayUnits(vel.X * Physics.DisplayToRealWorldRatio) * 3.6f;
if (controlledSub != null && controlledSub.FlippedX) { realWorldVel *= -1; }
return ((int)realWorldVel).ToString();
};
break;
@@ -440,8 +441,13 @@ namespace Barotrauma.Items.Components
(spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null);
steerRadius = steerArea.Rect.Width / 2;
pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), steerArea.RectTransform, Anchor.Center, Pivot.TopCenter),
TextManager.Get("SteeringDepthWarning"), Color.Red, GUI.LargeFont, Alignment.Center)
iceSpireWarningText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.25f), steerArea.RectTransform, Anchor.Center, Pivot.TopCenter),
TextManager.Get("NavTerminalIceSpireWarning"), GUI.Style.Red, GUI.SubHeadingFont, Alignment.Center, color: Color.Black * 0.8f, wrap: true)
{
Visible = false
};
pressureWarningText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.25f), steerArea.RectTransform, Anchor.Center, Pivot.TopCenter),
TextManager.Get("SteeringDepthWarning"), GUI.Style.Red, GUI.SubHeadingFont, Alignment.Center, color: Color.Black * 0.8f)
{
Visible = false
};
@@ -471,7 +477,11 @@ namespace Barotrauma.Items.Components
public void AttachToSonarHUD(GUICustomComponent sonarView)
{
steerArea.Visible = false;
sonarView.OnDraw += (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); };
sonarView.OnDraw += (spriteBatch, guiCustomComponent) =>
{
DrawHUD(spriteBatch, guiCustomComponent.Rect);
steerArea.DrawChildren(spriteBatch, recursive: true);
};
}
public void DrawHUD(SpriteBatch spriteBatch, Rectangle rect)
@@ -712,12 +722,13 @@ namespace Barotrauma.Items.Components
}
}
pressureWarningText.Visible = item.Submarine != null && item.Submarine.AtDamageDepth && Timing.TotalTime % 1.0f < 0.5f;
pressureWarningText.Visible = item.Submarine != null && item.Submarine.AtDamageDepth && Timing.TotalTime % 1.0f < 0.8f;
iceSpireWarningText.Visible = item.Submarine != null && !pressureWarningText.Visible && showIceSpireWarning && Timing.TotalTime % 1.0f < 0.8f;
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
{
if (PlayerInput.PrimaryMouseButtonHeld() && !CrewManager.IsCommandInterfaceOpen && !GameSession.IsTabMenuOpen &&
(!GameMain.GameSession?.Campaign?.ShowCampaignUI ?? true) && !GUIMessageBox.MessageBoxes.Any())
(!GameMain.GameSession?.Campaign?.ShowCampaignUI ?? true) && !GUIMessageBox.MessageBoxes.Any(msgBox => msgBox is GUIMessageBox { MessageBoxType: GUIMessageBox.Type.Default }))
{
Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2();
inputPos.Y = -inputPos.Y;
@@ -113,25 +113,28 @@ namespace Barotrauma.Items.Components
}
}
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem)
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem, bool showProgressBar)
{
float progressBarState = targetItem.ConditionPercentage / 100.0f;
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState) || prevProgressBarTarget != targetItem)
if (showProgressBar)
{
var door = targetItem.GetComponent<Door>();
if (door == null || door.Stuck <= 0)
float progressBarState = targetItem.ConditionPercentage / 100.0f;
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState) || prevProgressBarTarget != targetItem)
{
Vector2 progressBarPos = targetItem.DrawPosition;
var progressBar = user?.UpdateHUDProgressBar(
targetItem,
progressBarPos,
progressBarState,
GUI.Style.Red, GUI.Style.Green,
progressBarState < prevProgressBarState ? "progressbar.cutting" : "");
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
var door = targetItem.GetComponent<Door>();
if (door == null || door.Stuck <= 0)
{
Vector2 progressBarPos = targetItem.DrawPosition;
var progressBar = user?.UpdateHUDProgressBar(
targetItem,
progressBarPos,
progressBarState,
GUI.Style.Red, GUI.Style.Green,
progressBarState < prevProgressBarState ? "progressbar.cutting" : "");
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
}
prevProgressBarState = progressBarState;
prevProgressBarTarget = targetItem;
}
prevProgressBarState = progressBarState;
prevProgressBarTarget = targetItem;
}
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
@@ -53,13 +53,9 @@ namespace Barotrauma.Items.Components
{
//if the Character using the panel has a wire item equipped
//and the wire hasn't been connected yet, draw it on the panel
for (int i = 0; i < character.SelectedItems.Length; i++)
foreach (Item item in character.HeldItems)
{
Item selectedItem = character.SelectedItems[i];
if (selectedItem == null) { continue; }
Wire wireComponent = selectedItem.GetComponent<Wire>();
Wire wireComponent = item.GetComponent<Wire>();
if (wireComponent != null)
{
equippedWire = wireComponent;
@@ -94,7 +90,8 @@ namespace Barotrauma.Items.Components
int linkIndex = c.FindWireIndex(DraggingConnected.Item);
if (linkIndex > -1 || panel.DisconnectedWires.Contains(DraggingConnected))
{
Inventory.draggingItem = DraggingConnected.Item;
Inventory.DraggingItems.Clear();
Inventory.DraggingItems.Add(DraggingConnected.Item);
}
}
}
@@ -182,7 +179,11 @@ namespace Barotrauma.Items.Components
new Vector2(x + width / 2, y + height),
null, panel, "");
if (DraggingConnected == equippedWire) { Inventory.draggingItem = equippedWire.Item; }
if (DraggingConnected == equippedWire)
{
Inventory.DraggingItems.Clear();
Inventory.DraggingItems.Add(equippedWire.Item);
}
}
}
@@ -207,7 +208,7 @@ namespace Barotrauma.Items.Components
//(so we don't drop the item when dropping the wire on a connection)
if (mouseInRect || (GUI.MouseOn?.UserData is ConnectionPanel && GUI.MouseOn.MouseRect.Contains(PlayerInput.MousePosition)))
{
Inventory.draggingItem = null;
Inventory.DraggingItems.Clear();
}
}
@@ -236,7 +237,7 @@ namespace Barotrauma.Items.Components
{
float connectorSpriteScale = (35.0f / connectionSprite.SourceRect.Width) * panel.Scale;
for (int i = 0; i < MaxLinked; i++)
for (int i = 0; i < MaxWires; i++)
{
if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; }
if (wires[i].HiddenInGame && Screen.Selected == GameMain.GameScreen) { continue; }
@@ -122,7 +122,7 @@ namespace Barotrauma.Items.Components
msg.ReadUInt16(); //user ID
foreach (Connection connection in Connections)
{
for (int i = 0; i < Connection.MaxLinked; i++)
for (int i = 0; i < connection.MaxWires; i++)
{
msg.ReadUInt16();
}
@@ -168,7 +168,7 @@ namespace Barotrauma.Items.Components
foreach (Connection connection in Connections)
{
for (int i = 0; i < Connection.MaxLinked; i++)
for (int i = 0; i < connection.MaxWires; i++)
{
ushort wireId = msg.ReadUInt16();
@@ -4,7 +4,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
@@ -15,7 +14,7 @@ namespace Barotrauma.Items.Components
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale));
partial void InitProjSpecific(XElement element)
partial void InitProjSpecific()
{
CreateGUI();
}
@@ -37,41 +36,70 @@ namespace Barotrauma.Items.Components
float elementSize = Math.Min(1.0f / visibleElements.Count(), 1);
foreach (CustomInterfaceElement ciElement in visibleElements)
{
if (!string.IsNullOrEmpty(ciElement.PropertyName))
if (ciElement.HasPropertyName)
{
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), isHorizontal: true)
{
RelativeSpacing = 0.02f,
UserData = ciElement
};
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform),
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label);
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), "", style: "GUITextBoxNoIcon")
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), isHorizontal: true)
{
OverflowClip = true,
RelativeSpacing = 0.02f,
UserData = ciElement
};
//reset size restrictions set by the Style to make sure the elements can fit the interface
textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0);
textBox.RectTransform.MaxSize = textBox.Frame.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
textBox.OnDeselected += (tb, key) =>
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform),
TextManager.Get(ciElement.Label, returnNull: true) ?? ciElement.Label);
if (!ciElement.IsIntegerInput)
{
if (GameMain.Client == null)
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon")
{
TextChanged(tb.UserData as CustomInterfaceElement, textBox.Text);
}
else
OverflowClip = true,
UserData = ciElement
};
//reset size restrictions set by the Style to make sure the elements can fit the interface
textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0);
textBox.RectTransform.MaxSize = textBox.Frame.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
textBox.OnDeselected += (tb, key) =>
{
item.CreateClientEvent(this);
}
};
if (GameMain.Client == null)
{
TextChanged(tb.UserData as CustomInterfaceElement, textBox.Text);
}
else
{
item.CreateClientEvent(this);
}
};
textBox.OnEnterPressed += (tb, text) =>
textBox.OnEnterPressed += (tb, text) =>
{
tb.Deselect();
return true;
};
uiElements.Add(textBox);
}
else
{
tb.Deselect();
return true;
};
uiElements.Add(textBox);
int.TryParse(ciElement.Signal, out int signal);
var numberInput = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), GUINumberInput.NumberType.Int)
{
UserData = ciElement,
MinValueInt = ciElement.NumberInputMin,
MaxValueInt = ciElement.NumberInputMax,
IntValue = Math.Clamp(signal, ciElement.NumberInputMin, ciElement.NumberInputMax)
};
//reset size restrictions set by the Style to make sure the elements can fit the interface
numberInput.RectTransform.MinSize = numberInput.LayoutGroup.RectTransform.MinSize = new Point(0, 0);
numberInput.RectTransform.MaxSize = numberInput.LayoutGroup.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
numberInput.OnValueChanged += (ni) =>
{
if (GameMain.Client == null)
{
ValueChanged(ni.UserData as CustomInterfaceElement, ni.IntValue);
}
else
{
item.CreateClientEvent(this);
}
};
uiElements.Add(numberInput);
}
}
else if (ciElement.ContinuousSignal)
{
@@ -175,7 +203,7 @@ namespace Barotrauma.Items.Components
foreach (var uiElement in uiElements)
{
if (!(uiElement.UserData is CustomInterfaceElement element)) { continue; }
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || !string.IsNullOrEmpty(element.PropertyName) || (element.Connection != null && element.Connection.Wires.Any(w => w != null));
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || element.HasPropertyName || (element.Connection != null && element.Connection.Wires.Any(w => w != null));
if (visible) { visibleElementCount++; }
if (uiElement.Visible != visible)
{
@@ -203,36 +231,29 @@ namespace Barotrauma.Items.Components
{
if (uiElements[i] is GUIButton button)
{
button.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
button.Text = CreateLabelText(i);
button.TextBlock.Wrap = button.Text.Contains(' ');
}
else if (uiElements[i] is GUITickBox tickBox)
{
tickBox.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
tickBox.Text = CreateLabelText(i);
tickBox.TextBlock.Wrap = tickBox.Text.Contains(' ');
}
if (uiElements[i] is GUITextBox textBox)
else if (uiElements[i] is GUITextBox || uiElements[i] is GUINumberInput)
{
var textBlock = textBox.Parent.GetChild<GUITextBlock>();
textBlock.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
var textBlock = uiElements[i].Parent.GetChild<GUITextBlock>();
textBlock.Text = CreateLabelText(i);
textBlock.Wrap = textBlock.Text.Contains(' ');
foreach (ISerializableEntity e in item.AllPropertyObjects)
{
if (e.SerializableProperties.ContainsKey(customInterfaceElementList[i].PropertyName))
{
textBox.Text = e.SerializableProperties[customInterfaceElementList[i].PropertyName].GetValue(e) as string;
}
}
}
}
string CreateLabelText(int elementIndex)
{
return string.IsNullOrWhiteSpace(customInterfaceElementList[elementIndex].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (elementIndex + 1).ToString()) :
customInterfaceElementList[elementIndex].Label;
}
uiElementContainer.Recalculate();
var textBlocks = new List<GUITextBlock>();
foreach (GUIComponent element in uiElementContainer.Children)
@@ -258,14 +279,40 @@ namespace Barotrauma.Items.Components
GUITextBlock.AutoScaleAndNormalize(textBlocks);
}
partial void UpdateSignalsProjSpecific()
{
for (int i = 0; i < signals.Length && i < uiElements.Count; i++)
{
if (uiElements[i] is GUITextBox tb)
{
tb.Text = customInterfaceElementList[i].Signal;
}
else if (uiElements[i] is GUINumberInput ni)
{
if (ni.InputType == GUINumberInput.NumberType.Int)
{
int.TryParse(customInterfaceElementList[i].Signal, out int value);
ni.IntValue = value;
}
}
}
}
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
{
//extradata contains an array of buttons clicked by the player (or nothing if the player didn't click anything)
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
if (customInterfaceElementList[i].HasPropertyName)
{
msg.Write(((GUITextBox)uiElements[i]).Text);
if (!customInterfaceElementList[i].IsIntegerInput)
{
msg.Write(((GUITextBox)uiElements[i]).Text);
}
else
{
msg.Write(((GUINumberInput)uiElements[i]).IntValue.ToString());
}
}
else if (customInterfaceElementList[i].ContinuousSignal)
{
@@ -282,9 +329,17 @@ namespace Barotrauma.Items.Components
{
for (int i = 0; i < customInterfaceElementList.Count; i++)
{
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
if (customInterfaceElementList[i].HasPropertyName)
{
TextChanged(customInterfaceElementList[i], msg.ReadString());
if (!customInterfaceElementList[i].IsIntegerInput)
{
TextChanged(customInterfaceElementList[i], msg.ReadString());
}
else
{
int.TryParse(msg.ReadString(), out int value);
ValueChanged(customInterfaceElementList[i], value);
}
}
else
{
@@ -300,6 +355,8 @@ namespace Barotrauma.Items.Components
}
}
}
UpdateSignalsProjSpecific();
}
}
}
@@ -214,7 +214,10 @@ namespace Barotrauma.Items.Components
roundedGridPos += item.Submarine.Position;
}
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.7f);
if (!SubEditorScreen.IsSubEditor() || !SubEditorScreen.ShouldDrawGrid)
{
Submarine.DrawGrid(spriteBatch, 14, gridPos, roundedGridPos, alpha: 0.25f);
}
WireSection.Draw(
spriteBatch, this,
@@ -286,10 +289,8 @@ namespace Barotrauma.Items.Components
public static void UpdateEditing(List<Wire> wires)
{
var doubleClicked = PlayerInput.DoubleClicked();
Wire equippedWire =
Character.Controlled?.SelectedItems[0]?.GetComponent<Wire>() ??
Character.Controlled?.SelectedItems[1]?.GetComponent<Wire>();
Wire equippedWire = Character.Controlled.HeldItems.FirstOrDefault(it => it.GetComponent<Wire>() != null)?.GetComponent<Wire>();
if (equippedWire != null && GUI.MouseOn == null)
{
if (PlayerInput.PrimaryMouseButtonClicked() && Character.Controlled.SelectedConstruction == null)
@@ -329,6 +330,9 @@ namespace Barotrauma.Items.Components
nodeWorldPos = nodeWorldPos - sub.HiddenSubPosition - sub.Position;
}
if (selectedNodeIndex.HasValue && selectedNodeIndex.Value >= draggingWire.nodes.Count) { selectedNodeIndex = null; }
if (highlightedNodeIndex.HasValue && highlightedNodeIndex.Value >= draggingWire.nodes.Count) { highlightedNodeIndex = null; }
if (selectedNodeIndex.HasValue)
{
if (!PlayerInput.IsShiftDown())
@@ -342,14 +346,15 @@ namespace Barotrauma.Items.Components
}
else
{
if ((highlightedNodeIndex.HasValue && Vector2.DistanceSquared(nodeWorldPos, draggingWire.nodes[(int)highlightedNodeIndex]) > Submarine.GridSize.X * Submarine.GridSize.X) ||
float dragDistance = Submarine.GridSize.X * Submarine.GridSize.Y;
dragDistance *= 0.5f;
if ((highlightedNodeIndex.HasValue && Vector2.DistanceSquared(nodeWorldPos, draggingWire.nodes[(int)highlightedNodeIndex]) >= dragDistance) ||
PlayerInput.IsShiftDown())
{
selectedNodeIndex = highlightedNodeIndex;
}
}
MapEntity.SelectEntity(draggingWire.item);
}
@@ -396,6 +401,13 @@ namespace Barotrauma.Items.Components
if (closestIndex > -1)
{
highlightedNodeIndex = closestIndex;
Vector2 nudge = MapEntity.GetNudgeAmount(doHold: false);
if (nudge != Vector2.Zero && closestIndex < selectedWire.nodes.Count)
{
selectedWire.MoveNode(closestIndex, nudge);
}
//start dragging the node
if (PlayerInput.PrimaryMouseButtonHeld())
{
@@ -148,20 +148,20 @@ namespace Barotrauma.Items.Components
List<string> texts = new List<string>();
List<Color> textColors = new List<Color>();
if (target.Info != null)
{
texts.Add(target.Name);
textColors.Add(GUI.Style.TextColor);
}
texts.Add(target.Info == null ? target.DisplayName : target.Info.DisplayName);
textColors.Add(GUI.Style.TextColor);
if (target.IsDead)
{
texts.Add(TextManager.Get("Deceased"));
textColors.Add(GUI.Style.Red);
texts.Add(
target.CauseOfDeath.Affliction?.CauseOfDeathDescription ??
TextManager.AddPunctuation(':', TextManager.Get("CauseOfDeath"), TextManager.Get("CauseOfDeath." + target.CauseOfDeath.Type.ToString())));
textColors.Add(GUI.Style.Red);
if (target.CauseOfDeath != null)
{
texts.Add(
target.CauseOfDeath.Affliction?.CauseOfDeathDescription ??
TextManager.AddPunctuation(':', TextManager.Get("CauseOfDeath"), TextManager.Get("CauseOfDeath." + target.CauseOfDeath.Type.ToString())));
textColors.Add(GUI.Style.Red);
}
}
else
{
@@ -170,6 +170,21 @@ namespace Barotrauma.Items.Components
texts.Add(target.customInteractHUDText);
textColors.Add(GUI.Style.Green);
}
if (!target.IsIncapacitated && target.IsPet)
{
texts.Add(CharacterHUD.GetCachedHudText("PlayHint", GameMain.Config.KeyBindText(InputType.Use)));
textColors.Add(GUI.Style.Green);
}
if (target.CharacterHealth.UseHealthWindow && equipper?.FocusedCharacter == target && equipper.CanInteractWith(target, 160f, false))
{
texts.Add(CharacterHUD.GetCachedHudText("HealHint", GameMain.Config.KeyBindText(InputType.Health)));
textColors.Add(GUI.Style.Green);
}
if (target.CanBeDragged)
{
texts.Add(CharacterHUD.GetCachedHudText("GrabHint", GameMain.Config.KeyBindText(InputType.Grab)));
textColors.Add(GUI.Style.Green);
}
if (target.IsUnconscious)
{
@@ -181,7 +196,7 @@ namespace Barotrauma.Items.Components
texts.Add(TextManager.Get("Stunned"));
textColors.Add(GUI.Style.Orange);
}
int oxygenTextIndex = MathHelper.Clamp((int)Math.Floor((1.0f - (target.Oxygen / 100.0f)) * OxygenTexts.Length), 0, OxygenTexts.Length - 1);
texts.Add(OxygenTexts[oxygenTextIndex]);
textColors.Add(Color.Lerp(GUI.Style.Red, GUI.Style.Green, target.Oxygen / 100.0f));
@@ -181,14 +181,14 @@ namespace Barotrauma.Items.Components
{
if (moveSoundChannel == null && startMoveSound != null)
{
moveSoundChannel = SoundPlayer.PlaySound(startMoveSound.Sound, item.WorldPosition, startMoveSound.Volume, startMoveSound.Range);
moveSoundChannel = SoundPlayer.PlaySound(startMoveSound.Sound, item.WorldPosition, startMoveSound.Volume, startMoveSound.Range, ignoreMuffling: startMoveSound.IgnoreMuffling);
}
else if (moveSoundChannel == null || !moveSoundChannel.IsPlaying)
{
if (moveSound != null)
{
moveSoundChannel.FadeOutAndDispose();
moveSoundChannel = SoundPlayer.PlaySound(moveSound.Sound, item.WorldPosition, moveSound.Volume, moveSound.Range);
moveSoundChannel = SoundPlayer.PlaySound(moveSound.Sound, item.WorldPosition, moveSound.Volume, moveSound.Range, ignoreMuffling: moveSound.IgnoreMuffling);
if (moveSoundChannel != null) moveSoundChannel.Looping = true;
}
}
@@ -200,7 +200,7 @@ namespace Barotrauma.Items.Components
if (endMoveSound != null && moveSoundChannel.Sound != endMoveSound.Sound)
{
moveSoundChannel.FadeOutAndDispose();
moveSoundChannel = SoundPlayer.PlaySound(endMoveSound.Sound, item.WorldPosition, endMoveSound.Volume, endMoveSound.Range);
moveSoundChannel = SoundPlayer.PlaySound(endMoveSound.Sound, item.WorldPosition, endMoveSound.Volume, endMoveSound.Range, ignoreMuffling: endMoveSound.IgnoreMuffling);
if (moveSoundChannel != null) moveSoundChannel.Looping = false;
}
else if (!moveSoundChannel.IsPlaying)
@@ -286,40 +286,26 @@ namespace Barotrauma.Items.Components
rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
if (!GameMain.DebugDraw && (!editing || GUI.DisableHUD || !item.IsSelected)) { return; }
if (!editing || GUI.DisableHUD || !item.IsSelected) { return; }
const float widgetRadius = 60.0f;
Vector2 center = new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2));
GUI.DrawLine(spriteBatch,
drawPos,
drawPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * widgetRadius,
drawPos + center * widgetRadius,
Color.LightGreen);
if (GameMain.DebugDraw)
{
center = new Vector2((float)Math.Cos(targetRotation), (float)Math.Sin(targetRotation));
GUI.DrawLine(spriteBatch,
drawPos,
drawPos + center * widgetRadius,
Color.Red);
for (int i = 0; i < 5; i++)
{
center = new Vector2((float)Math.Cos(rotation + (angularVelocity * 0.05f * i)), (float)Math.Sin(rotation + (angularVelocity * 0.05f * i)));
GUI.DrawLine(spriteBatch,
drawPos,
drawPos + center * widgetRadius,
Color.Lerp(Color.Black, Color.Yellow, i * 0.25f));
}
}
const float coneRadius = 300.0f;
float radians = maxRotation - minRotation;
float circleRadius = coneRadius / Screen.Selected.Cam.Zoom * GUI.Scale;
float lineThickness = 1f / Screen.Selected.Cam.Zoom;
if (radians > Math.PI * 2)
if (Math.Abs(minRotation - maxRotation) < 0.02f)
{
spriteBatch.DrawLine(drawPos, drawPos + center * circleRadius, GUI.Style.Green, thickness: lineThickness);
}
else if (radians > Math.PI * 2)
{
spriteBatch.DrawCircle(drawPos, circleRadius, 180, GUI.Style.Red, thickness: lineThickness);
}
@@ -510,13 +496,8 @@ namespace Barotrauma.Items.Components
List<Item> availableAmmo = new List<Item>();
foreach (MapEntity e in item.linkedTo)
{
var linkedItem = e as Item;
if (linkedItem == null) continue;
var itemContainer = linkedItem.GetComponent<ItemContainer>();
if (itemContainer?.Inventory?.Items == null) continue;
availableAmmo.AddRange(itemContainer.Inventory.Items);
if (!(e is Item linkedItem)) { continue; }
availableAmmo.AddRange(linkedItem.ContainedItems);
}
float chargeRate =
@@ -558,7 +539,7 @@ namespace Barotrauma.Items.Components
{
// TODO: Optimize? Creates multiple new objects per frame?
Inventory.DrawSlot(spriteBatch, null,
new InventorySlot(new Rectangle(invSlotPos + new Point((i % slotsPerRow) * (slotSize.X + spacing), (int)Math.Floor(i / (float)slotsPerRow) * (slotSize.Y + spacing)), slotSize)),
new VisualSlot(new Rectangle(invSlotPos + new Point((i % slotsPerRow) * (slotSize.X + spacing), (int)Math.Floor(i / (float)slotsPerRow) * (slotSize.Y + spacing)), slotSize)),
availableAmmo[i], -1, true);
}
if (flashNoAmmo)
File diff suppressed because it is too large Load Diff
@@ -8,6 +8,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Barotrauma.Extensions;
using Barotrauma.MapCreatures.Behavior;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
@@ -15,7 +16,7 @@ namespace Barotrauma
{
partial class Item : MapEntity, IDamageable, ISerializableEntity, IServerSerializable, IClientSerializable
{
public static bool ShowItems = true;
public static bool ShowItems = true, ShowWires = true;
private readonly List<PosInfo> positionBuffer = new List<PosInfo>();
@@ -29,6 +30,7 @@ namespace Barotrauma
private bool editingHUDRefreshPending;
private float editingHUDRefreshTimer;
private ContainedItemSprite activeContainedSprite;
private readonly Dictionary<DecorativeSprite, DecorativeSprite.State> spriteAnimState = new Dictionary<DecorativeSprite, DecorativeSprite.State>();
@@ -103,13 +105,10 @@ namespace Barotrauma
Color color = spriteColor;
if (Prefab.UseContainedSpriteColor && ownInventory != null)
{
for (int i = 0; i < ownInventory.Items.Length; i++)
foreach (Item item in ContainedItems)
{
if (ownInventory.Items[i] != null)
{
color = ownInventory.Items[i].ContainerColor;
break;
}
color = item.ContainerColor;
break;
}
}
return color;
@@ -120,13 +119,10 @@ namespace Barotrauma
Color color = InventoryIconColor;
if (Prefab.UseContainedInventoryIconColor && ownInventory != null)
{
for (int i = 0; i < ownInventory.Items.Length; i++)
foreach (Item item in ContainedItems)
{
if (ownInventory.Items[i] != null)
{
color = ownInventory.Items[i].ContainerColor;
break;
}
color = item.ContainerColor;
break;
}
}
return color;
@@ -135,6 +131,7 @@ namespace Barotrauma
partial void SetActiveSpriteProjSpecific()
{
activeSprite = prefab.sprite;
activeContainedSprite = null;
Holdable holdable = GetComponent<Holdable>();
if (holdable != null && holdable.Attached)
{
@@ -142,7 +139,9 @@ namespace Barotrauma
{
if (containedSprite.UseWhenAttached)
{
activeSprite = containedSprite.Sprite;
activeContainedSprite = containedSprite;
activeSprite = containedSprite.Sprite;
UpdateSpriteStates(0.0f);
return;
}
}
@@ -154,7 +153,9 @@ namespace Barotrauma
{
if (containedSprite.MatchesContainer(Container))
{
activeContainedSprite = containedSprite;
activeSprite = containedSprite.Sprite;
UpdateSpriteStates(0.0f);
return;
}
}
@@ -187,6 +188,7 @@ namespace Barotrauma
decorativeSprite.Sprite.EnsureLazyLoaded();
spriteAnimState.Add(decorativeSprite, new DecorativeSprite.State());
}
SetActiveSprite();
UpdateSpriteStates(0.0f);
}
@@ -240,7 +242,15 @@ namespace Barotrauma
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!Visible || (!editing && HiddenInGame)) { return; }
if (editing && !ShowItems) { return; }
if (editing)
{
if (isWire)
{
if (!ShowWires) { return; }
}
else if (!ShowItems) { return; }
}
Color color = IsHighlighted && !GUI.DisableItemHighlights && Screen.Selected != GameMain.GameScreen ? GUI.Style.Orange : GetSpriteColor();
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
@@ -305,7 +315,7 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
decorativeSprite.Sprite.DrawTiled(spriteBatch,
@@ -328,7 +338,7 @@ namespace Barotrauma
}
activeSprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, origin, rotationRad, Scale, activeSprite.effects, depth);
fadeInBrokenSprite?.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + fadeInBrokenSprite.Offset.ToVector2() * Scale, color * fadeInBrokenSpriteAlpha, origin, rotationRad, Scale, activeSprite.effects, depth - 0.000001f);
if (Infector != null && Infector.ParentBallastFlora.HasBrokenThrough)
if (Infector != null && (Infector.ParentBallastFlora.HasBrokenThrough || BallastFloraBehavior.AlwaysShowBallastFloraSprite))
{
Prefab.InfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, color, Prefab.InfectedSprite.Origin, rotationRad, Scale, activeSprite.effects, depth - 0.001f);
Prefab.DamagedInfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, Infector.HealthColor, Prefab.DamagedInfectedSprite.Origin, rotationRad, Scale, activeSprite.effects, depth - 0.002f);
@@ -336,12 +346,12 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
float rot = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
rotationRad + rot, decorativeSprite.Scale * Scale, activeSprite.effects,
rotationRad + rot, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth), 0.999f));
}
}
@@ -353,7 +363,7 @@ namespace Barotrauma
{
if (!back) { return; }
float depthStep = 0.000001f;
if (holdable.Picker.SelectedItems[0] == this)
if (holdable.Picker.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == this)
{
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightHand);
if (holdLimb?.ActiveSprite != null)
@@ -365,7 +375,7 @@ namespace Barotrauma
}
}
}
else if (holdable.Picker.SelectedItems[1] == this)
else if (holdable.Picker.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == this)
{
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftHand);
if (holdLimb?.ActiveSprite != null)
@@ -384,8 +394,8 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
var ca = (float)Math.Cos(-body.Rotation);
@@ -393,7 +403,7 @@ namespace Barotrauma
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + transformedOffset.X, -(DrawPosition.Y + transformedOffset.Y)), color,
-body.Rotation + rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
-body.Rotation + rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
}
}
@@ -405,12 +415,12 @@ namespace Barotrauma
foreach (var decorativeSprite in upgradeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, -rotationRad) * Scale;
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier, -rotationRad) * Scale;
if (flippedX && Prefab.CanSpriteFlipX) { offset.X = -offset.X; }
if (flippedY && Prefab.CanSpriteFlipY) { offset.Y = -offset.Y; }
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
rotation, decorativeSprite.Scale * Scale, activeSprite.effects,
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, activeSprite.effects,
depth: depth + (decorativeSprite.Sprite.Depth - activeSprite.Depth));
}
@@ -505,12 +515,39 @@ namespace Barotrauma
public void UpdateSpriteStates(float deltaTime)
{
DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches);
if (activeContainedSprite != null)
{
if (activeContainedSprite.DecorativeSpriteBehavior == ContainedItemSprite.DecorativeSpriteBehaviorType.HideWhenVisible)
{
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
{
var spriteState = spriteAnimState[decorativeSprite];
spriteState.IsActive = false;
}
return;
}
}
else
{
foreach (var containedSprite in Prefab.ContainedSprites)
{
if (containedSprite.Sprite != activeSprite && containedSprite.DecorativeSpriteBehavior == ContainedItemSprite.DecorativeSpriteBehaviorType.HideWhenNotVisible)
{
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
{
var spriteState = spriteAnimState[decorativeSprite];
spriteState.IsActive = false;
}
return;
}
}
}
DecorativeSprite.UpdateSpriteStates(Prefab.DecorativeSpriteGroups, spriteAnimState, ID, deltaTime, ConditionalMatches);
foreach (var upgrade in Upgrades)
{
var upgradeSprites = GetUpgradeSprites(upgrade);
var upgradeSprites = GetUpgradeSprites(upgrade);
foreach (var decorativeSprite in upgradeSprites)
{
var spriteState = spriteAnimState[decorativeSprite];
@@ -1035,6 +1072,28 @@ namespace Barotrauma
// Always create the texts if they have not yet been created
if (texts.Any() && !recreateHudTexts) { return texts; }
texts.Clear();
string nameText = Name;
if (Prefab.Identifier == "idcard" || Tags.Contains("despawncontainer"))
{
string[] readTags = Tags.Split(',');
string idName = null;
foreach (string tag in readTags)
{
string[] s = tag.Split(':');
if (s[0] == "name")
{
idName = s[1];
break;
}
}
if (idName != null)
{
nameText += $" ({idName})";
}
}
texts.Add(new ColoredText(nameText, GUI.Style.TextColor, false, false));
foreach (ItemComponent ic in components)
{
if (string.IsNullOrEmpty(ic.DisplayMsg)) { continue; }
@@ -1259,7 +1318,7 @@ namespace Barotrauma
{
if (GameMain.Client == null) { return; }
if (parentInventory != null || body == null || !body.Enabled || Removed)
if (parentInventory != null || body == null || !body.Enabled || Removed || (GetComponent<Projectile>()?.IsStuckToTarget ?? false))
{
positionBuffer.Clear();
return;
@@ -1267,12 +1326,7 @@ namespace Barotrauma
isActive = true;
Vector2 newVelocity = body.LinearVelocity;
Vector2 newPosition = body.SimPosition;
float newAngularVelocity = body.AngularVelocity;
float newRotation = body.Rotation;
body.CorrectPosition(positionBuffer, out newPosition, out newVelocity, out newRotation, out newAngularVelocity);
body.CorrectPosition(positionBuffer, out Vector2 newPosition, out Vector2 newVelocity, out float newRotation, out float newAngularVelocity);
body.LinearVelocity = newVelocity;
body.AngularVelocity = newAngularVelocity;
if (Vector2.DistanceSquared(newPosition, body.SimPosition) > 0.0001f ||
@@ -1490,7 +1544,7 @@ namespace Barotrauma
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
{
wifiComponent.TeamID = (Character.TeamType)teamID;
wifiComponent.TeamID = (CharacterTeamType)teamID;
}
if (descriptionChanged) { item.Description = itemDesc; }
if (tagsChanged) { item.Tags = tags; }
@@ -1521,10 +1575,10 @@ namespace Barotrauma
partial void RemoveProjSpecific()
{
if (Inventory.draggingItem == this)
if (Inventory.DraggingItems.Contains(this))
{
Inventory.draggingItem = null;
Inventory.draggingSlot = null;
Inventory.DraggingItems.Clear();
Inventory.DraggingSlot = null;
}
}
}
@@ -24,14 +24,14 @@ namespace Barotrauma
protected override void CalculateBackgroundFrame()
{
var firstSlot = slots.FirstOrDefault();
var firstSlot = visualSlots.FirstOrDefault();
if (firstSlot == null) { return; }
Rectangle frame = firstSlot.Rect;
frame.Location += firstSlot.DrawOffset.ToPoint();
for (int i = 1; i < capacity; i++)
{
Rectangle slotRect = slots[i].Rect;
slotRect.Location += slots[i].DrawOffset.ToPoint();
Rectangle slotRect = visualSlots[i].Rect;
slotRect.Location += visualSlots[i].DrawOffset.ToPoint();
frame = Rectangle.Union(frame, slotRect);
}
BackgroundFrame = new Rectangle(
@@ -43,7 +43,7 @@ namespace Barotrauma
public override void Draw(SpriteBatch spriteBatch, bool subInventory = false)
{
if (slots != null && slots.Length > 0)
if (visualSlots != null && visualSlots.Length > 0)
{
CalculateBackgroundFrame();
if (container.InventoryBackSprite == null)
@@ -70,7 +70,7 @@ namespace Barotrauma
if (container.InventoryBottomSprite != null && !subInventory)
{
container.InventoryBottomSprite.Draw(spriteBatch,
new Vector2(BackgroundFrame.Center.X, BackgroundFrame.Bottom) + slots[0].DrawOffset,
new Vector2(BackgroundFrame.Center.X, BackgroundFrame.Bottom) + visualSlots[0].DrawOffset,
0.0f, UIScale);
}
@@ -27,8 +27,14 @@ namespace Barotrauma
class ContainedItemSprite
{
public enum DecorativeSpriteBehaviorType
{
None, HideWhenVisible, HideWhenNotVisible
}
public readonly Sprite Sprite;
public readonly bool UseWhenAttached;
public readonly DecorativeSpriteBehaviorType DecorativeSpriteBehavior;
public readonly string[] AllowedContainerIdentifiers;
public readonly string[] AllowedContainerTags;
@@ -36,6 +42,7 @@ namespace Barotrauma
{
Sprite = new Sprite(element, path, lazyLoad: lazyLoad);
UseWhenAttached = element.GetAttributeBool("usewhenattached", false);
Enum.TryParse(element.GetAttributeString("decorativespritebehavior", "None"), ignoreCase: true, out DecorativeSpriteBehavior);
AllowedContainerIdentifiers = element.GetAttributeStringArray("allowedcontaineridentifiers", new string[0], convertToLowerInvariant: true);
AllowedContainerTags = element.GetAttributeStringArray("allowedcontainertags", new string[0], convertToLowerInvariant: true);
}