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 MonoMod.RuntimeDetour.HookGen;
using MortalEnemies.Patches;
using MyceliumNetworking;
using Photon.Pun;
using UnityEngine;
using UnityEngine.UI;
using Zorro.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("rivinwin.MortalEnemies")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("A Content Warning mod to make enemies damageable, used as a dependancy.")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1+624a8facbb0bba106dfa56d43d9c2c0566ed0204")]
[assembly: AssemblyProduct("MortalEnemies")]
[assembly: AssemblyTitle("rivinwin.MortalEnemies")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/RivinwinCW/CW_MortalEnemies")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 MortalEnemies
{
[ContentWarningPlugin("rivinwin.MortalEnemies", "1.1.1", false)]
[BepInPlugin("rivinwin.MortalEnemies", "MortalEnemies", "1.1.1")]
public class MortalEnemies : BaseUnityPlugin
{
public static MortalEnemies Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
private void Awake()
{
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"rivinwin.MortalEnemies v1.1.1 installed, hooking...");
HookAll();
}
internal static void HookAll()
{
ClassPatches.Init();
Logger.LogDebug((object)"Finished hooking");
}
internal static void UnhookAll()
{
HookEndpointManager.RemoveAllOwnedBy((object)Assembly.GetExecutingAssembly());
Logger.LogDebug((object)"Finished unhooking");
}
}
public abstract class Mortality : MonoBehaviour
{
private enum TimedEffectState
{
None,
Damaging,
Healing
}
public class DoTSource
{
internal float damagePerTick;
internal uint expireTick;
internal uint ticksRemaining;
internal ushort ID;
internal bool paused;
internal bool Paused
{
get
{
return paused;
}
set
{
if (paused != value)
{
if (value)
{
ticksRemaining = expireTick - MortalSingleton.Instance.CurrentTick;
}
else
{
expireTick = MortalSingleton.Instance.CurrentTick + ticksRemaining;
}
paused = value;
}
}
}
internal DoTSource(float newDpT, uint newTicks, ushort newID)
{
damagePerTick = newDpT;
ticksRemaining = newTicks;
expireTick = MortalSingleton.Instance.CurrentTick + newTicks;
ID = newID;
}
}
public static readonly uint modId = (uint)"rivinwin.MortalEnemies".GetHashCode();
public int viewIDClone;
private bool isAutonomousProxy;
private MortalSingleton mortalSingleton = MortalSingleton.Instance;
private TimedEffectState uiEffectState;
private List<DoTSource> dotSources = new List<DoTSource>();
private static ushort nextDoTSourceID;
internal float damagePerTick;
private bool damagePerTickDirty;
public bool IsAlive => Health > 0f;
public abstract float MaxHealth { get; internal set; }
public abstract float Health { get; internal set; }
protected virtual void Awake()
{
mortalSingleton.Mortalities.Add(this);
viewIDClone = ((Component)this).GetComponent<PhotonView>().ViewID;
MyceliumNetwork.RegisterNetworkObject((object)this, modId, viewIDClone);
}
private void FixedUpdate()
{
if (dotSources.Count != 0)
{
while (dotSources.Count > 0 && dotSources[0].expireTick < mortalSingleton.CurrentTick)
{
dotSources.RemoveAt(0);
damagePerTickDirty = true;
}
if (damagePerTickDirty)
{
CalcDamagePerTick();
}
if (uiEffectState == TimedEffectState.Damaging)
{
DoTEffect();
}
else if (uiEffectState == TimedEffectState.Healing && Health < MaxHealth)
{
HoTEffect();
}
Health -= damagePerTick;
}
}
protected virtual void OnDestroy()
{
MyceliumNetwork.DeregisterNetworkObject((object)this, modId, viewIDClone);
mortalSingleton.Mortalities.Remove(this);
}
public virtual void DamageEffect()
{
}
public virtual void DoTEffect()
{
}
public virtual void HealEffect()
{
}
public virtual void HoTEffect()
{
}
protected abstract void KillEffect();
protected abstract void ReviveEffect();
public void Damage(float inDamage)
{
if (!(inDamage <= 0f))
{
if (isAutonomousProxy)
{
RPCA_Damage(inDamage);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_Damage", (ReliableType)1, viewIDClone, new object[1] { inDamage });
}
}
}
public ushort DamageOverTime(float inDamagePerSecond, float inSeconds)
{
if (!isAutonomousProxy && !MyceliumNetwork.IsHost)
{
return 0;
}
ushort unigueDoTSourceID = GetUnigueDoTSourceID();
uint num = (ushort)Mathf.RoundToInt(inSeconds / Time.fixedDeltaTime);
float num2 = inDamagePerSecond * Time.fixedDeltaTime;
if (isAutonomousProxy)
{
RPCA_AddDoTSource(num2, num, unigueDoTSourceID);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_AddDoTSource", (ReliableType)1, viewIDClone, new object[3] { num2, num, unigueDoTSourceID });
}
return unigueDoTSourceID;
}
public void Heal(float inHealth)
{
if (!(inHealth <= 0f))
{
if (isAutonomousProxy)
{
RPCA_Heal(inHealth);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_Heal", (ReliableType)1, viewIDClone, new object[1] { inHealth });
}
}
}
public ushort HealOverTime(float inHealthPerSecond, float inSeconds)
{
return DamageOverTime(0f - inHealthPerSecond, inSeconds);
}
public void Revive(float newHealth = 100f)
{
if (!(newHealth <= 0f))
{
if (newHealth > MaxHealth)
{
newHealth = MaxHealth;
}
if (isAutonomousProxy)
{
RPCA_Revive(newHealth);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_Revive", (ReliableType)1, viewIDClone, new object[1] { newHealth });
}
}
}
private static ushort GetUnigueDoTSourceID()
{
if (!MyceliumNetwork.IsHost)
{
return 0;
}
return ++nextDoTSourceID;
}
public void RemoveDot(ushort IDtoRemove)
{
if (isAutonomousProxy)
{
RPCA_RemoveDoTSource(IDtoRemove);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_RemoveDoTSource", (ReliableType)1, viewIDClone, new object[1] { IDtoRemove });
}
}
public void PauseDoT(ushort IDtoPause)
{
if (isAutonomousProxy)
{
RPCA_PauseDoTSource(IDtoPause);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_PauseDoTSource", (ReliableType)1, viewIDClone, new object[1] { IDtoPause });
}
}
public void ResumeDoT(ushort IDtoResume)
{
if (isAutonomousProxy)
{
RPCA_ResumeDoTSource(IDtoResume);
}
else if (MyceliumNetwork.IsHost)
{
MyceliumNetwork.RPCMasked(modId, "RPCA_ResumeDoTSource", (ReliableType)1, viewIDClone, new object[1] { IDtoResume });
}
}
protected virtual void CalcDamagePerTick()
{
damagePerTick = 0f;
foreach (DoTSource dotSource in dotSources)
{
if (!dotSource.paused)
{
damagePerTick += dotSource.damagePerTick;
}
}
damagePerTickDirty = false;
if ((double)Mathf.Abs(damagePerTick) > 0.015)
{
uiEffectState = ((damagePerTick > 0f) ? TimedEffectState.Damaging : TimedEffectState.Healing);
}
else
{
uiEffectState = TimedEffectState.None;
}
}
[CustomRPC]
internal void RPCA_Damage(float sentDamage)
{
DamageEffect();
Health -= sentDamage;
}
[CustomRPC]
internal void RPCA_Heal(float sentHealth)
{
HealEffect();
Health += sentHealth;
}
[CustomRPC]
internal void RPCA_Revive(float sentHealth)
{
Health = sentHealth;
ReviveEffect();
}
[CustomRPC]
internal void RPCA_AddDoTSource(float sentDpT, uint sentTicks, ushort sentID)
{
DoTSource doTSource = new DoTSource(sentDpT, sentTicks, sentID);
for (int num = dotSources.Count - 1; num >= 0; num--)
{
if (dotSources[num].expireTick <= doTSource.expireTick)
{
dotSources.Insert(num + 1, doTSource);
damagePerTickDirty = true;
return;
}
}
dotSources.Insert(0, doTSource);
damagePerTickDirty = true;
}
[CustomRPC]
internal void RPCA_RemoveDoTSource(ushort toRemove)
{
foreach (DoTSource dotSource in dotSources)
{
if (dotSource.ID == toRemove)
{
dotSources.Remove(dotSource);
damagePerTickDirty = true;
break;
}
}
}
[CustomRPC]
internal void RPCA_PauseDoTSource(ushort toPause)
{
foreach (DoTSource dotSource in dotSources)
{
if (dotSource.ID == toPause)
{
dotSource.Paused = true;
damagePerTickDirty = true;
break;
}
}
}
[CustomRPC]
internal void RPCA_ResumeDoTSource(ushort toResume)
{
foreach (DoTSource dotSource in dotSources)
{
if (dotSource.ID == toResume)
{
dotSource.Paused = false;
damagePerTickDirty = true;
break;
}
}
}
}
public class Mortality_Bot : Mortality
{
private float health;
private float maxHealth = 100f;
private Bot? botRef;
private Player? playerRef;
private HashSet<MonoBehaviour>? componentsToDeactivate;
private float storedConstantGravity = 2f;
private float storedGravity = 80f;
public override float Health
{
get
{
return health;
}
internal set
{
if (health > 0f && value <= 0f)
{
KillEffect();
}
health = Mathf.Min(value, MaxHealth);
}
}
public override float MaxHealth
{
get
{
return maxHealth;
}
internal set
{
maxHealth = value;
}
}
protected override void Awake()
{
base.Awake();
health = maxHealth;
MortalSingleton.Instance.BotMortalities.Add(this);
}
protected override void OnDestroy()
{
base.OnDestroy();
MortalSingleton.Instance.BotMortalities.Remove(this);
}
internal void SetBot(Bot newBotRef)
{
botRef = newBotRef;
componentsToDeactivate = new HashSet<MonoBehaviour>();
if (botRef == null)
{
playerRef = null;
return;
}
playerRef = ((Component)this).gameObject.GetComponentInChildren<Player>();
componentsToDeactivate.Add((MonoBehaviour)(object)botRef);
MonoBehaviour[] componentsInChildren = ((Component)this).gameObject.GetComponentsInChildren<MonoBehaviour>();
foreach (MonoBehaviour val in componentsInChildren)
{
if (((object)val).GetType().ToString().Contains("Bot_") || ((object)val).GetType().ToString().Contains("Attack"))
{
componentsToDeactivate.Add(val);
}
}
foreach (MonoBehaviour item in componentsToDeactivate)
{
string text = ((item == null || (object)((object)item).GetType() == null || ((object)item).GetType().ToString() == null) ? "null" : ((object)item).GetType().ToString());
}
}
protected override void KillEffect()
{
health = 0f;
if (botRef == null || componentsToDeactivate == null)
{
return;
}
BotHandler.instance.bots.Remove(botRef);
botRef.DoNothing();
if (playerRef != null)
{
playerRef.data.dead = true;
if (playerRef.refs.ragdoll != null)
{
}
if (playerRef.refs.controller != null)
{
storedConstantGravity = playerRef.refs.controller.constantGravity;
storedGravity = playerRef.refs.controller.gravity;
playerRef.refs.controller.constantGravity = 4f;
playerRef.refs.controller.gravity = 80f;
}
}
foreach (MonoBehaviour item in componentsToDeactivate)
{
if (item != null)
{
((Behaviour)item).enabled = false;
}
}
}
protected override void ReviveEffect()
{
if ((Object)(object)botRef == (Object)null || componentsToDeactivate == null)
{
return;
}
BotHandler.instance.bots.Add(botRef);
foreach (MonoBehaviour item in componentsToDeactivate)
{
if (item != null)
{
((Behaviour)item).enabled = true;
}
}
if (playerRef != null)
{
playerRef.data.dead = false;
if (playerRef.refs.ragdoll != null)
{
}
if (playerRef.refs.controller != null)
{
playerRef.refs.controller.constantGravity = storedConstantGravity;
playerRef.refs.controller.gravity = storedGravity;
}
}
}
}
internal class Mortality_Player : Mortality
{
protected float nextDoTEffects;
protected float nextDamageEffects;
protected float nextHealEffects;
internal bool attachedToLocalPlayer;
internal Player? playerRef;
internal PlayerData? playerData;
protected float dotEffectInterval = 0.75f;
protected float damageEffectInterval = 0.09f;
protected float healEffectInterval = 0.09f;
public override float Health
{
get
{
return (playerData == null) ? 100f : playerData.health;
}
internal set
{
if (playerData != null)
{
playerData.health = Mathf.Min(value, MaxHealth);
}
}
}
public override float MaxHealth
{
get
{
return 100f;
}
internal set
{
}
}
internal void SetPlayer(Player newPlayerRef)
{
if (!((Object)(object)newPlayerRef == (Object)(object)playerRef) && !((Object)(object)newPlayerRef == (Object)null))
{
attachedToLocalPlayer = (Object)(object)newPlayerRef == (Object)(object)Player.localPlayer;
playerRef = newPlayerRef;
playerData = playerRef.data;
}
}
public override void DamageEffect()
{
if (Time.time > nextDamageEffects)
{
UI_Feedback.instance.TakeDamage(false);
nextDamageEffects = Time.time + damageEffectInterval;
}
}
public override void DoTEffect()
{
if (Time.time > nextDoTEffects)
{
UI_Feedback.instance.TakeDamage(false);
nextDoTEffects = Time.time + dotEffectInterval;
}
}
public override void HealEffect()
{
if (Time.time > nextHealEffects)
{
UI_Feedback.instance.HealFeedback();
nextHealEffects = Time.time + healEffectInterval;
}
}
public override void HoTEffect()
{
if (Time.time > nextDoTEffects)
{
UI_Feedback.instance.HealFeedback();
nextDoTEffects = Time.time + dotEffectInterval;
}
}
protected override void KillEffect()
{
playerData.player.Die();
}
protected override void ReviveEffect()
{
if (playerData.dead)
{
playerData.dead = false;
if (attachedToLocalPlayer)
{
Player.justDied = false;
NetworkVoiceHandler.TalkToAlive();
UI_Feedback.instance.Revive();
}
if (!PlayerHandler.instance.playersAlive.Contains(playerData.player))
{
PlayerHandler.instance.playersAlive.Add(playerData.player);
}
}
}
}
public class MortalSingleton : MonoBehaviour
{
private static MortalSingleton? _instance;
private uint currentTick;
private HashSet<Mortality> _mortalities = new HashSet<Mortality>();
private HashSet<Mortality> _botMortalities = new HashSet<Mortality>();
public static MortalSingleton Instance
{
get
{
if (_instance == null)
{
CreateMortalSingleton();
}
return _instance;
}
}
public uint CurrentTick
{
get
{
return currentTick;
}
private set
{
}
}
public HashSet<Mortality> Mortalities
{
get
{
return _mortalities;
}
internal set
{
_mortalities = value;
}
}
public HashSet<Mortality> BotMortalities
{
get
{
return _botMortalities;
}
internal set
{
_botMortalities = value;
}
}
public static void CreateMortalSingleton()
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
_instance = Object.FindFirstObjectByType<MortalSingleton>();
if (_instance == null)
{
GameObject val = new GameObject("MortalSingleton", new Type[1] { typeof(MortalSingleton) });
Object.DontDestroyOnLoad((Object)(object)val);
}
}
private void Awake()
{
if ((Object)(object)_instance == (Object)null)
{
_instance = this;
}
else if ((Object)(object)_instance != (Object)(object)this)
{
MortalEnemies.Logger.LogWarning((object)"MortalSingleton already exists, destroying new duplicate");
Object.Destroy((Object)(object)this);
return;
}
Mortality[] array = Object.FindObjectsOfType<Mortality>();
foreach (Mortality item in array)
{
_mortalities.Add(item);
}
Mortality_Bot[] array2 = Object.FindObjectsOfType<Mortality_Bot>();
foreach (Mortality item2 in array2)
{
_botMortalities.Add(item2);
}
}
private void FixedUpdate()
{
currentTick++;
}
}
public class ScreenLogListener
{
private const int logLength = 52;
public static ScreenLogListener? Instance;
private Queue logQueue = new Queue(52);
private Text? MyText;
public GameObject gameObject;
public bool outputQueue = true;
public ScreenLogListener()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
gameObject = new GameObject("ScreenLogger");
GameObject val = ((Component)((Component)RetrievableResourceSingleton<TransitionHandler>.Instance).transform.Find("Canvas")).gameObject;
if ((Object)(object)val == (Object)null)
{
MortalEnemies.Logger.LogError((object)"Parent Canvas not found");
return;
}
gameObject.transform.SetParent(val.transform);
gameObject.transform.localPosition = Vector3.zero;
gameObject.transform.localScale = new Vector3(1f, 1f, 1f);
RectTransform val2 = gameObject.AddComponent<RectTransform>();
val2.anchorMin = new Vector2(0.75f, 0.05f);
val2.anchorMax = new Vector2(0.943f, 0.95f);
CanvasRenderer val3 = gameObject.AddComponent<CanvasRenderer>();
val3.SetColor(new Color(1f, 1f, 1f, 1f));
CanvasGroup val4 = gameObject.AddComponent<CanvasGroup>();
val4.blocksRaycasts = false;
Font font = Font.CreateDynamicFontFromOSFont("Arial", 16);
MyText = gameObject.AddComponent<Text>();
if (MyText != null)
{
MyText.font = font;
MyText.fontSize = 16;
MyText.supportRichText = false;
MortalEnemies.Logger.LogEvent += Log_LogEvent;
}
else
{
MortalEnemies.Logger.LogError((object)"Text component not created");
}
}
private void Log_LogEvent(object sender, LogEventArgs logEvent)
{
HandleLog(logEvent.Data.ToString().Replace("\n", ""));
}
public void HandleLog(string message)
{
if (logQueue.Count > 52)
{
logQueue.Dequeue();
}
logQueue.Enqueue(message);
if (!((Object)(object)MyText == (Object)null))
{
RepopulateText();
}
}
public void RepopulateText()
{
MyText.text = "";
if (!outputQueue)
{
return;
}
foreach (string item in logQueue)
{
Text? myText = MyText;
myText.text = myText.text + "> " + item + "\n";
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "rivinwin.MortalEnemies";
public const string PLUGIN_NAME = "MortalEnemies";
public const string PLUGIN_VERSION = "1.1.1";
}
}
namespace MortalEnemies.Patches
{
public class ClassPatches
{
internal static void Init()
{
HookEndpointManager.Add((MethodBase)AccessTools.Method(typeof(Bot), "Start", (Type[])null, (Type[])null), (Delegate)new Action<Action<Bot>, Bot>(HookBotAwake));
HookEndpointManager.Add((MethodBase)AccessTools.Method(typeof(Player), "Awake", (Type[])null, (Type[])null), (Delegate)new Action<Action<Player>, Player>(HookPlayerAwake));
}
public static void HookBotAwake(Action<Bot> orig, Bot self)
{
GameObject gameObject = ((Component)self).gameObject;
while (!((Object)gameObject).name.Contains("(Clone)") && gameObject.transform.parent != null)
{
gameObject = ((Component)gameObject.transform.parent).gameObject;
}
orig(self);
if (gameObject.GetComponent<Mortality>() == null)
{
gameObject.AddComponent<Mortality_Bot>()?.SetBot(self);
}
}
public static void HookPlayerAwake(Action<Player> orig, Player self)
{
orig(self);
if (!self.ai)
{
((Component)self).gameObject.AddComponent<Mortality_Player>()?.SetPlayer(self);
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}