diff --git a/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset b/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset index c94410e0..34a52fdb 100644 --- a/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset +++ b/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset @@ -14,7 +14,17 @@ MonoBehaviour: m_EditorClassIdentifier: m_GroupName: Default Local Group m_GUID: 6f3207429a65b3e4b83935ac19791077 - m_SerializeEntries: [] + m_SerializeEntries: + - m_GUID: 1a9d24004b795e147b8544845a7a9ae3 + m_Address: Puzzles/Testing + m_ReadOnly: 0 + m_SerializedLabels: [] + FlaggedDuringContentUpdateRestriction: 0 + - m_GUID: d28c589c05c122f449a8b34e696cda53 + m_Address: Puzzles/Quarry + m_ReadOnly: 0 + m_SerializedLabels: [] + FlaggedDuringContentUpdateRestriction: 0 m_ReadOnly: 0 m_Settings: {fileID: 11400000, guid: 11da9bb90d9dd5848b4f7629415a6937, type: 2} m_SchemaSet: diff --git a/Assets/Data/Puzzles/Quarry.meta b/Assets/Data/Puzzles/Quarry.meta new file mode 100644 index 00000000..36f2ab7f --- /dev/null +++ b/Assets/Data/Puzzles/Quarry.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a17ef190d30246143a8f7a83591f2c1f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Data/Puzzles/ChocolateBirdPuzzle.meta b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle.meta similarity index 100% rename from Assets/Data/Puzzles/ChocolateBirdPuzzle.meta rename to Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle.meta diff --git a/Assets/Data/Puzzles/ChocolateBirdPuzzle/LureWolter.asset b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/LureWolter.asset similarity index 95% rename from Assets/Data/Puzzles/ChocolateBirdPuzzle/LureWolter.asset rename to Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/LureWolter.asset index 8f148371..bebae427 100644 --- a/Assets/Data/Puzzles/ChocolateBirdPuzzle/LureWolter.asset +++ b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/LureWolter.asset @@ -13,7 +13,7 @@ MonoBehaviour: m_Name: LureWolter m_EditorClassIdentifier: stepId: LureWolter - displayName: Wolter Lured! + displayName: Wolter Lured!! description: Place Chocolate in the luring spot. icon: {fileID: 0} unlocks: diff --git a/Assets/Data/Puzzles/ChocolateBirdPuzzle/LureWolter.asset.meta b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/LureWolter.asset.meta similarity index 100% rename from Assets/Data/Puzzles/ChocolateBirdPuzzle/LureWolter.asset.meta rename to Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/LureWolter.asset.meta diff --git a/Assets/Data/Puzzles/ChocolateBirdPuzzle/PickChocolate.asset b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/PickChocolate.asset similarity index 88% rename from Assets/Data/Puzzles/ChocolateBirdPuzzle/PickChocolate.asset rename to Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/PickChocolate.asset index 3acec8c0..5510f772 100644 --- a/Assets/Data/Puzzles/ChocolateBirdPuzzle/PickChocolate.asset +++ b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/PickChocolate.asset @@ -17,4 +17,4 @@ MonoBehaviour: description: Avoid the gaze of the picnic lovers and steal their loot. icon: {fileID: 0} unlocks: - - {fileID: 0} + - {fileID: 11400000, guid: d0851a7610551104fa285c0748549d90, type: 2} diff --git a/Assets/Data/Puzzles/ChocolateBirdPuzzle/PickChocolate.asset.meta b/Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/PickChocolate.asset.meta similarity index 100% rename from Assets/Data/Puzzles/ChocolateBirdPuzzle/PickChocolate.asset.meta rename to Assets/Data/Puzzles/Quarry/ChocolateBirdPuzzle/PickChocolate.asset.meta diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle.meta b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle.meta similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle.meta rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle.meta diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle/InteractWithBallTree.asset b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/InteractWithBallTree.asset similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle/InteractWithBallTree.asset rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/InteractWithBallTree.asset diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle/InteractWithBallTree.asset.meta b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/InteractWithBallTree.asset.meta similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle/InteractWithBallTree.asset.meta rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/InteractWithBallTree.asset.meta diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle/PickUpFootball.asset b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PickUpFootball.asset similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle/PickUpFootball.asset rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PickUpFootball.asset diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle/PickUpFootball.asset.meta b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PickUpFootball.asset.meta similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle/PickUpFootball.asset.meta rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PickUpFootball.asset.meta diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset diff --git a/Assets/Data/Puzzles/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset.meta b/Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset.meta similarity index 100% rename from Assets/Data/Puzzles/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset.meta rename to Assets/Data/Puzzles/Quarry/FootballBirdPuzzle/PlaceFootballInLureSpotA.asset.meta diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle.meta b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle.meta similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle.meta rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle.meta diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/InteractWLawnMower.asset similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/InteractWLawnMower.asset diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset.meta b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/InteractWLawnMower.asset.meta similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset.meta rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/InteractWLawnMower.asset.meta diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/PickUpNails.asset b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PickUpNails.asset similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle/PickUpNails.asset rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PickUpNails.asset diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/PickUpNails.asset.meta b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PickUpNails.asset.meta similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle/PickUpNails.asset.meta rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PickUpNails.asset.meta diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/PlaceNailsinlureC.asset b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PlaceNailsinlureC.asset similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle/PlaceNailsinlureC.asset rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PlaceNailsinlureC.asset diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/PlaceNailsinlureC.asset.meta b/Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PlaceNailsinlureC.asset.meta similarity index 100% rename from Assets/Data/Puzzles/HammerBirdPuzzle/PlaceNailsinlureC.asset.meta rename to Assets/Data/Puzzles/Quarry/HammerBirdPuzzle/PlaceNailsinlureC.asset.meta diff --git a/Assets/Data/Puzzles/Quarry/Quarry.asset b/Assets/Data/Puzzles/Quarry/Quarry.asset new file mode 100644 index 00000000..021875da --- /dev/null +++ b/Assets/Data/Puzzles/Quarry/Quarry.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0a79780a5a0d498084afd737d4515e3b, type: 3} + m_Name: Quarry + m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.PuzzleLevelDataSO + levelId: Quarry + displayName: Quarry + allSteps: + - {fileID: 11400000, guid: d0851a7610551104fa285c0748549d90, type: 2} + - {fileID: 11400000, guid: ed967c44f3a8b914aabc1539f774efc7, type: 2} + - {fileID: 11400000, guid: 8ac614a698631554ab8ac39aed04a189, type: 2} + - {fileID: 11400000, guid: 6386246caab8faa40b2da221d9ab9b8a, type: 2} + - {fileID: 11400000, guid: 0fb0ab2b55d93a24685e9f6651adcf30, type: 2} + - {fileID: 11400000, guid: ea383d1dee861f54c9a1d4f32a2f6afc, type: 2} + - {fileID: 11400000, guid: f9da68caaae2a244885a13cf2e2e45c0, type: 2} + - {fileID: 11400000, guid: 28848561ff31fe24ea9f8590dee0bf8f, type: 2} + - {fileID: 11400000, guid: 5700dd3bf16fa9e4aa9905379118d1bd, type: 2} + - {fileID: 11400000, guid: 37409d749a15970438d761d1d658d7a6, type: 2} + initialSteps: + - {fileID: 11400000, guid: ed967c44f3a8b914aabc1539f774efc7, type: 2} + - {fileID: 11400000, guid: 8ac614a698631554ab8ac39aed04a189, type: 2} + - {fileID: 11400000, guid: ea383d1dee861f54c9a1d4f32a2f6afc, type: 2} diff --git a/Assets/Data/Puzzles/Quarry/Quarry.asset.meta b/Assets/Data/Puzzles/Quarry/Quarry.asset.meta new file mode 100644 index 00000000..fba4d3b7 --- /dev/null +++ b/Assets/Data/Puzzles/Quarry/Quarry.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d28c589c05c122f449a8b34e696cda53 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Data/Puzzles/SoundBirdPuzzle.meta b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle.meta similarity index 100% rename from Assets/Data/Puzzles/SoundBirdPuzzle.meta rename to Assets/Data/Puzzles/Quarry/SoundBirdPuzzle.meta diff --git a/Assets/Data/Puzzles/SoundBirdPuzzle/HeadbandPickup.asset b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/HeadbandPickup.asset similarity index 87% rename from Assets/Data/Puzzles/SoundBirdPuzzle/HeadbandPickup.asset rename to Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/HeadbandPickup.asset index fc9f6ab2..e6d15665 100644 --- a/Assets/Data/Puzzles/SoundBirdPuzzle/HeadbandPickup.asset +++ b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/HeadbandPickup.asset @@ -16,4 +16,5 @@ MonoBehaviour: displayName: Picked up Headband! description: Once Wolter jumps out of the bushes, the headband is interactable. icon: {fileID: 0} - unlocks: [] + unlocks: + - {fileID: 11400000, guid: 37409d749a15970438d761d1d658d7a6, type: 2} diff --git a/Assets/Data/Puzzles/SoundBirdPuzzle/HeadbandPickup.asset.meta b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/HeadbandPickup.asset.meta similarity index 100% rename from Assets/Data/Puzzles/SoundBirdPuzzle/HeadbandPickup.asset.meta rename to Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/HeadbandPickup.asset.meta diff --git a/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/SoundBirdDeafen.asset b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/SoundBirdDeafen.asset new file mode 100644 index 00000000..3f9383a4 --- /dev/null +++ b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/SoundBirdDeafen.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 84e39aac66cf4a10a89abc01b04b13af, type: 3} + m_Name: SoundBirdDeafen + m_EditorClassIdentifier: + stepId: Deafen Bird + displayName: Deaf SoundBird + description: sds + icon: {fileID: 0} + unlocks: [] diff --git a/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/SoundBirdDeafen.asset.meta b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/SoundBirdDeafen.asset.meta new file mode 100644 index 00000000..efd5eb28 --- /dev/null +++ b/Assets/Data/Puzzles/Quarry/SoundBirdPuzzle/SoundBirdDeafen.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 37409d749a15970438d761d1d658d7a6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Data/Puzzles/Testing.meta b/Assets/Data/Puzzles/Testing.meta new file mode 100644 index 00000000..f87db99d --- /dev/null +++ b/Assets/Data/Puzzles/Testing.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9958845b52d0d7468c9c36a6969e9ea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle.meta b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle.meta similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle.meta rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle.meta diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Ass1.asset b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass1.asset similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Ass1.asset rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass1.asset diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Ass1.asset.meta b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass1.asset.meta similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Ass1.asset.meta rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass1.asset.meta diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Ass2.asset b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass2.asset similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Ass2.asset rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass2.asset diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Ass2.asset.meta b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass2.asset.meta similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Ass2.asset.meta rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass2.asset.meta diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Ass3.asset b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass3.asset similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Ass3.asset rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass3.asset diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Ass3.asset.meta b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass3.asset.meta similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Ass3.asset.meta rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Ass3.asset.meta diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Head.asset b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Head.asset similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Head.asset rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Head.asset diff --git a/Assets/Data/Puzzles/ExampleAssPuzzle/Head.asset.meta b/Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Head.asset.meta similarity index 100% rename from Assets/Data/Puzzles/ExampleAssPuzzle/Head.asset.meta rename to Assets/Data/Puzzles/Testing/ExampleAssPuzzle/Head.asset.meta diff --git a/Assets/Data/Puzzles/Testing/Testing.asset b/Assets/Data/Puzzles/Testing/Testing.asset new file mode 100644 index 00000000..cf3ef9f7 --- /dev/null +++ b/Assets/Data/Puzzles/Testing/Testing.asset @@ -0,0 +1,24 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0a79780a5a0d498084afd737d4515e3b, type: 3} + m_Name: Testing + m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.PuzzleLevelDataSO + levelId: Testing + displayName: Testing + allSteps: + - {fileID: 11400000, guid: 0b13ff4f31443b74281b13e0eef865c2, type: 2} + - {fileID: 11400000, guid: a84cbe9804e13f74e857c55d90cc10d1, type: 2} + - {fileID: 11400000, guid: 13b0c411066f85a41ba40c3bbbc281ed, type: 2} + - {fileID: 11400000, guid: 9de0c57af6191384e96e2ba7c04a3d0d, type: 2} + initialSteps: + - {fileID: 11400000, guid: 0b13ff4f31443b74281b13e0eef865c2, type: 2} + - {fileID: 11400000, guid: a84cbe9804e13f74e857c55d90cc10d1, type: 2} diff --git a/Assets/Data/Puzzles/Testing/Testing.asset.meta b/Assets/Data/Puzzles/Testing/Testing.asset.meta new file mode 100644 index 00000000..70d7ef48 --- /dev/null +++ b/Assets/Data/Puzzles/Testing/Testing.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1a9d24004b795e147b8544845a7a9ae3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/PuzzleAssetProcessor.cs b/Assets/Editor/PuzzleAssetProcessor.cs new file mode 100644 index 00000000..a3fdb7d4 --- /dev/null +++ b/Assets/Editor/PuzzleAssetProcessor.cs @@ -0,0 +1,321 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEditor.AddressableAssets; +using UnityEditor.AddressableAssets.Settings; + +namespace PuzzleS.Editor +{ + /// + /// Handles asset post-processing for puzzle step data. + /// Automatically builds level data from folder structure. + /// + public class PuzzleAssetProcessor : AssetPostprocessor + { + // Base path for puzzle data + private const string PuzzleDataBasePath = "Assets/Data/Puzzles"; + + /// + /// Called after assets have been imported, deleted, or moved. + /// + private static void OnPostprocessAllAssets( + string[] importedAssets, + string[] deletedAssets, + string[] movedAssets, + string[] movedFromAssetPaths) + { + bool puzzleAssetsChanged = false; + + // Check for changes to puzzle step assets + foreach (string assetPath in importedAssets.Concat(movedAssets)) + { + if (IsPuzzleAssetPath(assetPath) && Path.GetExtension(assetPath) == ".asset") + { + var asset = AssetDatabase.LoadAssetAtPath(assetPath); + + if (asset is PuzzleStepSO) + { + // Find which level this step belongs to + string assetDir = Path.GetDirectoryName(assetPath); + string levelFolderPath = FindLevelFolder(assetDir); + + if (!string.IsNullOrEmpty(levelFolderPath)) + { + ProcessPuzzleLevelFolder(levelFolderPath); + puzzleAssetsChanged = true; + } + } + } + } + + // Check for changes to puzzle folder structure + foreach (string assetPath in deletedAssets.Concat(movedFromAssetPaths)) + { + if (IsPuzzleAssetPath(assetPath)) + { + // Extract parent folders for processing + string assetDir = Path.GetDirectoryName(assetPath); + string levelFolderPath = FindLevelFolder(assetDir); + + if (!string.IsNullOrEmpty(levelFolderPath) && Directory.Exists(levelFolderPath)) + { + ProcessPuzzleLevelFolder(levelFolderPath); + puzzleAssetsChanged = true; + } + } + } + + if (puzzleAssetsChanged) + { + // Make sure changes are saved + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + Debug.Log("[PuzzleProcessor] Puzzle data processing complete"); + } + } + + /// + /// Checks if an asset path is within the puzzle data folder structure + /// + private static bool IsPuzzleAssetPath(string assetPath) + { + // Unity's AssetDatabase always uses forward slashes, so we need to normalize for comparison + string normalizedPath = assetPath.Replace('\\', '/'); + string normalizedBasePath = PuzzleDataBasePath; + + return normalizedPath.StartsWith(normalizedBasePath) && + !normalizedPath.Contains("/.") && // Skip hidden folders + !Path.GetExtension(normalizedPath).Equals(".meta"); + } + + /// + /// Find the level folder that contains this asset path + /// Assumes level folders are direct children of PuzzleDataBasePath + /// + private static string FindLevelFolder(string assetPath) + { + if (string.IsNullOrEmpty(assetPath)) return null; + + // Unity's AssetDatabase always uses forward slashes + string normalizedPath = assetPath.Replace('\\', '/'); + + if (!normalizedPath.StartsWith(PuzzleDataBasePath)) + return null; + + // Get the relative path from the base path + string relativePath = normalizedPath.Substring(PuzzleDataBasePath.Length); + if (relativePath.StartsWith("/")) + relativePath = relativePath.Substring(1); + + // Split into path components and get the first folder (level name) + string[] pathComponents = relativePath.Split('/'); + + // First component after PuzzleDataBasePath should be the level name + if (pathComponents.Length > 0) + { + // Use proper path joining with Unity's forward slash convention + return PuzzleDataBasePath + "/" + pathComponents[0]; + } + + return null; + } + + /// + /// Process a level folder to build/update a PuzzleLevelDataSO with all puzzle steps + /// + private static void ProcessPuzzleLevelFolder(string folderPath) + { + if (!Directory.Exists(folderPath)) return; + + // Get level name from folder name + string levelName = Path.GetFileName(folderPath); + if (string.IsNullOrEmpty(levelName)) return; + + // Find all puzzle step assets in this level (including subfolders) + var stepAssets = FindAssetsOfTypeRecursive(folderPath); + if (stepAssets.Count == 0) return; + + // Get or create level data asset + var levelDataAsset = GetOrCreateLevelDataAsset(folderPath, levelName); + if (levelDataAsset == null) return; + + // Update level data + levelDataAsset.levelId = levelName; + levelDataAsset.displayName = levelName; // Default display name matches folder name + levelDataAsset.allSteps = stepAssets; + + // Pre-process initial steps (those with no dependencies) + levelDataAsset.initialSteps = FindInitialSteps(stepAssets); + + // Pre-process dependencies (which steps are required by each step) + PrecomputeDependencies(levelDataAsset); + + // Mark as dirty and save + EditorUtility.SetDirty(levelDataAsset); + + // Setup addressables + SetupAddressableAsset(AssetDatabase.GetAssetPath(levelDataAsset), $"Puzzles/{levelName}"); + + Debug.Log($"[PuzzleProcessor] Processed level: {levelName} with {stepAssets.Count} steps"); + } + + /// + /// Find all assets of a specific type in a folder and its subfolders + /// + private static List FindAssetsOfTypeRecursive(string folderPath) where T : ScriptableObject + { + var result = new List(); + + if (!Directory.Exists(folderPath)) return result; + + var guids = AssetDatabase.FindAssets("t:" + typeof(T).Name, new[] { folderPath }); + foreach (var guid in guids) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guid); + var asset = AssetDatabase.LoadAssetAtPath(assetPath); + if (asset != null) + { + result.Add(asset); + } + } + + return result; + } + + /// + /// Get existing level data asset or create a new one + /// + private static PuzzleLevelDataSO GetOrCreateLevelDataAsset(string folderPath, string levelName) + { + // Check for existing level data asset + string levelDataAssetPath = $"{folderPath}/{levelName}.asset"; + var levelDataAsset = AssetDatabase.LoadAssetAtPath(levelDataAssetPath); + + if (levelDataAsset == null) + { + // Create new level data asset + levelDataAsset = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(levelDataAsset, levelDataAssetPath); + Debug.Log($"[PuzzleProcessor] Created new level data asset: {levelDataAssetPath}"); + } + + return levelDataAsset; + } + + /// + /// Find steps that have no dependencies (initial steps) + /// + private static List FindInitialSteps(List steps) + { + var initialSteps = new List(); + var dependentSteps = new HashSet(); + + // Find all steps that are dependencies of other steps + foreach (var step in steps) + { + if (step == null) continue; + + foreach (var unlockStep in step.unlocks) + { + if (unlockStep != null && steps.Contains(unlockStep)) + { + dependentSteps.Add(unlockStep); + } + } + } + + // Initial steps are those not depended on by any other step + foreach (var step in steps) + { + if (step != null && !dependentSteps.Contains(step)) + { + initialSteps.Add(step); + } + } + + return initialSteps; + } + + /// + /// Pre-compute dependency information for a puzzle level + /// + private static void PrecomputeDependencies(PuzzleLevelDataSO levelDataAsset) + { + levelDataAsset.stepDependencies.Clear(); + + // Build reverse dependency map (which steps are required by each step) + var reverseDependencies = new Dictionary>(); + + foreach (var step in levelDataAsset.allSteps) + { + if (step == null) continue; + + foreach (var unlockStep in step.unlocks) + { + if (unlockStep == null) continue; + + if (!reverseDependencies.ContainsKey(unlockStep.stepId)) + { + reverseDependencies[unlockStep.stepId] = new List(); + } + + reverseDependencies[unlockStep.stepId].Add(step.stepId); + } + } + + // Convert to serialized form + foreach (var entry in reverseDependencies) + { + levelDataAsset.stepDependencies[entry.Key] = entry.Value.ToArray(); + } + } + + /// + /// Set up an asset as an Addressable with the specified address + /// + private static void SetupAddressableAsset(string assetPath, string address) + { + if (!File.Exists(assetPath)) return; + + // Get Addressable settings + var settings = AddressableAssetSettingsDefaultObject.Settings; + if (settings == null) + { + Debug.LogWarning("[PuzzleProcessor] Addressable Asset Settings not found. Make sure Addressables is set up in your project."); + return; + } + + // Get default group + var defaultGroup = settings.DefaultGroup; + if (defaultGroup == null) + { + Debug.LogWarning("[PuzzleProcessor] Default Addressable Asset Group not found."); + return; + } + + // Get asset GUID + var guid = AssetDatabase.AssetPathToGUID(assetPath); + + // Check if entry exists + var existingEntry = settings.FindAssetEntry(guid); + if (existingEntry != null) + { + // Update existing entry + existingEntry.SetAddress(address); + } + else + { + // Create new entry + settings.CreateOrMoveEntry(guid, defaultGroup); + var newEntry = settings.FindAssetEntry(guid); + if (newEntry != null) + { + newEntry.SetAddress(address); + } + } + } + } +} diff --git a/Assets/Editor/PuzzleAssetProcessor.cs.meta b/Assets/Editor/PuzzleAssetProcessor.cs.meta new file mode 100644 index 00000000..1e34c156 --- /dev/null +++ b/Assets/Editor/PuzzleAssetProcessor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5097566c60d341dbb6f2bf5175b048cb +timeCreated: 1760532147 \ No newline at end of file diff --git a/Assets/Editor/PuzzleChainEditorWindow.cs b/Assets/Editor/PuzzleChainEditorWindow.cs deleted file mode 100644 index 27c140ac..00000000 --- a/Assets/Editor/PuzzleChainEditorWindow.cs +++ /dev/null @@ -1,116 +0,0 @@ -using UnityEditor; -using UnityEngine; -using System.Collections.Generic; - -public class PuzzleChainEditorWindow : EditorWindow -{ - private List puzzleSteps = new List(); - private Dictionary> dependencyGraph; - private Vector2 scrollPos; - private const int INDENT_SIZE = 24; - - [MenuItem("AppleHills/Puzzle Chain Editor")] - public static void ShowWindow() - { - var window = GetWindow("Puzzle Chain Editor"); - window.minSize = new Vector2(600, 400); - window.maxSize = new Vector2(1200, 800); - window.position = new Rect(100, 100, 700, 500); // Reasonable default size and position - } - - private void OnEnable() - { - LoadPuzzleSteps(); - ProcessPuzzleChains(); - } - - private void LoadPuzzleSteps() - { - puzzleSteps.Clear(); - // Find all PuzzleStepSO assets in the project - string[] guids = AssetDatabase.FindAssets("t:PuzzleStepSO"); - foreach (var guid in guids) - { - var path = AssetDatabase.GUIDToAssetPath(guid); - // Only include those under Assets/Data/Puzzles (case-insensitive) - if (path.Replace('\\', '/').StartsWith("Assets/Data/Puzzles", System.StringComparison.OrdinalIgnoreCase)) - { - var step = AssetDatabase.LoadAssetAtPath(path); - if (step != null) - puzzleSteps.Add(step); - } - } - // Remove any nulls just in case - puzzleSteps.RemoveAll(s => s == null); - // Remove nulls from unlocks lists - foreach (var step in puzzleSteps) - { - if (step.unlocks != null) - step.unlocks.RemoveAll(u => u == null); - } - } - - private void ProcessPuzzleChains() - { - // Defensive: ensure no nulls in puzzleSteps or unlocks - puzzleSteps.RemoveAll(s => s == null); - foreach (var step in puzzleSteps) - { - if (step.unlocks != null) - step.unlocks.RemoveAll(u => u == null); - } - dependencyGraph = PuzzleGraphUtility.BuildDependencyGraph(puzzleSteps); - } - - private void OnGUI() - { - EditorGUILayout.LabelField("Puzzle Chain Visualization", EditorStyles.boldLabel); - if (puzzleSteps.Count == 0) - { - EditorGUILayout.HelpBox("No PuzzleStepSO assets found in Assets/Data/Puzzles.", MessageType.Warning); - return; - } - scrollPos = EditorGUILayout.BeginScrollView(scrollPos); - var initialSteps = dependencyGraph != null ? PuzzleGraphUtility.FindInitialSteps(dependencyGraph) : new List(); - foreach (var step in initialSteps) - { - if (step == null) continue; // Defensive - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField($"Step Path: {step.displayName} ({step.stepId})", EditorStyles.largeLabel); - GUILayout.Space(6); - DrawStepTree(step, 0); - EditorGUILayout.EndVertical(); - GUILayout.Space(12); // Space between step paths - } - EditorGUILayout.EndScrollView(); - } - - private void DrawStepTree(PuzzleStepSO step, int indent) - { - if (step == null) { - EditorGUILayout.LabelField("[Missing Step]", EditorStyles.boldLabel); - return; - } - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(indent * INDENT_SIZE); - EditorGUILayout.BeginVertical("box"); - EditorGUILayout.LabelField($"{step.displayName} ({step.stepId})", EditorStyles.boldLabel); - EditorGUILayout.LabelField(step.description ?? "", EditorStyles.wordWrappedLabel); - GUILayout.Space(4); - if (GUILayout.Button("Open in Inspector", GUILayout.Width(150))) - { - Selection.activeObject = step; - EditorGUIUtility.PingObject(step); - } - EditorGUILayout.EndVertical(); - EditorGUILayout.EndHorizontal(); - GUILayout.Space(6); - if (step.unlocks != null) - { - foreach (var unlock in step.unlocks) - { - DrawStepTree(unlock, indent + 1); - } - } - } -} diff --git a/Assets/Editor/PuzzleChainEditorWindow.cs.meta b/Assets/Editor/PuzzleChainEditorWindow.cs.meta deleted file mode 100644 index 26053c53..00000000 --- a/Assets/Editor/PuzzleChainEditorWindow.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: f7bfaa69d42e45adaa4a44dd143efc2f -timeCreated: 1756991142 \ No newline at end of file diff --git a/Assets/Editor/PuzzleSystem.meta b/Assets/Editor/PuzzleSystem.meta new file mode 100644 index 00000000..66996b2e --- /dev/null +++ b/Assets/Editor/PuzzleSystem.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 453e2745b86c424da42227fbc38ed6d7 +timeCreated: 1760539457 \ No newline at end of file diff --git a/Assets/Editor/PuzzleSystem/PuzzleEditorWindow.cs b/Assets/Editor/PuzzleSystem/PuzzleEditorWindow.cs new file mode 100644 index 00000000..cbbef1d6 --- /dev/null +++ b/Assets/Editor/PuzzleSystem/PuzzleEditorWindow.cs @@ -0,0 +1,875 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using PuzzleS; + +namespace AppleHills.Editor.PuzzleSystem +{ + /// + /// Editor utility for managing puzzle steps and debugging puzzle state at runtime. + /// Provides tabs for both editing puzzle data and runtime debugging. + /// + public class PuzzleEditorWindow : EditorWindow + { + // Paths + private const string PuzzleDataBasePath = "Assets/Data"; + private const string MenuPath = "AppleHills/Puzzle Editor"; + + // Editor state + private List _allPuzzleSteps = new List(); + private Dictionary> _puzzleStepsByFolder = new Dictionary>(); + private PuzzleStepSO _selectedStep; + private Dictionary _folderExpanded = new Dictionary(); + private Vector2 _puzzleListScrollPosition; + private Vector2 _puzzleEditScrollPosition; + private string _searchQuery = ""; + private bool _isDirty = false; + + // Tab management + private int _selectedTab = 0; + private readonly string[] _tabNames = { "Edit", "Debug" }; + + // Runtime debug state + private Dictionary _stepUnlockState = new Dictionary(); + private Dictionary _stepCompletedState = new Dictionary(); + private Vector2 _debugScrollPosition; + private bool _isPlaying = false; + private bool _hasRuntimeData = false; + private PuzzleLevelDataSO _runtimeLevelData; + + // New step creation + private string _newStepName = "New Step"; + private string _selectedFolder = ""; + private bool _showCreateNewStepDialog = false; + + [MenuItem(MenuPath)] + public static void ShowWindow() + { + var window = GetWindow("Puzzle Editor"); + window.minSize = new Vector2(800, 600); + window.Show(); + } + + private void OnEnable() + { + // Load all puzzle steps + LoadAllPuzzleSteps(); + + // Register for undo/redo + Undo.undoRedoPerformed += OnUndoRedo; + + // Set up update callbacks + EditorApplication.update += OnEditorUpdate; + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + } + + private void OnDisable() + { + // Unregister from undo/redo + Undo.undoRedoPerformed -= OnUndoRedo; + + // Unregister from update + EditorApplication.update -= OnEditorUpdate; + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; + } + + private void OnEditorUpdate() + { + // Check if we're in play mode + bool currentlyPlaying = EditorApplication.isPlaying && !EditorApplication.isPaused; + if (_isPlaying != currentlyPlaying) + { + _isPlaying = currentlyPlaying; + Repaint(); + } + + // In play mode, update runtime data periodically + if (_isPlaying) + { + UpdateRuntimeData(); + Repaint(); + } + } + + private void OnUndoRedo() + { + _isDirty = true; + Repaint(); + } + + private void OnPlayModeStateChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.EnteredPlayMode) + { + _isPlaying = true; + _hasRuntimeData = false; + _stepUnlockState.Clear(); + _stepCompletedState.Clear(); + } + else if (state == PlayModeStateChange.ExitingPlayMode) + { + _isPlaying = false; + _hasRuntimeData = false; + _runtimeLevelData = null; + } + + Repaint(); + } + + private void OnGUI() + { + DrawHeader(); + + _selectedTab = GUILayout.Toolbar(_selectedTab, _tabNames); + + EditorGUILayout.Space(); + + switch (_selectedTab) + { + case 0: // Edit tab + DrawEditTab(); + break; + case 1: // Debug tab + DrawDebugTab(); + break; + } + + // Apply any pending changes + if (_isDirty) + { + SaveChanges(); + _isDirty = false; + } + } + + #region Header UI + + private void DrawHeader() + { + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + + if (GUILayout.Button("Refresh", EditorStyles.toolbarButton, GUILayout.Width(60))) + { + LoadAllPuzzleSteps(); + } + + GUILayout.FlexibleSpace(); + + // Tab-specific toolbar options + if (_selectedTab == 0) // Edit tab + { + if (GUILayout.Button("Create New", EditorStyles.toolbarButton, GUILayout.Width(80))) + { + _showCreateNewStepDialog = true; + } + } + else if (_selectedTab == 1) // Debug tab + { + EditorGUILayout.LabelField(_isPlaying ? "Runtime Active" : "Editor Mode", EditorStyles.toolbarButton, GUILayout.Width(100)); + } + + EditorGUILayout.EndHorizontal(); + } + + #endregion + + #region Edit Tab + + private void DrawEditTab() + { + EditorGUILayout.BeginHorizontal(); + + // Left panel - puzzle step list + EditorGUILayout.BeginVertical(GUILayout.Width(250)); + DrawStepListPanel(); + EditorGUILayout.EndVertical(); + + // Separator + EditorGUILayout.Space(); + + // Right panel - puzzle step editor + EditorGUILayout.BeginVertical(); + DrawStepEditorPanel(); + EditorGUILayout.EndVertical(); + + EditorGUILayout.EndHorizontal(); + + // Draw create new step dialog if needed + if (_showCreateNewStepDialog) + { + DrawCreateNewStepDialog(); + } + } + + private void DrawStepListPanel() + { + // Search field + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + _searchQuery = EditorGUILayout.TextField(_searchQuery, EditorStyles.toolbarSearchField); + if (GUILayout.Button("×", EditorStyles.toolbarButton, GUILayout.Width(20)) && !string.IsNullOrEmpty(_searchQuery)) + { + _searchQuery = ""; + GUI.FocusControl(null); + } + EditorGUILayout.EndHorizontal(); + + _puzzleListScrollPosition = EditorGUILayout.BeginScrollView(_puzzleListScrollPosition); + + // If search query exists, show filtered results across all folders + if (!string.IsNullOrEmpty(_searchQuery)) + { + var filteredSteps = _allPuzzleSteps.Where(step => + step.displayName.ToLower().Contains(_searchQuery.ToLower()) || + step.stepId.ToLower().Contains(_searchQuery.ToLower())).ToList(); + + if (filteredSteps.Any()) + { + EditorGUILayout.LabelField($"Search Results ({filteredSteps.Count}):", EditorStyles.boldLabel); + + foreach (var step in filteredSteps) + { + if (DrawStepListItem(step)) + { + _selectedStep = step; + GUI.FocusControl(null); + } + } + } + else + { + EditorGUILayout.LabelField("No matching steps found"); + } + } + // Otherwise show organized by folder + else + { + foreach (var folderEntry in _puzzleStepsByFolder) + { + string folderName = folderEntry.Key; + List steps = folderEntry.Value; + + if (!_folderExpanded.ContainsKey(folderName)) + { + _folderExpanded[folderName] = true; // Default to expanded + } + + // Folder header with toggle + EditorGUILayout.BeginHorizontal(); + _folderExpanded[folderName] = EditorGUILayout.Foldout(_folderExpanded[folderName], folderName, true); + + // Show step count + EditorGUILayout.LabelField($"({steps.Count})", GUILayout.Width(40)); + EditorGUILayout.EndHorizontal(); + + // Draw steps in folder if expanded + if (_folderExpanded[folderName]) + { + EditorGUI.indentLevel++; + + foreach (var step in steps) + { + if (DrawStepListItem(step)) + { + _selectedStep = step; + GUI.FocusControl(null); + } + } + + EditorGUI.indentLevel--; + } + } + } + + EditorGUILayout.EndScrollView(); + } + + private bool DrawStepListItem(PuzzleStepSO step) + { + if (step == null) return false; + + bool isSelected = step == _selectedStep; + EditorGUILayout.BeginHorizontal(isSelected ? EditorStyles.selectionRect : EditorStyles.helpBox); + + // Icon if available + if (step.icon != null) + { + GUILayout.Label(new GUIContent(step.icon.texture), GUILayout.Width(20), GUILayout.Height(20)); + } + else + { + GUILayout.Space(24); + } + + // Name and ID + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField(step.displayName, EditorStyles.boldLabel); + EditorGUILayout.LabelField(step.stepId, EditorStyles.miniLabel); + EditorGUILayout.EndVertical(); + + EditorGUILayout.EndHorizontal(); + + // Check if this item was clicked + Rect itemRect = GUILayoutUtility.GetLastRect(); + bool wasClicked = Event.current.type == EventType.MouseDown && Event.current.button == 0 + && itemRect.Contains(Event.current.mousePosition); + + if (wasClicked) + { + Event.current.Use(); + } + + return wasClicked; + } + + private void DrawStepEditorPanel() + { + if (_selectedStep == null) + { + EditorGUILayout.HelpBox("Select a puzzle step to edit", MessageType.Info); + return; + } + + _puzzleEditScrollPosition = EditorGUILayout.BeginScrollView(_puzzleEditScrollPosition); + + EditorGUI.BeginChangeCheck(); + + // Header with name and ID + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Editing:", EditorStyles.boldLabel, GUILayout.Width(60)); + EditorGUILayout.LabelField(_selectedStep.displayName, EditorStyles.boldLabel); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + // Basic properties + EditorGUILayout.LabelField("Basic Properties", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + + // Step ID + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Step ID:", GUILayout.Width(100)); + string newStepId = EditorGUILayout.TextField(_selectedStep.stepId); + if (newStepId != _selectedStep.stepId) + { + Undo.RecordObject(_selectedStep, "Change Step ID"); + _selectedStep.stepId = newStepId; + _isDirty = true; + } + EditorGUILayout.EndHorizontal(); + + // Display Name + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Display Name:", GUILayout.Width(100)); + string newDisplayName = EditorGUILayout.TextField(_selectedStep.displayName); + if (newDisplayName != _selectedStep.displayName) + { + Undo.RecordObject(_selectedStep, "Change Display Name"); + _selectedStep.displayName = newDisplayName; + _isDirty = true; + } + EditorGUILayout.EndHorizontal(); + + // Description + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Description:", GUILayout.Width(100)); + string newDescription = EditorGUILayout.TextArea(_selectedStep.description, GUILayout.Height(60)); + if (newDescription != _selectedStep.description) + { + Undo.RecordObject(_selectedStep, "Change Description"); + _selectedStep.description = newDescription; + _isDirty = true; + } + EditorGUILayout.EndHorizontal(); + + // Icon + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Icon:", GUILayout.Width(100)); + Sprite newIcon = (Sprite)EditorGUILayout.ObjectField(_selectedStep.icon, typeof(Sprite), false); + if (newIcon != _selectedStep.icon) + { + Undo.RecordObject(_selectedStep, "Change Icon"); + _selectedStep.icon = newIcon; + _isDirty = true; + } + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + + // Unlocks (dependencies) + EditorGUILayout.LabelField("Unlocks", EditorStyles.boldLabel); + EditorGUILayout.HelpBox("Steps that will be unlocked when this step is completed", MessageType.Info); + + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + + // Show unlocked steps list + if (_selectedStep.unlocks.Count > 0) + { + for (int i = 0; i < _selectedStep.unlocks.Count; i++) + { + EditorGUILayout.BeginHorizontal(); + + // Draw step selector + PuzzleStepSO newUnlockedStep = (PuzzleStepSO)EditorGUILayout.ObjectField( + _selectedStep.unlocks[i], typeof(PuzzleStepSO), false); + + if (newUnlockedStep != _selectedStep.unlocks[i]) + { + Undo.RecordObject(_selectedStep, "Change Unlocked Step"); + _selectedStep.unlocks[i] = newUnlockedStep; + _isDirty = true; + } + + // Remove button + if (GUILayout.Button("-", GUILayout.Width(20))) + { + Undo.RecordObject(_selectedStep, "Remove Unlocked Step"); + _selectedStep.unlocks.RemoveAt(i); + _isDirty = true; + i--; + } + + EditorGUILayout.EndHorizontal(); + } + } + else + { + EditorGUILayout.LabelField("No steps will be unlocked"); + } + + // Add new dependency + if (GUILayout.Button("Add Unlocked Step")) + { + Undo.RecordObject(_selectedStep, "Add Unlocked Step"); + _selectedStep.unlocks.Add(null); + _isDirty = true; + } + + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + + // Asset path info + string assetPath = AssetDatabase.GetAssetPath(_selectedStep); + EditorGUILayout.LabelField("Asset Path:", EditorStyles.miniLabel); + EditorGUILayout.LabelField(assetPath, EditorStyles.miniLabel); + + // Delete button + EditorGUILayout.Space(); + if (GUILayout.Button("Delete Step", GUILayout.Width(100))) + { + if (EditorUtility.DisplayDialog("Delete Puzzle Step", + $"Are you sure you want to delete '{_selectedStep.displayName}'? This action cannot be undone.", + "Delete", "Cancel")) + { + DeletePuzzleStep(_selectedStep); + _selectedStep = null; + } + } + + if (EditorGUI.EndChangeCheck()) + { + EditorUtility.SetDirty(_selectedStep); + } + + EditorGUILayout.EndScrollView(); + } + + private void DrawCreateNewStepDialog() + { + // Create a centered window + Rect windowRect = new Rect( + (position.width - 400) / 2, + (position.height - 200) / 2, + 400, 200); + + GUI.Box(windowRect, "Create New Puzzle Step", EditorStyles.helpBox); + GUILayout.BeginArea(new Rect(windowRect.x + 10, windowRect.y + 30, windowRect.width - 20, windowRect.height - 40)); + + // Name field + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Name:", GUILayout.Width(80)); + _newStepName = EditorGUILayout.TextField(_newStepName); + EditorGUILayout.EndHorizontal(); + + // Folder selection + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Folder:", GUILayout.Width(80)); + + // Create folder dropdown + List folderNames = _puzzleStepsByFolder.Keys.ToList(); + int selectedFolderIndex = folderNames.IndexOf(_selectedFolder); + int newSelectedFolderIndex = EditorGUILayout.Popup(selectedFolderIndex >= 0 ? selectedFolderIndex : 0, folderNames.ToArray()); + if (newSelectedFolderIndex >= 0 && newSelectedFolderIndex < folderNames.Count) + { + _selectedFolder = folderNames[newSelectedFolderIndex]; + } + else if (folderNames.Count > 0) + { + _selectedFolder = folderNames[0]; + } + + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + // Buttons + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + + if (GUILayout.Button("Cancel", GUILayout.Width(100))) + { + _showCreateNewStepDialog = false; + } + + if (GUILayout.Button("Create", GUILayout.Width(100))) + { + if (!string.IsNullOrEmpty(_newStepName) && !string.IsNullOrEmpty(_selectedFolder)) + { + CreateNewPuzzleStep(_newStepName, _selectedFolder); + _showCreateNewStepDialog = false; + _newStepName = "New Step"; + } + } + + EditorGUILayout.EndHorizontal(); + + GUILayout.EndArea(); + } + + #endregion + + #region Debug Tab + + private void DrawDebugTab() + { + if (!_isPlaying) + { + EditorGUILayout.HelpBox("Enter Play Mode to debug puzzles at runtime", MessageType.Info); + return; + } + + if (!_hasRuntimeData || _runtimeLevelData == null) + { + EditorGUILayout.HelpBox("Waiting for puzzle data to be loaded...", MessageType.Info); + return; + } + + EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); + EditorGUILayout.LabelField($"Current Level: {_runtimeLevelData.levelId}", EditorStyles.boldLabel); + EditorGUILayout.EndHorizontal(); + + _debugScrollPosition = EditorGUILayout.BeginScrollView(_debugScrollPosition); + + // List all steps with their current state + EditorGUILayout.LabelField("Puzzle Steps", EditorStyles.boldLabel); + + // Show steps directly from the level data in a flat list + foreach (var step in _runtimeLevelData.allSteps) + { + if (step == null) continue; + + DrawRuntimeStepItem(step); + } + + EditorGUILayout.EndScrollView(); + } + + private void DrawRuntimeStepItem(PuzzleStepSO step) + { + bool isUnlocked = _stepUnlockState.ContainsKey(step.stepId) && _stepUnlockState[step.stepId]; + bool isCompleted = _stepCompletedState.ContainsKey(step.stepId) && _stepCompletedState[step.stepId]; + + // Set background color based on state + Color originalColor = GUI.backgroundColor; + + if (isCompleted) + GUI.backgroundColor = new Color(0.5f, 1f, 0.5f); // Green for completed + else if (isUnlocked) + GUI.backgroundColor = new Color(1f, 1f, 0.5f); // Yellow for unlocked but not completed + else + GUI.backgroundColor = new Color(1f, 0.5f, 0.5f); // Red for locked + + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + + // Reset color + GUI.backgroundColor = originalColor; + + EditorGUILayout.BeginHorizontal(); + + // Step info + EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true)); + EditorGUILayout.LabelField(step.displayName, EditorStyles.boldLabel); + EditorGUILayout.LabelField(step.stepId, EditorStyles.miniLabel); + + // Status text + string statusText = isCompleted ? "Completed" : (isUnlocked ? "Unlocked" : "Locked"); + EditorGUILayout.LabelField($"Status: {statusText}", EditorStyles.miniLabel); + + EditorGUILayout.EndVertical(); + + // Action buttons + EditorGUILayout.BeginVertical(GUILayout.Width(100)); + + EditorGUI.BeginDisabledGroup(isCompleted); + if (GUILayout.Button(isUnlocked ? "Lock" : "Unlock")) + { + ToggleStepUnlocked(step); + } + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(!isUnlocked || isCompleted); + if (GUILayout.Button("Complete")) + { + CompleteStep(step); + } + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.EndVertical(); + + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + } + + #endregion + + #region Data Management + + private void LoadAllPuzzleSteps() + { + _allPuzzleSteps.Clear(); + _puzzleStepsByFolder.Clear(); + + // Find all PuzzleStepSO assets in the project + string[] guids = AssetDatabase.FindAssets("t:PuzzleStepSO"); + + foreach (string guid in guids) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guid); + + // Only include assets from the Data folder + if (assetPath.StartsWith(PuzzleDataBasePath)) + { + PuzzleStepSO step = AssetDatabase.LoadAssetAtPath(assetPath); + + if (step != null) + { + _allPuzzleSteps.Add(step); + + // Add to folder dictionary for organization + string folder = Path.GetDirectoryName(assetPath)?.Replace("\\", "/"); + + if (folder != null) + { + if (!_puzzleStepsByFolder.ContainsKey(folder)) + { + _puzzleStepsByFolder[folder] = new List(); + } + + _puzzleStepsByFolder[folder].Add(step); + } + } + } + } + + // Make sure each folder is sorted by name + foreach (var key in _puzzleStepsByFolder.Keys.ToList()) + { + _puzzleStepsByFolder[key] = _puzzleStepsByFolder[key] + .OrderBy(step => step.displayName) + .ToList(); + } + + _isDirty = false; + } + + private void SaveChanges() + { + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + private void CreateNewPuzzleStep(string stepName, string folderPath) + { + // Create a new PuzzleStepSO + PuzzleStepSO newStep = CreateInstance(); + newStep.stepId = GenerateUniqueStepId(stepName); + newStep.displayName = stepName; + + // Create the path + string assetPath = Path.Combine(folderPath, $"{stepName}.asset").Replace("\\", "/"); + + // Make sure the directory exists + string directory = Path.GetDirectoryName(assetPath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + // Create the asset + AssetDatabase.CreateAsset(newStep, assetPath); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + // Reload all steps and select the new one + LoadAllPuzzleSteps(); + _selectedStep = newStep; + } + + private void DeletePuzzleStep(PuzzleStepSO step) + { + if (step == null) return; + + string assetPath = AssetDatabase.GetAssetPath(step); + + if (!string.IsNullOrEmpty(assetPath)) + { + // Also need to remove all references to this step from other steps' unlocks lists + foreach (var otherStep in _allPuzzleSteps) + { + if (otherStep != null && otherStep != step) + { + if (otherStep.unlocks.Contains(step)) + { + Undo.RecordObject(otherStep, "Remove Deleted Step Reference"); + otherStep.unlocks.Remove(step); + EditorUtility.SetDirty(otherStep); + } + } + } + + AssetDatabase.DeleteAsset(assetPath); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + // Reload all steps + LoadAllPuzzleSteps(); + } + } + + private string GenerateUniqueStepId(string baseName) + { + // Convert to lowercase and replace spaces with underscores + string baseId = baseName.ToLower().Replace(" ", "_"); + + // Check if this ID already exists + bool idExists = _allPuzzleSteps.Any(step => step.stepId == baseId); + + if (!idExists) + { + return baseId; + } + + // Add a number suffix if ID already exists + int counter = 1; + while (_allPuzzleSteps.Any(step => step.stepId == $"{baseId}_{counter}")) + { + counter++; + } + + return $"{baseId}_{counter}"; + } + + #endregion + + #region Runtime Debug Helpers + + private void UpdateRuntimeData() + { + if (!_isPlaying) return; + + // Find PuzzleManager instance + PuzzleManager puzzleManager = Object.FindObjectOfType(); + + if (puzzleManager == null) + { + _hasRuntimeData = false; + return; + } + + // Get current level data + var levelData = puzzleManager.GetCurrentLevelData(); + if (levelData == null) + { + _hasRuntimeData = false; + return; + } + + _hasRuntimeData = true; + _runtimeLevelData = levelData; + + // Update step states + foreach (var step in _runtimeLevelData.allSteps) + { + if (step != null) + { + _stepUnlockState[step.stepId] = puzzleManager.IsStepUnlocked(step); + _stepCompletedState[step.stepId] = puzzleManager.IsPuzzleStepCompleted(step.stepId); + } + } + } + + private void ToggleStepUnlocked(PuzzleStepSO step) + { + if (!_isPlaying || step == null) return; + + PuzzleManager puzzleManager = Object.FindObjectOfType(); + if (puzzleManager == null) return; + + // Get current unlock state + bool isCurrentlyUnlocked = _stepUnlockState.ContainsKey(step.stepId) && _stepUnlockState[step.stepId]; + + // Call appropriate method using reflection since these might be private methods + System.Type managerType = puzzleManager.GetType(); + + if (isCurrentlyUnlocked) + { + // Find the LockStep method that takes a PuzzleStepSO parameter + System.Reflection.MethodInfo lockMethod = managerType.GetMethod("LockStep", + System.Reflection.BindingFlags.Instance | + System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.NonPublic); + + if (lockMethod != null) + { + lockMethod.Invoke(puzzleManager, new object[] { step }); + } + } + else + { + // Find the UnlockStep method that takes a PuzzleStepSO parameter + System.Reflection.MethodInfo unlockMethod = managerType.GetMethod("UnlockStep", + System.Reflection.BindingFlags.Instance | + System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.NonPublic); + + if (unlockMethod != null) + { + unlockMethod.Invoke(puzzleManager, new object[] { step }); + } + } + + // Update state + UpdateRuntimeData(); + } + + private void CompleteStep(PuzzleStepSO step) + { + if (!_isPlaying || step == null) return; + + PuzzleManager puzzleManager = Object.FindObjectOfType(); + if (puzzleManager == null) return; + + // Complete the step + puzzleManager.MarkPuzzleStepCompleted(step); + + // Update state + UpdateRuntimeData(); + } + + #endregion + } +} diff --git a/Assets/Editor/PuzzleSystem/PuzzleEditorWindow.cs.meta b/Assets/Editor/PuzzleSystem/PuzzleEditorWindow.cs.meta new file mode 100644 index 00000000..9eccad68 --- /dev/null +++ b/Assets/Editor/PuzzleSystem/PuzzleEditorWindow.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c733f3c6624e4e5486c07abfe4fab81e +timeCreated: 1760539457 \ No newline at end of file diff --git a/Assets/Prefabs/Environment/Placeholders/BallTree.prefab b/Assets/Prefabs/Environment/Placeholders/BallTree.prefab index f49f6fc6..918b50fa 100644 --- a/Assets/Prefabs/Environment/Placeholders/BallTree.prefab +++ b/Assets/Prefabs/Environment/Placeholders/BallTree.prefab @@ -26,7 +26,7 @@ Transform: m_GameObject: {fileID: 1646387898454772943} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -4.4615383, y: 0.61538696, z: 0} + m_LocalPosition: {x: -1.854, y: -0, z: 0} m_LocalScale: {x: 0.7692308, y: 0.7692308, z: 0.7692308} m_ConstrainProportionsScale: 0 m_Children: [] @@ -46,6 +46,38 @@ MonoBehaviour: m_EditorClassIdentifier: AppleHillsScripts::Interactions.CharacterMoveToTarget characterType: 2 positionOffset: {x: 0, y: 0, z: 1} +--- !u!1 &2654542252039360806 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2084964592986606867} + m_Layer: 10 + m_Name: AnimContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2084964592986606867 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2654542252039360806} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.826, y: 1.333, z: 0} + m_LocalScale: {x: 0.1851852, y: 0.1851852, z: 0.1851852} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 305861995533261809} + m_Father: {fileID: 4937390562043858043} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &3591802784221671576 GameObject: m_ObjectHideFlags: 0 @@ -72,7 +104,7 @@ Transform: m_GameObject: {fileID: 3591802784221671576} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalPosition: {x: 0.9, y: -0.16, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 1 m_Children: [] @@ -124,10 +156,10 @@ PolygonCollider2D: m_AutoTiling: 0 m_Points: m_Paths: - - - {x: 0.69036514, y: -0.039288044} - - {x: -0.7429288, y: 0.004180908} - - {x: -0.73904544, y: 2.4819212} - - {x: 0.5286481, y: 2.5456142} + - - {x: 0.5431701, y: -0.027021673} + - {x: -0.62026507, y: -0.020351835} + - {x: -0.48145303, y: 1.4024833} + - {x: 0.36918524, y: 1.3803146} m_UseDelaunayMesh: 0 --- !u!1 &7379304988657006554 GameObject: @@ -144,7 +176,8 @@ GameObject: - component: {fileID: 492578671844741631} - component: {fileID: 8984729148657672365} - component: {fileID: 1569498917964935965} - - component: {fileID: 3871210969445384207} + - component: {fileID: 6417332830266550134} + - component: {fileID: 4544320034237251646} m_Layer: 10 m_Name: BallTree m_TagString: Untagged @@ -162,9 +195,10 @@ Transform: serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1.3, y: 1.3, z: 1.3} + m_LocalScale: {x: 2.7, y: 2.7, z: 2.7} m_ConstrainProportionsScale: 1 m_Children: + - {fileID: 2084964592986606867} - {fileID: 6631072601870453588} - {fileID: 7371967679236352629} m_Father: {fileID: 0} @@ -216,7 +250,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 1 - m_Sprite: {fileID: 4974115186881715698, guid: e1aa947fcf3609045ba89a6ddb609ae3, type: 3} + m_Sprite: {fileID: 768869974157336279, guid: ab1e8f5d45ee00247af9314b56f4af91, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 m_FlipY: 0 @@ -261,17 +295,17 @@ BoxCollider2D: m_UsedByEffector: 0 m_CompositeOperation: 0 m_CompositeOrder: 0 - m_Offset: {x: -0.1844703, y: 2.8477936} + m_Offset: {x: 0.76, y: 2.88} m_SpriteTilingProperty: border: {x: 0, y: 0, z: 0, w: 0} - pivot: {x: 0.5, y: 0.08} - oldSize: {x: 9.23, y: 11.48} + pivot: {x: 0.5, y: 0.2} + oldSize: {x: 14.969999, y: 9.060193} newSize: {x: 9.23, y: 11.48} adaptiveTilingThreshold: 0.5 drawMode: 0 adaptiveTiling: 0 m_AutoTiling: 0 - m_Size: {x: 3.437712, y: 7.532383} + m_Size: {x: 3.8, y: 7.34} m_EdgeRadius: 0 --- !u!114 &8437452310832126615 MonoBehaviour: @@ -313,7 +347,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: 8ac614a698631554ab8ac39aed04a189, type: 2} - puzzleIndicator: {fileID: 0} + puzzleIndicator: {fileID: 214996082823304376} drawPromptRangeGizmo: 1 --- !u!114 &8984729148657672365 MonoBehaviour: @@ -327,18 +361,20 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 42e77a0c97604b6eb7674e58726c831a, type: 3} m_Name: m_EditorClassIdentifier: AppleHillsScripts::Interactions.InteractionTimelineAction - respondToEvents: 04000000 + respondToEvents: 02000000 pauseInteractionFlow: 1 - playableDirector: {fileID: 0} + playableDirector: {fileID: 1569498917964935965} timelineMappings: - - eventType: 4 - timelines: [] + - eventType: 2 + timelines: + - {fileID: 11400000, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} + - {fileID: 11400000, guid: ee609df51f47bd541a23d5425e289e30, type: 2} bindPlayerCharacter: 0 bindPulverCharacter: 0 - playerTrackName: - pulverTrackName: + playerTrackName: Player + pulverTrackName: Pulver timeoutSeconds: 30 - loopLast: 0 + loopLast: 1 loopAll: 0 --- !u!320 &1569498917964935965 PlayableDirector: @@ -349,21 +385,43 @@ PlayableDirector: m_GameObject: {fileID: 7379304988657006554} m_Enabled: 1 serializedVersion: 3 - m_PlayableAsset: {fileID: 11400000, guid: dd9566026364e814a8dad109e6c365ca, type: 2} + m_PlayableAsset: {fileID: 11400000, guid: ee609df51f47bd541a23d5425e289e30, type: 2} m_InitialState: 0 m_WrapMode: 2 m_DirectorUpdateMode: 1 m_InitialTime: 0 m_SceneBindings: - key: {fileID: -7584736085941489071, guid: dd9566026364e814a8dad109e6c365ca, type: 2} - value: {fileID: 3871210969445384207} + value: {fileID: 0} - key: {fileID: -2395336864975438248, guid: dd9566026364e814a8dad109e6c365ca, type: 2} value: {fileID: 0} - key: {fileID: -7231857257271738743, guid: dd9566026364e814a8dad109e6c365ca, type: 2} value: {fileID: 0} + - key: {fileID: -7584736085941489071, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} + value: {fileID: 4544320034237251646} + - key: {fileID: -2395336864975438248, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} + value: {fileID: 0} + - key: {fileID: 3942302933360259000, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} + value: {fileID: 0} + - key: {fileID: -2395336864975438248, guid: ee609df51f47bd541a23d5425e289e30, type: 2} + value: {fileID: 0} + - key: {fileID: -7584736085941489071, guid: ee609df51f47bd541a23d5425e289e30, type: 2} + value: {fileID: 4544320034237251646} m_ExposedReferences: m_References: [] ---- !u!95 &3871210969445384207 +--- !u!114 &6417332830266550134 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7379304988657006554} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 833a4ccef651449e973e623d9107bef5, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!95 &4544320034237251646 Animator: serializedVersion: 7 m_ObjectHideFlags: 0 @@ -385,3 +443,90 @@ Animator: m_AllowConstantClipSamplingOptimization: 1 m_KeepAnimatorStateOnDisable: 0 m_WriteDefaultValuesOnDisable: 0 +--- !u!1001 &5210361341888085501 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 2084964592986606867} + m_Modifications: + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_Name + value: NextStepIndicator + objectReference: {fileID: 0} + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_ConstrainProportionsScale + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} +--- !u!1 &214996082823304376 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 5210361341888085501} + m_PrefabAsset: {fileID: 0} +--- !u!4 &305861995533261809 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 5210361341888085501} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Scenes/Levels/Quarry.unity b/Assets/Scenes/Levels/Quarry.unity index fe24982d..cae7b24e 100644 --- a/Assets/Scenes/Levels/Quarry.unity +++ b/Assets/Scenes/Levels/Quarry.unity @@ -1385,6 +1385,38 @@ Transform: m_CorrespondingSourceObject: {fileID: 5145306031820616614, guid: fbbe1f4baf226904b96f839fe0c00181, type: 3} m_PrefabInstance: {fileID: 94815899} m_PrefabAsset: {fileID: 0} +--- !u!1 &96550921 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 96550922} + m_Layer: 10 + m_Name: AnimContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &96550922 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 96550921} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 3.52, z: 0} + m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1563916674} + m_Father: {fileID: 733706664} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &104952029 PrefabInstance: m_ObjectHideFlags: 0 @@ -430282,6 +430314,88 @@ Transform: m_CorrespondingSourceObject: {fileID: 5145306031820616614, guid: fbbe1f4baf226904b96f839fe0c00181, type: 3} m_PrefabInstance: {fileID: 227102088} m_PrefabAsset: {fileID: 0} +--- !u!1001 &231972014 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 515768253} + m_Modifications: + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_Name + value: NextStepIndicator + objectReference: {fileID: 0} + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_ConstrainProportionsScale + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} +--- !u!4 &231972015 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 231972014} + m_PrefabAsset: {fileID: 0} --- !u!1001 &237175701 PrefabInstance: m_ObjectHideFlags: 0 @@ -436581,6 +436695,38 @@ Transform: m_CorrespondingSourceObject: {fileID: 9067462609398217044, guid: 6cbcaf4eb20e63e4fb462f6fb1ada3a7, type: 3} m_PrefabInstance: {fileID: 514383803} m_PrefabAsset: {fileID: 0} +--- !u!1 &515768252 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 515768253} + m_Layer: 10 + m_Name: AnimContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &515768253 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 515768252} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 3.4, z: 0} + m_LocalScale: {x: 0.6053269, y: 0.6053269, z: 2.4213076} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 231972015} + m_Father: {fileID: 520186665} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &515824553 GameObject: m_ObjectHideFlags: 0 @@ -436816,14 +436962,40 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 3984039030829909690, guid: b3fc964bec385174f85a143f2fcff121, type: 3} + insertIndex: -1 + addedObject: {fileID: 515768253} + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 5193479583796800754, guid: b3fc964bec385174f85a143f2fcff121, type: 3} + insertIndex: -1 + addedObject: {fileID: 520186667} m_SourcePrefab: {fileID: 100100000, guid: b3fc964bec385174f85a143f2fcff121, type: 3} --- !u!4 &520186665 stripped Transform: m_CorrespondingSourceObject: {fileID: 3984039030829909690, guid: b3fc964bec385174f85a143f2fcff121, type: 3} m_PrefabInstance: {fileID: 520186664} m_PrefabAsset: {fileID: 0} +--- !u!1 &520186666 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5193479583796800754, guid: b3fc964bec385174f85a143f2fcff121, type: 3} + m_PrefabInstance: {fileID: 520186664} + m_PrefabAsset: {fileID: 0} +--- !u!114 &520186667 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 520186666} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.ObjectiveStepBehaviour + stepData: {fileID: 11400000, guid: ed967c44f3a8b914aabc1539f774efc7, type: 2} + puzzleIndicator: {fileID: 871315074} + drawPromptRangeGizmo: 1 --- !u!4 &526812634 stripped Transform: m_CorrespondingSourceObject: {fileID: 7815739457642955130, guid: f645a67c7970b124cacb6450fefdebad, type: 3} @@ -437676,6 +437848,93 @@ Transform: - {fileID: 1042636115} m_Father: {fileID: 965792696} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &563364658 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1757318243} + m_Modifications: + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_Name + value: NextStepIndicator + objectReference: {fileID: 0} + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_ConstrainProportionsScale + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} +--- !u!1 &563364659 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 563364658} + m_PrefabAsset: {fileID: 0} +--- !u!4 &563364660 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 563364658} + m_PrefabAsset: {fileID: 0} --- !u!4 &564343622 stripped Transform: m_CorrespondingSourceObject: {fileID: 2064225848720495177, guid: 0bbded61e58193848ac59c8eea761bcc, type: 3} @@ -442286,6 +442545,93 @@ PrefabInstance: insertIndex: -1 addedObject: {fileID: 1249289164} m_SourcePrefab: {fileID: 100100000, guid: 9b2926886934b554f9a1727331d34787, type: 3} +--- !u!1001 &843574202 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1409667037} + m_Modifications: + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_Name + value: NextStepIndicator + objectReference: {fileID: 0} + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.x + value: 10.08 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.y + value: -11.56 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_ConstrainProportionsScale + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} +--- !u!4 &843574203 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 843574202} + m_PrefabAsset: {fileID: 0} +--- !u!1 &843574204 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 843574202} + m_PrefabAsset: {fileID: 0} --- !u!1001 &845071531 PrefabInstance: m_ObjectHideFlags: 0 @@ -448682,92 +449028,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 6583016841553003224, guid: df01157608cce6447b7ccde0bfa290e1, type: 3} m_PrefabInstance: {fileID: 3978117984697153445} m_PrefabAsset: {fileID: 0} ---- !u!1 &1182494929 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 7379304988657006554, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - m_PrefabInstance: {fileID: 7530821580781571560} - m_PrefabAsset: {fileID: 0} ---- !u!114 &1182494933 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1182494929} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 73d6494a73174ffabc6a7d3089d51e73, type: 3} - m_Name: - m_EditorClassIdentifier: - isOneTime: 0 - cooldown: -1 - characterToInteract: 1 - interactionStarted: - m_PersistentCalls: - m_Calls: [] - interactionInterrupted: - m_PersistentCalls: - m_Calls: [] - characterArrived: - m_PersistentCalls: - m_Calls: [] - interactionComplete: - m_PersistentCalls: - m_Calls: [] ---- !u!114 &1182494937 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1182494929} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} - m_Name: - m_EditorClassIdentifier: - stepData: {fileID: 11400000, guid: 8ac614a698631554ab8ac39aed04a189, type: 2} - puzzleIndicator: {fileID: 1974667227} - drawPromptRangeGizmo: 1 ---- !u!114 &1182494941 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1182494929} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 833a4ccef651449e973e623d9107bef5, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!95 &1182494942 -Animator: - serializedVersion: 7 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1182494929} - m_Enabled: 1 - m_Avatar: {fileID: 0} - m_Controller: {fileID: 0} - m_CullingMode: 0 - m_UpdateMode: 0 - m_ApplyRootMotion: 0 - m_LinearVelocityBlending: 0 - m_StabilizeFeet: 0 - m_AnimatePhysics: 0 - m_WarningMessage: - m_HasTransformHierarchy: 1 - m_AllowConstantClipSamplingOptimization: 1 - m_KeepAnimatorStateOnDisable: 0 - m_WriteDefaultValuesOnDisable: 0 ---- !u!320 &1182494943 stripped -PlayableDirector: - m_CorrespondingSourceObject: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - m_PrefabInstance: {fileID: 7530821580781571560} - m_PrefabAsset: {fileID: 0} --- !u!4 &1185030192 stripped Transform: m_CorrespondingSourceObject: {fileID: 9067462609398217044, guid: 6cbcaf4eb20e63e4fb462f6fb1ada3a7, type: 3} @@ -449631,38 +449891,6 @@ Transform: m_Children: [] m_Father: {fileID: 764788851} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 7.957} ---- !u!1 &1230365908 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1230365909} - m_Layer: 10 - m_Name: AnimContainer - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1230365909 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1230365908} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.826, y: 1.333, z: 0} - m_LocalScale: {x: 0.1851852, y: 0.1851852, z: 0.1851852} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1974667228} - m_Father: {fileID: 7530821580781571561} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1230441486 GameObject: m_ObjectHideFlags: 0 @@ -450654,7 +450882,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 3606875748053192296, guid: 30285f2632211504484661965ed61c57, type: 3} propertyPath: m_IsActive - value: 1 + value: 0 objectReference: {fileID: 0} - target: {fileID: 4386785291364665203, guid: 30285f2632211504484661965ed61c57, type: 3} propertyPath: characterToInteract @@ -452278,6 +452506,38 @@ Animator: m_AllowConstantClipSamplingOptimization: 1 m_KeepAnimatorStateOnDisable: 0 m_WriteDefaultValuesOnDisable: 0 +--- !u!1 &1409667036 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1409667037} + m_Layer: 10 + m_Name: AnimContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1409667037 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1409667036} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.02, y: 4.06, z: 0} + m_LocalScale: {x: 0.71428573, y: 0.71428573, z: 2.857143} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 843574203} + m_Father: {fileID: 1494074967} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!4 &1413812638 stripped Transform: m_CorrespondingSourceObject: {fileID: 2064225848720495177, guid: 0bbded61e58193848ac59c8eea761bcc, type: 3} @@ -453842,6 +454102,11 @@ Transform: m_CorrespondingSourceObject: {fileID: 2064225848720495177, guid: 0bbded61e58193848ac59c8eea761bcc, type: 3} m_PrefabInstance: {fileID: 1488038905} m_PrefabAsset: {fileID: 0} +--- !u!4 &1494074967 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5990546859970263031, guid: 3346526f3046f424196615241a307104, type: 3} + m_PrefabInstance: {fileID: 3708074769586677211} + m_PrefabAsset: {fileID: 0} --- !u!1001 &1497304415 PrefabInstance: m_ObjectHideFlags: 0 @@ -455352,6 +455617,93 @@ Transform: m_CorrespondingSourceObject: {fileID: 2064225848720495177, guid: 0bbded61e58193848ac59c8eea761bcc, type: 3} m_PrefabInstance: {fileID: 1758157935} m_PrefabAsset: {fileID: 0} +--- !u!1001 &1563916672 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 96550922} + m_Modifications: + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_Name + value: NextStepIndicator + objectReference: {fileID: 0} + - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + propertyPath: m_ConstrainProportionsScale + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} +--- !u!1 &1563916673 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 1563916672} + m_PrefabAsset: {fileID: 0} +--- !u!4 &1563916674 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} + m_PrefabInstance: {fileID: 1563916672} + m_PrefabAsset: {fileID: 0} --- !u!1001 &1567929234 PrefabInstance: m_ObjectHideFlags: 0 @@ -459284,6 +459636,38 @@ Transform: m_CorrespondingSourceObject: {fileID: 7815739457642955130, guid: f645a67c7970b124cacb6450fefdebad, type: 3} m_PrefabInstance: {fileID: 1655345416} m_PrefabAsset: {fileID: 0} +--- !u!1 &1757318242 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1757318243} + m_Layer: 10 + m_Name: AnimContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1757318243 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1757318242} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1.937, z: 0} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 563364660} + m_Father: {fileID: 332724605} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &1758157935 PrefabInstance: m_ObjectHideFlags: 0 @@ -463059,93 +463443,6 @@ BoxCollider2D: m_AutoTiling: 0 m_Size: {x: 1.5, y: 1.5} m_EdgeRadius: 0 ---- !u!1001 &1974667226 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 1230365909} - m_Modifications: - - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_Name - value: NextStepIndicator - objectReference: {fileID: 0} - - target: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_IsActive - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalScale.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalScale.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalScale.z - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalRotation.x - value: -0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalRotation.y - value: -0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalRotation.z - value: -0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - propertyPath: m_ConstrainProportionsScale - value: 1 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} ---- !u!1 &1974667227 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 5383276844808284485, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - m_PrefabInstance: {fileID: 1974667226} - m_PrefabAsset: {fileID: 0} ---- !u!4 &1974667228 stripped -Transform: - m_CorrespondingSourceObject: {fileID: 5507990123417429516, guid: afbb486e5456a20479aee4cf8bc949b6, type: 3} - m_PrefabInstance: {fileID: 1974667226} - m_PrefabAsset: {fileID: 0} --- !u!4 &1979553424 stripped Transform: m_CorrespondingSourceObject: {fileID: 2064225848720495177, guid: 0bbded61e58193848ac59c8eea761bcc, type: 3} @@ -463638,6 +463935,21 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: '::' canFly: 1 +--- !u!114 &2022162753 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2022162745} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.ObjectiveStepBehaviour + stepData: {fileID: 11400000, guid: 37409d749a15970438d761d1d658d7a6, type: 2} + puzzleIndicator: {fileID: 563364659} + drawPromptRangeGizmo: 1 --- !u!1001 &2024588806 PrefabInstance: m_ObjectHideFlags: 0 @@ -466364,11 +466676,17 @@ PrefabInstance: m_RemovedComponents: - {fileID: 9196152289301358918, guid: 9ad58c5e86338824db8a6daebdb432b5, type: 3} m_RemovedGameObjects: [] - m_AddedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 2523333015159032981, guid: 9ad58c5e86338824db8a6daebdb432b5, type: 3} + insertIndex: -1 + addedObject: {fileID: 1757318243} m_AddedComponents: - targetCorrespondingSourceObject: {fileID: 588897581313790951, guid: 9ad58c5e86338824db8a6daebdb432b5, type: 3} insertIndex: -1 addedObject: {fileID: 2022162752} + - targetCorrespondingSourceObject: {fileID: 588897581313790951, guid: 9ad58c5e86338824db8a6daebdb432b5, type: 3} + insertIndex: -1 + addedObject: {fileID: 2022162753} m_SourcePrefab: {fileID: 100100000, guid: 9ad58c5e86338824db8a6daebdb432b5, type: 3} --- !u!1001 &3708074769586677211 PrefabInstance: @@ -466498,6 +466816,14 @@ PrefabInstance: propertyPath: m_LocalScale.z value: 0.0875 objectReference: {fileID: 0} + - target: {fileID: 5990546859970263031, guid: 3346526f3046f424196615241a307104, type: 3} + propertyPath: m_LocalPosition.x + value: 3.586 + objectReference: {fileID: 0} + - target: {fileID: 5990546859970263031, guid: 3346526f3046f424196615241a307104, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} - target: {fileID: 5990546859970263031, guid: 3346526f3046f424196615241a307104, type: 3} propertyPath: m_ConstrainProportionsScale value: 1 @@ -466574,6 +466900,14 @@ PrefabInstance: propertyPath: m_SpriteTilingProperty.oldSize.y value: 5.3199997 objectReference: {fileID: 0} + - target: {fileID: 8758136668472096799, guid: 3346526f3046f424196615241a307104, type: 3} + propertyPath: puzzleIndicator + value: + objectReference: {fileID: 1563916673} + - target: {fileID: 8824447189060448086, guid: 3346526f3046f424196615241a307104, type: 3} + propertyPath: puzzleIndicator + value: + objectReference: {fileID: 843574204} m_RemovedComponents: - {fileID: 488333850132012697, guid: 3346526f3046f424196615241a307104, type: 3} - {fileID: 5493660251969001565, guid: 3346526f3046f424196615241a307104, type: 3} @@ -466582,6 +466916,9 @@ PrefabInstance: m_AddedGameObjects: - targetCorrespondingSourceObject: {fileID: 6078012632802010276, guid: 3346526f3046f424196615241a307104, type: 3} insertIndex: 0 + addedObject: {fileID: 96550922} + - targetCorrespondingSourceObject: {fileID: 6078012632802010276, guid: 3346526f3046f424196615241a307104, type: 3} + insertIndex: 1 addedObject: {fileID: 291207989} - targetCorrespondingSourceObject: {fileID: 5654042452373662053, guid: 3346526f3046f424196615241a307104, type: 3} insertIndex: -1 @@ -466592,6 +466929,9 @@ PrefabInstance: - targetCorrespondingSourceObject: {fileID: 5654042452373662053, guid: 3346526f3046f424196615241a307104, type: 3} insertIndex: -1 addedObject: {fileID: 941275210} + - targetCorrespondingSourceObject: {fileID: 5990546859970263031, guid: 3346526f3046f424196615241a307104, type: 3} + insertIndex: -1 + addedObject: {fileID: 1409667037} m_AddedComponents: - targetCorrespondingSourceObject: {fileID: 5236930998804014616, guid: 3346526f3046f424196615241a307104, type: 3} insertIndex: -1 @@ -467754,46 +468094,6 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 0} m_Modifications: - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_WrapMode - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_PlayableAsset - value: - objectReference: {fileID: 11400000, guid: ee609df51f47bd541a23d5425e289e30, type: 2} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.size - value: 8 - objectReference: {fileID: 0} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[3].key - value: - objectReference: {fileID: -7584736085941489071, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[4].key - value: - objectReference: {fileID: -2395336864975438248, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[5].key - value: - objectReference: {fileID: 3942302933360259000, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[6].key - value: - objectReference: {fileID: -2395336864975438248, guid: ee609df51f47bd541a23d5425e289e30, type: 2} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[7].key - value: - objectReference: {fileID: -7584736085941489071, guid: ee609df51f47bd541a23d5425e289e30, type: 2} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[0].value - value: - objectReference: {fileID: 0} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[3].value - value: - objectReference: {fileID: 1182494942} - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} propertyPath: m_SceneBindings.Array.data[4].value value: @@ -467806,26 +468106,6 @@ PrefabInstance: propertyPath: m_SceneBindings.Array.data[6].value value: objectReference: {fileID: 1682217633} - - target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SceneBindings.Array.data[7].value - value: - objectReference: {fileID: 1182494942} - - target: {fileID: 2720557426779044373, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Sprite - value: - objectReference: {fileID: 768869974157336279, guid: ab1e8f5d45ee00247af9314b56f4af91, type: 3} - - target: {fileID: 4937390562043858043, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalScale.x - value: 2.7 - objectReference: {fileID: 0} - - target: {fileID: 4937390562043858043, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalScale.y - value: 2.7 - objectReference: {fileID: 0} - - target: {fileID: 4937390562043858043, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalScale.z - value: 2.7 - objectReference: {fileID: 0} - target: {fileID: 4937390562043858043, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} propertyPath: m_LocalPosition.x value: -38.7 @@ -467866,159 +468146,15 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 6631072601870453588, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalPosition.x - value: 0.9 - objectReference: {fileID: 0} - - target: {fileID: 6631072601870453588, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalPosition.y - value: -0.16 - objectReference: {fileID: 0} - - target: {fileID: 7371967679236352629, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalPosition.x - value: -1.854 - objectReference: {fileID: 0} - - target: {fileID: 7371967679236352629, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_LocalPosition.y - value: -0 - objectReference: {fileID: 0} - target: {fileID: 7379304988657006554, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} propertyPath: m_Name value: BallTree objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[0].x - value: 0.5431701 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[0].y - value: -0.027021673 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[1].x - value: -0.62026507 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[1].y - value: -0.020351835 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[2].x - value: -0.48145303 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[2].y - value: 1.4024833 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[3].x - value: 0.36918524 - objectReference: {fileID: 0} - - target: {fileID: 8491926070868252979, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Points.m_Paths.Array.data[0].Array.data[3].y - value: 1.3803146 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Size.x - value: 3.8 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Size.y - value: 7.34 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Enabled - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Offset.x - value: 0.76 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_Offset.y - value: 2.88 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SpriteTilingProperty.pivot.y - value: 0.2 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SpriteTilingProperty.oldSize.x - value: 14.969999 - objectReference: {fileID: 0} - - target: {fileID: 8897661028274890141, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: m_SpriteTilingProperty.oldSize.y - value: 9.060193 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: playableDirector - value: - objectReference: {fileID: 1182494943} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: 'respondToEvents.Array.data[0]' - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].loopLast - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].eventType - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].playerTrackName - value: Player - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].pulverTrackName - value: Pulver - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].bindPlayerCharacter - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].bindPulverCharacter - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: timelineMappings.Array.data[0].timelines.Array.size - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: 'timelineMappings.Array.data[0].timelines.Array.data[0]' - value: - objectReference: {fileID: 11400000, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2} - - target: {fileID: 8984729148657672365, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - propertyPath: 'timelineMappings.Array.data[0].timelines.Array.data[1]' - value: - objectReference: {fileID: 11400000, guid: ee609df51f47bd541a23d5425e289e30, type: 2} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: - - targetCorrespondingSourceObject: {fileID: 4937390562043858043, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - insertIndex: 0 - addedObject: {fileID: 1230365909} - m_AddedComponents: - - targetCorrespondingSourceObject: {fileID: 7379304988657006554, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - insertIndex: -1 - addedObject: {fileID: 1182494933} - - targetCorrespondingSourceObject: {fileID: 7379304988657006554, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - insertIndex: -1 - addedObject: {fileID: 1182494937} - - targetCorrespondingSourceObject: {fileID: 7379304988657006554, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - insertIndex: -1 - addedObject: {fileID: 1182494941} - - targetCorrespondingSourceObject: {fileID: 7379304988657006554, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - insertIndex: -1 - addedObject: {fileID: 1182494942} + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} ---- !u!4 &7530821580781571561 stripped -Transform: - m_CorrespondingSourceObject: {fileID: 4937390562043858043, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3} - m_PrefabInstance: {fileID: 7530821580781571560} - m_PrefabAsset: {fileID: 0} --- !u!1001 &7535757761066548300 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Interactions/Interactable.cs b/Assets/Scripts/Interactions/Interactable.cs index 521d3c1b..e21cec6a 100644 --- a/Assets/Scripts/Interactions/Interactable.cs +++ b/Assets/Scripts/Interactions/Interactable.cs @@ -418,7 +418,8 @@ namespace Interactions { // Check for ObjectiveStepBehaviour and lock state var step = GetComponent(); - if (step != null && !step.IsStepUnlocked()) + var slot = GetComponent(); + if (step != null && !step.IsStepUnlocked() && slot == null) { DebugUIMessage.Show("This step is locked!", Color.yellow); BroadcastInteractionComplete(false); diff --git a/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs b/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs index e11e168d..a86b69b2 100644 --- a/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs +++ b/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs @@ -1,10 +1,7 @@ using Input; using Interactions; using UnityEngine; -using System; -using AppleHills.Core.Settings; using Core; -using UnityEngine.Serialization; namespace PuzzleS { @@ -37,23 +34,46 @@ namespace PuzzleS void Awake() { _interactable = GetComponent(); + + // Initialize the indicator if it exists, but ensure it's hidden initially + if (puzzleIndicator != null) + { + // The indicator should start inactive until we determine its proper state + puzzleIndicator.SetActive(false); + + // Get the IPuzzlePrompt component + _indicator = puzzleIndicator.GetComponent(); + + if (_indicator == null) + { + // Try to find it in children if not on the root + _indicator = puzzleIndicator.GetComponentInChildren(); + } + + if (_indicator == null) + { + Logging.Warning($"[Puzzles] Indicator prefab for {stepData?.stepId} does not implement IPuzzlePrompt"); + } + } } void OnEnable() { if (_interactable == null) _interactable = GetComponent(); + if (_interactable != null) { _interactable.interactionStarted.AddListener(OnInteractionStarted); _interactable.interactionComplete.AddListener(OnInteractionComplete); } + } + + void Start() + { + // Register with PuzzleManager, regardless of enabled/disabled state + // PuzzleManager will call UnlockStep or LockStep based on current puzzle state PuzzleManager.Instance?.RegisterStepBehaviour(this); - // Check if this step was already unlocked - if (stepData != null && PuzzleManager.Instance != null && PuzzleManager.Instance.IsStepUnlocked(stepData)) - { - UnlockStep(); - } } void OnDestroy() @@ -73,7 +93,7 @@ namespace PuzzleS public void UpdateProximityState(ProximityState newState) { if (_currentProximityState == newState) return; - if (_indicator == null) return; + if (!_isUnlocked) return; // Don't process state changes if locked // Determine state changes and call appropriate methods if (newState == ProximityState.Close) @@ -97,6 +117,9 @@ namespace PuzzleS /// public virtual void OnShow() { + if (puzzleIndicator != null) + puzzleIndicator.SetActive(true); + // Delegate to indicator if available if (IsIndicatorValid()) { @@ -104,7 +127,6 @@ namespace PuzzleS return; } - // Default fallback behavior Logging.Debug($"[Puzzles] Prompt shown for {stepData?.stepId} on {gameObject.name}"); } @@ -113,14 +135,15 @@ namespace PuzzleS /// public virtual void OnHide() { + if (puzzleIndicator != null) + puzzleIndicator.SetActive(false); + // Delegate to indicator if available if (IsIndicatorValid()) { _indicator.OnHide(); - return; } - // Default fallback behavior Logging.Debug($"[Puzzles] Prompt hidden for {stepData?.stepId} on {gameObject.name}"); } @@ -138,9 +161,6 @@ namespace PuzzleS _indicator.ShowFar(); return; } - - // Default fallback behavior - Logging.Debug($"[Puzzles] Player entered far range of {stepData?.stepId} on {gameObject.name}"); } /// @@ -157,9 +177,6 @@ namespace PuzzleS _indicator.ShowClose(); return; } - - // Default fallback behavior - Logging.Debug($"[Puzzles] Player entered close range of {stepData?.stepId} on {gameObject.name}"); } /// @@ -176,9 +193,6 @@ namespace PuzzleS _indicator.HideClose(); return; } - - // Default fallback behavior - Logging.Debug($"[Puzzles] Player exited close range of {stepData?.stepId} on {gameObject.name}"); } /// @@ -195,9 +209,6 @@ namespace PuzzleS _indicator.HideFar(); return; } - - // Default fallback behavior - Logging.Debug($"[Puzzles] Player exited far range of {stepData?.stepId} on {gameObject.name}"); } /// @@ -205,57 +216,42 @@ namespace PuzzleS /// public void UnlockStep() { + if (_isUnlocked) return; + _isUnlocked = true; Logging.Debug($"[Puzzles] Step unlocked: {stepData?.stepId} on {gameObject.name}"); - // Show indicator if enabled in settings - if (puzzleIndicator != null) + // Make the indicator visible since this step is now unlocked + OnShow(); + + if (IsIndicatorValid()) { - // Try to get the IPuzzlePrompt component from the spawned indicator - _indicator = puzzleIndicator.GetComponent(); - - if (_indicator == null) + // Set the correct state based on current player distance + Transform playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; + if (playerTransform != null) { - // Try to find it in children if not on the root - _indicator = puzzleIndicator.GetComponentInChildren(); - } - - if (_indicator == null) - { - Logging.Warning($"[Puzzles] Indicator prefab for {stepData?.stepId} does not implement IPuzzlePrompt"); - } - else - { - // First show the indicator - _indicator.OnShow(); + float distance = Vector3.Distance(transform.position, playerTransform.position); + float promptRange = AppleHills.SettingsAccess.GetPuzzlePromptRange(); - // Then set the correct state based on current player distance - Transform playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; - if (playerTransform != null) + if (distance <= promptRange) { - float distance = Vector3.Distance(transform.position, playerTransform.position); - float promptRange = AppleHills.SettingsAccess.GetPuzzlePromptRange(); - - if (distance <= promptRange) - { - // Player is in close range - _currentProximityState = ProximityState.Close; - _indicator.ShowClose(); - } - else - { - // Player is in far range - _currentProximityState = ProximityState.Far; - _indicator.ShowFar(); - } + // Player is in close range + _currentProximityState = ProximityState.Close; + _indicator.ShowClose(); } else { - // Default to far if player not found + // Player is in far range _currentProximityState = ProximityState.Far; _indicator.ShowFar(); } } + else + { + // Default to far if player not found + _currentProximityState = ProximityState.Far; + _indicator.ShowFar(); + } } } @@ -264,14 +260,18 @@ namespace PuzzleS /// public void LockStep() { + if (!_isUnlocked && puzzleIndicator != null) + { + // Make sure indicator is hidden if we're already locked + puzzleIndicator.SetActive(false); + return; + } + _isUnlocked = false; Logging.Debug($"[Puzzles] Step locked: {stepData?.stepId} on {gameObject.name}"); - // Hide indicator - if (IsIndicatorValid()) - { - _indicator.OnHide(); - } + // Hide the indicator + OnHide(); } /// @@ -287,7 +287,7 @@ namespace PuzzleS /// private void OnInteractionStarted(PlayerTouchController playerRef, FollowerController followerRef) { - // Optionally handle started interaction (e.g. visual feedback) + // Empty - handled by Interactable } /// @@ -297,12 +297,17 @@ namespace PuzzleS private void OnInteractionComplete(bool success) { if (!_isUnlocked) return; - if (success) + if (success && !_isCompleted) { Logging.Debug($"[Puzzles] Step interacted: {stepData?.stepId} on {gameObject.name}"); _isCompleted = true; PuzzleManager.Instance?.MarkPuzzleStepCompleted(stepData); - Destroy(puzzleIndicator); + + if (puzzleIndicator != null) + { + Destroy(puzzleIndicator); + _indicator = null; + } } } @@ -323,7 +328,7 @@ namespace PuzzleS // Draw threshold circle Gizmos.color = Color.cyan; - Gizmos.DrawWireSphere(transform.position, promptRange / 2f); + Gizmos.DrawWireSphere(transform.position, promptRange); } } } diff --git a/Assets/Scripts/PuzzleS/PuzzleChainSO.cs b/Assets/Scripts/PuzzleS/PuzzleChainSO.cs new file mode 100644 index 00000000..3340dfa7 --- /dev/null +++ b/Assets/Scripts/PuzzleS/PuzzleChainSO.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace PuzzleS +{ + /// + /// Represents a complete chain of puzzle steps that form a logical sequence. + /// This is automatically generated from folder structure during asset import. + /// + [CreateAssetMenu(fileName = "PuzzleChain", menuName = "AppleHills/Items & Puzzles/PuzzleChain")] + public class PuzzleChainSO : ScriptableObject + { + /// + /// Unique identifier for this puzzle chain, automatically set to match folder name + /// + public string chainId; + + /// + /// Display name for this chain + /// + public string displayName; + + /// + /// Description of this puzzle chain + /// + [TextArea] + public string description; + + /// + /// All steps that belong to this puzzle chain + /// + public List allSteps = new List(); + + /// + /// Initial steps that should be unlocked when the puzzle chain starts + /// (steps with no dependencies) + /// + public List initialSteps = new List(); + + /// + /// Optional requirement for this entire chain to be activated + /// If not null, this chain requires the specified chain to be completed first + /// + public PuzzleChainSO requiredChain; + + /// + /// Pre-processed dependency data built at edit time. + /// Maps step IDs to arrays of dependency step IDs + /// + [HideInInspector] + public Dictionary stepDependencies = new Dictionary(); + + /// + /// Gets all steps that will be unlocked by completing the given step + /// + public List GetUnlockedSteps(string stepId) + { + var result = new List(); + foreach (var step in allSteps) + { + if (step.stepId == stepId && step != null) + { + return step.unlocks; + } + } + return result; + } + + /// + /// Gets all steps that will be unlocked by completing the given step + /// + public List GetUnlockedSteps(PuzzleStepSO completedStep) + { + return completedStep != null ? completedStep.unlocks : new List(); + } + + /// + /// Check if this step is an initial step (no dependencies) + /// + public bool IsInitialStep(PuzzleStepSO step) + { + return step != null && initialSteps.Contains(step); + } + + /// + /// Check if all steps in this chain are completed + /// + public bool IsChainComplete(HashSet completedSteps) + { + if (completedSteps == null) return false; + + foreach (var step in allSteps) + { + if (step != null && !completedSteps.Contains(step)) + { + return false; + } + } + return true; + } + } +} diff --git a/Assets/Scripts/PuzzleS/PuzzleChainSO.cs.meta b/Assets/Scripts/PuzzleS/PuzzleChainSO.cs.meta new file mode 100644 index 00000000..62518a80 --- /dev/null +++ b/Assets/Scripts/PuzzleS/PuzzleChainSO.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 58109a40325e47f2a8a3b9264d8938dd +timeCreated: 1760532067 \ No newline at end of file diff --git a/Assets/Scripts/PuzzleS/PuzzleLevelDataSO.cs b/Assets/Scripts/PuzzleS/PuzzleLevelDataSO.cs new file mode 100644 index 00000000..086a8a13 --- /dev/null +++ b/Assets/Scripts/PuzzleS/PuzzleLevelDataSO.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace PuzzleS +{ + /// + /// Represents all puzzle steps in a level. + /// This is automatically generated from folder structure during asset import. + /// + [CreateAssetMenu(fileName = "LevelPuzzleData", menuName = "AppleHills/Items & Puzzles/LevelPuzzleData")] + public class PuzzleLevelDataSO : ScriptableObject + { + /// + /// Unique identifier for this level, automatically set to match folder name + /// + public string levelId; + + /// + /// Display name for this level + /// + public string displayName; + + /// + /// All puzzle steps in this level + /// + public List allSteps = new List(); + + /// + /// Steps that should be unlocked at level start (no dependencies) + /// + public List initialSteps = new List(); + + /// + /// Pre-processed dependency data built at edit time. + /// Maps step IDs to arrays of dependency step IDs (which steps are required by each step) + /// + public Dictionary stepDependencies = new Dictionary(); + + /// + /// Check if all steps in the level are complete + /// + public bool IsLevelComplete(HashSet completedSteps) + { + if (completedSteps == null) return false; + + foreach (var step in allSteps) + { + if (step != null && !completedSteps.Contains(step)) + { + return false; + } + } + return true; + } + + /// + /// Gets all steps that will be unlocked by completing the given step + /// + public List GetUnlockedSteps(PuzzleStepSO completedStep) + { + return completedStep != null ? completedStep.unlocks : new List(); + } + + /// + /// Check if this step is an initial step (no dependencies) + /// + public bool IsInitialStep(PuzzleStepSO step) + { + return step != null && initialSteps.Contains(step); + } + } +} diff --git a/Assets/Scripts/PuzzleS/PuzzleLevelDataSO.cs.meta b/Assets/Scripts/PuzzleS/PuzzleLevelDataSO.cs.meta new file mode 100644 index 00000000..0fde9380 --- /dev/null +++ b/Assets/Scripts/PuzzleS/PuzzleLevelDataSO.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0a79780a5a0d498084afd737d4515e3b +timeCreated: 1760532084 \ No newline at end of file diff --git a/Assets/Scripts/PuzzleS/PuzzleManager.cs b/Assets/Scripts/PuzzleS/PuzzleManager.cs index 61e1a2b3..514a1cfd 100644 --- a/Assets/Scripts/PuzzleS/PuzzleManager.cs +++ b/Assets/Scripts/PuzzleS/PuzzleManager.cs @@ -5,7 +5,10 @@ using System.Linq; using UnityEngine; using UnityEngine.SceneManagement; using AppleHills.Core.Settings; -using Core; // Added for IInteractionSettings +using Core; +using UnityEngine.AddressableAssets; +using UnityEngine.ResourceManagement.AsyncOperations; +using Utils; namespace PuzzleS { @@ -26,6 +29,11 @@ namespace PuzzleS // Settings reference private IInteractionSettings _interactionSettings; + // Current level puzzle data + private PuzzleLevelDataSO _currentLevelData; + private AsyncOperationHandle _levelDataLoadOperation; + private bool _isLoadingLevelData = false; + /// /// Singleton instance of the PuzzleManager. /// @@ -50,47 +58,76 @@ namespace PuzzleS // Events to notify about step lifecycle public event Action OnStepCompleted; public event Action OnStepUnlocked; + public event Action OnLevelDataLoaded; + public event Action OnAllPuzzlesComplete; 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; - + // Initialize settings reference _interactionSettings = GameManager.GetSettingsObject(); } + void OnEnable() + { + // Subscribe to scene manager events + + } + void Start() { + SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted; + // Find player transform _playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; // Start proximity check coroutine StartProximityChecks(); + + // Load puzzle data for the current scene if not already loading + if (_currentLevelData == null && !_isLoadingLevelData) + { + LoadPuzzleDataForCurrentScene(); + } } void OnDestroy() { - SceneManager.sceneLoaded -= OnSceneLoaded; StopProximityChecks(); + + // Unsubscribe from scene manager events + if (SceneManagerService.Instance != null) + { + SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted; + } + + // Release addressable handle if needed + if (_levelDataLoadOperation.IsValid()) + { + Addressables.Release(_levelDataLoadOperation); + } } - private void OnSceneLoaded(Scene scene, LoadSceneMode mode) + /// + /// Called when a scene is loaded + /// + public void OnSceneLoadCompleted(string sceneName) { - SceneManager.sceneLoaded -= OnSceneLoaded; + // Skip for non-gameplay scenes + if (sceneName == "BootstrapScene" || string.IsNullOrEmpty(sceneName)) + { + return; + } - Logging.Debug("[MDPI] OnSceneLoaded"); - _runtimeDependencies.Clear(); - BuildRuntimeDependencies(); - UnlockInitialSteps(); + Logging.Debug($"[Puzzles] Scene loaded: {sceneName}, loading puzzle data"); + LoadPuzzleDataForCurrentScene(sceneName); // Find player transform again in case it changed with scene load _playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; @@ -99,6 +136,66 @@ namespace PuzzleS StartProximityChecks(); } + /// + /// Load puzzle data for the current scene + /// + private void LoadPuzzleDataForCurrentScene(string sceneName = null) + { + string currentScene = sceneName ?? SceneManagerService.Instance.CurrentGameplayScene; + if (string.IsNullOrEmpty(currentScene)) + { + Logging.Warning("[Puzzles] Cannot load puzzle data: Current scene name is empty"); + return; + } + + _isLoadingLevelData = true; + string addressablePath = $"Puzzles/{currentScene}"; + + Logging.Debug($"[Puzzles] Loading puzzle data from addressable: {addressablePath}"); + + // Release previous handle if needed + if (_levelDataLoadOperation.IsValid()) + { + Addressables.Release(_levelDataLoadOperation); + } + + if (!AppleHillsUtils.AddressableKeyExists(addressablePath)) + { + Logging.Warning($"[Puzzles] Puzzle key does not exist in Addressables: {addressablePath}. Returning early!"); + return; + } + + // Load the level data asset + _levelDataLoadOperation = Addressables.LoadAssetAsync(addressablePath); + _levelDataLoadOperation.Completed += handle => + { + _isLoadingLevelData = false; + + if (handle.Status == AsyncOperationStatus.Succeeded) + { + _currentLevelData = handle.Result; + Logging.Debug($"[Puzzles] Loaded level data: {_currentLevelData.levelId} with {_currentLevelData.allSteps.Count} steps"); + + // Reset state + _completedSteps.Clear(); + _unlockedSteps.Clear(); + + // Unlock initial steps + UnlockInitialSteps(); + + // Update existing ObjectiveStepBehaviours with the current state + UpdateRegisteredStepStates(); + + // Notify listeners + OnLevelDataLoaded?.Invoke(_currentLevelData); + } + else + { + Logging.Warning($"[Puzzles] Failed to load puzzle data for {currentScene}: {handle.OperationException?.Message}"); + } + }; + } + /// /// Start the proximity check coroutine. /// @@ -138,7 +235,7 @@ namespace PuzzleS foreach (var kvp in _stepBehaviours) { if (kvp.Value == null) continue; - if (IsPuzzleStepCompleted(kvp.Value.stepData.stepId)) continue; + if (IsPuzzleStepCompleted(kvp.Key.stepId)) continue; float distance = Vector3.Distance(_playerTransform.position, kvp.Value.transform.position); @@ -164,18 +261,48 @@ namespace PuzzleS public void RegisterStepBehaviour(ObjectiveStepBehaviour behaviour) { if (behaviour?.stepData == null) return; + if (!_stepBehaviours.ContainsKey(behaviour.stepData)) { _stepBehaviours.Add(behaviour.stepData, behaviour); - _runtimeDependencies.Clear(); - foreach (var step in _stepBehaviours.Values) - { - step.LockStep(); - } - _unlockedSteps.Clear(); - BuildRuntimeDependencies(); - UnlockInitialSteps(); Logging.Debug($"[Puzzles] Registered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); + + // Immediately set the correct state based on current puzzle state + UpdateStepState(behaviour); + } + } + + /// + /// Updates a step's state based on the current puzzle state. + /// + private void UpdateStepState(ObjectiveStepBehaviour behaviour) + { + if (behaviour?.stepData == null) return; + + // If step is already completed, ignore + if (_completedSteps.Contains(behaviour.stepData)) + return; + + // If step is already unlocked, update the behaviour + if (_unlockedSteps.Contains(behaviour.stepData)) + { + behaviour.UnlockStep(); + } + else + { + // Make sure it's locked + behaviour.LockStep(); + } + } + + /// + /// Updates the states of all registered step behaviours based on current puzzle state. + /// + private void UpdateRegisteredStepStates() + { + foreach (var kvp in _stepBehaviours) + { + UpdateStepState(kvp.Value); } } @@ -191,52 +318,19 @@ namespace PuzzleS } /// - /// 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]) - { - Logging.Debug($"[Puzzles] Step {step.stepId} depends on {dep.stepId}"); - } - } - Logging.Debug($"[Puzzles] Runtime dependencies built. Total steps: {_stepBehaviours.Count}"); - } - - /// - /// Unlocks all initial steps (those with no dependencies) and any steps whose dependencies are already met. + /// Unlocks all initial steps (those with no dependencies) /// private void UnlockInitialSteps() { - // First, unlock all steps with no dependencies (initial steps) - var initialSteps = PuzzleGraphUtility.FindInitialSteps(_runtimeDependencies); - foreach (var step in initialSteps) + if (_currentLevelData == null) return; + + // Unlock initial steps + foreach (var step in _currentLevelData.initialSteps) { - Logging.Debug($"[Puzzles] Initial step unlocked: {step.stepId}"); UnlockStep(step); } - // Keep trying to unlock steps as long as we're making progress - bool madeProgress; - do - { - madeProgress = false; - - // Check all steps that haven't been unlocked yet - foreach (var step in _runtimeDependencies.Keys.Where(s => !_unlockedSteps.Contains(s))) - { - // Check if all dependencies have been completed - if (AreRuntimeDependenciesMet(step)) - { - Logging.Debug($"[Puzzles] Chain step unlocked: {step.stepId}"); - UnlockStep(step); - madeProgress = true; - } - } - } while (madeProgress); + Logging.Debug($"[Puzzles] Unlocked {_unlockedSteps.Count} initial steps"); } /// @@ -246,24 +340,29 @@ namespace PuzzleS public void MarkPuzzleStepCompleted(PuzzleStepSO step) { if (_completedSteps.Contains(step)) return; + if (_currentLevelData == null) return; + _completedSteps.Add(step); Logging.Debug($"[Puzzles] Step completed: {step.stepId}"); // Broadcast completion OnStepCompleted?.Invoke(step); - foreach (var unlock in step.unlocks) + // Unlock steps that are unlocked by this step + foreach (var unlockStep in _currentLevelData.GetUnlockedSteps(step)) { - if (AreRuntimeDependenciesMet(unlock)) + if (AreStepDependenciesMet(unlockStep)) { - Logging.Debug($"[Puzzles] Unlocking step {unlock.stepId} after completing {step.stepId}"); - UnlockStep(unlock); + Logging.Debug($"[Puzzles] Unlocking step {unlockStep.stepId} after completing {step.stepId}"); + UnlockStep(unlockStep); } else { - Logging.Debug($"[Puzzles] Step {unlock.stepId} not unlocked yet, waiting for other dependencies"); + Logging.Debug($"[Puzzles] Step {unlockStep.stepId} not unlocked yet, waiting for other dependencies"); } } + + // Check if all puzzle steps are now complete CheckPuzzleCompletion(); } @@ -272,13 +371,33 @@ namespace PuzzleS /// /// The step to check. /// True if all dependencies are met, false otherwise. - private bool AreRuntimeDependenciesMet(PuzzleStepSO step) + private bool AreStepDependenciesMet(PuzzleStepSO step) { - if (!_runtimeDependencies.ContainsKey(step) || _runtimeDependencies[step].Count == 0) return true; - foreach (var dep in _runtimeDependencies[step]) + if (_currentLevelData == null || step == null) return false; + + // If it's an initial step, it has no dependencies + if (_currentLevelData.IsInitialStep(step)) return true; + + // Check if dependencies are met using pre-processed data + if (_currentLevelData.stepDependencies.TryGetValue(step.stepId, out string[] dependencies)) { - if (!_completedSteps.Contains(dep)) return false; + foreach (var depId in dependencies) + { + // Find the dependency step + bool dependencyMet = false; + foreach (var completedStep in _completedSteps) + { + if (completedStep.stepId == depId) + { + dependencyMet = true; + break; + } + } + + if (!dependencyMet) return false; + } } + return true; } @@ -290,6 +409,7 @@ namespace PuzzleS { if (_unlockedSteps.Contains(step)) return; _unlockedSteps.Add(step); + if (_stepBehaviours.TryGetValue(step, out var behaviour)) { behaviour.UnlockStep(); @@ -301,14 +421,18 @@ namespace PuzzleS } /// - /// Checks if the puzzle is complete (all steps finished). + /// Checks if the puzzle is complete (all steps in level finished). /// private void CheckPuzzleCompletion() { - if (_completedSteps.Count == _stepBehaviours.Count) + if (_currentLevelData == null) return; + + if (_currentLevelData.IsLevelComplete(_completedSteps)) { - Logging.Debug("[Puzzles] Puzzle complete! All steps finished."); - // TODO: Fire puzzle complete event or trigger outcome logic + Logging.Debug("[Puzzles] All puzzles complete! Level finished."); + + // Fire level complete event + OnAllPuzzlesComplete?.Invoke(_currentLevelData); } } @@ -317,9 +441,6 @@ namespace PuzzleS /// public bool IsStepUnlocked(PuzzleStepSO step) { - // _runtimeDependencies.Clear(); - // BuildRuntimeDependencies(); - // UnlockInitialSteps(); return _unlockedSteps.Contains(step); } @@ -332,6 +453,14 @@ namespace PuzzleS { return _completedSteps.Any(step => step.stepId == stepId); } + + /// + /// Get the current level puzzle data + /// + public PuzzleLevelDataSO GetCurrentLevelData() + { + return _currentLevelData; + } void OnApplicationQuit() { diff --git a/Assets/Scripts/UI/Tutorial/DivingTutorial.cs b/Assets/Scripts/UI/Tutorial/DivingTutorial.cs index a7368ff4..16e9a8e6 100644 --- a/Assets/Scripts/UI/Tutorial/DivingTutorial.cs +++ b/Assets/Scripts/UI/Tutorial/DivingTutorial.cs @@ -42,22 +42,21 @@ public class DivingTutorial : MonoBehaviour, ITouchInputConsumer public void OnTap(Vector2 position) { - stateMachine.Next(true); } public void OnHoldStart(Vector2 position) { - throw new System.NotImplementedException(); + return; } public void OnHoldMove(Vector2 position) { - throw new System.NotImplementedException(); + return; } public void OnHoldEnd(Vector2 position) { - throw new System.NotImplementedException(); + return; } } diff --git a/Assets/Scripts/Utils/AppleHillsUtils.cs b/Assets/Scripts/Utils/AppleHillsUtils.cs index 62df8b17..7a90a65f 100644 --- a/Assets/Scripts/Utils/AppleHillsUtils.cs +++ b/Assets/Scripts/Utils/AppleHillsUtils.cs @@ -1,6 +1,9 @@ -using UnityEngine; +using System.Collections.Generic; +using UnityEngine; using AppleHills.Core.Settings; using Core; +using UnityEngine.AddressableAssets; +using UnityEngine.ResourceManagement.ResourceLocations; namespace Utils { @@ -68,5 +71,11 @@ namespace Utils // Apply screen normalization return frameAdjustedSpeed * screenNormalizationFactor; } + + public static bool AddressableKeyExists(object key) + { + IList locations; + return Addressables.LoadResourceLocationsAsync(key).WaitForCompletion()?.Count > 0; + } } } diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 5f084eba..1e425d08 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -329,42 +329,6 @@ PlayerSettings: m_Height: 36 m_Kind: 0 m_SubKind: - - m_Textures: - - {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} - - {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} - m_Width: 432 - m_Height: 432 - m_Kind: 2 - m_SubKind: - - m_Textures: - - {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} - - {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} - m_Width: 324 - m_Height: 324 - m_Kind: 2 - m_SubKind: - - m_Textures: - - {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} - - {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} - m_Width: 216 - m_Height: 216 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 162 - m_Height: 162 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 108 - m_Height: 108 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 81 - m_Height: 81 - m_Kind: 2 - m_SubKind: - m_Textures: [] m_Width: 192 m_Height: 192 @@ -395,6 +359,42 @@ PlayerSettings: m_Height: 36 m_Kind: 1 m_SubKind: + - m_Textures: + - {fileID: 2800000, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + - {fileID: 2800000, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: + - {fileID: 2800000, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + - {fileID: 2800000, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: + - {fileID: 2800000, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + - {fileID: 2800000, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: - m_BuildTarget: iPhone m_Icons: - m_Textures: []