diff --git a/Assets/Editor/Settings/EditorSettingsProvider.cs b/Assets/Editor/Settings/EditorSettingsProvider.cs index 5efef722..4270f489 100644 --- a/Assets/Editor/Settings/EditorSettingsProvider.cs +++ b/Assets/Editor/Settings/EditorSettingsProvider.cs @@ -1,6 +1,7 @@ using UnityEditor; using AppleHills.Core.Settings; using Core; +using Core.Settings; namespace AppleHills.Editor { diff --git a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster.prefab b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster.prefab index acccd9c6..8e4887f4 100644 --- a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster.prefab +++ b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster.prefab @@ -46,6 +46,7 @@ RectTransform: m_Pivot: {x: 0.5, y: 0.5} --- !u!212 &8447572436637192077 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -91,6 +92,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 2 + m_MaskInteraction: 0 m_Sprite: {fileID: -9125130289615156199, guid: 1021fffcba2a03d40ae5371555089a22, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -100,7 +102,6 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!58 &4998672042618199381 CircleCollider2D: @@ -151,6 +152,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: detectionCollider: {fileID: 4998672042618199381} + proximityIndicator: {fileID: 5329236367077024222} monsterClips: - {fileID: 8300000, guid: 30abed376d8a6914191b1bf3fcf60ad4, type: 3} - {fileID: 8300000, guid: d8af9afe04d49fe45aa8b92d26a8bb9e, type: 3} @@ -158,7 +160,6 @@ MonoBehaviour: - {fileID: 8300000, guid: 6ff3fbda41c71d941aec69b7056b8341, type: 3} - {fileID: 8300000, guid: 3d0c4641496e430449ec0538f89cac29, type: 3} - {fileID: 8300000, guid: 1bfc562c713739c408d220a9de9a5240, type: 3} - playerAudioSource: {fileID: 0} monsterSpottedAudio: {fileID: 6418180475301049370, guid: 552945b348ea52749a29b5e327b8eab1, type: 2} --- !u!222 &8725474797166928194 CanvasRenderer: @@ -348,6 +349,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &229656908633211390 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -393,6 +395,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_Sprite: {fileID: 7400855017442887979, guid: 5b93832cb7470ca4586e9ee5640b2c25, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -402,7 +405,6 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!1 &5329236367077024222 GameObject: @@ -451,6 +453,7 @@ CanvasRenderer: m_CullTransparentMesh: 1 --- !u!212 &1007575356016584257 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -496,6 +499,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_Sprite: {fileID: -1042073035024568290, guid: 0bbb26ed6c3670b4293fca36266cacd6, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -505,7 +509,6 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!1 &5413791071529450429 GameObject: @@ -541,6 +544,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &6069960697164849265 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -586,6 +590,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 3 + m_MaskInteraction: 0 m_Sprite: {fileID: -6961586202046793095, guid: b7db73d33c7f1cb4bba316c12a0cc2fc, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -595,5 +600,4 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 diff --git a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head1_1.prefab b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head1_1.prefab index b0094c9f..3ecd4df7 100644 --- a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head1_1.prefab +++ b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head1_1.prefab @@ -12,6 +12,10 @@ PrefabInstance: propertyPath: m_Name value: QuarryMonster_monster_head1_1 objectReference: {fileID: 0} + - target: {fileID: 3714732064953161914, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + propertyPath: proximityIndicator + value: + objectReference: {fileID: 2600949834545141394} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.x value: 0 @@ -57,3 +61,8 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3} +--- !u!1 &2600949834545141394 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5329236367077024222, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + m_PrefabInstance: {fileID: 7921038058497292108} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head2_0.prefab b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head2_0.prefab index e08fad93..45f3f044 100644 --- a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head2_0.prefab +++ b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head2_0.prefab @@ -12,6 +12,10 @@ PrefabInstance: propertyPath: m_Name value: QuarryMonster_monster_head2_0 objectReference: {fileID: 0} + - target: {fileID: 3714732064953161914, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + propertyPath: proximityIndicator + value: + objectReference: {fileID: 2683229114311619924} - target: {fileID: 5319963476921229849, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_Controller value: @@ -66,10 +70,15 @@ PrefabInstance: objectReference: {fileID: -7812277834941893986, guid: e9ac6c3e349f9b247a0ea03665da57ce, type: 3} - target: {fileID: 8447572436637192077, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_SortingLayer - value: 32709 + value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3} +--- !u!1 &2683229114311619924 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5329236367077024222, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + m_PrefabInstance: {fileID: 7839076539202245770} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head3_0.prefab b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head3_0.prefab index 76e8feb3..98c432a6 100644 --- a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head3_0.prefab +++ b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head3_0.prefab @@ -12,17 +12,21 @@ PrefabInstance: propertyPath: m_Name value: QuarryMonster_monster_head3_0 objectReference: {fileID: 0} + - target: {fileID: 3714732064953161914, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + propertyPath: proximityIndicator + value: + objectReference: {fileID: 8570471056331183209} - target: {fileID: 5319963476921229849, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_Controller value: objectReference: {fileID: 9100000, guid: 094c957fe60c6cf44931aa216570afd7, type: 2} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.x - value: 2.46 + value: 0 objectReference: {fileID: 0} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.y - value: -1.79 + value: 0 objectReference: {fileID: 0} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.z @@ -65,3 +69,8 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3} +--- !u!1 &8570471056331183209 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5329236367077024222, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + m_PrefabInstance: {fileID: 4541086625678702007} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head4_0.prefab b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head4_0.prefab index f2e6ebc3..85c58ee7 100644 --- a/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head4_0.prefab +++ b/Assets/Prefabs/Minigames/DivingForPictures/QuarryMonster_monster_head4_0.prefab @@ -12,17 +12,21 @@ PrefabInstance: propertyPath: m_Name value: QuarryMonster_monster_head4_0 objectReference: {fileID: 0} + - target: {fileID: 3714732064953161914, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + propertyPath: proximityIndicator + value: + objectReference: {fileID: 6444740853843644247} - target: {fileID: 5319963476921229849, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_Controller value: objectReference: {fileID: 9100000, guid: 7dfd9b960984c0341b20afa16b274f5c, type: 2} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.x - value: 2.46 + value: 0 objectReference: {fileID: 0} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.y - value: -1.79 + value: 0 objectReference: {fileID: 0} - target: {fileID: 6779310478082390115, guid: 7754d064d743d1b419acb859c2db6121, type: 3} propertyPath: m_LocalPosition.z @@ -65,3 +69,8 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 7754d064d743d1b419acb859c2db6121, type: 3} +--- !u!1 &6444740853843644247 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5329236367077024222, guid: 7754d064d743d1b419acb859c2db6121, type: 3} + m_PrefabInstance: {fileID: 1190377006705176201} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Scenes/MiniGames/DivingForPictures.unity b/Assets/Scenes/MiniGames/DivingForPictures.unity index 811b4acf..bdfa7ce8 100644 --- a/Assets/Scenes/MiniGames/DivingForPictures.unity +++ b/Assets/Scenes/MiniGames/DivingForPictures.unity @@ -419,13 +419,13 @@ LineRenderer: m_SortingOrder: 0 m_MaskInteraction: 0 m_Positions: - - {x: -0.15602553, y: 4.0749445, z: 0} - - {x: -0.1566351, y: 3.9736378, z: 0} + - {x: -0.15602553, y: 4.074945, z: 0} + - {x: -0.1566351, y: 3.9736383, z: 0} - {x: -0.1572447, y: 3.8729858, z: 0} - {x: -0.15785426, y: 3.7729874, z: 0} - - {x: -0.15846384, y: 3.6736438, z: 0} + - {x: -0.15846384, y: 3.6736436, z: 0} - {x: -0.15907341, y: 3.5749545, z: 0} - - {x: -0.15968299, y: 3.4769197, z: 0} + - {x: -0.15968299, y: 3.4769192, z: 0} - {x: -0.16029257, y: 3.379539, z: 0} - {x: -0.16090216, y: 3.2828128, z: 0} - {x: -0.16151173, y: 3.186741, z: 0} @@ -1241,10 +1241,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 341271022} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 52.88064, y: -106.98245} - m_SizeDelta: {x: 105.76128, y: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 217.37007} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &495116985 MonoBehaviour: @@ -1983,16 +1983,16 @@ LineRenderer: m_SortingOrder: 0 m_MaskInteraction: 0 m_Positions: - - {x: -0.15602553, y: 4.0749445, z: 0} - - {x: -0.11662118, y: 3.8796222, z: 0} - - {x: -0.07721684, y: 3.7057445, z: 0} - - {x: -0.03781248, y: 3.5533106, z: 0} + - {x: -0.15602553, y: 4.074945, z: 0} + - {x: -0.11662118, y: 3.8796225, z: 0} + - {x: -0.07721684, y: 3.7057447, z: 0} + - {x: -0.03781248, y: 3.5533109, z: 0} - {x: 0.0015918687, y: 3.4223216, z: 0} - {x: 0.040996216, y: 3.3127766, z: 0} - {x: 0.08040057, y: 3.2246761, z: 0} - {x: 0.11980491, y: 3.15802, z: 0} - {x: 0.15920927, y: 3.1128082, z: 0} - - {x: 0.1986136, y: 3.0890408, z: 0} + - {x: 0.1986136, y: 3.0890405, z: 0} - {x: 0.23801796, y: 3.0867176, z: 0} m_Parameters: serializedVersion: 3 @@ -2704,16 +2704,16 @@ LineRenderer: m_SortingOrder: 0 m_MaskInteraction: 0 m_Positions: - - {x: -0.15602553, y: 4.0749445, z: 0} - - {x: -0.18956745, y: 3.8764973, z: 0} + - {x: -0.15602553, y: 4.074945, z: 0} + - {x: -0.18956745, y: 3.8764977, z: 0} - {x: -0.22310936, y: 3.7000234, z: 0} - {x: -0.25665125, y: 3.5455208, z: 0} - {x: -0.29019317, y: 3.412991, z: 0} - - {x: -0.32373506, y: 3.3024337, z: 0} + - {x: -0.32373506, y: 3.3024335, z: 0} - {x: -0.35727698, y: 3.2138486, z: 0} - {x: -0.39081886, y: 3.147236, z: 0} - - {x: -0.4243608, y: 3.1025963, z: 0} - - {x: -0.45790267, y: 3.0799284, z: 0} + - {x: -0.4243608, y: 3.1025958, z: 0} + - {x: -0.45790267, y: 3.0799282, z: 0} - {x: -0.4914446, y: 3.079233, z: 0} m_Parameters: serializedVersion: 3 diff --git a/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs b/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs index 5c6fef18..3f39e005 100644 --- a/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs +++ b/Assets/Scripts/Core/Settings/DivingMinigameSettings.cs @@ -1,7 +1,7 @@ -using Core.Settings; +using AppleHills.Core.Settings; using UnityEngine; -namespace AppleHills.Core.Settings +namespace Core.Settings { /// /// Settings related to minigames @@ -139,6 +139,12 @@ namespace AppleHills.Core.Settings [Header("Photo Input")] [Tooltip("Input mode for photo taking sequence")] [SerializeField] private PhotoInputModes photoInputMode = PhotoInputModes.Tap; + + [Tooltip("Photo taking mode - whether photo sequence is triggered by input or automatically")] + [SerializeField] private PhotoTakingMode photoTakingMode = PhotoTakingMode.Input; + + [Tooltip("Delay before automatic photo when PhotoTakingMode is Automatic (in seconds)")] + [SerializeField] private float autoPhotoDelay = 0.5f; [Tooltip("Padding factor to add space around the monster (1.0 = exact size, 1.2 = 20% extra)")] [SerializeField] private float paddingFactor = 1.2f; @@ -222,6 +228,8 @@ namespace AppleHills.Core.Settings public float MaxSizePercent => maxSizePercent; public float MinSizePercent => minSizePercent; public PhotoInputModes PhotoInputMode => photoInputMode; + public PhotoTakingMode PhotoTakingMode => photoTakingMode; + public float AutoPhotoDelay => autoPhotoDelay; public override void OnValidate() { @@ -294,6 +302,9 @@ namespace AppleHills.Core.Settings { viewfinderProgressThresholds[i] = Mathf.Clamp01(viewfinderProgressThresholds[i]); } + + // Validate photo taking settings + autoPhotoDelay = Mathf.Max(0f, autoPhotoDelay); } } } diff --git a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs index c3c0ac69..41361788 100644 --- a/Assets/Scripts/Core/Settings/SettingsInterfaces.cs +++ b/Assets/Scripts/Core/Settings/SettingsInterfaces.cs @@ -14,6 +14,15 @@ namespace Core.Settings Hold // New hold-based input } + /// + /// Enum defining when photos are taken + /// + public enum PhotoTakingMode + { + Input, // Player must tap/hold to initiate photo sequence + Automatic // Photos are taken automatically when player enters range + } + /// /// Interface for player movement settings (used by all player controllers) /// @@ -149,6 +158,10 @@ namespace Core.Settings float MaxSizePercent { get; } public float MinSizePercent { get; } public PhotoInputModes PhotoInputMode { get; } + + // Photo Taking Mode + PhotoTakingMode PhotoTakingMode { get; } // Whether photos are taken via input or automatically + float AutoPhotoDelay { get; } // Delay before automatic photo (when PhotoTakingMode is Automatic) } /// diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs index 2f192786..18d00f20 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs @@ -1,4 +1,4 @@ -using AppleHills.Core.Interfaces; +using AppleHills.Core.Interfaces; using Cinematics; using Core; using Core.Lifecycle; @@ -44,7 +44,7 @@ namespace Minigames.DivingForPictures private float _currentSpawnProbability; private float _lastSpawnTime = -100f; private float _timeSinceLastSpawn = 0f; - private List _activeMonsters = new List(); + private List _activeMonsters = new List(); // Velocity management // Velocity state tracking @@ -59,8 +59,8 @@ namespace Minigames.DivingForPictures // Events public event Action OnScoreChanged; - public event Action OnMonsterSpawned; - public event Action OnPictureTaken; + public event Action OnMonsterSpawned; + public event Action OnPictureTaken; public event Action OnSpawnProbabilityChanged; public event Action OnGameOver; public event Action OnRopeBroken; // Passes remaining ropes count @@ -86,15 +86,16 @@ namespace Minigames.DivingForPictures // Photo sequence state private bool _isPhotoSequenceActive = false; - private Monster _currentPhotoTarget = null; + private Monster.Monster _currentPhotoTarget = null; private float _capturedProximity = 0f; + private Coroutine _autoPhotoCoroutine = null; // Coroutine for automatic photo taking // List of components to exempt from pausing during photo sequence private List _exemptFromPhotoSequencePausing = new List(); // Photo sequence events - public event Action OnPhotoSequenceStarted; - public event Action OnPhotoSequenceCompleted; // Now includes proximity score + public event Action OnPhotoSequenceStarted; + public event Action OnPhotoSequenceCompleted; // Now includes proximity score private static DivingGameManager _instance = null; @@ -151,6 +152,7 @@ namespace Minigames.DivingForPictures viewfinderManager.OnProximityUpdated += OnProximityUpdated; viewfinderManager.OnViewfinderTappedDuringAnimation += OnViewfinderTappedDuringAnimation; viewfinderManager.OnReverseAnimationStarted += OnReverseAnimationStarted; + viewfinderManager.OnPerfectPositionReached += OnPerfectPositionReached; // TODO: Give this a second look and make sure this is correct // Add the viewfinder manager to exempt list to ensure it keeps working during photo sequences @@ -183,6 +185,7 @@ namespace Minigames.DivingForPictures viewfinderManager.OnProximityUpdated -= OnProximityUpdated; viewfinderManager.OnViewfinderTappedDuringAnimation -= OnViewfinderTappedDuringAnimation; viewfinderManager.OnReverseAnimationStarted -= OnReverseAnimationStarted; + viewfinderManager.OnPerfectPositionReached -= OnPerfectPositionReached; } } @@ -255,7 +258,7 @@ namespace Minigames.DivingForPictures // Instantiate monster at spawn point position GameObject monsterObj = Instantiate(prefab, spawnPoint.position, Quaternion.identity); - Monster monster = monsterObj.GetComponent(); + Monster.Monster monster = monsterObj.GetComponent(); if (monster != null) { @@ -281,7 +284,7 @@ namespace Minigames.DivingForPictures } } - private void DoPictureTaken(Monster monster) + private void DoPictureTaken(Monster.Monster monster) { // Calculate points based on depth int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier); @@ -838,14 +841,57 @@ namespace Minigames.DivingForPictures component.DoResume(); } - // Change input mode to UI when menu is open - InputManager.Instance.SetInputMode(InputMode.GameAndUI); + // Restore game input mode + InputManager.Instance.SetInputMode(InputMode.Game); Logging.Debug($"[DivingGameManager] Game resumed. Resumed {_pausableComponents.Count} components."); } #region Photo Sequence Methods + /// + /// Coroutine to automatically take a photo after a configured delay + /// + private IEnumerator AutomaticPhotoSequence(Monster.Monster monster) + { + // Wait for the configured delay + yield return new WaitForSeconds(_settings.AutoPhotoDelay); + + // Check if monster is still valid and player is still in range + if (monster != null && monster.IsPlayerInDetectionRange && !_isPhotoSequenceActive && !monster.IsPictureTaken) + { + // Start photo sequence automatically + _isPhotoSequenceActive = true; + _currentPhotoTarget = monster; + + // Pause the game + DoPause(false); + + // Mark monster as in photo sequence + monster.SetPhotoSequenceInProgress(); + + // Reset captured proximity + _capturedProximity = 0f; + + // Notify listeners + OnPhotoSequenceStarted?.Invoke(monster); + + // Start the viewfinder animation + if (viewfinderManager != null) + { + viewfinderManager.StartViewfinderSequence(monster.transform); + Logging.Debug($"[DivingGameManager] Automatically started photo sequence for monster {monster.name}"); + } + else + { + Debug.LogError("[DivingGameManager] No ViewfinderManager available!"); + CompletePhotoSequence(); + } + } + + _autoPhotoCoroutine = null; + } + /// /// Called when the viewfinder animation phase changes to reverse (zoom out) /// @@ -854,6 +900,22 @@ namespace Minigames.DivingForPictures Logging.Debug("[DivingGameManager] Viewfinder animation entering reverse (zoom-out) phase"); } + /// + /// Called when the viewfinder reaches perfect position (end of zoom-in phase) + /// In automatic mode, this triggers the photo capture + /// + private void OnPerfectPositionReached() + { + Logging.Debug("[DivingGameManager] Viewfinder reached perfect position"); + + // In automatic mode, take the photo when perfect position is reached + if (_settings.PhotoTakingMode == PhotoTakingMode.Automatic && _isPhotoSequenceActive) + { + Logging.Debug("[DivingGameManager] Automatic mode - taking photo at perfect position"); + TakePicture(); + } + } + /// /// Called when proximity value is updated during animation /// @@ -888,6 +950,12 @@ namespace Minigames.DivingForPictures if (!_isPhotoSequenceActive || _currentPhotoTarget == null) return; + // Stop the viewfinder animation if it's still running + if (viewfinderManager != null) + { + viewfinderManager.StopViewfinderAnimation(); + } + // Notify the monster that its picture was taken _currentPhotoTarget.NotifyPictureTaken(); @@ -914,7 +982,7 @@ namespace Minigames.DivingForPictures /// /// Calculates the score for a picture based on proximity to target and monster depth /// - private void CalculateScore(Monster monster, float proximity) + private void CalculateScore(Monster.Monster monster, float proximity) { if (monster == null) return; @@ -1035,7 +1103,7 @@ namespace Minigames.DivingForPictures #endregion - private void DoMonsterSpawned(Monster monster) + private void DoMonsterSpawned(Monster.Monster monster) { if (monster != null) { @@ -1049,7 +1117,7 @@ namespace Minigames.DivingForPictures } } - private void DoMonsterDespawned(Monster monster) + private void DoMonsterDespawned(Monster.Monster monster) { // Remove from active list _activeMonsters.Remove(monster); @@ -1064,29 +1132,47 @@ namespace Minigames.DivingForPictures } // Handles player entering monster detection range - private void OnPlayerEnterMonsterRange(Monster monster) + private void OnPlayerEnterMonsterRange(Monster.Monster monster) { if (monster != null && !_isPhotoSequenceActive) { // Store current target for later use _currentPhotoTarget = monster; - // Show the full-screen viewfinder (first step in two-step process) - if (viewfinderManager != null) + // Check the photo taking mode from settings + if (_settings.PhotoTakingMode == PhotoTakingMode.Automatic) { - viewfinderManager.ShowFullScreenViewfinder(); - Logging.Debug($"[DivingGameManager] Player entered range of monster {monster.name}, showing full-screen viewfinder"); + // Automatic mode: Start coroutine to automatically take photo after delay + _autoPhotoCoroutine = StartCoroutine(AutomaticPhotoSequence(monster)); + Logging.Debug($"[DivingGameManager] Player entered range of monster {monster.name}, starting automatic photo sequence"); + } + else + { + // Input mode: Show the full-screen viewfinder (first step in two-step process) + if (viewfinderManager != null) + { + viewfinderManager.ShowFullScreenViewfinder(); + Logging.Debug($"[DivingGameManager] Player entered range of monster {monster.name}, showing full-screen viewfinder"); + } } } } // Handles player exiting monster detection range - private void OnPlayerExitMonsterRange(Monster monster) + private void OnPlayerExitMonsterRange(Monster.Monster monster) { // Only hide viewfinder if we're not already in a photo sequence if (!_isPhotoSequenceActive && monster == _currentPhotoTarget) { - // Hide the viewfinder + // Cancel automatic photo coroutine if it's running + if (_autoPhotoCoroutine != null) + { + StopCoroutine(_autoPhotoCoroutine); + _autoPhotoCoroutine = null; + Logging.Debug($"[DivingGameManager] Player exited range, cancelled automatic photo sequence"); + } + + // Hide the viewfinder (only relevant for input mode) if (viewfinderManager != null) { viewfinderManager.HideViewfinder(); diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs index 9f536c53..232038f1 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs @@ -44,7 +44,7 @@ namespace Minigames.DivingForPictures } } - private void ShowScorePopup(Monster monster, int points) + private void ShowScorePopup(Monster.Monster monster, int points) { if (scorePopupPrefab == null) return; diff --git a/Assets/Scripts/Minigames/DivingForPictures/Monster/Monster.cs b/Assets/Scripts/Minigames/DivingForPictures/Monster/Monster.cs index f342e507..4657920c 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/Monster/Monster.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/Monster/Monster.cs @@ -1,23 +1,24 @@ -using AudioSourceEvents; -using Core; -using System; +using System; using System.Collections; +using AudioSourceEvents; +using Core; using UnityEngine; using UnityEngine.Audio; -namespace Minigames.DivingForPictures +namespace Minigames.DivingForPictures.Monster { public class Monster : MonoBehaviour { [Header("References")] [SerializeField] private CircleCollider2D detectionCollider; + [SerializeField] private GameObject proximityIndicator; // Visual sprite showing detection range - private bool pictureAlreadyTaken = false; - private bool photoSequenceInProgress = false; - private UnityEngine.Camera mainCamera; + private bool _pictureAlreadyTaken = false; + private bool _photoSequenceInProgress = false; + private Camera _mainCamera; // Track if player is in detection range - private bool playerInDetectionRange = false; + private bool _playerInDetectionRange = false; // Events public event Action OnMonsterDespawned; @@ -26,18 +27,18 @@ namespace Minigames.DivingForPictures // Properties public float PictureRadius => detectionCollider != null ? detectionCollider.radius : 0f; - public bool IsPhotoSequenceInProgress => photoSequenceInProgress; - public bool IsPlayerInDetectionRange => playerInDetectionRange; - public bool IsPictureTaken => pictureAlreadyTaken; + public bool IsPhotoSequenceInProgress => _photoSequenceInProgress; + public bool IsPlayerInDetectionRange => _playerInDetectionRange; + public bool IsPictureTaken => _pictureAlreadyTaken; public enum MonsterSounds {Hello, RareBeast, Pooping,Smile,Whatsup1, Whatsup2} private AudioSource _audioSource; public AudioResource[] monsterClips; - private AudioSource playerAudioSource; + private AudioSource _playerAudioSource; public AudioResource monsterSpottedAudio; private IAudioEventSource _eventSource; - private GameObject playerObject; + private GameObject _playerObject; private void Awake() { @@ -46,37 +47,37 @@ namespace Minigames.DivingForPictures if (detectionCollider == null) detectionCollider = GetComponent(); - mainCamera = UnityEngine.Camera.main; + _mainCamera = UnityEngine.Camera.main; _audioSource = GetComponent(); - playerObject = GameObject.FindGameObjectsWithTag("Player")[0]; - playerAudioSource = playerObject.GetComponent(); - _eventSource = playerAudioSource.RequestEventHandlers(); - _eventSource.AudioStopped += playerAudioDone; + _playerObject = GameObject.FindGameObjectsWithTag("Player")[0]; + _playerAudioSource = _playerObject.GetComponent(); + _eventSource = _playerAudioSource.RequestEventHandlers(); + _eventSource.AudioStopped += PlayerAudioDone; // Start checking if monster is off-screen StartCoroutine(CheckIfOffScreen()); } - private void playerAudioDone(object sender, EventArgs e) + private void PlayerAudioDone(object sender, EventArgs e) { _audioSource.Play(); } private void OnEnable() { - playerAudioSource.resource = monsterSpottedAudio; - playerAudioSource.Play(); - pictureAlreadyTaken = false; - photoSequenceInProgress = false; + _playerAudioSource.resource = monsterSpottedAudio; + _playerAudioSource.Play(); + _pictureAlreadyTaken = false; + _photoSequenceInProgress = false; } private void OnDestroy() { Logging.Debug("Monster destroyed: " + gameObject.name); - _eventSource.AudioStopped -= playerAudioDone; + _eventSource.AudioStopped -= PlayerAudioDone; } private IEnumerator CheckIfOffScreen() @@ -97,15 +98,15 @@ namespace Minigames.DivingForPictures private bool IsVisibleToCamera() { - if (mainCamera == null) - mainCamera = UnityEngine.Camera.main; + if (_mainCamera == null) + _mainCamera = UnityEngine.Camera.main; - if (mainCamera == null) + if (_mainCamera == null) return false; // Get the world position (will account for parent movement) Vector3 worldPosition = transform.position; - Vector3 viewportPoint = mainCamera.WorldToViewportPoint(worldPosition); + Vector3 viewportPoint = _mainCamera.WorldToViewportPoint(worldPosition); // If z is negative, the object is behind the camera if (viewportPoint.z < 0) @@ -129,10 +130,14 @@ namespace Minigames.DivingForPictures private void OnTriggerEnter2D(Collider2D other) { + // Don't trigger if picture already taken - prevents re-triggering photo sequence + if (_pictureAlreadyTaken) + return; + // Check if it's the player - if (other.CompareTag("Player") && !pictureAlreadyTaken) + if (other.CompareTag("Player")) { - playerInDetectionRange = true; + _playerInDetectionRange = true; // Fire the event so the game manager can display the viewfinder without pausing OnPlayerEnterDetectionRange?.Invoke(this); } @@ -140,10 +145,14 @@ namespace Minigames.DivingForPictures private void OnTriggerExit2D(Collider2D other) { + // Don't trigger if picture already taken + if (_pictureAlreadyTaken) + return; + // Check if it's the player if (other.CompareTag("Player")) { - playerInDetectionRange = false; + _playerInDetectionRange = false; // Fire the event so the game manager can hide the viewfinder OnPlayerExitDetectionRange?.Invoke(this); } @@ -154,8 +163,8 @@ namespace Minigames.DivingForPictures /// public void SetPhotoSequenceInProgress(bool inProgress = true) { - if (pictureAlreadyTaken) return; - photoSequenceInProgress = inProgress; + if (_pictureAlreadyTaken) return; + _photoSequenceInProgress = inProgress; } /// @@ -164,10 +173,19 @@ namespace Minigames.DivingForPictures /// public void NotifyPictureTaken() { - if (pictureAlreadyTaken) return; + if (_pictureAlreadyTaken) return; - pictureAlreadyTaken = true; - photoSequenceInProgress = false; + _pictureAlreadyTaken = true; + _photoSequenceInProgress = false; + + // Destroy the proximity indicator visual + if (proximityIndicator != null) + { + Destroy(proximityIndicator); + proximityIndicator = null; + } + + Logging.Debug($"[Monster] {gameObject.name} picture taken, collider still enabled for debugging"); } /// diff --git a/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs b/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs index 73b86ad1..f73a529d 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs @@ -1,7 +1,6 @@ using UnityEngine; using System; using System.Collections; -using AppleHills.Core.Settings; using Core; using Core.Settings; using UnityEngine.Audio; @@ -71,6 +70,7 @@ namespace Minigames.DivingForPictures.PictureCamera public event Action OnAnimationStarted; public event Action OnAnimationCompleted; public event Action OnReverseAnimationStarted; // New event for when zoom-out phase starts + public event Action OnPerfectPositionReached; // New event for when viewfinder reaches perfect position (end of zoom-in) public event Action OnProximityUpdated; // New event for proximity updates public event Action OnProgressThresholdReached; // Fires at configured thresholds (25%, 50%, etc.) public event Action OnViewfinderTapped; // Event when viewfinder is tapped during normal display @@ -308,8 +308,16 @@ namespace Minigames.DivingForPictures.PictureCamera if (viewfinderInstance != null) { + // Remove input override before destroying + if (viewfinderComponent != null) + { + viewfinderComponent.RemoveInputOverride(); + } + Destroy(viewfinderInstance); viewfinderInstance = null; + viewfinderComponent = null; + viewfinderRectTransform = null; } isAnimating = false; @@ -484,8 +492,17 @@ namespace Minigames.DivingForPictures.PictureCamera { if (viewfinderInstance != null) { + // Remove input override before destroying old viewfinder + if (viewfinderComponent != null) + { + viewfinderComponent.RemoveInputOverride(); + } + // Already showing a viewfinder, destroy it first Destroy(viewfinderInstance); + viewfinderInstance = null; + viewfinderComponent = null; + viewfinderRectTransform = null; } if (settings.ViewfinderPrefab == null) @@ -712,6 +729,9 @@ namespace Minigames.DivingForPictures.PictureCamera currentProximity = 1.0f; // At target OnProximityUpdated?.Invoke(currentProximity); + // Fire event that we've reached perfect position + OnPerfectPositionReached?.Invoke(); + // Brief pause at target yield return new WaitForSecondsRealtime(0.2f); diff --git a/Assets/Settings/DivingMinigameSettings.asset b/Assets/Settings/DivingMinigameSettings.asset index 7f8c32b8..a393100a 100644 --- a/Assets/Settings/DivingMinigameSettings.asset +++ b/Assets/Settings/DivingMinigameSettings.asset @@ -75,6 +75,8 @@ MonoBehaviour: m_PostInfinity: 2 m_RotationOrder: 4 photoInputMode: 0 + photoTakingMode: 1 + autoPhotoDelay: 0.5 paddingFactor: 1 minSizePercent: 0.15 maxSizePercent: 1