From e713a580a9bcd68d4f14fa73b1ae94f7cc35a6d3 Mon Sep 17 00:00:00 2001 From: tschesky Date: Thu, 2 Oct 2025 05:42:17 +0000 Subject: [PATCH] puzzlestep_indicators (#14) Co-authored-by: Michal Pikulski Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/14 --- .../HammerBirdPuzzle/InteractWLawnMower.asset | 1 + Assets/Editor/EditorSettingsProvider.cs | 11 +- Assets/External/Placeholders/Materials.meta | 8 + .../Placeholders/Materials/apple_red.mat | 43 ++++ .../Placeholders/Materials/apple_red.mat.meta | 8 + .../Environment/Placeholders/LureSpotA.prefab | 2 + .../Placeholders/LuringSpotB.prefab | 2 + .../Placeholders/LuringSpotC.prefab | 2 + .../Items/PrefabsPLACEHOLDER/Football.prefab | 2 + .../Items/PrefabsPLACEHOLDER/HeadBand.prefab | 2 + .../Items/PrefabsPLACEHOLDER/Nails.prefab | 2 + .../Prefabs/Puzzles/BasePuzzlePickup.prefab | 2 + Assets/Prefabs/UI/TestIndicator.prefab | 105 +++++++++ Assets/Prefabs/UI/TestIndicator.prefab.meta | 7 + .../Scenes/Levels/AppleHillsOverworld.unity | 180 +++++++++++++- Assets/Scenes/Levels/Quarry.unity | 83 ++++++- Assets/Scripts/Core/GameManager.cs | 5 + .../Core/Settings/InteractionSettings.cs | 9 + .../Core/Settings/SettingsInterfaces.cs | 4 + Assets/Scripts/Core/SettingsAccess.cs | 17 +- Assets/Scripts/Interactions/ItemSlot.cs | 2 +- Assets/Scripts/PuzzleS/IPuzzlePrompt.cs | 41 ++++ Assets/Scripts/PuzzleS/IPuzzlePrompt.cs.meta | 3 + .../Scripts/PuzzleS/ObjectiveStepBehaviour.cs | 223 +++++++++++++++++- Assets/Scripts/PuzzleS/PuzzleManager.cs | 80 +++++++ Assets/Scripts/PuzzleS/PuzzleStepSO.cs | 15 ++ Assets/Scripts/UI/TestIndicator.cs | 46 ++++ Assets/Scripts/UI/TestIndicator.cs.meta | 2 + Assets/Settings/InteractionSettings.asset | 2 + 29 files changed, 899 insertions(+), 10 deletions(-) create mode 100644 Assets/External/Placeholders/Materials.meta create mode 100644 Assets/External/Placeholders/Materials/apple_red.mat create mode 100644 Assets/External/Placeholders/Materials/apple_red.mat.meta create mode 100644 Assets/Prefabs/UI/TestIndicator.prefab create mode 100644 Assets/Prefabs/UI/TestIndicator.prefab.meta create mode 100644 Assets/Scripts/PuzzleS/IPuzzlePrompt.cs create mode 100644 Assets/Scripts/PuzzleS/IPuzzlePrompt.cs.meta create mode 100644 Assets/Scripts/UI/TestIndicator.cs create mode 100644 Assets/Scripts/UI/TestIndicator.cs.meta diff --git a/Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset b/Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset index 36bc2621..fe58854c 100644 --- a/Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset +++ b/Assets/Data/Puzzles/HammerBirdPuzzle/InteractWLawnMower.asset @@ -17,3 +17,4 @@ MonoBehaviour: description: Start up the lawnmower so the Gardener runs after it. icon: {fileID: 0} unlocks: [] + showIndicator: 1 diff --git a/Assets/Editor/EditorSettingsProvider.cs b/Assets/Editor/EditorSettingsProvider.cs index 6c102515..8e1ffec4 100644 --- a/Assets/Editor/EditorSettingsProvider.cs +++ b/Assets/Editor/EditorSettingsProvider.cs @@ -22,7 +22,8 @@ namespace AppleHills.Editor // Set up the delegates in SettingsAccess AppleHills.SettingsAccess.SetupEditorProviders( GetPlayerStopDistance, - GetPlayerStopDistanceDirectInteraction + GetPlayerStopDistanceDirectInteraction, + GetPuzzlePromptRange ); // Subscribe to asset changes to auto-refresh when settings are modified @@ -58,7 +59,8 @@ namespace AppleHills.Editor // Re-register the delegates in case they were lost AppleHills.SettingsAccess.SetupEditorProviders( GetPlayerStopDistance, - GetPlayerStopDistanceDirectInteraction + GetPlayerStopDistanceDirectInteraction, + GetPuzzlePromptRange ); Debug.Log("Editor settings loaded for Scene View use"); @@ -81,6 +83,11 @@ namespace AppleHills.Editor return _interactionSettings?.PlayerStopDistanceDirectInteraction ?? 2.0f; } + private static float GetPuzzlePromptRange() + { + return _interactionSettings?.DefaultPuzzlePromptRange ?? 3.0f; + } + // Other utility methods public static T GetSettings() where T : BaseSettings { diff --git a/Assets/External/Placeholders/Materials.meta b/Assets/External/Placeholders/Materials.meta new file mode 100644 index 00000000..e199b720 --- /dev/null +++ b/Assets/External/Placeholders/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 40c86a69ce6198849928969c19c95ca1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Placeholders/Materials/apple_red.mat b/Assets/External/Placeholders/Materials/apple_red.mat new file mode 100644 index 00000000..556fdd56 --- /dev/null +++ b/Assets/External/Placeholders/Materials/apple_red.mat @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: apple_red + m_Shader: {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _AlphaTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 00354ded9d8f8d643acc14837a229544, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - PixelSnap: 0 + - _EnableExternalAlpha: 0 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _Flip: {r: 1, g: 1, b: 1, a: 1} + - _RendererColor: {r: 1, g: 1, b: 1, a: 1} + m_BuildTextureStacks: [] + m_AllowLocking: 1 diff --git a/Assets/External/Placeholders/Materials/apple_red.mat.meta b/Assets/External/Placeholders/Materials/apple_red.mat.meta new file mode 100644 index 00000000..c094d527 --- /dev/null +++ b/Assets/External/Placeholders/Materials/apple_red.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 807266c5634eb434f9ada258a07c1c5c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Environment/Placeholders/LureSpotA.prefab b/Assets/Prefabs/Environment/Placeholders/LureSpotA.prefab index fc5382fe..7465ec3d 100644 --- a/Assets/Prefabs/Environment/Placeholders/LureSpotA.prefab +++ b/Assets/Prefabs/Environment/Placeholders/LureSpotA.prefab @@ -354,6 +354,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: 0fb0ab2b55d93a24685e9f6651adcf30, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 --- !u!1 &7675352645851726746 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Environment/Placeholders/LuringSpotB.prefab b/Assets/Prefabs/Environment/Placeholders/LuringSpotB.prefab index e362a043..f764d39d 100644 --- a/Assets/Prefabs/Environment/Placeholders/LuringSpotB.prefab +++ b/Assets/Prefabs/Environment/Placeholders/LuringSpotB.prefab @@ -430,6 +430,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: d0851a7610551104fa285c0748549d90, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 --- !u!114 &488333850132012697 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Environment/Placeholders/LuringSpotC.prefab b/Assets/Prefabs/Environment/Placeholders/LuringSpotC.prefab index b49199e1..85a56268 100644 --- a/Assets/Prefabs/Environment/Placeholders/LuringSpotC.prefab +++ b/Assets/Prefabs/Environment/Placeholders/LuringSpotC.prefab @@ -439,6 +439,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: 28848561ff31fe24ea9f8590dee0bf8f, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 --- !u!114 &8370367816617117734 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Football.prefab b/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Football.prefab index d822839e..688e1532 100644 --- a/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Football.prefab +++ b/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Football.prefab @@ -150,3 +150,5 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: 6386246caab8faa40b2da221d9ab9b8a, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 diff --git a/Assets/Prefabs/Items/PrefabsPLACEHOLDER/HeadBand.prefab b/Assets/Prefabs/Items/PrefabsPLACEHOLDER/HeadBand.prefab index 6ee73924..8ed1fc97 100644 --- a/Assets/Prefabs/Items/PrefabsPLACEHOLDER/HeadBand.prefab +++ b/Assets/Prefabs/Items/PrefabsPLACEHOLDER/HeadBand.prefab @@ -150,3 +150,5 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: 5700dd3bf16fa9e4aa9905379118d1bd, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 diff --git a/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Nails.prefab b/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Nails.prefab index 3db7f64c..2ef5d887 100644 --- a/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Nails.prefab +++ b/Assets/Prefabs/Items/PrefabsPLACEHOLDER/Nails.prefab @@ -150,3 +150,5 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: f9da68caaae2a244885a13cf2e2e45c0, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 diff --git a/Assets/Prefabs/Puzzles/BasePuzzlePickup.prefab b/Assets/Prefabs/Puzzles/BasePuzzlePickup.prefab index c52311f4..20db50ab 100644 --- a/Assets/Prefabs/Puzzles/BasePuzzlePickup.prefab +++ b/Assets/Prefabs/Puzzles/BasePuzzlePickup.prefab @@ -78,3 +78,5 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 0} + puzzleIndicator: {fileID: 0} + drawPromptRangeGizmo: 1 diff --git a/Assets/Prefabs/UI/TestIndicator.prefab b/Assets/Prefabs/UI/TestIndicator.prefab new file mode 100644 index 00000000..92d985be --- /dev/null +++ b/Assets/Prefabs/UI/TestIndicator.prefab @@ -0,0 +1,105 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4963699568605073487 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6675530734045362487} + - component: {fileID: 6456168790767136091} + - component: {fileID: 7639410009611357915} + m_Layer: 0 + m_Name: TestIndicator + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6675530734045362487 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4963699568605073487} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: 0.99978626, w: -0.020675343} + m_LocalPosition: {x: 46.58, y: -1.77, z: 0} + m_LocalScale: {x: -0.1, y: 0.1, z: 0.1} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 182.369} +--- !u!212 &6456168790767136091 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4963699568605073487} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: -1067459232888207889, guid: 6767e1e5c0a16f14e926a72a81bf95cb, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 1 + m_DrawMode: 0 + m_Size: {x: 13.32, y: 12.85} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!114 &7639410009611357915 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4963699568605073487} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7a691a95f74c07245b64469dda594bfb, type: 3} + m_Name: + m_EditorClassIdentifier: '::' diff --git a/Assets/Prefabs/UI/TestIndicator.prefab.meta b/Assets/Prefabs/UI/TestIndicator.prefab.meta new file mode 100644 index 00000000..51dca652 --- /dev/null +++ b/Assets/Prefabs/UI/TestIndicator.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: cac39b7f8f414e7499e7b672d8710642 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Levels/AppleHillsOverworld.unity b/Assets/Scenes/Levels/AppleHillsOverworld.unity index 5af05e20..4fe71ee7 100644 --- a/Assets/Scenes/Levels/AppleHillsOverworld.unity +++ b/Assets/Scenes/Levels/AppleHillsOverworld.unity @@ -299,6 +299,14 @@ PrefabInstance: propertyPath: stepData value: objectReference: {fileID: 11400000, guid: 13b0c411066f85a41ba40c3bbbc281ed, type: 2} + - target: {fileID: 4778083634590203921, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} + propertyPath: indicatorPrefab + value: + objectReference: {fileID: 517425340} + - target: {fileID: 4778083634590203921, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} + propertyPath: puzzleIndicator + value: + objectReference: {fileID: 517425340} - target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} propertyPath: characterToInteract value: 1 @@ -313,7 +321,10 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} + insertIndex: -1 + addedObject: {fileID: 517425339} m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} --- !u!1 &124275611 @@ -578,6 +589,14 @@ PrefabInstance: propertyPath: m_Enabled value: 1 objectReference: {fileID: 0} + - target: {fileID: 4778083634590203921, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} + propertyPath: indicatorPrefab + value: + objectReference: {fileID: 1398956015} + - target: {fileID: 4778083634590203921, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} + propertyPath: puzzleIndicator + value: + objectReference: {fileID: 1398956015} - target: {fileID: 6254953093500072797, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} propertyPath: isOneTime value: 0 @@ -592,7 +611,10 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} + insertIndex: -1 + addedObject: {fileID: 2027386480} m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} --- !u!1 &384576743 @@ -770,6 +792,81 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} +--- !u!1001 &517425338 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 2102167558} + m_Modifications: + - target: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_Name + value: TestIndicator + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalScale.x + value: -0.02353178 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalScale.y + value: 0.024997333 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.x + value: 0.64 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.y + value: 0.5220351 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.w + value: -0.020675343 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.z + value: 0.99978626 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 182.369 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} +--- !u!4 &517425339 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + m_PrefabInstance: {fileID: 517425338} + m_PrefabAsset: {fileID: 0} +--- !u!1 &517425340 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + m_PrefabInstance: {fileID: 517425338} + m_PrefabAsset: {fileID: 0} --- !u!114 &614125440 stripped MonoBehaviour: m_CorrespondingSourceObject: {fileID: 4573570654593171780, guid: a8b0a1c6cf21352439dc24d3b03182db, type: 3} @@ -1887,6 +1984,11 @@ PrefabInstance: insertIndex: -1 addedObject: {fileID: 1631660124} m_SourcePrefab: {fileID: 100100000, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3} +--- !u!1 &1398956015 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + m_PrefabInstance: {fileID: 2027386479} + m_PrefabAsset: {fileID: 0} --- !u!1 &1443361595 GameObject: m_ObjectHideFlags: 0 @@ -2556,6 +2658,80 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &2027386479 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 754397347} + m_Modifications: + - target: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_Name + value: TestIndicator + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalScale.x + value: -0.02 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalScale.y + value: 0.022568762 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalScale.z + value: 0.36117727 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.x + value: 0.62 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.y + value: 0.53 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.w + value: -0.020675343 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.z + value: 0.99978626 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 182.369 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} +--- !u!4 &2027386480 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + m_PrefabInstance: {fileID: 2027386479} + m_PrefabAsset: {fileID: 0} --- !u!4 &2102167558 stripped Transform: m_CorrespondingSourceObject: {fileID: 2844046668579196942, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3} diff --git a/Assets/Scenes/Levels/Quarry.unity b/Assets/Scenes/Levels/Quarry.unity index 3b246c4b..e085e057 100644 --- a/Assets/Scenes/Levels/Quarry.unity +++ b/Assets/Scenes/Levels/Quarry.unity @@ -442044,6 +442044,73 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 93ab59741ddc4e045a61cd8e05b65578, type: 3} +--- !u!1001 &1034525253 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 1267682468} + m_Modifications: + - target: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_Name + value: TestIndicator + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.x + value: 5.83 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.y + value: 7.38814 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.w + value: -0.020675343 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalRotation.z + value: 0.99978626 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 182.369 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} +--- !u!1 &1034525254 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + m_PrefabInstance: {fileID: 1034525253} + m_PrefabAsset: {fileID: 0} +--- !u!4 &1034525255 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 6675530734045362487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + m_PrefabInstance: {fileID: 1034525253} + m_PrefabAsset: {fileID: 0} --- !u!1001 &1042636114 PrefabInstance: m_ObjectHideFlags: 0 @@ -444607,6 +444674,8 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: stepData: {fileID: 11400000, guid: 8ac614a698631554ab8ac39aed04a189, type: 2} + indicatorPrefab: {fileID: 0} + drawPromptRangeGizmo: 1 --- !u!114 &1182494941 MonoBehaviour: m_ObjectHideFlags: 0 @@ -445683,6 +445752,11 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 9fba2c868971b20439aaea06a939d8e7, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!4 &1267682468 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 7402687028936857164, guid: 1fda7fccaa5fbd04695f4c98d29bcbe0, type: 3} + m_PrefabInstance: {fileID: 4912039252317080710} + m_PrefabAsset: {fileID: 0} --- !u!1001 &1269263373 PrefabInstance: m_ObjectHideFlags: 0 @@ -458506,6 +458580,10 @@ PrefabInstance: propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} + - target: {fileID: 2341456216084136881, guid: 1fda7fccaa5fbd04695f4c98d29bcbe0, type: 3} + propertyPath: indicatorPrefab + value: + objectReference: {fileID: 1034525254} - target: {fileID: 2767794910448825193, guid: 1fda7fccaa5fbd04695f4c98d29bcbe0, type: 3} propertyPath: isOneTime value: 1 @@ -458693,7 +458771,10 @@ PrefabInstance: m_RemovedComponents: - {fileID: 1126777572448403549, guid: 1fda7fccaa5fbd04695f4c98d29bcbe0, type: 3} m_RemovedGameObjects: [] - m_AddedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 7402687028936857164, guid: 1fda7fccaa5fbd04695f4c98d29bcbe0, type: 3} + insertIndex: -1 + addedObject: {fileID: 1034525255} m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 1fda7fccaa5fbd04695f4c98d29bcbe0, type: 3} --- !u!1001 &5288063114372713135 diff --git a/Assets/Scripts/Core/GameManager.cs b/Assets/Scripts/Core/GameManager.cs index 0797b577..65f1cada 100644 --- a/Assets/Scripts/Core/GameManager.cs +++ b/Assets/Scripts/Core/GameManager.cs @@ -187,6 +187,11 @@ public class GameManager : MonoBehaviour public LayerMask InteractableLayerMask => GetSettings()?.InteractableLayerMask ?? -1; public GameObject BasePickupPrefab => GetSettings()?.BasePickupPrefab; public GameObject LevelSwitchMenuPrefab => GetSettings()?.LevelSwitchMenuPrefab; + + // PUZZLE SETTINGS + + public float DefaultPuzzlePromptRange => GetSettings()?.DefaultPuzzlePromptRange ?? 3.0f; + public GameObject DefaultPuzzleIndicatorPrefab => GetSettings()?.DefaultPuzzleIndicatorPrefab; /// /// Returns the combination rule for two items, if any. diff --git a/Assets/Scripts/Core/Settings/InteractionSettings.cs b/Assets/Scripts/Core/Settings/InteractionSettings.cs index 8ba9664f..d4ae1bf7 100644 --- a/Assets/Scripts/Core/Settings/InteractionSettings.cs +++ b/Assets/Scripts/Core/Settings/InteractionSettings.cs @@ -22,6 +22,12 @@ namespace AppleHills.Core.Settings [SerializeField] private GameObject basePickupPrefab; [SerializeField] private GameObject levelSwitchMenuPrefab; + [Header("Puzzle Settings")] + [Tooltip("Default prefab for puzzle step indicators")] + [SerializeField] private GameObject defaultPuzzleIndicatorPrefab; + [Tooltip("Default range for puzzle prompts")] + [SerializeField] private float defaultPuzzlePromptRange = 3.0f; + [Header("Item Configuration")] [SerializeField] private List combinationRules = new List(); [SerializeField] private List slotItemConfigs = new List(); @@ -35,6 +41,8 @@ namespace AppleHills.Core.Settings public GameObject LevelSwitchMenuPrefab => levelSwitchMenuPrefab; public List CombinationRules => combinationRules; public List SlotItemConfigs => slotItemConfigs; + public GameObject DefaultPuzzleIndicatorPrefab => defaultPuzzleIndicatorPrefab; + public float DefaultPuzzlePromptRange => defaultPuzzlePromptRange; public override void OnValidate() { @@ -43,6 +51,7 @@ namespace AppleHills.Core.Settings playerStopDistance = Mathf.Max(0.1f, playerStopDistance); playerStopDistanceDirectInteraction = Mathf.Max(0.1f, playerStopDistanceDirectInteraction); followerPickupDelay = Mathf.Max(0f, followerPickupDelay); + defaultPuzzlePromptRange = Mathf.Max(0.1f, defaultPuzzlePromptRange); } } } diff --git a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs index 33da8d20..eb00e754 100644 --- a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs +++ b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs @@ -38,6 +38,10 @@ namespace AppleHills.Core.Settings GameObject LevelSwitchMenuPrefab { get; } List CombinationRules { get; } List SlotItemConfigs { get; } + + // Puzzle settings + GameObject DefaultPuzzleIndicatorPrefab { get; } + float DefaultPuzzlePromptRange { get; } } /// diff --git a/Assets/Scripts/Core/SettingsAccess.cs b/Assets/Scripts/Core/SettingsAccess.cs index 9bf875a1..502ecb9b 100644 --- a/Assets/Scripts/Core/SettingsAccess.cs +++ b/Assets/Scripts/Core/SettingsAccess.cs @@ -13,17 +13,20 @@ namespace AppleHills // Static delegates that will be set by editor code private static GetSettingsValueDelegate getPlayerStopDistanceProvider; private static GetSettingsValueDelegate getPlayerStopDistanceDirectInteractionProvider; + private static GetSettingsValueDelegate getPuzzlePromptRangeProvider; // Editor-only method to set up providers - will be called from editor code public static void SetupEditorProviders( GetSettingsValueDelegate playerStopDistanceProvider, - GetSettingsValueDelegate playerStopDistanceDirectInteractionProvider) + GetSettingsValueDelegate playerStopDistanceDirectInteractionProvider, + GetSettingsValueDelegate puzzlePromptRangeProvider) { #if UNITY_EDITOR if (!Application.isPlaying) { getPlayerStopDistanceProvider = playerStopDistanceProvider; getPlayerStopDistanceDirectInteractionProvider = playerStopDistanceDirectInteractionProvider; + getPuzzlePromptRangeProvider = puzzlePromptRangeProvider; } #endif } @@ -52,6 +55,18 @@ namespace AppleHills return GameManager.Instance.PlayerStopDistanceDirectInteraction; } + public static float GetPuzzlePromptRange() + { + #if UNITY_EDITOR + if (!Application.isPlaying && getPuzzlePromptRangeProvider != null) + { + return getPuzzlePromptRangeProvider(); + } + #endif + + return GameManager.Instance.DefaultPuzzlePromptRange; + } + // Add more methods as needed for other settings } } diff --git a/Assets/Scripts/Interactions/ItemSlot.cs b/Assets/Scripts/Interactions/ItemSlot.cs index 409b9edf..2826d7a8 100644 --- a/Assets/Scripts/Interactions/ItemSlot.cs +++ b/Assets/Scripts/Interactions/ItemSlot.cs @@ -177,7 +177,7 @@ namespace Interactions // the correct item we're looking for var config = GameManager.Instance.GetSlotItemConfig(itemData); var allowed = config?.allowedItems ?? new List(); - if (PickupItemData.ListContainsEquivalent(allowed, itemToSlotData)) + if (itemToSlotData != null && PickupItemData.ListContainsEquivalent(allowed, itemToSlotData)) { if (itemToSlot != null) { diff --git a/Assets/Scripts/PuzzleS/IPuzzlePrompt.cs b/Assets/Scripts/PuzzleS/IPuzzlePrompt.cs new file mode 100644 index 00000000..158a55f8 --- /dev/null +++ b/Assets/Scripts/PuzzleS/IPuzzlePrompt.cs @@ -0,0 +1,41 @@ +using System; + +namespace PuzzleS +{ + /// + /// Interface for proximity-based puzzle prompts that can show far/close indicators + /// based on player distance. + /// + public interface IPuzzlePrompt + { + /// + /// Called when the prompt should be initially shown (e.g., when step is unlocked) + /// + void OnShow(); + + /// + /// Called when the prompt should be hidden (e.g., when step is locked) + /// + void OnHide(); + + /// + /// Called when the player enters the outer range of the prompt. + /// + void ShowFar(); + + /// + /// Called when the player enters the inner range of the prompt. + /// + void ShowClose(); + + /// + /// Called when the player exits the inner range of the prompt. + /// + void HideClose(); + + /// + /// Called when the player exits the outer range of the prompt. + /// + void HideFar(); + } +} diff --git a/Assets/Scripts/PuzzleS/IPuzzlePrompt.cs.meta b/Assets/Scripts/PuzzleS/IPuzzlePrompt.cs.meta new file mode 100644 index 00000000..ec150d02 --- /dev/null +++ b/Assets/Scripts/PuzzleS/IPuzzlePrompt.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 84466e5dfeeb4908adf7f0f1f2b82531 +timeCreated: 1759312472 \ No newline at end of file diff --git a/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs b/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs index f19ff65c..e0a7f3ea 100644 --- a/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs +++ b/Assets/Scripts/PuzzleS/ObjectiveStepBehaviour.cs @@ -1,6 +1,9 @@ using Input; using Interactions; using UnityEngine; +using System; +using AppleHills.Core.Settings; +using UnityEngine.Serialization; namespace PuzzleS { @@ -8,14 +11,26 @@ namespace PuzzleS /// Manages the state and interactions for a single puzzle step, including unlock/lock logic and event handling. /// [RequireComponent(typeof(Interactable))] - public class ObjectiveStepBehaviour : MonoBehaviour + public class ObjectiveStepBehaviour : MonoBehaviour, IPuzzlePrompt { /// /// The data object representing this puzzle step. /// public PuzzleStepSO stepData; + + [Header("Indicator Settings")] + [SerializeField] private GameObject puzzleIndicator; + [SerializeField] private bool drawPromptRangeGizmo = true; + private Interactable _interactable; private bool _isUnlocked = false; + private IPuzzlePrompt _indicator; + + // Current proximity state tracked by PuzzleManager + private ProximityState _currentProximityState = ProximityState.Far; + + // Enum for tracking proximity state (simplified to just Close and Far) + public enum ProximityState { Close, Far } void Awake() { @@ -48,6 +63,139 @@ namespace PuzzleS } PuzzleManager.Instance?.UnregisterStepBehaviour(this); } + + /// + /// Updates the proximity state from PuzzleManager and triggers appropriate methods. + /// + /// The new proximity state. + public void UpdateProximityState(ProximityState newState) + { + if (_currentProximityState == newState) return; + + // Determine state changes and call appropriate methods + if (newState == ProximityState.Close) + { + // Transitioning from Far to Close + ShowClose(); + } + else // newState == ProximityState.Far + { + // Transitioning from Close to Far + HideClose(); + } + + _currentProximityState = newState; + } + + // IPuzzlePrompt interface implementation - delegates to indicator if available + + /// + /// Called when the prompt should be initially shown (e.g., when step is unlocked) + /// + public virtual void OnShow() + { + // Delegate to indicator if available + if (_indicator != null) + { + _indicator.OnShow(); + return; + } + + // Default fallback behavior + Debug.Log($"[Puzzles] Prompt shown for {stepData?.stepId} on {gameObject.name}"); + } + + /// + /// Called when the prompt should be hidden (e.g., when step is locked) + /// + public virtual void OnHide() + { + // Delegate to indicator if available + if (_indicator != null) + { + _indicator.OnHide(); + return; + } + + // Default fallback behavior + Debug.Log($"[Puzzles] Prompt hidden for {stepData?.stepId} on {gameObject.name}"); + } + + /// + /// Called when player enters the far range + /// + public virtual void ShowFar() + { + // Only show if step is unlocked + if (!_isUnlocked) return; + + // Delegate to indicator if available + if (_indicator != null) + { + _indicator.ShowFar(); + return; + } + + // Default fallback behavior + Debug.Log($"[Puzzles] Player entered far range of {stepData?.stepId} on {gameObject.name}"); + } + + /// + /// Called when player enters the close range + /// + public virtual void ShowClose() + { + // Only show if step is unlocked + if (!_isUnlocked) return; + + // Delegate to indicator if available + if (_indicator != null) + { + _indicator.ShowClose(); + return; + } + + // Default fallback behavior + Debug.Log($"[Puzzles] Player entered close range of {stepData?.stepId} on {gameObject.name}"); + } + + /// + /// Called when player exits the close range + /// + public virtual void HideClose() + { + // Only respond if step is unlocked + if (!_isUnlocked) return; + + // Delegate to indicator if available + if (_indicator != null) + { + _indicator.HideClose(); + return; + } + + // Default fallback behavior + Debug.Log($"[Puzzles] Player exited close range of {stepData?.stepId} on {gameObject.name}"); + } + + /// + /// Called when player exits the far range + /// + public virtual void HideFar() + { + // Only respond if step is unlocked + if (!_isUnlocked) return; + + // Delegate to indicator if available + if (_indicator != null) + { + _indicator.HideFar(); + return; + } + + // Default fallback behavior + Debug.Log($"[Puzzles] Player exited far range of {stepData?.stepId} on {gameObject.name}"); + } /// /// Unlocks this puzzle step, allowing interaction. @@ -56,7 +204,56 @@ namespace PuzzleS { _isUnlocked = true; Debug.Log($"[Puzzles] Step unlocked: {stepData?.stepId} on {gameObject.name}"); - // Optionally, show visual feedback for unlocked state + + // Show indicator if enabled in settings + if (puzzleIndicator != null) + { + // Try to get the IPuzzlePrompt component from the spawned indicator + _indicator = puzzleIndicator.GetComponent(); + + if (_indicator == null) + { + // Try to find it in children if not on the root + _indicator = puzzleIndicator.GetComponentInChildren(); + } + + if (_indicator == null) + { + Debug.LogWarning($"[Puzzles] Indicator prefab for {stepData?.stepId} does not implement IPuzzlePrompt"); + } + else + { + // First show the indicator + _indicator.OnShow(); + + // Then set the correct state based on current player distance + Transform playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; + if (playerTransform != null) + { + 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(); + } + } + else + { + // Default to far if player not found + _currentProximityState = ProximityState.Far; + _indicator.ShowFar(); + } + } + } } /// @@ -66,7 +263,12 @@ namespace PuzzleS { _isUnlocked = false; Debug.Log($"[Puzzles] Step locked: {stepData?.stepId} on {gameObject.name}"); - // Optionally, show visual feedback for locked state + + // Hide indicator + if (_indicator != null) + { + _indicator.OnHide(); + } } /// @@ -98,5 +300,20 @@ namespace PuzzleS PuzzleManager.Instance?.MarkPuzzleStepCompleted(stepData); } } + + /// + /// Visualizes the puzzle prompt ranges in the editor. + /// + private void OnDrawGizmos() + { + if (!drawPromptRangeGizmo) return; + + // Use the global puzzle prompt range from settings + float promptRange = AppleHills.SettingsAccess.GetPuzzlePromptRange(); + + // Draw threshold circle + Gizmos.color = Color.cyan; + Gizmos.DrawWireSphere(transform.position, promptRange / 2f); + } } } diff --git a/Assets/Scripts/PuzzleS/PuzzleManager.cs b/Assets/Scripts/PuzzleS/PuzzleManager.cs index 0c7d2c28..210f2bd5 100644 --- a/Assets/Scripts/PuzzleS/PuzzleManager.cs +++ b/Assets/Scripts/PuzzleS/PuzzleManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -14,6 +15,12 @@ namespace PuzzleS private static PuzzleManager _instance; private static bool _isQuitting; + [SerializeField] private float proximityCheckInterval = 0.02f; + + // Reference to player transform for proximity calculations + private Transform _playerTransform; + private Coroutine _proximityCheckCoroutine; + /// /// Singleton instance of the PuzzleManager. /// @@ -53,9 +60,19 @@ namespace PuzzleS SceneManager.sceneLoaded += OnSceneLoaded; } + void Start() + { + // Find player transform + _playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; + + // Start proximity check coroutine + StartProximityChecks(); + } + void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; + StopProximityChecks(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) @@ -66,6 +83,69 @@ namespace PuzzleS _runtimeDependencies.Clear(); BuildRuntimeDependencies(); UnlockInitialSteps(); + + // Find player transform again in case it changed with scene load + _playerTransform = GameObject.FindGameObjectWithTag("Player")?.transform; + + // Restart proximity checks + StartProximityChecks(); + } + + /// + /// Start the proximity check coroutine. + /// + private void StartProximityChecks() + { + StopProximityChecks(); + _proximityCheckCoroutine = StartCoroutine(CheckProximityRoutine()); + } + + /// + /// Stop the proximity check coroutine. + /// + private void StopProximityChecks() + { + if (_proximityCheckCoroutine != null) + { + StopCoroutine(_proximityCheckCoroutine); + _proximityCheckCoroutine = null; + } + } + + /// + /// Coroutine that periodically checks player proximity to all puzzle steps. + /// + private IEnumerator CheckProximityRoutine() + { + WaitForSeconds wait = new WaitForSeconds(proximityCheckInterval); + + while (true) + { + if (_playerTransform != null) + { + // Get the proximity threshold from settings (half of the prompt range) + float proximityThreshold = GameManager.Instance.DefaultPuzzlePromptRange; + + // Check distance to each step behavior + foreach (var kvp in _stepBehaviours) + { + if (kvp.Value == null) continue; + + float distance = Vector3.Distance(_playerTransform.position, kvp.Value.transform.position); + + // Determine the proximity state - only Close or Far now + ObjectiveStepBehaviour.ProximityState state = + (distance <= proximityThreshold) + ? ObjectiveStepBehaviour.ProximityState.Close + : ObjectiveStepBehaviour.ProximityState.Far; + + // Update the step's proximity state + kvp.Value.UpdateProximityState(state); + } + } + + yield return wait; + } } /// diff --git a/Assets/Scripts/PuzzleS/PuzzleStepSO.cs b/Assets/Scripts/PuzzleS/PuzzleStepSO.cs index 80336e05..65968105 100644 --- a/Assets/Scripts/PuzzleS/PuzzleStepSO.cs +++ b/Assets/Scripts/PuzzleS/PuzzleStepSO.cs @@ -29,4 +29,19 @@ public class PuzzleStepSO : ScriptableObject /// [Header("Unlocks")] public List unlocks = new List(); + + [Header("Interaction Settings")] + [Tooltip("Whether to show an indicator when this step is unlocked")] + [SerializeField] private bool showIndicator = false; + + /// + /// Whether to show an indicator when this step is unlocked. + /// + public bool ShowIndicator => showIndicator; + + /// + /// Gets or sets whether to show an indicator. + /// + public bool GetShowIndicator() => showIndicator; + public void SetShowIndicator(bool value) => showIndicator = value; } diff --git a/Assets/Scripts/UI/TestIndicator.cs b/Assets/Scripts/UI/TestIndicator.cs new file mode 100644 index 00000000..ae2dcbf2 --- /dev/null +++ b/Assets/Scripts/UI/TestIndicator.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +public class TestIndicator : MonoBehaviour, PuzzleS.IPuzzlePrompt +{ + // Start is called once before the first execution of Update after the MonoBehaviour is created + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } + + public void OnShow() + { + gameObject.SetActive(true); + } + + public void OnHide() + { + gameObject.SetActive(false); + } + + public void ShowFar() + { + gameObject.SetActive(true); + } + + public void ShowClose() + { + gameObject.transform.localScale = new Vector3(-0.2f, 0.2f, 0.2f); + } + + public void HideClose() + { + gameObject.transform.localScale = new Vector3(-0.1f, 0.1f, 0.1f); + } + + public void HideFar() + { + gameObject.SetActive(false); + } +} diff --git a/Assets/Scripts/UI/TestIndicator.cs.meta b/Assets/Scripts/UI/TestIndicator.cs.meta new file mode 100644 index 00000000..eecf5ebe --- /dev/null +++ b/Assets/Scripts/UI/TestIndicator.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7a691a95f74c07245b64469dda594bfb \ No newline at end of file diff --git a/Assets/Settings/InteractionSettings.asset b/Assets/Settings/InteractionSettings.asset index d3804a57..0ff04e34 100644 --- a/Assets/Settings/InteractionSettings.asset +++ b/Assets/Settings/InteractionSettings.asset @@ -20,6 +20,8 @@ MonoBehaviour: m_Bits: 1024 basePickupPrefab: {fileID: 7447346505753002421, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3} levelSwitchMenuPrefab: {fileID: 4062459998181038721, guid: de2ed28e4200a4340a5af4086c98a0dc, type: 3} + defaultPuzzleIndicatorPrefab: {fileID: 4963699568605073487, guid: cac39b7f8f414e7499e7b672d8710642, type: 3} + defaultPuzzlePromptRange: 10 combinationRules: - itemA: {fileID: 11400000, guid: 8b2616beb14825a46b9b1ed85ad3cb25, type: 2} itemB: {fileID: 11400000, guid: 33e7ca06b22108d4e802486e08bcdfd1, type: 2}