Update slot items to simplified slotting logic + reveal renderers
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Interactions;
|
using Interactions;
|
||||||
using Core.Lifecycle;
|
using Core.Lifecycle;
|
||||||
using Core.SaveLoad;
|
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
@@ -31,18 +30,10 @@ namespace Core
|
|||||||
// Broadcasts when any registered ItemSlot reports a correct item slotted
|
// Broadcasts when any registered ItemSlot reports a correct item slotted
|
||||||
// Args: slot's itemData (the slot definition), then the slotted item data
|
// Args: slot's itemData (the slot definition), then the slotted item data
|
||||||
public event Action<PickupItemData, PickupItemData> OnCorrectItemSlotted;
|
public event Action<PickupItemData, PickupItemData> OnCorrectItemSlotted;
|
||||||
|
|
||||||
// Broadcasts when any registered ItemSlot reports an incorrect item slotted
|
// Broadcasts when a wrong item is attempted (not slotted, just attempted)
|
||||||
// Args: slot's itemData (the slot definition), then the slotted item data
|
// Args: slot's itemData (the slot definition), then the attempted item data
|
||||||
public event Action<PickupItemData, PickupItemData> OnIncorrectItemSlotted;
|
public event Action<PickupItemData, PickupItemData> OnWrongItemAttempted;
|
||||||
|
|
||||||
// Broadcasts when any registered ItemSlot reports a forbidden item slotted
|
|
||||||
// Args: slot's itemData (the slot definition), then the slotted item data
|
|
||||||
public event Action<PickupItemData, PickupItemData> OnForbiddenItemSlotted;
|
|
||||||
|
|
||||||
// Broadcasts when any registered ItemSlot is cleared (item removed)
|
|
||||||
// Args: the item data that was removed
|
|
||||||
public event Action<PickupItemData> OnItemSlotCleared;
|
|
||||||
|
|
||||||
// Broadcasts when any two items are successfully combined
|
// Broadcasts when any two items are successfully combined
|
||||||
// Args: first item data, second item data, result item data
|
// Args: first item data, second item data, result item data
|
||||||
@@ -82,17 +73,11 @@ namespace Core
|
|||||||
{
|
{
|
||||||
OnCorrectItemSlotted?.Invoke(slotData, slottedItem);
|
OnCorrectItemSlotted?.Invoke(slotData, slottedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler that forwards incorrect-slot events
|
// Handler that forwards wrong-item-attempted events
|
||||||
private void ItemSlot_OnIncorrectItemSlotted(PickupItemData slotData, PickupItemData slottedItem)
|
private void ItemSlot_OnWrongItemAttempted(PickupItemData slotData, PickupItemData attemptedItem)
|
||||||
{
|
{
|
||||||
OnIncorrectItemSlotted?.Invoke(slotData, slottedItem);
|
OnWrongItemAttempted?.Invoke(slotData, attemptedItem);
|
||||||
}
|
|
||||||
|
|
||||||
// Handler that forwards forbidden-slot events
|
|
||||||
private void ItemSlot_OnForbiddenItemSlotted(PickupItemData slotData, PickupItemData slottedItem)
|
|
||||||
{
|
|
||||||
OnForbiddenItemSlotted?.Invoke(slotData, slottedItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler that forwards item combination events
|
// Handler that forwards item combination events
|
||||||
@@ -107,12 +92,6 @@ namespace Core
|
|||||||
OnItemsCombined?.Invoke(itemA, itemB, resultItem);
|
OnItemsCombined?.Invoke(itemA, itemB, resultItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler that forwards slot-removed events
|
|
||||||
private void ItemSlot_OnItemSlotRemoved(PickupItemData removedItem)
|
|
||||||
{
|
|
||||||
OnItemSlotCleared?.Invoke(removedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unsubscribe all pickup/slot event handlers and clear registries and manager events.
|
/// Unsubscribe all pickup/slot event handlers and clear registries and manager events.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -137,8 +116,7 @@ namespace Core
|
|||||||
if (s != null)
|
if (s != null)
|
||||||
{
|
{
|
||||||
s.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
s.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
||||||
s.OnIncorrectItemSlotted -= ItemSlot_OnIncorrectItemSlotted;
|
s.OnWrongItemAttempted -= ItemSlot_OnWrongItemAttempted;
|
||||||
s.OnItemSlotRemoved -= ItemSlot_OnItemSlotRemoved;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_itemSlots.Clear();
|
_itemSlots.Clear();
|
||||||
@@ -149,9 +127,7 @@ namespace Core
|
|||||||
// Clear manager-level event subscribers
|
// Clear manager-level event subscribers
|
||||||
OnItemPickedUp = null;
|
OnItemPickedUp = null;
|
||||||
OnCorrectItemSlotted = null;
|
OnCorrectItemSlotted = null;
|
||||||
OnIncorrectItemSlotted = null;
|
OnWrongItemAttempted = null;
|
||||||
OnForbiddenItemSlotted = null;
|
|
||||||
OnItemSlotCleared = null;
|
|
||||||
OnItemsCombined = null;
|
OnItemsCombined = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +157,9 @@ namespace Core
|
|||||||
if (slot == null) return;
|
if (slot == null) return;
|
||||||
if (_itemSlots.Add(slot))
|
if (_itemSlots.Add(slot))
|
||||||
{
|
{
|
||||||
// Subscribe to all slot events
|
// Subscribe to active slot events only
|
||||||
slot.OnCorrectItemSlotted += ItemSlot_OnCorrectItemSlotted;
|
slot.OnCorrectItemSlotted += ItemSlot_OnCorrectItemSlotted;
|
||||||
slot.OnIncorrectItemSlotted += ItemSlot_OnIncorrectItemSlotted;
|
slot.OnWrongItemAttempted += ItemSlot_OnWrongItemAttempted;
|
||||||
slot.OnItemSlotRemoved += ItemSlot_OnItemSlotRemoved;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +168,9 @@ namespace Core
|
|||||||
if (slot == null) return;
|
if (slot == null) return;
|
||||||
if (_itemSlots.Remove(slot))
|
if (_itemSlots.Remove(slot))
|
||||||
{
|
{
|
||||||
// Unsubscribe from all slot events
|
// Unsubscribe from active slot events
|
||||||
slot.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
slot.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
|
||||||
slot.OnIncorrectItemSlotted -= ItemSlot_OnIncorrectItemSlotted;
|
slot.OnWrongItemAttempted -= ItemSlot_OnWrongItemAttempted;
|
||||||
slot.OnItemSlotRemoved -= ItemSlot_OnItemSlotRemoved;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,7 @@ namespace Dialogue
|
|||||||
PuzzleManager.Instance.OnStepCompleted += OnAnyPuzzleStepCompleted;
|
PuzzleManager.Instance.OnStepCompleted += OnAnyPuzzleStepCompleted;
|
||||||
ItemManager.Instance.OnItemPickedUp += OnAnyItemPickedUp;
|
ItemManager.Instance.OnItemPickedUp += OnAnyItemPickedUp;
|
||||||
ItemManager.Instance.OnCorrectItemSlotted += OnAnyItemSlotted;
|
ItemManager.Instance.OnCorrectItemSlotted += OnAnyItemSlotted;
|
||||||
ItemManager.Instance.OnIncorrectItemSlotted += OnAnyIncorrectItemSlotted;
|
ItemManager.Instance.OnWrongItemAttempted += OnAnyWrongItemAttempted;
|
||||||
ItemManager.Instance.OnForbiddenItemSlotted += OnAnyForbiddenItemSlotted;
|
|
||||||
ItemManager.Instance.OnItemSlotCleared += OnAnyItemSlotCleared;
|
|
||||||
ItemManager.Instance.OnItemsCombined += OnAnyItemsCombined;
|
ItemManager.Instance.OnItemsCombined += OnAnyItemsCombined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,9 +189,7 @@ namespace Dialogue
|
|||||||
{
|
{
|
||||||
ItemManager.Instance.OnItemPickedUp -= OnAnyItemPickedUp;
|
ItemManager.Instance.OnItemPickedUp -= OnAnyItemPickedUp;
|
||||||
ItemManager.Instance.OnCorrectItemSlotted -= OnAnyItemSlotted;
|
ItemManager.Instance.OnCorrectItemSlotted -= OnAnyItemSlotted;
|
||||||
ItemManager.Instance.OnIncorrectItemSlotted -= OnAnyIncorrectItemSlotted;
|
ItemManager.Instance.OnWrongItemAttempted -= OnAnyWrongItemAttempted;
|
||||||
ItemManager.Instance.OnForbiddenItemSlotted -= OnAnyForbiddenItemSlotted;
|
|
||||||
ItemManager.Instance.OnItemSlotCleared -= OnAnyItemSlotCleared;
|
|
||||||
ItemManager.Instance.OnItemsCombined -= OnAnyItemsCombined;
|
ItemManager.Instance.OnItemsCombined -= OnAnyItemsCombined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,7 +534,7 @@ namespace Dialogue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAnyIncorrectItemSlotted(PickupItemData slotDefinition, PickupItemData slottedItem)
|
private void OnAnyWrongItemAttempted(PickupItemData slotDefinition, PickupItemData attemptedItem)
|
||||||
{
|
{
|
||||||
// Initialize if needed
|
// Initialize if needed
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
@@ -554,53 +550,10 @@ namespace Dialogue
|
|||||||
if (currentNode.nodeType == RuntimeDialogueNodeType.WaitOnSlot &&
|
if (currentNode.nodeType == RuntimeDialogueNodeType.WaitOnSlot &&
|
||||||
slotDefinition.itemId == currentNode.slotItemID)
|
slotDefinition.itemId == currentNode.slotItemID)
|
||||||
{
|
{
|
||||||
|
// Treat as Incorrect for dialogue purposes
|
||||||
_currentSlotState = ItemSlotState.Incorrect;
|
_currentSlotState = ItemSlotState.Incorrect;
|
||||||
_lastSlottedItem = slottedItem;
|
_lastSlottedItem = attemptedItem;
|
||||||
|
|
||||||
UpdateDialogueVisibilityOnItemEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAnyForbiddenItemSlotted(PickupItemData slotDefinition, PickupItemData slottedItem)
|
|
||||||
{
|
|
||||||
// Initialize if needed
|
|
||||||
if (!initialized)
|
|
||||||
{
|
|
||||||
StartDialogue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the slot state for displaying the correct dialogue lines
|
|
||||||
if (!IsActive || IsCompleted || currentNode == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Only update state if we're actively waiting on this slot
|
|
||||||
if (currentNode.nodeType == RuntimeDialogueNodeType.WaitOnSlot &&
|
|
||||||
slotDefinition.itemId == currentNode.slotItemID)
|
|
||||||
{
|
|
||||||
_currentSlotState = ItemSlotState.Forbidden;
|
|
||||||
_lastSlottedItem = slottedItem;
|
|
||||||
|
|
||||||
UpdateDialogueVisibilityOnItemEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAnyItemSlotCleared(PickupItemData removedItem)
|
|
||||||
{
|
|
||||||
// Initialize if needed
|
|
||||||
if (!initialized)
|
|
||||||
{
|
|
||||||
StartDialogue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the slot state when an item is removed
|
|
||||||
if (!IsActive || IsCompleted || currentNode == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Reset slot state if we were tracking this item
|
|
||||||
if (_lastSlottedItem != null && _lastSlottedItem == removedItem)
|
|
||||||
{
|
|
||||||
_currentSlotState = ItemSlotState.None;
|
|
||||||
_lastSlottedItem = null;
|
|
||||||
|
|
||||||
UpdateDialogueVisibilityOnItemEvent();
|
UpdateDialogueVisibilityOnItemEvent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq; // for Count() on List<bool>
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using System; // for Action<T>
|
using System; // for Action<T>
|
||||||
using Core; // register with ItemManager
|
using Core; // register with ItemManager
|
||||||
using AppleHills.Core.Settings;
|
|
||||||
using Core.Settings; // Added for IInteractionSettings
|
using Core.Settings; // Added for IInteractionSettings
|
||||||
|
|
||||||
namespace Interactions
|
namespace Interactions
|
||||||
@@ -18,6 +16,16 @@ namespace Interactions
|
|||||||
Forbidden
|
Forbidden
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Display behavior for slot renderers
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public enum SlotRendererDisplayType
|
||||||
|
{
|
||||||
|
UseConfig = 0, // Assign sprite from slotted item's config (default)
|
||||||
|
RevealExisting = 1 // Just make the renderer visible (sprite already on renderer)
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps a sprite renderer to an optional item assignment
|
/// Maps a sprite renderer to an optional item assignment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -27,6 +35,8 @@ namespace Interactions
|
|||||||
public SpriteRenderer renderer;
|
public SpriteRenderer renderer;
|
||||||
[Tooltip("Optional: If set, this renderer slot is dedicated to this specific item. Leave null for flexible slots.")]
|
[Tooltip("Optional: If set, this renderer slot is dedicated to this specific item. Leave null for flexible slots.")]
|
||||||
public PickupItemData assignedItem;
|
public PickupItemData assignedItem;
|
||||||
|
[Tooltip("Display behavior: UseConfig assigns sprite from item config, RevealExisting just makes renderer visible")]
|
||||||
|
public SlotRendererDisplayType displayType = SlotRendererDisplayType.UseConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -42,8 +52,9 @@ namespace Interactions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction that allows slotting, swapping, or picking up items in a slot.
|
/// Interaction that allows slotting items in a slot.
|
||||||
/// ItemSlot is a CONTAINER, not a Pickup itself.
|
/// ItemSlot is a CONTAINER, not a Pickup itself.
|
||||||
|
/// Items cannot be removed or swapped once slotted (except via combinations).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ItemSlot : SaveableInteractable
|
public class ItemSlot : SaveableInteractable
|
||||||
{
|
{
|
||||||
@@ -51,11 +62,10 @@ namespace Interactions
|
|||||||
public PickupItemData itemData;
|
public PickupItemData itemData;
|
||||||
public SpriteRenderer iconRenderer;
|
public SpriteRenderer iconRenderer;
|
||||||
|
|
||||||
// Multi-slot item tracking
|
// Multi-slot item tracking - now only stores correct items (dense arrays)
|
||||||
private List<PickupItemData> slottedItemsData = new List<PickupItemData>();
|
private List<PickupItemData> slottedItemsData = new List<PickupItemData>();
|
||||||
public SlotRendererMapping[] slottedItemRenderers; // Array of renderers with optional item assignments
|
public SlotRendererMapping[] slottedItemRenderers; // Array of renderers with optional item assignments
|
||||||
private List<GameObject> slottedItemObjects = new List<GameObject>();
|
private List<GameObject> slottedItemObjects = new List<GameObject>();
|
||||||
private List<bool> slottedItemCorrectness = new List<bool>(); // Track which items are correct
|
|
||||||
|
|
||||||
// Tracks the current state of the slotted item(s)
|
// Tracks the current state of the slotted item(s)
|
||||||
private ItemSlotState currentState = ItemSlotState.None;
|
private ItemSlotState currentState = ItemSlotState.None;
|
||||||
@@ -72,26 +82,14 @@ namespace Interactions
|
|||||||
public ItemSlotState CurrentSlottedState => currentState;
|
public ItemSlotState CurrentSlottedState => currentState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of items currently slotted (correct or incorrect)
|
/// Number of items currently slotted (all are correct in new system)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int CurrentSlottedCount => slottedItemObjects.Count(obj => obj != null);
|
public int CurrentSlottedCount => slottedItemObjects.Count;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of CORRECT items currently slotted
|
/// Number of CORRECT items currently slotted (all items are correct now)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int CurrentCorrectCount
|
public int CurrentCorrectCount => slottedItemObjects.Count;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < slottedItemCorrectness.Count; i++)
|
|
||||||
{
|
|
||||||
if (i < slottedItemObjects.Count && slottedItemObjects[i] != null && slottedItemCorrectness[i])
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of items required to complete this slot
|
/// Number of items required to complete this slot
|
||||||
@@ -125,21 +123,15 @@ namespace Interactions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool IsMultiSlot => slottedItemRenderers != null && slottedItemRenderers.Length > 1;
|
private bool IsMultiSlot => slottedItemRenderers != null && slottedItemRenderers.Length > 1;
|
||||||
|
|
||||||
|
// Event dispatchers (only 3 events needed)
|
||||||
public UnityEvent onItemSlotted;
|
public UnityEvent onItemSlotted;
|
||||||
public UnityEvent onItemSlotRemoved;
|
|
||||||
// Native C# event alternatives for code-only subscribers
|
|
||||||
public event Action<PickupItemData, PickupItemData> OnItemSlotted; // (slotData, slottedItemData)
|
public event Action<PickupItemData, PickupItemData> OnItemSlotted; // (slotData, slottedItemData)
|
||||||
public event Action<PickupItemData> OnItemSlotRemoved;
|
|
||||||
|
|
||||||
public UnityEvent onCorrectItemSlotted;
|
public UnityEvent onCorrectItemSlotted;
|
||||||
// Native C# event alternative to the UnityEvent for code-only subscribers
|
public event Action<PickupItemData, PickupItemData> OnCorrectItemSlotted; // (slotData, slottedItemData)
|
||||||
public event Action<PickupItemData, PickupItemData> OnCorrectItemSlotted;
|
|
||||||
|
public UnityEvent onWrongItemAttempted;
|
||||||
public UnityEvent onIncorrectItemSlotted;
|
public event Action<PickupItemData, PickupItemData> OnWrongItemAttempted; // (slotData, attemptedItem)
|
||||||
// Native C# event alternative for code-only subscribers
|
|
||||||
public event Action<PickupItemData, PickupItemData> OnIncorrectItemSlotted;
|
|
||||||
|
|
||||||
public UnityEvent onForbiddenItemSlotted;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the first (or only) slotted object - for backward compatibility
|
/// Get the first (or only) slotted object - for backward compatibility
|
||||||
@@ -180,6 +172,19 @@ namespace Interactions
|
|||||||
|
|
||||||
// Initialize settings references
|
// Initialize settings references
|
||||||
interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
|
||||||
|
|
||||||
|
// Hide all RevealExisting renderers at start
|
||||||
|
if (slottedItemRenderers != null)
|
||||||
|
{
|
||||||
|
foreach (var mapping in slottedItemRenderers)
|
||||||
|
{
|
||||||
|
if (mapping != null && mapping.renderer != null &&
|
||||||
|
mapping.displayType == SlotRendererDisplayType.RevealExisting)
|
||||||
|
{
|
||||||
|
mapping.renderer.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
@@ -213,6 +218,8 @@ namespace Interactions
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validation: Check if interaction can proceed based on held item and slot state.
|
/// Validation: Check if interaction can proceed based on held item and slot state.
|
||||||
|
/// Now allows all items to proceed - wrong items will trigger reactions without slotting.
|
||||||
|
/// No unslotting or swapping allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override (bool canProceed, string errorMessage) CanProceedWithInteraction()
|
protected override (bool canProceed, string errorMessage) CanProceedWithInteraction()
|
||||||
{
|
{
|
||||||
@@ -231,32 +238,21 @@ namespace Interactions
|
|||||||
if (heldItem == null && CurrentSlottedCount == 0)
|
if (heldItem == null && CurrentSlottedCount == 0)
|
||||||
return (false, "This requires an item.");
|
return (false, "This requires an item.");
|
||||||
|
|
||||||
// If holding an item and slot is full but not complete, allow swap
|
// Scenario: Nothing held + Has items = Can't remove (no unslotting)
|
||||||
|
if (heldItem == null && CurrentSlottedCount > 0)
|
||||||
|
return (false, "I can't remove these items.");
|
||||||
|
|
||||||
|
// Scenario: Holding item + Slot full = Error (no swapping)
|
||||||
if (heldItem != null && !HasSpace)
|
if (heldItem != null && !HasSpace)
|
||||||
{
|
|
||||||
// Allow swap for fixing mistakes (single-slot or multi-slot not complete)
|
|
||||||
if (!IsMultiSlot || !IsComplete)
|
|
||||||
return (true, null); // Allow swap
|
|
||||||
|
|
||||||
// Multi-slot is complete - can't swap
|
|
||||||
return (false, "This slot is full.");
|
return (false, "This slot is full.");
|
||||||
}
|
|
||||||
|
|
||||||
// Check forbidden items if trying to slot
|
|
||||||
if (heldItem != null)
|
|
||||||
{
|
|
||||||
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
|
||||||
var forbidden = config?.forbiddenItems ?? new List<PickupItemData>();
|
|
||||||
|
|
||||||
if (PickupItemData.ListContainsEquivalent(forbidden, heldItem))
|
|
||||||
return (false, "Can't place that here.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// All other cases proceed (holding item + has space)
|
||||||
return (true, null);
|
return (true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main interaction logic: Slot, pickup, swap, or combine items.
|
/// Main interaction logic: Slot correct items or trigger reactions for wrong items.
|
||||||
|
/// No swapping, unslotting, or combinations allowed - items stay once slotted.
|
||||||
/// Returns true only if correct item was slotted AND slot is now complete.
|
/// Returns true only if correct item was slotted AND slot is now complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override bool DoInteraction()
|
protected override bool DoInteraction()
|
||||||
@@ -266,221 +262,60 @@ namespace Interactions
|
|||||||
var heldItemData = FollowerController.CurrentlyHeldItemData;
|
var heldItemData = FollowerController.CurrentlyHeldItemData;
|
||||||
var heldItemObj = FollowerController.GetHeldPickupObject();
|
var heldItemObj = FollowerController.GetHeldPickupObject();
|
||||||
|
|
||||||
// Scenario 1: Held item + Has space = Slot it
|
// Only scenario: Held item + Has space = Check if allowed, then slot or react
|
||||||
if (heldItemData != null && HasSpace)
|
if (heldItemData != null && HasSpace)
|
||||||
{
|
{
|
||||||
SlotItem(heldItemObj, heldItemData);
|
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
||||||
FollowerController.ClearHeldItem(); // Clear follower's hand after slotting
|
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
||||||
|
|
||||||
// Check if we completed the slot
|
// Check if item is allowed
|
||||||
if (IsComplete)
|
if (PickupItemData.ListContainsEquivalent(allowed, heldItemData))
|
||||||
{
|
{
|
||||||
isLockedAfterCompletion = true;
|
// CORRECT ITEM - Slot it
|
||||||
currentState = ItemSlotState.Correct;
|
SlotItem(heldItemObj, heldItemData);
|
||||||
return true; // Completed!
|
FollowerController.ClearHeldItem(); // Clear follower's hand after slotting
|
||||||
}
|
|
||||||
|
// Check if we completed the slot
|
||||||
return false; // Slotted but not complete yet
|
if (IsComplete)
|
||||||
}
|
|
||||||
|
|
||||||
// Scenario 2 & 3: Slot is full
|
|
||||||
if (CurrentSlottedCount > 0)
|
|
||||||
{
|
|
||||||
// Try combination if both items present (only for single slots)
|
|
||||||
if (heldItemData != null && !IsMultiSlot)
|
|
||||||
{
|
|
||||||
var slottedPickup = slottedItemObjects[0].GetComponent<Pickup>();
|
|
||||||
if (slottedPickup != null)
|
|
||||||
{
|
{
|
||||||
var comboResult = FollowerController.TryCombineItems(slottedPickup, out _);
|
isLockedAfterCompletion = true;
|
||||||
|
currentState = ItemSlotState.Correct;
|
||||||
if (comboResult == FollowerController.CombinationResult.Successful)
|
return true; // Completed!
|
||||||
{
|
|
||||||
// Combination succeeded - clear slot and return false (not a "slot success")
|
|
||||||
ClearSlot();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap behavior when slot is full (single slots OR multi-slots that aren't complete)
|
|
||||||
if (heldItemData != null && !HasSpace)
|
|
||||||
{
|
|
||||||
// For single slots: always allow swap
|
|
||||||
// For multi-slots: only allow swap if not complete yet (allows fixing mistakes)
|
|
||||||
if (!IsMultiSlot || !IsComplete)
|
|
||||||
{
|
|
||||||
// Determine target index for the new item
|
|
||||||
int targetIndex = GetTargetSlotIndexForItem(heldItemData);
|
|
||||||
|
|
||||||
int indexToSwap;
|
|
||||||
if (targetIndex >= 0 && targetIndex < slottedItemObjects.Count && slottedItemObjects[targetIndex] != null)
|
|
||||||
{
|
|
||||||
// Swap with the item in the assigned slot
|
|
||||||
indexToSwap = targetIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// LIFO swap - swap with the last non-null item
|
|
||||||
indexToSwap = -1;
|
|
||||||
for (int i = slottedItemObjects.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (slottedItemObjects[i] != null)
|
|
||||||
{
|
|
||||||
indexToSwap = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indexToSwap < 0)
|
|
||||||
{
|
|
||||||
// No items to swap (shouldn't happen, but fallback)
|
|
||||||
SlotItem(heldItemObj, heldItemData);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemToReturn = slottedItemObjects[indexToSwap];
|
|
||||||
var itemDataToReturn = slottedItemsData[indexToSwap];
|
|
||||||
|
|
||||||
// Step 1: Give old item to follower
|
|
||||||
FollowerController.TryPickupItem(itemToReturn, itemDataToReturn, dropItem: false);
|
|
||||||
|
|
||||||
// Step 2: Remove old item from slot
|
|
||||||
RemoveItemAtIndex(indexToSwap);
|
|
||||||
|
|
||||||
// Step 3: Slot the new item
|
|
||||||
SlotItem(heldItemObj, heldItemData);
|
|
||||||
|
|
||||||
// Check if we completed the slot with this swap
|
|
||||||
if (IsComplete)
|
|
||||||
{
|
|
||||||
isLockedAfterCompletion = true;
|
|
||||||
currentState = ItemSlotState.Correct;
|
|
||||||
return true; // Completed!
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Swapped but not complete
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pickup from slot (empty hands) - LIFO removal
|
|
||||||
if (heldItemData == null)
|
|
||||||
{
|
|
||||||
// Find last non-null item
|
|
||||||
int lastIndex = -1;
|
|
||||||
for (int i = slottedItemObjects.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (slottedItemObjects[i] != null)
|
|
||||||
{
|
|
||||||
lastIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastIndex >= 0)
|
return false; // Slotted but not complete yet
|
||||||
{
|
}
|
||||||
var itemToPickup = slottedItemObjects[lastIndex];
|
else
|
||||||
var itemDataToPickup = slottedItemsData[lastIndex];
|
{
|
||||||
|
// WRONG ITEM - Trigger reaction, don't slot, item stays in hand
|
||||||
// Try to give item to follower
|
TriggerWrongItemReaction(heldItemData);
|
||||||
FollowerController.TryPickupItem(itemToPickup, itemDataToPickup, dropItem: false);
|
|
||||||
|
|
||||||
// Remove from slot
|
|
||||||
RemoveItemAtIndex(lastIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just picked up from slot - not a success
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shouldn't reach here (validation prevents empty + no held)
|
// No other scenarios
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper: Clear the slot and fire removal events.
|
/// Triggers a "wrong item" reaction without slotting.
|
||||||
|
/// Integrates with DialogueComponent for NPC feedback.
|
||||||
|
/// Item stays in player's hand.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ClearSlot()
|
private void TriggerWrongItemReaction(PickupItemData wrongItem)
|
||||||
{
|
{
|
||||||
// Find first non-null data for event
|
DebugUIMessage.Show($"{wrongItem.itemName} doesn't belong here.", Color.yellow);
|
||||||
PickupItemData previousData = null;
|
|
||||||
foreach (var data in slottedItemsData)
|
|
||||||
{
|
|
||||||
if (data != null)
|
|
||||||
{
|
|
||||||
previousData = data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear all pickup's OwningSlot references
|
// Fire event for DialogueComponent integration
|
||||||
foreach (var itemObj in slottedItemObjects)
|
onWrongItemAttempted?.Invoke();
|
||||||
{
|
OnWrongItemAttempted?.Invoke(itemData, wrongItem);
|
||||||
if (itemObj != null)
|
|
||||||
{
|
|
||||||
var pickup = itemObj.GetComponent<Pickup>();
|
|
||||||
if (pickup != null)
|
|
||||||
{
|
|
||||||
pickup.OwningSlot = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slottedItemObjects.Clear();
|
// Item stays in player's hand - no state change
|
||||||
slottedItemsData.Clear();
|
|
||||||
slottedItemCorrectness.Clear(); // Also clear correctness tracking
|
|
||||||
currentState = ItemSlotState.None;
|
|
||||||
isLockedAfterCompletion = false;
|
|
||||||
UpdateSlottedSprite();
|
|
||||||
|
|
||||||
// Fire removal events
|
|
||||||
onItemSlotRemoved?.Invoke();
|
|
||||||
OnItemSlotRemoved?.Invoke(previousData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper: Remove a specific item from the slot by index.
|
|
||||||
/// </summary>
|
|
||||||
private void RemoveItemAtIndex(int index)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= slottedItemObjects.Count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var itemObj = slottedItemObjects[index];
|
|
||||||
var removedItemData = slottedItemsData[index];
|
|
||||||
|
|
||||||
// Clear the pickup's OwningSlot reference
|
|
||||||
if (itemObj != null)
|
|
||||||
{
|
|
||||||
var pickup = itemObj.GetComponent<Pickup>();
|
|
||||||
if (pickup != null)
|
|
||||||
{
|
|
||||||
pickup.OwningSlot = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set to null instead of removing to maintain sparse storage
|
|
||||||
slottedItemObjects[index] = null;
|
|
||||||
slottedItemsData[index] = null;
|
|
||||||
slottedItemCorrectness[index] = false;
|
|
||||||
|
|
||||||
if (CurrentSlottedCount == 0)
|
|
||||||
{
|
|
||||||
currentState = ItemSlotState.None;
|
|
||||||
isLockedAfterCompletion = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateSlottedSprite();
|
|
||||||
|
|
||||||
// Fire removal events
|
|
||||||
onItemSlotRemoved?.Invoke();
|
|
||||||
OnItemSlotRemoved?.Invoke(removedItemData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Visual Updates
|
#region Visual Updates
|
||||||
@@ -488,11 +323,12 @@ namespace Interactions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines the best slot index for an item based on assignments and availability.
|
/// Determines the best slot index for an item based on assignments and availability.
|
||||||
/// Returns -1 if no mappings are configured (uses append behavior).
|
/// Returns -1 if no mappings are configured (uses append behavior).
|
||||||
|
/// Simplified for dense arrays.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int GetTargetSlotIndexForItem(PickupItemData itemData)
|
private int GetTargetSlotIndexForItem(PickupItemData itemData)
|
||||||
{
|
{
|
||||||
if (slottedItemRenderers == null || slottedItemRenderers.Length == 0)
|
if (slottedItemRenderers == null || slottedItemRenderers.Length == 0)
|
||||||
return -1;
|
return -1; // Append behavior
|
||||||
|
|
||||||
// Check if any renderer has assignments configured
|
// Check if any renderer has assignments configured
|
||||||
bool hasAnyAssignments = false;
|
bool hasAnyAssignments = false;
|
||||||
@@ -509,7 +345,7 @@ namespace Interactions
|
|||||||
if (!hasAnyAssignments)
|
if (!hasAnyAssignments)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Step 1: Check if this item has a dedicated assigned slot
|
// Check if this item has a dedicated assigned slot
|
||||||
for (int i = 0; i < slottedItemRenderers.Length; i++)
|
for (int i = 0; i < slottedItemRenderers.Length; i++)
|
||||||
{
|
{
|
||||||
var mapping = slottedItemRenderers[i];
|
var mapping = slottedItemRenderers[i];
|
||||||
@@ -520,41 +356,16 @@ namespace Interactions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Item is not assigned to a specific slot - find best available slot
|
// Item is not assigned to a specific slot - return next available index
|
||||||
// Ensure lists are large enough to check
|
// Dense arrays: just return current count if there's space
|
||||||
while (slottedItemObjects.Count < slottedItemRenderers.Length)
|
return slottedItemObjects.Count < slottedItemRenderers.Length
|
||||||
{
|
? slottedItemObjects.Count
|
||||||
slottedItemObjects.Add(null);
|
: -1; // No space, use append (will trigger swap logic)
|
||||||
slottedItemsData.Add(null);
|
|
||||||
slottedItemCorrectness.Add(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer unassigned empty slots first
|
|
||||||
for (int i = 0; i < slottedItemRenderers.Length; i++)
|
|
||||||
{
|
|
||||||
var mapping = slottedItemRenderers[i];
|
|
||||||
if (mapping?.assignedItem == null && slottedItemObjects[i] == null)
|
|
||||||
{
|
|
||||||
return i; // Empty unassigned slot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then try assigned but empty slots
|
|
||||||
for (int i = 0; i < slottedItemRenderers.Length; i++)
|
|
||||||
{
|
|
||||||
var mapping = slottedItemRenderers[i];
|
|
||||||
if (mapping?.assignedItem != null && slottedItemObjects[i] == null)
|
|
||||||
{
|
|
||||||
return i; // Empty assigned slot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All slots full - return -1 to trigger swap logic
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the sprite and scale for all slotted items.
|
/// Updates the sprite and scale for all slotted items.
|
||||||
|
/// Handles both UseConfig (assign sprite) and RevealExisting (just enable renderer) display modes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateSlottedSprite()
|
private void UpdateSlottedSprite()
|
||||||
{
|
{
|
||||||
@@ -574,31 +385,51 @@ namespace Interactions
|
|||||||
if (i < slottedItemsData.Count && slottedItemsData[i] != null)
|
if (i < slottedItemsData.Count && slottedItemsData[i] != null)
|
||||||
{
|
{
|
||||||
var slottedData = slottedItemsData[i];
|
var slottedData = slottedItemsData[i];
|
||||||
if (slottedData.mapSprite != null)
|
|
||||||
|
// Handle display mode
|
||||||
|
if (mapping.displayType == SlotRendererDisplayType.RevealExisting)
|
||||||
{
|
{
|
||||||
slotRenderer.sprite = slottedData.mapSprite;
|
// RevealExisting: Just make the renderer visible
|
||||||
|
slotRenderer.enabled = true;
|
||||||
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
|
}
|
||||||
var configs = GameManager.GetSettingsObject<IPlayerMovementConfigs>();
|
else // UseConfig (default)
|
||||||
float desiredHeight = configs?.FollowerMovement?.HeldIconDisplayHeight ?? 2.0f;
|
{
|
||||||
var sprite = slottedData.mapSprite;
|
// UseConfig: Assign sprite from item config
|
||||||
float spriteHeight = sprite.bounds.size.y;
|
if (slottedData.mapSprite != null)
|
||||||
Vector3 parentScale = slotRenderer.transform.parent != null
|
|
||||||
? slotRenderer.transform.parent.localScale
|
|
||||||
: Vector3.one;
|
|
||||||
|
|
||||||
if (spriteHeight > 0f)
|
|
||||||
{
|
{
|
||||||
float uniformScale = desiredHeight / spriteHeight;
|
slotRenderer.sprite = slottedData.mapSprite;
|
||||||
float scale = uniformScale / Mathf.Max(parentScale.x, parentScale.y);
|
|
||||||
slotRenderer.transform.localScale = new Vector3(scale, scale, 1f);
|
// Scale sprite to desired height, preserve aspect ratio, compensate for parent scale
|
||||||
|
var configs = GameManager.GetSettingsObject<IPlayerMovementConfigs>();
|
||||||
|
float desiredHeight = configs?.FollowerMovement?.HeldIconDisplayHeight ?? 2.0f;
|
||||||
|
var sprite = slottedData.mapSprite;
|
||||||
|
float spriteHeight = sprite.bounds.size.y;
|
||||||
|
Vector3 parentScale = slotRenderer.transform.parent != null
|
||||||
|
? slotRenderer.transform.parent.localScale
|
||||||
|
: Vector3.one;
|
||||||
|
|
||||||
|
if (spriteHeight > 0f)
|
||||||
|
{
|
||||||
|
float uniformScale = desiredHeight / spriteHeight;
|
||||||
|
float scale = uniformScale / Mathf.Max(parentScale.x, parentScale.y);
|
||||||
|
slotRenderer.transform.localScale = new Vector3(scale, scale, 1f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Clear renderer if no item at this index
|
// No item at this index - clear/hide renderer
|
||||||
slotRenderer.sprite = null;
|
if (mapping.displayType == SlotRendererDisplayType.RevealExisting)
|
||||||
|
{
|
||||||
|
// RevealExisting: Hide the renderer
|
||||||
|
slotRenderer.enabled = false;
|
||||||
|
}
|
||||||
|
else // UseConfig (default)
|
||||||
|
{
|
||||||
|
// UseConfig: Clear sprite
|
||||||
|
slotRenderer.sprite = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -767,15 +598,10 @@ namespace Interactions
|
|||||||
|
|
||||||
// Add to slotted items list (no events, no interaction completion)
|
// Add to slotted items list (no events, no interaction completion)
|
||||||
// Follower state is managed separately during save/load restoration
|
// Follower state is managed separately during save/load restoration
|
||||||
|
// All saved items are correct (wrong items never get slotted)
|
||||||
slottedItemObjects.Add(slottedObject);
|
slottedItemObjects.Add(slottedObject);
|
||||||
slottedItemsData.Add(slottedData);
|
slottedItemsData.Add(slottedData);
|
||||||
|
|
||||||
// Determine if this item is correct for correctness tracking
|
|
||||||
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
|
||||||
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
|
||||||
bool isCorrectItem = PickupItemData.ListContainsEquivalent(allowed, slottedData);
|
|
||||||
slottedItemCorrectness.Add(isCorrectItem);
|
|
||||||
|
|
||||||
// Deactivate the item and set pickup state
|
// Deactivate the item and set pickup state
|
||||||
slottedObject.SetActive(false);
|
slottedObject.SetActive(false);
|
||||||
if (pickup != null)
|
if (pickup != null)
|
||||||
@@ -784,12 +610,13 @@ namespace Interactions
|
|||||||
pickup.OwningSlot = this;
|
pickup.OwningSlot = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Debug($"[ItemSlot] Successfully restored slotted item: {slottedData.itemName} (itemId: {slottedData.itemId}, correct: {isCorrectItem})");
|
Logging.Debug($"[ItemSlot] Successfully restored slotted item: {slottedData.itemName} (itemId: {slottedData.itemId})");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Public API for slotting items during gameplay.
|
/// Public API for slotting items during gameplay.
|
||||||
/// Adds item to the slot (multi-slot support with positional awareness).
|
/// Adds item to the slot (multi-slot support with positional awareness).
|
||||||
|
/// Only called for correct items - wrong items trigger reactions instead.
|
||||||
/// Caller is responsible for managing follower's held item state.
|
/// Caller is responsible for managing follower's held item state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SlotItem(GameObject itemToSlot, PickupItemData itemToSlotData)
|
public void SlotItem(GameObject itemToSlot, PickupItemData itemToSlotData)
|
||||||
@@ -800,35 +627,22 @@ namespace Interactions
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if this item is correct (allowed)
|
// NOTE: Only called for CORRECT items now (validation done in DoInteraction)
|
||||||
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
|
||||||
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
|
||||||
bool isCorrectItem = PickupItemData.ListContainsEquivalent(allowed, itemToSlotData);
|
|
||||||
|
|
||||||
// Determine target slot index
|
// Determine target slot index
|
||||||
int targetIndex = GetTargetSlotIndexForItem(itemToSlotData);
|
int targetIndex = GetTargetSlotIndexForItem(itemToSlotData);
|
||||||
|
|
||||||
if (targetIndex >= 0)
|
if (targetIndex >= 0 && targetIndex < slottedItemObjects.Count)
|
||||||
{
|
{
|
||||||
// Positional slotting - ensure lists are large enough
|
// Insert at specific position (shifts items if needed)
|
||||||
while (slottedItemObjects.Count <= targetIndex)
|
slottedItemObjects.Insert(targetIndex, itemToSlot);
|
||||||
{
|
slottedItemsData.Insert(targetIndex, itemToSlotData);
|
||||||
slottedItemObjects.Add(null);
|
|
||||||
slottedItemsData.Add(null);
|
|
||||||
slottedItemCorrectness.Add(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Place at specific index
|
|
||||||
slottedItemObjects[targetIndex] = itemToSlot;
|
|
||||||
slottedItemsData[targetIndex] = itemToSlotData;
|
|
||||||
slottedItemCorrectness[targetIndex] = isCorrectItem;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Append behavior (backward compatible or when all slots full)
|
// Append to end (backward compatible or when all slots full)
|
||||||
slottedItemObjects.Add(itemToSlot);
|
slottedItemObjects.Add(itemToSlot);
|
||||||
slottedItemsData.Add(itemToSlotData);
|
slottedItemsData.Add(itemToSlotData);
|
||||||
slottedItemCorrectness.Add(isCorrectItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deactivate item and set pickup state
|
// Deactivate item and set pickup state
|
||||||
@@ -845,32 +659,18 @@ namespace Interactions
|
|||||||
// Update visuals
|
// Update visuals
|
||||||
UpdateSlottedSprite();
|
UpdateSlottedSprite();
|
||||||
|
|
||||||
// Fire events based on correctness
|
// Fire success events (all items are correct now)
|
||||||
if (isCorrectItem)
|
DebugUIMessage.Show($"Slotted {itemToSlotData.itemName}", Color.green);
|
||||||
|
onItemSlotted?.Invoke();
|
||||||
|
OnItemSlotted?.Invoke(itemData, itemToSlotData);
|
||||||
|
|
||||||
|
// Check if slot is complete
|
||||||
|
if (IsComplete)
|
||||||
{
|
{
|
||||||
DebugUIMessage.Show($"You slotted {itemToSlotData.itemName} into: {itemData.itemName}", Color.green);
|
currentState = ItemSlotState.Correct;
|
||||||
|
DebugUIMessage.Show($"Completed: {itemData.itemName}", Color.green);
|
||||||
// Fire generic slot event
|
onCorrectItemSlotted?.Invoke();
|
||||||
onItemSlotted?.Invoke();
|
OnCorrectItemSlotted?.Invoke(itemData, itemToSlotData);
|
||||||
OnItemSlotted?.Invoke(itemData, itemToSlotData);
|
|
||||||
|
|
||||||
// Only fire correct completion event if ALL required CORRECT items are now slotted
|
|
||||||
if (IsComplete)
|
|
||||||
{
|
|
||||||
currentState = ItemSlotState.Correct;
|
|
||||||
DebugUIMessage.Show($"Completed: {itemData.itemName}", Color.green);
|
|
||||||
onCorrectItemSlotted?.Invoke();
|
|
||||||
OnCorrectItemSlotted?.Invoke(itemData, itemToSlotData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Incorrect item slotted
|
|
||||||
DebugUIMessage.Show($"Slotted {itemToSlotData.itemName}, but it might not be right...", Color.yellow);
|
|
||||||
onItemSlotted?.Invoke(); // Still fire generic event
|
|
||||||
OnItemSlotted?.Invoke(itemData, itemToSlotData);
|
|
||||||
onIncorrectItemSlotted?.Invoke();
|
|
||||||
OnIncorrectItemSlotted?.Invoke(itemData, itemToSlotData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,21 +694,15 @@ namespace Interactions
|
|||||||
// Note: We don't have easy access to the expected SaveId here, so we just accept it
|
// Note: We don't have easy access to the expected SaveId here, so we just accept it
|
||||||
// The Pickup's bilateral restoration ensures it only claims the correct slot
|
// The Pickup's bilateral restoration ensures it only claims the correct slot
|
||||||
|
|
||||||
// Add the item to lists
|
// Add the item to lists (all items are correct in new system)
|
||||||
slottedItemObjects.Add(pickup.gameObject);
|
slottedItemObjects.Add(pickup.gameObject);
|
||||||
slottedItemsData.Add(pickup.itemData);
|
slottedItemsData.Add(pickup.itemData);
|
||||||
|
|
||||||
// Determine correctness for tracking
|
|
||||||
var config = interactionSettings?.GetSlotItemConfig(itemData);
|
|
||||||
var allowed = config?.allowedItems ?? new List<PickupItemData>();
|
|
||||||
bool isCorrectItem = PickupItemData.ListContainsEquivalent(allowed, pickup.itemData);
|
|
||||||
slottedItemCorrectness.Add(isCorrectItem);
|
|
||||||
|
|
||||||
pickup.gameObject.SetActive(false);
|
pickup.gameObject.SetActive(false);
|
||||||
pickup.IsPickedUp = true;
|
pickup.IsPickedUp = true;
|
||||||
pickup.OwningSlot = this;
|
pickup.OwningSlot = this;
|
||||||
|
|
||||||
Logging.Debug($"[ItemSlot] Successfully claimed slotted item: {pickup.itemData?.itemName} (correct: {isCorrectItem})");
|
Logging.Debug($"[ItemSlot] Successfully claimed slotted item: {pickup.itemData?.itemName}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user