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 pickup = GetComponent(); var slotItem = pickup != null ? pickup.itemData : null; var config = GameManager.Instance.GetSlotItemConfig(slotItem); var allowed = config?.allowedItems ?? new List(); var forbidden = config?.forbiddenItems ?? new List(); if ((heldItemData == null && _currentlySlottedItemObject != null) || (heldItemData != null && _currentlySlottedItemObject != null)) { FollowerController.TryPickupItem(_currentlySlottedItemObject, _currentlySlottedItemData); _currentlySlottedItemObject = null; _currentlySlottedItemData = null; onItemSlotRemoved?.Invoke(); UpdateSlottedSprite(); return; } // // CASE 1: No held item, slot has item -> pick up slotted item // if (heldItemData == null && _cachedSlottedObject != null) // { // InteractionOrchestrator.Instance.PickupItem(FollowerController, _cachedSlottedObject); // _cachedSlottedObject = null; // currentlySlottedItem = null; // UpdateSlottedSprite(); // Interactable.BroadcastInteractionComplete(false); // return; // } // // CASE 2: Held item, slot has item -> swap // if // { // InteractionOrchestrator.Instance.SwapItems(FollowerController, this); // currentlySlottedItem = heldItemData; // UpdateSlottedSprite(); // return; // } // CASE 3: Held item, slot empty -> slot the held item if (heldItemData != null && _currentlySlottedItemObject == null) { if (forbidden.Contains(heldItemData)) { DebugUIMessage.Show("Can't place that here."); onForbiddenItemSlotted?.Invoke(); Interactable.BroadcastInteractionComplete(false); return; } SlotItem(heldItemObj, heldItemData); if (allowed.Contains(heldItemData)) { onCorrectItemSlotted?.Invoke(); Interactable.BroadcastInteractionComplete(true); return; } else { DebugUIMessage.Show("I'm not sure this works."); onIncorrectItemSlotted?.Invoke(); Interactable.BroadcastInteractionComplete(false); return; } } // CASE 4: No held item, slot empty -> show warning if (heldItemData == null && _currentlySlottedItemObject == null) { DebugUIMessage.Show("This requires an item."); return; } 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) { if (itemToSlot == null) return; itemToSlot.SetActive(false); itemToSlot.transform.SetParent(null); SetSlottedObject(itemToSlot); _currentlySlottedItemData = itemToSlotData; UpdateSlottedSprite(); FollowerController.ClearHeldItem(); } } }