Files
BABA_YAGA/Assets/Third Parties/Opsive/UltimateCharacterController/Scripts/Character/Abilities/Revive.cs
2026-06-09 09:18:17 +07:00

131 lines
5.1 KiB
C#

/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Character.Abilities
{
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Traits;
using UnityEngine;
/// <summary>
/// The Revive ability will play a standing animation from laying on the ground. The OnRespawn event will be executed when the animation is complete.
/// </summary>
[DefaultStartType(AbilityStartType.Manual)]
[DefaultState("Death")]
[DefaultAbilityIndex(5)]
public class Revive : Ability
{
[Tooltip("Should the ability start when the character dies?")]
[SerializeField] protected bool m_StartOnDeath;
[Tooltip("Specifies the number of seconds after the character dies that the ability should start.")]
[SerializeField] protected float m_DeathStartDelay = 3;
public bool StartOnDeath { get { return m_StartOnDeath; } set { m_StartOnDeath = value; } }
public float DeathStartDelay { get { return m_DeathStartDelay; } set { m_DeathStartDelay = value; } }
private Respawner m_Respawner;
public override bool CanStayActivatedOnDeath { get { return true; } }
/// <summary>
/// The type of animation that the ability should play.
/// </summary>
private enum ReviveType {
Forward, // Play a forward revive animation.
Backward // Play a backward revive animation.
}
private int m_ReviveTypeIndex;
public override int AbilityIntData { get { return m_ReviveTypeIndex; } }
/// <summary>
/// Initialize the default values.
/// </summary>
public override void Awake()
{
base.Awake();
m_Respawner = m_GameObject.GetCachedComponent<Respawner>();
if (!m_Respawner) {
Debug.LogError("Error: The Revive ability requires the Respawner component to be added to the character.");
return;
}
// If the ragdoll is starting when the character dies then the respawner will be called manually and should not reposition the character.
if (m_StartOnDeath && Enabled) {
m_Respawner.PositioningMode = Respawner.SpawnPositioningMode.None;
m_Respawner.ScheduleRespawnOnDeath = false;
m_Respawner.ScheduleRespawnOnDisable = false;
}
EventHandler.RegisterEvent<Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath);
EventHandler.RegisterEvent(m_GameObject, "OnAnimatorReviveComplete", OnReviveComplete);
}
/// <summary>
/// The character has died. Start the ability if requested.
/// </summary>
/// <param name="position">The position of the force.</param>
/// <param name="force">The amount of force which killed the character.</param>
/// <param name="attacker">The GameObject that killed the character.</param>
private void OnDeath(Vector3 position, Vector3 force, GameObject attacker)
{
// The ability may not need to start from the death event.
if (!m_StartOnDeath) {
return;
}
m_ReviveTypeIndex = GetReviveTypeIndex(position, force, attacker);
Scheduler.ScheduleFixed(m_DeathStartDelay, StartRevive);
}
/// <summary>
/// Returns the value that the AbilityIntData parameter should be set to.
/// </summary>
/// <param name="position">The position of the force.</param>
/// <param name="force">The amount of force which killed the character.</param>
/// <param name="attacker">The GameObject that killed the character.</param>
/// <returns>The value that the AbilityIntData parameter should be set to.</returns>
protected virtual int GetReviveTypeIndex(Vector3 position, Vector3 force, GameObject attacker)
{
return (int)(m_Transform.InverseTransformPoint(position).z > 0 ? ReviveType.Forward : ReviveType.Backward);
}
/// <summary>
/// Starts the ability.
/// </summary>
private void StartRevive()
{
StartAbility();
}
/// <summary>
/// The revive animation has completed.
/// </summary>
private void OnReviveComplete()
{
StopAbility();
// The respawn component will perform the necessary cleanup after the character has died.
if (m_StartOnDeath) {
m_Respawner.Respawn();
}
}
/// <summary>
/// Called when the character is destroyed.
/// </summary>
public override void OnDestroy()
{
base.OnDestroy();
EventHandler.UnregisterEvent<Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath);
EventHandler.UnregisterEvent(m_GameObject, "OnAnimatorReviveComplete", OnReviveComplete);
}
}
}