diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index 615423b53..87d29a9e2 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -327,6 +327,8 @@ namespace Barotrauma debugInteractablesAtCursor.Clear(); debugInteractablesNearCursor.Clear(); + bool draggingItemToWorld = CharacterInventory.DraggingItemToWorld; + //reduce the amount of aim assist if an item has been selected //= can't switch selection to another item without deselecting the current one first UNLESS the cursor is directly on the item //otherwise it would be too easy to accidentally switch the selected item when rewiring items @@ -348,6 +350,15 @@ namespace Barotrauma if (item.body != null && !item.body.Enabled) continue; if (item.ParentInventory != null) continue; if (ignoredItems != null && ignoredItems.Contains(item)) continue; + + if (draggingItemToWorld) + { + if (item.OwnInventory == null || + !item.OwnInventory.CanBePut(CharacterInventory.draggingItem)) + { + continue; + } + } float distanceToItem = float.PositiveInfinity; if (item.IsInsideTrigger(displayPosition, out Rectangle transformedTrigger)) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index fd0af8cf0..a2137e660 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -248,7 +248,7 @@ namespace Barotrauma scale: scale); } - if (!GUI.DisableItemHighlights) + if (!GUI.DisableItemHighlights && !Inventory.DraggingItemToWorld) { var hudTexts = focusedItem.GetHUDTexts(character); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs index 44c39061f..7944ddf9d 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs @@ -1,4 +1,5 @@ -using Barotrauma.Items.Components; +using Barotrauma.Extensions; +using Barotrauma.Items.Components; using Barotrauma.Networking; using Lidgren.Network; using Microsoft.Xna.Framework; @@ -165,6 +166,16 @@ namespace Barotrauma public static InventorySlot draggingSlot; public static Item draggingItem; + public static bool DraggingItemToWorld + { + get + { + return draggingItem != null && + Character.Controlled != null && + Character.Controlled.SelectedConstruction == null && + CharacterHealth.OpenHealthWindow == null; + } + } public static Item doubleClickedItem; @@ -290,7 +301,7 @@ namespace Barotrauma protected virtual void ControlInput(Camera cam) { // Note that these targets are static. Therefore the outcome is the same if this method is called multiple times or only once. - if (selectedSlot != null || draggingItem != null) + if (selectedSlot != null && !DraggingItemToWorld) { cam.Freeze = true; } @@ -598,8 +609,17 @@ namespace Barotrauma if (selectedSlot == null) { - draggingItem.Drop(Character.Controlled); - GUI.PlayUISound(GUISoundType.DropItem); + if (DraggingItemToWorld && + Character.Controlled.FocusedItem?.OwnInventory != null && + Character.Controlled.FocusedItem.OwnInventory.TryPutItem(draggingItem, Character.Controlled)) + { + GUI.PlayUISound(GUISoundType.PickItem); + } + else + { + GUI.PlayUISound(GUISoundType.DropItem); + draggingItem.Drop(Character.Controlled); + } } else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem) { @@ -691,10 +711,27 @@ namespace Barotrauma int iconSize = (int)(64 * GUI.Scale); float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f); Vector2 itemPos = PlayerInput.MousePosition; + + if (GUI.MouseOn == null && selectedSlot == null) + { + var shadowSprite = GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0]; + string toolTip = Character.Controlled.FocusedItem != null ? + TextManager.Get("PutItemIn").Replace("[itemname]", Character.Controlled.FocusedItem.Name) : + TextManager.Get("DropItem"); + int textWidth = (int)Math.Max(GUI.Font.MeasureString(draggingItem.Name).X, GUI.SmallFont.MeasureString(toolTip).X); + int textSpacing = (int)(15 * GUI.Scale); + Point shadowBorders = (new Point(40, 10)).Multiply(GUI.Scale); + shadowSprite.Draw(spriteBatch, + new Rectangle(itemPos.ToPoint() - new Point(iconSize / 2) - shadowBorders, new Point(iconSize + textWidth + textSpacing, iconSize) + shadowBorders.Multiply(2)), Color.Black * 0.8f); + GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y - iconSize / 2), draggingItem.Name, Color.White); + GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y), toolTip, + color: Character.Controlled.FocusedItem == null ? Color.Red : Color.LightGreen, + font: GUI.SmallFont); + } sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black, scale: scale); - sprite.Draw(spriteBatch, - itemPos, - sprite == draggingItem.Sprite ? draggingItem.GetSpriteColor() : draggingItem.GetInventoryIconColor(), + sprite.Draw(spriteBatch, + itemPos, + sprite == draggingItem.Sprite ? draggingItem.GetSpriteColor() : draggingItem.GetInventoryIconColor(), scale: scale); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index c45253b0b..adcdb54ac 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1652,7 +1652,8 @@ namespace Barotrauma #if CLIENT if (isLocalPlayer) { - if (GUI.MouseOn == null && !CharacterInventory.IsMouseOnInventory()) + if (GUI.MouseOn == null && + (!CharacterInventory.IsMouseOnInventory() || CharacterInventory.DraggingItemToWorld)) { if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs b/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs index 563a2dcb7..678582ed2 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Inventory.cs @@ -88,10 +88,19 @@ namespace Barotrauma { if (Items[i] == null) return i; } - + return -1; } + public bool CanBePut(Item item) + { + for (int i = 0; i < capacity; i++) + { + if (CanBePut(item, i)) { return true; } + } + return false; + } + public virtual bool CanBePut(Item item, int i) { if (ItemOwnsSelf(item)) return false; diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs index 76866dfdf..eb0ae3a08 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/ItemInventory.cs @@ -43,10 +43,9 @@ namespace Barotrauma { if (ItemOwnsSelf(item)) return false; if (i < 0 || i >= Items.Length) return false; - return (item!=null && Items[i]==null && container.CanBeContained(item)); + return (item != null && Items[i] == null && container.CanBeContained(item)); } - public override bool TryPutItem(Item item, Character user, List allowedSlots = null, bool createNetworkEvent = true) { bool wasPut = base.TryPutItem(item, user, allowedSlots, createNetworkEvent); diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs index 898506400..fdf3a8511 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs @@ -785,6 +785,39 @@ namespace Barotrauma AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList(); + if (sprite == null) + { + DebugConsole.ThrowError("Item \"" + Name + "\" has no sprite!"); +#if SERVER + sprite = new Sprite("", Vector2.Zero); + sprite.SourceRect = new Rectangle(0, 0, 32, 32); +#else + sprite = new Sprite(TextureLoader.PlaceHolderTexture, null, null) + { + Origin = TextureLoader.PlaceHolderTexture.Bounds.Size.ToVector2() / 2 + }; +#endif + size = sprite.size; + sprite.EntityID = identifier; + } + + if (!category.HasFlag(MapEntityCategory.Legacy) && string.IsNullOrEmpty(identifier)) + { + DebugConsole.ThrowError( + "Item prefab \"" + name + "\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading."); + } + if (!string.IsNullOrEmpty(identifier)) + { + MapEntityPrefab existingPrefab = List.Find(e => e.Identifier == identifier); + if (existingPrefab != null) + { + DebugConsole.ThrowError( + "Map entity prefabs \"" + name + "\" and \"" + existingPrefab.Name + "\" have the same identifier!"); + } + } + + AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList(); + List.Add(this); }