using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("ManyLives")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7041b3d7886ea27dabc546a333c8cf4428fa2d4c")]
[assembly: AssemblyProduct("live multiple lives")]
[assembly: AssemblyTitle("ManyLives")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ManyLives
{
public class NetworkManager : MonoBehaviourPunCallbacks
{
public static NetworkManager Instance { get; private set; }
private void Awake()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
if (!Object.op_Implicit((Object)(object)((MonoBehaviourPun)this).photonView))
{
PhotonView val = ((Component)this).gameObject.AddComponent<PhotonView>();
val.ViewID = 999;
val.Synchronization = (ViewSynchronization)0;
val.ObservedComponents = new List<Component>();
val.OwnershipTransfer = (OwnershipOption)0;
}
}
else
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
public override void OnJoinedRoom()
{
((MonoBehaviourPunCallbacks)this).OnJoinedRoom();
if (Object.op_Implicit((Object)(object)((MonoBehaviourPun)this).photonView) && !((MonoBehaviourPun)this).photonView.IsMine)
{
Plugin.Log.LogInfo((object)"Taking ownership of NetworkManager PhotonView");
((MonoBehaviourPun)this).photonView.TransferOwnership(PhotonNetwork.LocalPlayer);
}
Plugin.Lives = Plugin.MaxLives;
Plugin.TotalDeaths = 0;
Plugin.hasSetHealth = false;
Plugin.Log.LogInfo((object)$"Joined room - Reset lives to {Plugin.Lives}");
}
[PunRPC]
public void SyncLivesRPC(int lives, int deaths)
{
Plugin.Lives = lives;
Plugin.TotalDeaths = deaths;
Plugin.hasSetHealth = false;
Plugin.Log.LogInfo((object)$"Received sync - Lives: {lives}, Deaths: {deaths}");
}
[PunRPC]
public void SetPlayerHealthRPC(int targetHealth)
{
try
{
PlayerAvatar val = GameDirector.instance?.PlayerList?.Find((PlayerAvatar p) => p.photonView.IsMine);
if ((Object)(object)val != (Object)null && (Object)(object)val.playerHealth != (Object)null)
{
Traverse val2 = Traverse.Create((object)val.playerHealth);
val2.Field("health").SetValue((object)targetHealth);
Plugin.Log.LogInfo((object)$"RPC set health to {targetHealth} for local player");
val.playerHealth.Heal(0, true);
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("Error in SetPlayerHealthRPC: " + ex.Message));
}
}
public void SyncToAll(int lives, int deaths)
{
if (!SemiFunc.IsMultiplayer() || !PhotonNetwork.IsMasterClient)
{
return;
}
try
{
if (Object.op_Implicit((Object)(object)((MonoBehaviourPun)this).photonView) && ((MonoBehaviourPun)this).photonView.ViewID != 0)
{
Plugin.Log.LogInfo((object)$"Syncing lives ({lives}) and deaths ({deaths}) with ViewID: {((MonoBehaviourPun)this).photonView.ViewID}");
((MonoBehaviourPun)this).photonView.RPC("SyncLivesRPC", (RpcTarget)0, new object[2] { lives, deaths });
}
else
{
Plugin.Log.LogError((object)"PhotonView not properly initialized for sync!");
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("Error syncing lives and deaths: " + ex.Message));
}
}
public void SetHealthForAll(int targetHealth)
{
try
{
if (Object.op_Implicit((Object)(object)((MonoBehaviourPun)this).photonView) && ((MonoBehaviourPun)this).photonView.ViewID != 0)
{
Plugin.Log.LogInfo((object)$"Setting health to {targetHealth} for all players");
((MonoBehaviourPun)this).photonView.RPC("SetPlayerHealthRPC", (RpcTarget)0, new object[1] { targetHealth });
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("Error setting health for all: " + ex.Message));
}
}
}
[BepInPlugin("ManyLives", "live multiple lives", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Log;
public static int MaxLives = 3;
public static int Lives = 3;
public static int TotalDeaths = 0;
public static float HealthMultiplier = 1f;
public static bool hasSetHealth = false;
private GameObject networkManagerObj;
public static Plugin Instance { get; private set; }
public void Awake()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"Plugin ManyLives is loaded!");
Harmony val = new Harmony("ManyLives");
val.PatchAll();
}
public void Start()
{
((MonoBehaviour)this).StartCoroutine(CreateNetworkManager());
}
private IEnumerator CreateNetworkManager()
{
yield return null;
if ((Object)(object)networkManagerObj == (Object)null)
{
networkManagerObj = new GameObject("ManyLivesNetworkManager");
networkManagerObj.AddComponent<NetworkManager>();
Object.DontDestroyOnLoad((Object)(object)networkManagerObj);
Log.LogInfo((object)"Created NetworkManager");
}
}
public static bool ShouldHandleGameLogic()
{
return !SemiFunc.IsMultiplayer() || PhotonNetwork.IsMasterClient;
}
public static void SyncLivesAndDeaths()
{
if ((Object)(object)NetworkManager.Instance != (Object)null)
{
NetworkManager.Instance.SyncToAll(Lives, TotalDeaths);
}
}
}
[HarmonyPatch(typeof(PlayerAvatar), "Update")]
public static class PlayerAvatar_Update_Patch
{
private static void Postfix(PlayerAvatar __instance)
{
if (Plugin.hasSetHealth || Plugin.TotalDeaths <= 0 || (SemiFunc.IsMultiplayer() && !__instance.photonView.IsMine))
{
return;
}
PlayerHealth playerHealth = __instance.playerHealth;
if ((Object)(object)playerHealth == (Object)null)
{
return;
}
Traverse val = Traverse.Create((object)playerHealth);
if (val.Field("healthSet").GetValue<bool>())
{
float num = ((Plugin.TotalDeaths == 1) ? 0.5f : 0.01f);
int value = val.Field("maxHealth").GetValue<int>();
int num2 = Mathf.Max(1, Mathf.RoundToInt((float)value * num));
Plugin.Log.LogInfo((object)$"Setting health - Max: {value}, Target: {num2}");
if (SemiFunc.IsMultiplayer())
{
NetworkManager.Instance?.SetHealthForAll(num2);
playerHealth.Heal(0, true);
playerHealth.HealOther(0, true);
playerHealth.HealOtherRPC(0, true);
}
else
{
val.Field("health").SetValue((object)num2);
playerHealth.Heal(0, true);
playerHealth.HealOther(0, true);
playerHealth.HealOtherRPC(0, true);
}
Plugin.hasSetHealth = true;
}
}
}
[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
public static class RunManager_ChangeLevel_Patch
{
private static void Postfix(RunManager __instance, bool _completedLevel, bool _levelFailed)
{
if (Plugin.ShouldHandleGameLogic())
{
if (_levelFailed || (Object)(object)__instance.levelCurrent == (Object)(object)__instance.levelLobby || (Object)(object)__instance.levelCurrent == (Object)(object)__instance.levelLobbyMenu)
{
Plugin.Log.LogInfo((object)$"Going to {((Object)__instance.levelCurrent).name} - Resetting lives from {Plugin.Lives} to {Plugin.MaxLives}");
Plugin.Lives = Plugin.MaxLives;
Plugin.TotalDeaths = 0;
Plugin.SyncLivesAndDeaths();
}
else
{
Plugin.Log.LogInfo((object)$"Restarting level - Keeping lives at {Plugin.Lives} and deaths at {Plugin.TotalDeaths}");
Plugin.hasSetHealth = false;
}
}
}
}
[HarmonyPatch(typeof(RunManager), "Update")]
public static class RunManager_Update_Patch
{
private static void Postfix(RunManager __instance)
{
if (!Plugin.ShouldHandleGameLogic())
{
return;
}
bool value = Traverse.Create((object)__instance).Field("allPlayersDead").GetValue<bool>();
bool value2 = Traverse.Create((object)__instance).Field("restarting").GetValue<bool>();
if (value && !value2)
{
Plugin.TotalDeaths++;
Plugin.Lives--;
Plugin.Log.LogInfo((object)$"All players dead - TotalDeaths: {Plugin.TotalDeaths}, Lives remaining: {Plugin.Lives}");
Plugin.SyncLivesAndDeaths();
if (Plugin.Lives <= 0)
{
Plugin.Log.LogInfo((object)"No lives remaining - Transitioning to arena");
__instance.ChangeLevel(false, true, (ChangeLevelType)0);
}
else
{
Plugin.Log.LogInfo((object)$"Restarting level with {Plugin.Lives} lives remaining");
__instance.ChangeLevel(false, false, (ChangeLevelType)0);
}
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "ManyLives";
public const string PLUGIN_NAME = "live multiple lives";
public const string PLUGIN_VERSION = "1.0.0";
}
}