Files
DevourClient/DevourClient/Helpers/ReviveHelper.cs
2025-11-30 02:01:07 +11:00

111 lines
3.6 KiB
C#

using System;
using DevourClient.Network;
using MelonLoader;
using UnityEngine;
namespace DevourClient.Helpers
{
/// <summary>
/// Shared revive utilities. When running as host we mirror DevourX's revive flow.
/// </summary>
public static class ReviveHelper
{
private static readonly Vector3 HostFallbackPosition = new Vector3(0f, -150f, 0f);
/// <summary>
/// Try to revive the provided NolanBehaviour using host-specific logic first,
/// then fall back to the standard interactable flow.
/// </summary>
public static bool TryRevive(Il2Cpp.NolanBehaviour target)
{
if (target == null || target.gameObject == null)
{
return false;
}
if (TryHostRevive(target))
{
return true;
}
return TryInteractRevive(target);
}
private static bool TryHostRevive(Il2Cpp.NolanBehaviour target)
{
if (!NetworkHelper.IsHost() || !Player.IsInGame())
{
return false;
}
if (!target.IsCrawling())
{
return false;
}
try
{
Il2Cpp.SurvivalReviveInteractable interactable = UnityEngine.Object.FindObjectOfType<Il2Cpp.SurvivalReviveInteractable>();
if (interactable == null)
{
target.TeleportTo(HostFallbackPosition, Quaternion.identity);
MelonLogger.Msg("[ReviveHelper] Host fallback teleport executed (no interactable found).");
return true;
}
interactable.Interact(target.gameObject);
MelonLogger.Msg("[ReviveHelper] Host revive interactable triggered.");
return true;
}
catch (Exception ex)
{
MelonLogger.Warning($"[ReviveHelper] Host revive flow failed: {ex.Message}");
return false;
}
}
private static bool TryInteractRevive(Il2Cpp.NolanBehaviour target)
{
try
{
Il2Cpp.SurvivalReviveInteractable interactable = UnityEngine.Object.FindObjectOfType<Il2Cpp.SurvivalReviveInteractable>();
if (interactable == null)
{
return false;
}
if (interactable.CanInteract(target.gameObject))
{
interactable.Interact(target.gameObject);
return true;
}
}
catch (Exception ex)
{
MelonLogger.Warning($"[ReviveHelper] Interact revive failed: {ex.Message}");
}
return false;
}
/// <summary>
/// Legacy revive method migrated from StateHelper.BasePlayer.Revive().
/// This method preserves the original implementation from StateHelper.
/// </summary>
/// <param name="targetGameObject">The GameObject of the player to revive</param>
public static void ReviveLegacy(GameObject targetGameObject)
{
if (targetGameObject == null)
{
return;
}
Il2Cpp.NolanBehaviour nb = targetGameObject.GetComponent<Il2Cpp.NolanBehaviour>();
Il2Cpp.SurvivalReviveInteractable _reviveInteractable = UnityEngine.Object.FindObjectOfType<Il2Cpp.SurvivalReviveInteractable>();
if (_reviveInteractable.CanInteract(nb.gameObject) == true) { _reviveInteractable.Interact(nb.gameObject); }
}
}
}