using UnityEngine;
using OctoCore.Components;
using Unheimlich.Core;
using Unheimlich.Features.Player.Data;
using Unheimlich.Features.Dialogue;
using Unheimlich.Core.Interaction;
using Unheimlich.Features.DetectiveBoard;
using Unheimlich.Features.Diapason;
using Unheimlich.Features.OctoArms;
using Unheimlich.World.CameraSystem;
using InputManager = Unheimlich.Core.Input.InputManager;
namespace Unheimlich.Features.Player
{
///
/// Central hub for all player systems.
/// Exposes components and settings with zero Inspector refs needed for other scripts.
///
[RequireComponent(typeof(OctoPlayer))]
[RequireComponent(typeof(CharacterController))]
public class PlayerController : Singleton
{
// Auto-found components (exposed publicly, found once in Awake)
public OctoPlayer Movement { get; private set; }
public CharacterController CharController { get; private set; }
public Camera PlayerCamera { get; private set; }
public Transform CameraTransform { get; private set; }
public Transform CameraPivot { get; private set; }
public CameraEffects CameraEffects { get; private set; }
public CameraPanController CameraPanController { get; private set; }
public DiapasonListeningHandlerV2 DiapasonHandler { get; private set; }
public DiapasonEquipmentManager DiapasonEquipment { get; private set; }
public PlayerInspectionHandler InspectionHandler { get; private set; }
public DetectiveBoardController DetectiveBoardController { get; private set; }
public OctoIkArmsImproved ArmsSystem { get; private set; }
public InputManager Inputs => InputManager.Instance;
// Cached sprint InputAction — resolved once in OnAwake to avoid per-frame foreach.
private UnityEngine.InputSystem.InputAction _sprintAction;
///
/// True when the character is physically moving (based on CharacterController velocity,
/// not raw input — correctly synced with OctoPlayer's inertia).
///
public bool IsMoving => CharController != null && CharController.velocity.magnitude > 0.1f;
///
/// True while the sprint input is held and the player is moving.
///
public bool IsRunning => _sprintAction != null && _sprintAction.IsPressed() && IsMoving;
protected override void OnAwake()
{
// Auto-find all components once
Movement = GetComponent();
CharController = GetComponent();
CameraEffects = GetComponent();
CameraPanController = GetComponent();
DiapasonHandler = GetComponent();
DiapasonEquipment = GetComponent();
InspectionHandler = GetComponent();
DetectiveBoardController = GetComponent();
PlayerCamera = GetComponentInChildren();
ArmsSystem = GetComponentInChildren();
if (PlayerCamera != null)
{
CameraTransform = PlayerCamera.transform;
CameraPivot = CameraTransform.parent;
}
CacheSprintAction();
}
///
/// Resolves the Sprint InputAction once from OctoCore to avoid per-frame foreach iteration.
///
private void CacheSprintAction()
{
if (OctoCore.OctoCore.Instance?.Inputs?.Actions == null) return;
foreach (var actionInfo in OctoCore.OctoCore.Instance.Inputs.Actions)
{
if (actionInfo.Name == "Sprint" && actionInfo.Reference != null)
{
_sprintAction = actionInfo.Reference.action;
break;
}
}
}
// Teleport
public void Teleport(Vector3 position, Quaternion rotation)
{
Movement.Teleport(position, rotation);
PlayerEvents.TriggerTeleport(position, rotation);
}
// Helper methods
public Vector3 GetForward()
{
if (PlayerCamera == null) return transform.forward;
Vector3 forward = PlayerCamera.transform.forward;
forward.y = 0;
return forward.normalized;
}
public Vector3 GetRight()
{
if (PlayerCamera == null) return transform.right;
Vector3 right = PlayerCamera.transform.right;
right.y = 0;
return right.normalized;
}
}
}