puzzlestep_indicators (#14)

Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #14
This commit is contained in:
2025-10-02 05:42:17 +00:00
parent a6c63af911
commit e713a580a9
29 changed files with 899 additions and 10 deletions

View File

@@ -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.
/// </summary>
[RequireComponent(typeof(Interactable))]
public class ObjectiveStepBehaviour : MonoBehaviour
public class ObjectiveStepBehaviour : MonoBehaviour, IPuzzlePrompt
{
/// <summary>
/// The data object representing this puzzle step.
/// </summary>
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);
}
/// <summary>
/// Updates the proximity state from PuzzleManager and triggers appropriate methods.
/// </summary>
/// <param name="newState">The new proximity state.</param>
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
/// <summary>
/// Called when the prompt should be initially shown (e.g., when step is unlocked)
/// </summary>
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}");
}
/// <summary>
/// Called when the prompt should be hidden (e.g., when step is locked)
/// </summary>
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}");
}
/// <summary>
/// Called when player enters the far range
/// </summary>
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}");
}
/// <summary>
/// Called when player enters the close range
/// </summary>
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}");
}
/// <summary>
/// Called when player exits the close range
/// </summary>
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}");
}
/// <summary>
/// Called when player exits the far range
/// </summary>
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}");
}
/// <summary>
/// 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<IPuzzlePrompt>();
if (_indicator == null)
{
// Try to find it in children if not on the root
_indicator = puzzleIndicator.GetComponentInChildren<IPuzzlePrompt>();
}
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();
}
}
}
}
/// <summary>
@@ -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();
}
}
/// <summary>
@@ -98,5 +300,20 @@ namespace PuzzleS
PuzzleManager.Instance?.MarkPuzzleStepCompleted(stepData);
}
}
/// <summary>
/// Visualizes the puzzle prompt ranges in the editor.
/// </summary>
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);
}
}
}