using UnityEngine;
namespace Ashwild.Player
{
///
/// Owns the local player's death-and-return. It flips locomotion into its dead state when the
/// player dies, and on teleports the body back to the current respawn pose,
/// revives the stats and clears the dead state. The respawn pose starts at the assigned spawn
/// point (or wherever the player begins) and is reassigned live when the player claims a bed โ
/// pushed in over the bus, so it stays pure local state that never crosses the wire (ยง3).
///
[DisallowMultipleComponent]
public class PlayerLifecycle : MonoBehaviour
{
#region Serialized Fields
[Header("Spawn point (auto-captured at scene start if left empty)")]
[SerializeField] private Transform spawnPoint;
#endregion
#region State
private PlayerLocomotion locomotion;
private Rigidbody rb;
private Vector3 spawnPosition;
private Quaternion spawnRotation;
private bool isDead;
#endregion
#region Unity Lifecycle
///
/// Caches the sibling components the respawn drives.
///
private void Awake()
{
locomotion = GetComponent();
rb = GetComponent();
}
///
/// Seeds the respawn pose from the assigned spawn point, or the player's starting pose when
/// none is set, so a death before any bed is claimed still returns somewhere valid.
///
private void Start()
{
if (spawnPoint != null)
{
spawnPosition = spawnPoint.position;
spawnRotation = spawnPoint.rotation;
}
else
{
spawnPosition = transform.position;
spawnRotation = transform.rotation;
}
}
///
/// Subscribes to death and to respawn-point reassignments (claiming a bed).
///
private void OnEnable()
{
PlayerEvents.Died += OnDied;
PlayerEvents.RespawnPointChanged += HandleRespawnPointChanged;
}
///
/// Unsubscribes โ mirrors OnEnable exactly.
///
private void OnDisable()
{
PlayerEvents.Died -= OnDied;
PlayerEvents.RespawnPointChanged -= HandleRespawnPointChanged;
}
#endregion
#region Event Handlers
///
/// Freezes the player into its dead state once, ignoring repeat death events.
///
private void OnDied()
{
if (isDead) return;
isDead = true;
if (locomotion != null) locomotion.SetDead(true);
}
///
/// Adopts a new respawn pose pushed over the bus (the player claimed a bed). Local state
/// only โ the respawn location is never networked, so each client keeps its own.
///
private void HandleRespawnPointChanged(Vector3 position, Quaternion rotation)
=> SetSpawnPoint(position, rotation);
#endregion
#region Public API
///
/// Returns the player to the current respawn pose: zeroes momentum, teleports the body,
/// revives the stats and clears the dead state.
///
public void Respawn()
{
if (rb != null)
{
rb.linearVelocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
transform.SetPositionAndRotation(spawnPosition, spawnRotation);
if (PlayerStats.Instance != null) PlayerStats.Instance.Revive();
if (locomotion != null) locomotion.SetDead(false);
isDead = false;
}
///
/// Overrides the respawn pose directly with a world position and rotation.
///
public void SetSpawnPoint(Vector3 position, Quaternion rotation)
{
spawnPosition = position;
spawnRotation = rotation;
}
#endregion
}
}