Rework of base interactables and managed behaviors

This commit is contained in:
Michal Pikulski
2025-11-04 11:11:27 +01:00
committed by Michal Pikulski
parent 00e1746ac4
commit f88bd0e2c9
60 changed files with 11175 additions and 1340 deletions

View File

@@ -1,20 +1,18 @@
using Input;
using UnityEngine;
using UnityEngine;
using System;
using System.Linq;
using Bootstrap; // added for Action<T>
using Core; // register with ItemManager
using Core;
namespace Interactions
{
/// <summary>
/// Saveable data for Pickup state
/// </summary>
[System.Serializable]
[Serializable]
public class PickupSaveData
{
public bool isPickedUp;
public bool wasHeldByFollower; // Track if held by follower for bilateral restoration
public bool wasHeldByFollower;
public Vector3 worldPosition;
public Quaternion worldRotation;
public bool isActive;
@@ -24,19 +22,11 @@ namespace Interactions
{
public PickupItemData itemData;
public SpriteRenderer iconRenderer;
// Track if the item has been picked up
public bool IsPickedUp { get; internal set; }
// Event: invoked when the item was picked up successfully
public event Action<PickupItemData> OnItemPickedUp;
// Event: invoked when this item is successfully combined with another
public event Action<PickupItemData> OnItemPickedUp;
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
/// <summary>
/// Unity Awake callback. Sets up icon and applies item data.
/// </summary>
protected override void Awake()
{
base.Awake(); // Register with save system
@@ -46,26 +36,16 @@ namespace Interactions
ApplyItemData();
}
/// <summary>
/// Register with ItemManager on Start
/// </summary>
protected override void Start()
{
base.Start(); // Register with save system
// Always register with ItemManager, even if picked up
// This allows the save/load system to find held items when restoring state
BootCompletionService.RegisterInitAction(() =>
{
ItemManager.Instance?.RegisterPickup(this);
});
ItemManager.Instance?.RegisterPickup(this);
}
/// <summary>
/// Unity OnDestroy callback. Unregisters from ItemManager.
/// </summary>
protected override void OnDestroy()
{
base.OnDestroy(); // Unregister from save system
@@ -103,64 +83,54 @@ namespace Interactions
}
}
/// <summary>
/// Override: Called when character arrives at the interaction point.
/// Handles item pickup and combination logic.
/// </summary>
protected override void OnCharacterArrived()
{
Logging.Debug("[Pickup] OnCharacterArrived");
var combinationResult = _followerController.TryCombineItems(this, out var combinationResultItem);
if (combinationResultItem != null)
{
CompleteInteraction(true);
// Fire the combination event when items are successfully combined
if (combinationResult == FollowerController.CombinationResult.Successful)
{
var resultPickup = combinationResultItem.GetComponent<Pickup>();
if (resultPickup != null && resultPickup.itemData != null)
{
// Get the combined item data
var resultItemData = resultPickup.itemData;
var heldItem = _followerController.GetHeldPickupObject();
if (heldItem != null)
{
var heldPickup = heldItem.GetComponent<Pickup>();
if (heldPickup != null && heldPickup.itemData != null)
{
// Trigger the combination event
OnItemsCombined?.Invoke(itemData, heldPickup.itemData, resultItemData);
}
}
}
}
return;
}
_followerController?.TryPickupItem(gameObject, itemData);
var step = GetComponent<PuzzleS.ObjectiveStepBehaviour>();
if (step != null && !step.IsStepUnlocked())
{
CompleteInteraction(false);
return;
}
bool wasPickedUp = (combinationResult == FollowerController.CombinationResult.NotApplicable
|| combinationResult == FollowerController.CombinationResult.Unsuccessful);
CompleteInteraction(wasPickedUp);
#region Interaction Logic
// Update pickup state and invoke event when the item was picked up successfully
if (wasPickedUp)
/// <summary>
/// Main interaction logic: Try combination, then try pickup.
/// </summary>
protected override bool DoInteraction()
{
Logging.Debug("[Pickup] DoInteraction");
// IMPORTANT: Capture held item data BEFORE combination
// TryCombineItems destroys the original items, so we need this data for the event
var heldItemObject = FollowerController?.GetHeldPickupObject();
var heldItemData = heldItemObject?.GetComponent<Pickup>()?.itemData;
// Try combination first
var combinationResult = FollowerController.TryCombineItems(this, out var resultItem);
if (combinationResult == FollowerController.CombinationResult.Successful)
{
IsPickedUp = true;
OnItemPickedUp?.Invoke(itemData);
// Combination succeeded - original items destroyed, result picked up by TryCombineItems
FireCombinationEvent(resultItem, heldItemData);
return true;
}
// No combination (or unsuccessful) - do regular pickup
FollowerController?.TryPickupItem(gameObject, itemData);
IsPickedUp = true;
OnItemPickedUp?.Invoke(itemData);
return true;
}
/// <summary>
/// Helper method to fire the combination event with correct item data.
/// </summary>
/// <param name="resultItem">The spawned result item</param>
/// <param name="originalHeldItemData">The ORIGINAL held item data (before destruction)</param>
private void FireCombinationEvent(GameObject resultItem, PickupItemData originalHeldItemData)
{
var resultPickup = resultItem?.GetComponent<Pickup>();
// Verify we have all required data
if (resultPickup?.itemData != null && originalHeldItemData != null && itemData != null)
{
OnItemsCombined?.Invoke(itemData, originalHeldItemData, resultPickup.itemData);
}
}
#endregion
#region Save/Load Implementation