From c8cbc45f04722abef4bd3073634e4aa0f9992090 Mon Sep 17 00:00:00 2001 From: AlexanderT Date: Fri, 26 Sep 2025 14:06:03 +0200 Subject: [PATCH] Small updates to dispatchers in items and puzzles --- Assets/Data/Items/ExampleAss/Ass1.asset | 2 +- Assets/Data/Items/ExampleAss/Ass2.asset | 2 +- Assets/Data/Items/ExampleAss/Ass3.asset | 2 +- Assets/Dialogue/TestDialogue.dialoguegraph | 313 +++++++++++++++- Assets/Scripts/Interactions/Interactable.cs | 2 +- Assets/Scripts/Interactions/ItemSlot.cs | 27 ++ Assets/Scripts/Interactions/Pickup.cs | 13 +- .../Scripts/PuzzleS/ObjectiveStepBehaviour.cs | 2 +- Assets/Scripts/PuzzleS/PuzzleManager.cs | 346 +++++++++--------- Assets/Settings/InteractionSettings.asset | 4 +- 10 files changed, 531 insertions(+), 182 deletions(-) diff --git a/Assets/Data/Items/ExampleAss/Ass1.asset b/Assets/Data/Items/ExampleAss/Ass1.asset index e677139b..0b653942 100644 --- a/Assets/Data/Items/ExampleAss/Ass1.asset +++ b/Assets/Data/Items/ExampleAss/Ass1.asset @@ -12,6 +12,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3} m_Name: Ass1 m_EditorClassIdentifier: - itemName: TestAss + itemName: TestAss1 description: Well... how do you like 'em? mapSprite: {fileID: -5471482676633547895, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3} diff --git a/Assets/Data/Items/ExampleAss/Ass2.asset b/Assets/Data/Items/ExampleAss/Ass2.asset index 8c7e1a85..eb94e2df 100644 --- a/Assets/Data/Items/ExampleAss/Ass2.asset +++ b/Assets/Data/Items/ExampleAss/Ass2.asset @@ -12,6 +12,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3} m_Name: Ass2 m_EditorClassIdentifier: - itemName: TestAss + itemName: TestAss2 description: Well... how do you like 'em? mapSprite: {fileID: 4013237533433454447, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3} diff --git a/Assets/Data/Items/ExampleAss/Ass3.asset b/Assets/Data/Items/ExampleAss/Ass3.asset index 973a8429..cb343013 100644 --- a/Assets/Data/Items/ExampleAss/Ass3.asset +++ b/Assets/Data/Items/ExampleAss/Ass3.asset @@ -12,6 +12,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3} m_Name: Ass3 m_EditorClassIdentifier: - itemName: TestAss + itemName: TestAss3 description: Well... how do you like 'em? mapSprite: {fileID: -8109988653212156562, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3} diff --git a/Assets/Dialogue/TestDialogue.dialoguegraph b/Assets/Dialogue/TestDialogue.dialoguegraph index d96e88a7..ad2a248a 100644 --- a/Assets/Dialogue/TestDialogue.dialoguegraph +++ b/Assets/Dialogue/TestDialogue.dialoguegraph @@ -36,6 +36,9 @@ MonoBehaviour: - rid: 1219994508087787764 - rid: 1219994508087787770 - rid: 1219994508087787776 + - rid: 1219994508087787907 + - rid: 1219994508087787922 + - rid: 1219994508087787946 m_GraphWireModels: - rid: 1219994508087787755 - rid: 1219994508087787773 @@ -55,7 +58,7 @@ MonoBehaviour: x: 123 y: -65 width: 1698 - height: 242 + height: 763 m_GraphElementMetaData: - m_Guid: m_Value0: 13346176596883742728 @@ -153,6 +156,30 @@ MonoBehaviour: Hash: 1b76d4d1d2059b91f866d271199acbfd m_Category: 2 m_Index: 4 + - m_Guid: + m_Value0: 17687616821000604665 + m_Value1: 11418671301582040963 + m_HashGuid: + serializedVersion: 2 + Hash: f90bf722c90977f583afbed10c45779e + m_Category: 0 + m_Index: 6 + - m_Guid: + m_Value0: 5830891262905902794 + m_Value1: 8531471494669057217 + m_HashGuid: + serializedVersion: 2 + Hash: ca666fd1b57ceb50c1bc1e6b1fe06576 + m_Category: 0 + m_Index: 7 + - m_Guid: + m_Value0: 16523742220227669027 + m_Value1: 12072672733572090161 + m_HashGuid: + serializedVersion: 2 + Hash: 236ccbb4002050e531c91b2ee3bf8aa7 + m_Category: 0 + m_Index: 8 m_EntryPoint: rid: 1219994508087787747 m_Graph: @@ -693,3 +720,287 @@ MonoBehaviour: type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} data: m_Value: 0 + - rid: 1219994508087787907 + type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor} + data: + m_Guid: + m_Value0: 17687616821000604665 + m_Value1: 11418671301582040963 + m_HashGuid: + serializedVersion: 2 + Hash: f90bf722c90977f583afbed10c45779e + m_Version: 2 + m_Position: {x: 337.83755, y: 301.66} + m_Title: + m_Tooltip: + m_NodePreviewModel: + rid: -2 + m_State: 0 + m_InputConstantsById: + m_KeyList: + - __option_DialogueLineType + - __option_NoLines + - DefaultDialogueLine + - LoopThroughDefaultLines + - RequiredPickup + m_ValueList: + - rid: 1219994508087787908 + - rid: 1219994508087787909 + - rid: 1219994508087787910 + - rid: 1219994508087787911 + - rid: 1219994508087787916 + m_InputPortInfos: + expandedPortsById: + m_KeyList: [] + m_ValueList: + m_OutputPortInfos: + expandedPortsById: + m_KeyList: [] + m_ValueList: + m_Collapsed: 0 + m_CurrentModeIndex: 0 + m_ElementColor: + m_Color: {r: 0, g: 0, b: 0, a: 0} + m_HasUserColor: 0 + m_Node: + rid: 1219994508087787913 + - rid: 1219994508087787908 + type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + m_Value: 0 + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + - rid: 1219994508087787909 + type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 1 + - rid: 1219994508087787910 + type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + - rid: 1219994508087787911 + type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 0 + - rid: 1219994508087787913 + type: {class: WaitOnPickup, ns: Editor.Dialogue, asm: AppleHillsEditor} + data: + - rid: 1219994508087787916 + type: {class: 'Constant`1[[PickupItemData, AppleHillsScripts]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: {fileID: 0} + - rid: 1219994508087787922 + type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor} + data: + m_Guid: + m_Value0: 5830891262905902794 + m_Value1: 8531471494669057217 + m_HashGuid: + serializedVersion: 2 + Hash: ca666fd1b57ceb50c1bc1e6b1fe06576 + m_Version: 2 + m_Position: {x: 806, y: 304} + m_Title: + m_Tooltip: + m_NodePreviewModel: + rid: -2 + m_State: 0 + m_InputConstantsById: + m_KeyList: + - __option_DialogueLineType + - __option_NoLines + - __option_IncorrectItemDialogueLineType + - __option_IncorrectItemNoLines + - __option_ForbiddenItemDialogueLineType + - __option_ForbiddenItemNoLines + - DefaultDialogueLine + - LoopThroughDefaultLines + - RequiredSlot + - LoopThroughIncorrectItemLines + - ForbiddenItemDialogueLine + - LoopThroughForbiddenItemLines + - IncorrectItemDialogueLine1 + m_ValueList: + - rid: 1219994508087787923 + - rid: 1219994508087787924 + - rid: 1219994508087787925 + - rid: 1219994508087787926 + - rid: 1219994508087787927 + - rid: 1219994508087787928 + - rid: 1219994508087787929 + - rid: 1219994508087787930 + - rid: 1219994508087787931 + - rid: 1219994508087787933 + - rid: 1219994508087787934 + - rid: 1219994508087787935 + - rid: 1219994508087787938 + m_InputPortInfos: + expandedPortsById: + m_KeyList: [] + m_ValueList: + m_OutputPortInfos: + expandedPortsById: + m_KeyList: [] + m_ValueList: + m_Collapsed: 0 + m_CurrentModeIndex: 0 + m_ElementColor: + m_Color: {r: 0, g: 0, b: 0, a: 0} + m_HasUserColor: 0 + m_Node: + rid: 1219994508087787936 + - rid: 1219994508087787923 + type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + m_Value: 0 + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + - rid: 1219994508087787924 + type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 1 + - rid: 1219994508087787925 + type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + m_Value: 1 + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + - rid: 1219994508087787926 + type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 1 + - rid: 1219994508087787927 + type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + m_Value: 0 + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + - rid: 1219994508087787928 + type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 1 + - rid: 1219994508087787929 + type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + - rid: 1219994508087787930 + type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 0 + - rid: 1219994508087787931 + type: {class: 'Constant`1[[PickupItemData, AppleHillsScripts]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: {fileID: 0} + - rid: 1219994508087787933 + type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 0 + - rid: 1219994508087787934 + type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + - rid: 1219994508087787935 + type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 0 + - rid: 1219994508087787936 + type: {class: WaitOnSlot, ns: Editor.Dialogue, asm: AppleHillsEditor} + data: + - rid: 1219994508087787938 + type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + - rid: 1219994508087787946 + type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor} + data: + m_Guid: + m_Value0: 16523742220227669027 + m_Value1: 12072672733572090161 + m_HashGuid: + serializedVersion: 2 + Hash: 236ccbb4002050e531c91b2ee3bf8aa7 + m_Version: 2 + m_Position: {x: 1347.0507, y: 296.67874} + m_Title: + m_Tooltip: + m_NodePreviewModel: + rid: -2 + m_State: 0 + m_InputConstantsById: + m_KeyList: + - __option_DialogueLineType + - __option_NoLines + - RequiredPuzzleStep + - DefaultDialogueLine + - LoopThroughDefaultLines + m_ValueList: + - rid: 1219994508087787947 + - rid: 1219994508087787948 + - rid: 1219994508087787949 + - rid: 1219994508087787950 + - rid: 1219994508087787951 + m_InputPortInfos: + expandedPortsById: + m_KeyList: [] + m_ValueList: + m_OutputPortInfos: + expandedPortsById: + m_KeyList: [] + m_ValueList: + m_Collapsed: 0 + m_CurrentModeIndex: 0 + m_ElementColor: + m_Color: {r: 0, g: 0, b: 0, a: 0} + m_HasUserColor: 0 + m_Node: + rid: 1219994508087787952 + - rid: 1219994508087787947 + type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + m_Value: 0 + m_EnumType: + m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + - rid: 1219994508087787948 + type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 1 + - rid: 1219994508087787949 + type: {class: 'Constant`1[[PuzzleStepSO, AppleHillsScripts]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: {fileID: 0} + - rid: 1219994508087787950 + type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: + - rid: 1219994508087787951 + type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor} + data: + m_Value: 0 + - rid: 1219994508087787952 + type: {class: WaitOnPuzzleStep, ns: Editor.Dialogue, asm: AppleHillsEditor} + data: diff --git a/Assets/Scripts/Interactions/Interactable.cs b/Assets/Scripts/Interactions/Interactable.cs index f39baed3..1bdb6b78 100644 --- a/Assets/Scripts/Interactions/Interactable.cs +++ b/Assets/Scripts/Interactions/Interactable.cs @@ -25,7 +25,7 @@ namespace Interactions public UnityEvent interactionInterrupted; public UnityEvent characterArrived; public UnityEvent interactionComplete; - + // Helpers for managing interaction state private bool _interactionInProgress; private PlayerTouchController _playerRef; diff --git a/Assets/Scripts/Interactions/ItemSlot.cs b/Assets/Scripts/Interactions/ItemSlot.cs index cd529315..4c9abf57 100644 --- a/Assets/Scripts/Interactions/ItemSlot.cs +++ b/Assets/Scripts/Interactions/ItemSlot.cs @@ -1,18 +1,38 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; +using System; // for Action namespace Interactions { + // New enum describing possible states for the slotted item + public enum ItemSlotState + { + None, + Correct, + Incorrect, + Forbidden + } + /// /// Interaction requirement that allows slotting, swapping, or picking up items in a slot. /// [RequireComponent(typeof(Interactable))] public class ItemSlot : Pickup { + // Tracks the current state of the slotted item + private ItemSlotState _currentState = ItemSlotState.None; + + /// + /// Read-only access to the current slotted item state. + /// + public ItemSlotState CurrentSlottedState => _currentState; + public UnityEvent onItemSlotted; public UnityEvent onItemSlotRemoved; public UnityEvent onCorrectItemSlotted; + // Native C# event alternative to the UnityEvent for code-only subscribers + public event Action OnCorrectItemSlotted; public UnityEvent onIncorrectItemSlotted; public UnityEvent onForbiddenItemSlotted; private PickupItemData _currentlySlottedItemData; @@ -48,6 +68,7 @@ namespace Interactions { DebugUIMessage.Show("Can't place that here.", Color.red); onForbiddenItemSlotted?.Invoke(); + _currentState = ItemSlotState.Forbidden; Interactable.BroadcastInteractionComplete(false); return; } @@ -62,6 +83,7 @@ namespace Interactions { FollowerController.TryPickupItem(_currentlySlottedItemObject, _currentlySlottedItemData, false); onItemSlotRemoved?.Invoke(); + _currentState = ItemSlotState.None; SlotItem(heldItemObj, heldItemData, _currentlySlottedItemObject == null); return; } @@ -109,6 +131,8 @@ namespace Interactions { _currentlySlottedItemObject = null; _currentlySlottedItemData = null; + // Clear state when no item is slotted + _currentState = ItemSlotState.None; } else { @@ -133,6 +157,8 @@ namespace Interactions { DebugUIMessage.Show("You correctly slotted " + itemToSlotData.itemName + " into: " + itemData.itemName, Color.green); onCorrectItemSlotted?.Invoke(); + OnCorrectItemSlotted?.Invoke(itemData, _currentlySlottedItemData); + _currentState = ItemSlotState.Correct; } Interactable.BroadcastInteractionComplete(true); @@ -143,6 +169,7 @@ namespace Interactions { DebugUIMessage.Show("I'm not sure this works.", Color.yellow); onIncorrectItemSlotted?.Invoke(); + _currentState = ItemSlotState.Incorrect; } Interactable.BroadcastInteractionComplete(false); } diff --git a/Assets/Scripts/Interactions/Pickup.cs b/Assets/Scripts/Interactions/Pickup.cs index 864667f7..9827523a 100644 --- a/Assets/Scripts/Interactions/Pickup.cs +++ b/Assets/Scripts/Interactions/Pickup.cs @@ -1,5 +1,6 @@ using Input; using UnityEngine; +using System; // added for Action namespace Interactions { @@ -11,6 +12,9 @@ namespace Interactions protected Interactable Interactable; private PlayerTouchController _playerRef; protected FollowerController FollowerController; + + // Event: invoked when the item was picked up successfully + public event Action OnItemPickedUp; /// /// Unity Awake callback. Sets up icon, interactable, and event handlers. @@ -89,7 +93,14 @@ namespace Interactions } FollowerController?.TryPickupItem(gameObject, itemData); - Interactable.BroadcastInteractionComplete(combinationResult == FollowerController.CombinationResult.NotApplicable); + bool wasPickedUp = (combinationResult == FollowerController.CombinationResult.NotApplicable); + Interactable.BroadcastInteractionComplete(wasPickedUp); + + // Invoke native C# event when the item was picked up successfully + if (wasPickedUp) + { + OnItemPickedUp?.Invoke(itemData); + } } } } \ No newline at end of file diff --git a/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs b/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs index d1347484..f19ff65c 100644 --- a/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs +++ b/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs @@ -95,7 +95,7 @@ namespace PuzzleS if (success) { Debug.Log($"[Puzzles] Step interacted: {stepData?.stepId} on {gameObject.name}"); - PuzzleManager.Instance?.OnStepCompleted(stepData); + PuzzleManager.Instance?.MarkPuzzleStepCompleted(stepData); } } } diff --git a/Assets/Scripts/PuzzleS/PuzzleManager.cs b/Assets/Scripts/PuzzleS/PuzzleManager.cs index 45412a68..77f1cdb4 100644 --- a/Assets/Scripts/PuzzleS/PuzzleManager.cs +++ b/Assets/Scripts/PuzzleS/PuzzleManager.cs @@ -1,208 +1,208 @@ -using UnityEngine; +using System; using System.Collections.Generic; -using PuzzleS; +using UnityEngine; using UnityEngine.SceneManagement; -using System; // added for Action -/// -/// Manages puzzle step registration, dependency management, and step completion for the puzzle system. -/// -public class PuzzleManager : MonoBehaviour +namespace PuzzleS { - private static PuzzleManager _instance; - private static bool _isQuitting = false; - /// - /// Singleton instance of the PuzzleManager. + /// Manages puzzle step registration, dependency management, and step completion for the puzzle system. /// - public static PuzzleManager Instance + public class PuzzleManager : MonoBehaviour { - get + private static PuzzleManager _instance; + private static bool _isQuitting; + + /// + /// Singleton instance of the PuzzleManager. + /// + public static PuzzleManager Instance { - if (_instance == null && Application.isPlaying && !_isQuitting) + get { - _instance = FindAnyObjectByType(); - if (_instance == null) + if (_instance == null && Application.isPlaying && !_isQuitting) { - var go = new GameObject("PuzzleManager"); - _instance = go.AddComponent(); - // DontDestroyOnLoad(go); + _instance = FindAnyObjectByType(); + if (_instance == null) + { + var go = new GameObject("PuzzleManager"); + _instance = go.AddComponent(); + // DontDestroyOnLoad(go); + } + } + return _instance; + } + } + + // Events to notify about step lifecycle + public event Action OnStepCompleted; + public event Action OnStepUnlocked; + + private HashSet _completedSteps = new HashSet(); + private HashSet _unlockedSteps = new HashSet(); + // Registration for ObjectiveStepBehaviour + private Dictionary _stepBehaviours = new Dictionary(); + // Runtime dependency graph + private Dictionary> _runtimeDependencies = new Dictionary>(); + + void Awake() + { + _instance = this; + // DontDestroyOnLoad(gameObject); + SceneManager.sceneLoaded += OnSceneLoaded; + } + + void OnDestroy() + { + SceneManager.sceneLoaded -= OnSceneLoaded; + } + + private void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + BuildRuntimeDependencies(); + UnlockInitialSteps(); + } + + /// + /// Registers a step behaviour with the manager. + /// + /// The step behaviour to register. + public void RegisterStepBehaviour(ObjectiveStepBehaviour behaviour) + { + if (behaviour?.stepData == null) return; + if (!_stepBehaviours.ContainsKey(behaviour.stepData)) + { + _stepBehaviours.Add(behaviour.stepData, behaviour); + Debug.Log($"[Puzzles] Registered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); + } + } + + /// + /// Unregisters a step behaviour from the manager. + /// + /// The step behaviour to unregister. + public void UnregisterStepBehaviour(ObjectiveStepBehaviour behaviour) + { + if (behaviour?.stepData == null) return; + _stepBehaviours.Remove(behaviour.stepData); + Debug.Log($"[Puzzles] Unregistered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); + } + + /// + /// Builds the runtime dependency graph for all registered steps. + /// + private void BuildRuntimeDependencies() + { + _runtimeDependencies = PuzzleGraphUtility.BuildDependencyGraph(_stepBehaviours.Keys); + foreach (var step in _runtimeDependencies.Keys) + { + foreach (var dep in _runtimeDependencies[step]) + { + Debug.Log($"[Puzzles] Step {step.stepId} depends on {dep.stepId}"); } } - return _instance; + Debug.Log($"[Puzzles] Runtime dependencies built. Total steps: {_stepBehaviours.Count}"); } - } - // Events to notify about step lifecycle - public event Action StepCompleted; - public event Action StepUnlocked; - - private HashSet completedSteps = new HashSet(); - private HashSet unlockedSteps = new HashSet(); - - // Registration for ObjectiveStepBehaviour - private Dictionary stepBehaviours = new Dictionary(); - - // Runtime dependency graph - private Dictionary> runtimeDependencies = new Dictionary>(); - - void Awake() - { - _instance = this; - // DontDestroyOnLoad(gameObject); - SceneManager.sceneLoaded += OnSceneLoaded; - } - - void OnDestroy() - { - SceneManager.sceneLoaded -= OnSceneLoaded; - } - - private void OnSceneLoaded(Scene scene, LoadSceneMode mode) - { - BuildRuntimeDependencies(); - UnlockInitialSteps(); - } - - /// - /// Registers a step behaviour with the manager. - /// - /// The step behaviour to register. - public void RegisterStepBehaviour(ObjectiveStepBehaviour behaviour) - { - if (behaviour?.stepData == null) return; - if (!stepBehaviours.ContainsKey(behaviour.stepData)) + /// + /// Unlocks all initial steps (those with no dependencies). + /// + private void UnlockInitialSteps() { - stepBehaviours.Add(behaviour.stepData, behaviour); - Debug.Log($"[Puzzles] Registered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); - } - } - - /// - /// Unregisters a step behaviour from the manager. - /// - /// The step behaviour to unregister. - public void UnregisterStepBehaviour(ObjectiveStepBehaviour behaviour) - { - if (behaviour?.stepData == null) return; - stepBehaviours.Remove(behaviour.stepData); - Debug.Log($"[Puzzles] Unregistered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); - } - - /// - /// Builds the runtime dependency graph for all registered steps. - /// - private void BuildRuntimeDependencies() - { - runtimeDependencies = PuzzleGraphUtility.BuildDependencyGraph(stepBehaviours.Keys); - foreach (var step in runtimeDependencies.Keys) - { - foreach (var dep in runtimeDependencies[step]) + var initialSteps = PuzzleGraphUtility.FindInitialSteps(_runtimeDependencies); + foreach (var step in initialSteps) { - Debug.Log($"[Puzzles] Step {step.stepId} depends on {dep.stepId}"); + Debug.Log($"[Puzzles] Initial step unlocked: {step.stepId}"); + UnlockStep(step); } } - Debug.Log($"[Puzzles] Runtime dependencies built. Total steps: {stepBehaviours.Count}"); - } - /// - /// Unlocks all initial steps (those with no dependencies). - /// - private void UnlockInitialSteps() - { - var initialSteps = PuzzleGraphUtility.FindInitialSteps(runtimeDependencies); - foreach (var step in initialSteps) + /// + /// Called when a step is completed. Unlocks dependent steps if their dependencies are met. + /// + /// The completed step. + public void MarkPuzzleStepCompleted(PuzzleStepSO step) { - Debug.Log($"[Puzzles] Initial step unlocked: {step.stepId}"); - UnlockStep(step); - } - } + if (_completedSteps.Contains(step)) return; + _completedSteps.Add(step); + Debug.Log($"[Puzzles] Step completed: {step.stepId}"); - /// - /// Called when a step is completed. Unlocks dependent steps if their dependencies are met. - /// - /// The completed step. - public void OnStepCompleted(PuzzleStepSO step) - { - if (completedSteps.Contains(step)) return; - completedSteps.Add(step); - Debug.Log($"[Puzzles] Step completed: {step.stepId}"); + // Broadcast completion + OnStepCompleted?.Invoke(step); - // Broadcast completion - StepCompleted?.Invoke(step); - - foreach (var unlock in step.unlocks) - { - if (AreRuntimeDependenciesMet(unlock)) + foreach (var unlock in step.unlocks) { - Debug.Log($"[Puzzles] Unlocking step {unlock.stepId} after completing {step.stepId}"); - UnlockStep(unlock); + if (AreRuntimeDependenciesMet(unlock)) + { + Debug.Log($"[Puzzles] Unlocking step {unlock.stepId} after completing {step.stepId}"); + UnlockStep(unlock); + } + else + { + Debug.Log($"[Puzzles] Step {unlock.stepId} not unlocked yet, waiting for other dependencies"); + } } - else + CheckPuzzleCompletion(); + } + + /// + /// Checks if all dependencies for a step are met. + /// + /// The step to check. + /// True if all dependencies are met, false otherwise. + private bool AreRuntimeDependenciesMet(PuzzleStepSO step) + { + if (!_runtimeDependencies.ContainsKey(step) || _runtimeDependencies[step].Count == 0) return true; + foreach (var dep in _runtimeDependencies[step]) { - Debug.Log($"[Puzzles] Step {unlock.stepId} not unlocked yet, waiting for other dependencies"); + if (!_completedSteps.Contains(dep)) return false; + } + return true; + } + + /// + /// Unlocks a specific step and notifies its behaviour. + /// + /// The step to unlock. + private void UnlockStep(PuzzleStepSO step) + { + if (_unlockedSteps.Contains(step)) return; + _unlockedSteps.Add(step); + if (_stepBehaviours.TryGetValue(step, out var behaviour)) + { + behaviour.UnlockStep(); + } + Debug.Log($"[Puzzles] Step unlocked: {step.stepId}"); + + // Broadcast unlock + OnStepUnlocked?.Invoke(step); + } + + /// + /// Checks if the puzzle is complete (all steps finished). + /// + private void CheckPuzzleCompletion() + { + if (_completedSteps.Count == _stepBehaviours.Count) + { + Debug.Log("[Puzzles] Puzzle complete! All steps finished."); + // TODO: Fire puzzle complete event or trigger outcome logic } } - CheckPuzzleCompletion(); - } - /// - /// Checks if all dependencies for a step are met. - /// - /// The step to check. - /// True if all dependencies are met, false otherwise. - private bool AreRuntimeDependenciesMet(PuzzleStepSO step) - { - if (!runtimeDependencies.ContainsKey(step) || runtimeDependencies[step].Count == 0) return true; - foreach (var dep in runtimeDependencies[step]) + /// + /// Returns whether a step is already unlocked. + /// + public bool IsStepUnlocked(PuzzleStepSO step) { - if (!completedSteps.Contains(dep)) return false; + BuildRuntimeDependencies(); + UnlockInitialSteps(); + return _unlockedSteps.Contains(step); } - return true; - } - /// - /// Unlocks a specific step and notifies its behaviour. - /// - /// The step to unlock. - private void UnlockStep(PuzzleStepSO step) - { - if (unlockedSteps.Contains(step)) return; - unlockedSteps.Add(step); - if (stepBehaviours.TryGetValue(step, out var behaviour)) + void OnApplicationQuit() { - behaviour.UnlockStep(); + _isQuitting = true; } - Debug.Log($"[Puzzles] Step unlocked: {step.stepId}"); - - // Broadcast unlock - StepUnlocked?.Invoke(step); - } - - /// - /// Checks if the puzzle is complete (all steps finished). - /// - private void CheckPuzzleCompletion() - { - if (completedSteps.Count == stepBehaviours.Count) - { - Debug.Log("[Puzzles] Puzzle complete! All steps finished."); - // TODO: Fire puzzle complete event or trigger outcome logic - } - } - - /// - /// Returns whether a step is already unlocked. - /// - public bool IsStepUnlocked(PuzzleStepSO step) - { - BuildRuntimeDependencies(); - UnlockInitialSteps(); - return unlockedSteps.Contains(step); - } - - void OnApplicationQuit() - { - _isQuitting = true; } } diff --git a/Assets/Settings/InteractionSettings.asset b/Assets/Settings/InteractionSettings.asset index eb6a2465..d3804a57 100644 --- a/Assets/Settings/InteractionSettings.asset +++ b/Assets/Settings/InteractionSettings.asset @@ -21,8 +21,8 @@ MonoBehaviour: basePickupPrefab: {fileID: 7447346505753002421, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3} levelSwitchMenuPrefab: {fileID: 4062459998181038721, guid: de2ed28e4200a4340a5af4086c98a0dc, type: 3} combinationRules: - - itemA: {fileID: 11400000, guid: 33e7ca06b22108d4e802486e08bcdfd1, type: 2} - itemB: {fileID: 11400000, guid: 8b2616beb14825a46b9b1ed85ad3cb25, type: 2} + - itemA: {fileID: 11400000, guid: 8b2616beb14825a46b9b1ed85ad3cb25, type: 2} + itemB: {fileID: 11400000, guid: 33e7ca06b22108d4e802486e08bcdfd1, type: 2} resultPrefab: {fileID: 1610562450228973293, guid: 58654125374567147839eb382fcde422, type: 3} - itemA: {fileID: 11400000, guid: 983414276ae3f004c854e9c450f27f88, type: 2} itemB: {fileID: 11400000, guid: 0c6986639ca176a419c92f5a327d95ce, type: 2}