165 lines
5.7 KiB
C#
165 lines
5.7 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using System.Collections.Generic;
|
|
|
|
/// <summary>
|
|
/// Interaction requirement that allows slotting, swapping, or picking up items in a slot.
|
|
/// </summary>
|
|
[RequireComponent(typeof(Interactable))]
|
|
[RequireComponent(typeof(Pickup))]
|
|
public class SlotItemBehavior : InteractionRequirementBase
|
|
{
|
|
[Header("Slot State")]
|
|
/// <summary>
|
|
/// The item currently slotted in this slot.
|
|
/// </summary>
|
|
public PickupItemData currentlySlottedItem;
|
|
/// <summary>
|
|
/// The renderer for the slotted item's sprite.
|
|
/// </summary>
|
|
public SpriteRenderer slottedItemRenderer;
|
|
|
|
private GameObject _cachedSlottedObject = null;
|
|
|
|
// Helper for slotting an object, with option to skip destruction (for swap)
|
|
private void SetSlottedObject(GameObject obj)
|
|
{
|
|
_cachedSlottedObject = obj;
|
|
if (_cachedSlottedObject != null)
|
|
{
|
|
_cachedSlottedObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
private void RemoveSlottedObject()
|
|
{
|
|
if (_cachedSlottedObject != null)
|
|
{
|
|
Destroy(_cachedSlottedObject);
|
|
_cachedSlottedObject = null;
|
|
}
|
|
}
|
|
|
|
private void CacheSlottedObject(GameObject obj)
|
|
{
|
|
// Only destroy if not swapping
|
|
RemoveSlottedObject();
|
|
SetSlottedObject(obj);
|
|
}
|
|
|
|
private void RestoreSlottedObject(Vector3 position)
|
|
{
|
|
if (_cachedSlottedObject != null)
|
|
{
|
|
_cachedSlottedObject.transform.position = position;
|
|
_cachedSlottedObject.transform.SetParent(null);
|
|
_cachedSlottedObject.SetActive(true);
|
|
_cachedSlottedObject = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts to interact with the slot, handling slotting, swapping, or picking up items.
|
|
/// </summary>
|
|
/// <param name="follower">The follower attempting the interaction.</param>
|
|
/// <returns>True if the interaction was successful, false otherwise.</returns>
|
|
public override bool TryInteract(FollowerController follower)
|
|
{
|
|
var heldItem = follower.CurrentlyHeldItem;
|
|
var heldObj = follower.GetHeldPickupObject();
|
|
var pickup = GetComponent<Pickup>();
|
|
var slotItem = pickup != null ? pickup.itemData : null;
|
|
var config = GameManager.Instance.GetSlotItemConfig(slotItem);
|
|
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
|
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
|
|
|
|
// CASE 1: No held item, slot has item -> pick up slotted item
|
|
if (heldItem == null && _cachedSlottedObject != null)
|
|
{
|
|
follower.SetHeldItemFromObject(_cachedSlottedObject);
|
|
RemoveSlottedObject();
|
|
currentlySlottedItem = null;
|
|
UpdateSlottedSprite();
|
|
return true;
|
|
}
|
|
// CASE 2: Held item, slot has item -> swap
|
|
if (heldItem != null && _cachedSlottedObject != null)
|
|
{
|
|
var followerHeldObj = heldObj;
|
|
var followerHeldItem = heldItem;
|
|
var slotObj = _cachedSlottedObject;
|
|
var slotItemData = currentlySlottedItem;
|
|
|
|
// 1. Slot the follower's held object (do NOT destroy the old one)
|
|
SetSlottedObject(followerHeldObj);
|
|
currentlySlottedItem = followerHeldItem;
|
|
UpdateSlottedSprite();
|
|
|
|
// 2. Give the slot's object to the follower
|
|
follower.SetHeldItemFromObject(slotObj);
|
|
|
|
return true;
|
|
}
|
|
// CASE 3: Held item, slot empty -> slot the held item
|
|
if (heldItem != null && _cachedSlottedObject == null)
|
|
{
|
|
if (forbidden.Contains(heldItem))
|
|
{
|
|
DebugUIMessage.Show("Can't place that here.");
|
|
return false;
|
|
}
|
|
CacheSlottedObject(heldObj);
|
|
currentlySlottedItem = heldItem;
|
|
UpdateSlottedSprite();
|
|
follower.ClearHeldItem();
|
|
if (allowed.Contains(heldItem))
|
|
{
|
|
OnSuccess?.Invoke();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
DebugUIMessage.Show("I'm not sure this works.");
|
|
OnFailure?.Invoke();
|
|
return true;
|
|
}
|
|
}
|
|
// CASE 4: No held item, slot empty -> show warning
|
|
if (heldItem == null && _cachedSlottedObject == null)
|
|
{
|
|
DebugUIMessage.Show("This requires an item.");
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the sprite and scale for the currently slotted item.
|
|
/// </summary>
|
|
private void UpdateSlottedSprite()
|
|
{
|
|
if (slottedItemRenderer != null && currentlySlottedItem != null && currentlySlottedItem.mapSprite != null)
|
|
{
|
|
slottedItemRenderer.sprite = currentlySlottedItem.mapSprite;
|
|
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
|
|
float desiredHeight = GameManager.Instance.HeldIconDisplayHeight;
|
|
var sprite = currentlySlottedItem.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;
|
|
}
|
|
}
|
|
}
|