using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; namespace Interactions { /// /// Interaction requirement that allows slotting, swapping, or picking up items in a slot. /// [RequireComponent(typeof(Interactable))] public class ItemSlot : Pickup { public UnityEvent onItemSlotted; public UnityEvent onItemSlotRemoved; public UnityEvent onCorrectItemSlotted; public UnityEvent onIncorrectItemSlotted; public UnityEvent onForbiddenItemSlotted; private PickupItemData _currentlySlottedItemData; public SpriteRenderer slottedItemRenderer; private GameObject _currentlySlottedItemObject = null; public GameObject GetSlottedObject() { return _currentlySlottedItemObject; } public void SetSlottedObject(GameObject obj) { _currentlySlottedItemObject = obj; if (_currentlySlottedItemObject != null) { _currentlySlottedItemObject.SetActive(false); } } protected override void OnCharacterArrived() { var heldItemData = FollowerController.CurrentlyHeldItemData; var heldItemObj = FollowerController.GetHeldPickupObject(); var config = GameManager.Instance.GetSlotItemConfig(itemData); var forbidden = config?.forbiddenItems ?? new List(); // Held item, slot empty -> try to slot item if (heldItemData != null && _currentlySlottedItemObject == null) { // First check for forbidden items at the very start so we don't continue unnecessarily if (PickupItemData.ListContainsEquivalent(forbidden, heldItemData)) { DebugUIMessage.Show("Can't place that here.", Color.red); onForbiddenItemSlotted?.Invoke(); Interactable.BroadcastInteractionComplete(false); return; } SlotItem(heldItemObj, heldItemData, true); return; } // Either pickup or swap items if ((heldItemData == null && _currentlySlottedItemObject != null) || (heldItemData != null && _currentlySlottedItemObject != null)) { FollowerController.TryPickupItem(_currentlySlottedItemObject, _currentlySlottedItemData, false); onItemSlotRemoved?.Invoke(); SlotItem(heldItemObj, heldItemData, _currentlySlottedItemObject == null); return; } // No held item, slot empty -> show warning if (heldItemData == null && _currentlySlottedItemObject == null) { DebugUIMessage.Show("This requires an item.", Color.red); return; } } /// /// Updates the sprite and scale for the currently slotted item. /// private void UpdateSlottedSprite() { if (slottedItemRenderer != null && _currentlySlottedItemData != null && _currentlySlottedItemData.mapSprite != null) { slottedItemRenderer.sprite = _currentlySlottedItemData.mapSprite; // Scale sprite to desired height, preserve aspect ratio, compensate for parent scale float desiredHeight = GameManager.Instance.HeldIconDisplayHeight; var sprite = _currentlySlottedItemData.mapSprite; float spriteHeight = sprite.bounds.size.y; float spriteWidth = sprite.bounds.size.x; Vector3 parentScale = slottedItemRenderer.transform.parent != null ? slottedItemRenderer.transform.parent.localScale : Vector3.one; if (spriteHeight > 0f) { float uniformScale = desiredHeight / spriteHeight; float scale = uniformScale / Mathf.Max(parentScale.x, parentScale.y); slottedItemRenderer.transform.localScale = new Vector3(scale, scale, 1f); } } else if (slottedItemRenderer != null) { slottedItemRenderer.sprite = null; } } public void SlotItem(GameObject itemToSlot, PickupItemData itemToSlotData, bool clearFollowerHeldItem = true) { if (itemToSlot == null) { _currentlySlottedItemObject = null; _currentlySlottedItemData = null; } else { itemToSlot.SetActive(false); itemToSlot.transform.SetParent(null); SetSlottedObject(itemToSlot); _currentlySlottedItemData = itemToSlotData; } if (clearFollowerHeldItem) { FollowerController.ClearHeldItem(); } UpdateSlottedSprite(); // Once an item is slotted, we know it is not forbidden, so we can skip that check, but now check if it was // the correct item we're looking for var config = GameManager.Instance.GetSlotItemConfig(itemData); var allowed = config?.allowedItems ?? new List(); if (PickupItemData.ListContainsEquivalent(allowed, itemToSlotData)) { if (itemToSlot != null) { DebugUIMessage.Show("You correctly slotted " + itemToSlotData.itemName + " into: " + itemData.itemName, Color.green); onCorrectItemSlotted?.Invoke(); } Interactable.BroadcastInteractionComplete(true); } else { if (itemToSlot != null) { DebugUIMessage.Show("I'm not sure this works.", Color.yellow); onIncorrectItemSlotted?.Invoke(); } Interactable.BroadcastInteractionComplete(false); } } } }