Decompiled source of REPO Hard Mode v1.2.1

plugins/REPOHardMode.dll

Decompiled a day ago
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("YourName")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("R.E.P.O. Hard Mode - Modular difficulty mod")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("REPOHardMode")]
[assembly: AssemblyTitle("REPOHardMode")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.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 REPOHardMode
{
	[BepInPlugin("com.gosufrutita.repohardmode", "R.E.P.O. Hard Mode", "1.2.1")]
	public class HardModePlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.yourname.repohardmode";

		public const string PluginName = "R.E.P.O. Hard Mode";

		public const string PluginVersion = "1.2.1";

		internal static ManualLogSource Log;

		internal static HardModePlugin Instance;

		private Harmony _harmony;

		public static ConfigEntry<float> PriceMultiplier;

		public static ConfigEntry<float> EnemySpeedMultiplier;

		public static ConfigEntry<float> ItemWeightMultiplier;

		public static ConfigEntry<float> ItemSpawnMultiplier;

		public static ConfigEntry<int> PlayerMaxHealth;

		public static ConfigEntry<float> ItemFragilityMultiplier;

		public static ConfigEntry<float> ItemDurabilityMultiplier;

		private void Awake()
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			PriceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "PriceMultiplier", 2.5f, "Multiplier for all shop item prices (2.5 = x2.5 prices)");
			EnemySpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "EnemySpeedMultiplier", 2f, "Multiplier for enemy movement speed (2.0 = 2x faster)");
			ItemWeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "ItemWeightMultiplier", 2f, "Multiplier for item weight/mass (2.0 = 2x heavier)");
			ItemSpawnMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "ItemSpawnMultiplier", 1.15f, "Multiplier for item spawn count (1.15 = 15% more items)");
			PlayerMaxHealth = ((BaseUnityPlugin)this).Config.Bind<int>("Difficulty", "PlayerMaxHealth", 50, "Maximum health for players (default game value is 100, set to 50 for harder difficulty)");
			ItemFragilityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "ItemFragilityMultiplier", 2f, "Multiplier for item fragility (2.0 = items break 2x easier from impacts)");
			ItemDurabilityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Difficulty", "ItemDurabilityMultiplier", 0.5f, "Multiplier for item durability (0.5 = items have half durability, break 2x faster)");
			_harmony = new Harmony("com.yourname.repohardmode");
			_harmony.PatchAll();
			Log.LogInfo((object)"R.E.P.O. Hard Mode v1.2.1 loaded!");
			Log.LogInfo((object)$"Settings: Prices x{PriceMultiplier.Value}, Enemy Speed x{EnemySpeedMultiplier.Value}, Weight x{ItemWeightMultiplier.Value}, Max HP: {PlayerMaxHealth.Value}");
			Log.LogInfo((object)$"Fragility x{ItemFragilityMultiplier.Value}, Durability x{ItemDurabilityMultiplier.Value}");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class PatchUtils
	{
		public static bool ShouldApplyPatch()
		{
			if (!PhotonNetwork.IsConnected)
			{
				return true;
			}
			return PhotonNetwork.IsMasterClient;
		}

		public static bool ShouldApplyToSelf()
		{
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemAttributes), "GetValue")]
	public class ItemPricePatch
	{
		private static readonly FieldRef<ShopManager, float> _getItemValueMultiplier;

		private static readonly FieldRef<ShopManager, float> _getUpgradeValueIncrease;

		private static readonly FieldRef<ShopManager, float> _getHealthPackValueIncrease;

		private static readonly FieldRef<ShopManager, float> _getCrystalValueIncrease;

		static ItemPricePatch()
		{
			try
			{
				_getItemValueMultiplier = AccessTools.FieldRefAccess<ShopManager, float>(typeof(ShopManager).GetField("itemValueMultiplier", BindingFlags.Instance | BindingFlags.NonPublic));
				_getUpgradeValueIncrease = AccessTools.FieldRefAccess<ShopManager, float>(typeof(ShopManager).GetField("upgradeValueIncrease", BindingFlags.Instance | BindingFlags.NonPublic));
				_getHealthPackValueIncrease = AccessTools.FieldRefAccess<ShopManager, float>(typeof(ShopManager).GetField("healthPackValueIncrease", BindingFlags.Instance | BindingFlags.NonPublic));
				_getCrystalValueIncrease = AccessTools.FieldRefAccess<ShopManager, float>(typeof(ShopManager).GetField("crystalValueIncrease", BindingFlags.Instance | BindingFlags.NonPublic));
				HardModePlugin.Log.LogInfo((object)"Item price patch initialized successfully");
			}
			catch (Exception arg)
			{
				HardModePlugin.Log.LogError((object)$"Failed to initialize item price patch: {arg}");
			}
		}

		public static bool Prefix(ref int ___value, float ___itemValueMin, float ___itemValueMax, itemType ___itemType, string ___itemAssetName, PhotonView ___photonView)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Invalid comparison between Unknown and I4
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient)
			{
				return true;
			}
			if (!SemiFunc.RunIsShop())
			{
				return true;
			}
			if (!PatchUtils.ShouldApplyPatch())
			{
				return true;
			}
			try
			{
				float num = Random.Range(___itemValueMin, ___itemValueMax) * _getItemValueMultiplier.Invoke(ShopManager.instance);
				if (num < 1000f)
				{
					num = 1000f;
				}
				if (num >= 1000f)
				{
					num = Mathf.Ceil(num / 1000f);
				}
				if ((int)___itemType == 3)
				{
					num += num * _getUpgradeValueIncrease.Invoke(ShopManager.instance) * (float)StatsManager.instance.GetItemsUpgradesPurchased(___itemAssetName);
				}
				else if ((int)___itemType == 8)
				{
					num += num * _getHealthPackValueIncrease.Invoke(ShopManager.instance) * (float)RunManager.instance.levelsCompleted;
				}
				else if ((int)___itemType == 5)
				{
					num += num * _getCrystalValueIncrease.Invoke(ShopManager.instance) * (float)RunManager.instance.levelsCompleted;
				}
				float num2 = num * HardModePlugin.PriceMultiplier.Value;
				___value = Mathf.Max(1, Mathf.RoundToInt(num2));
				if (GameManager.Multiplayer() && PhotonNetwork.IsMasterClient && (Object)(object)___photonView != (Object)null)
				{
					___photonView.RPC("RpcValueChange", (RpcTarget)4, new object[1] { ___value });
				}
				return false;
			}
			catch (Exception arg)
			{
				HardModePlugin.Log.LogError((object)$"Error in price patch: {arg}");
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyNavMeshAgent), "Awake")]
	public class EnemySpeedPatch
	{
		private static HashSet<int> processedAgents = new HashSet<int>();

		private static FieldInfo FI_Agent = AccessTools.Field(typeof(EnemyNavMeshAgent), "Agent");

		private static FieldInfo FI_DefaultSpeed = AccessTools.Field(typeof(EnemyNavMeshAgent), "DefaultSpeed");

		[HarmonyPostfix]
		private static void Postfix(EnemyNavMeshAgent __instance)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (!PatchUtils.ShouldApplyPatch() || (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsArena()))
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (processedAgents.Contains(instanceID))
			{
				return;
			}
			processedAgents.Add(instanceID);
			try
			{
				NavMeshAgent val = (NavMeshAgent)FI_Agent.GetValue(__instance);
				float num = (float)FI_DefaultSpeed.GetValue(__instance);
				if ((Object)(object)val != (Object)null && num > 0f)
				{
					float num2 = num * HardModePlugin.EnemySpeedMultiplier.Value;
					FI_DefaultSpeed.SetValue(__instance, num2);
					val.speed = num2;
					HardModePlugin.Log.LogInfo((object)$"Enemy speed: {num:F2} -> {num2:F2}");
				}
			}
			catch (Exception arg)
			{
				HardModePlugin.Log.LogError((object)$"Error in enemy speed patch: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Awake")]
	public class PlayerHealthPatch
	{
		private static FieldInfo FI_playerAvatar = AccessTools.Field(typeof(PlayerHealth), "playerAvatar");

		private static FieldInfo FI_maxHealth = AccessTools.Field(typeof(PlayerHealth), "maxHealth");

		private static FieldInfo FI_health = AccessTools.Field(typeof(PlayerHealth), "health");

		[HarmonyPostfix]
		private static void Postfix(PlayerHealth __instance)
		{
			((MonoBehaviour)__instance).StartCoroutine(ApplyHealthModifiersDelayed(__instance));
		}

		private static IEnumerator ApplyHealthModifiersDelayed(PlayerHealth healthInstance)
		{
			while ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				yield return (object)new WaitForSeconds(0.1f);
			}
			yield return (object)new WaitForSeconds(0.5f);
			try
			{
				PlayerAvatar val = (PlayerAvatar)(FI_playerAvatar?.GetValue(healthInstance));
				if ((Object)(object)val == (Object)null)
				{
					HardModePlugin.Log.LogWarning((object)"PlayerAvatar is null!");
					yield break;
				}
				if (!SemiFunc.RunIsLevel())
				{
					HardModePlugin.Log.LogInfo((object)"Not on level, skipping");
					yield break;
				}
				int num = (int)FI_health.GetValue(healthInstance);
				int num2 = (int)FI_maxHealth.GetValue(healthInstance);
				int value = HardModePlugin.PlayerMaxHealth.Value;
				int num3 = Mathf.Min(num, value);
				FI_maxHealth.SetValue(healthInstance, value);
				FI_health.SetValue(healthInstance, num3);
				string text = "Unknown";
				try
				{
					text = ((!((Object)(object)val.photonView != (Object)null) || val.photonView.Owner == null) ? "SinglePlayer/Local" : $"{val.photonView.Owner.NickName} (ID: {val.photonView.Owner.ActorNumber})");
				}
				catch
				{
				}
				HardModePlugin.Log.LogInfo((object)$"[MULTIPLAYER] Player {text} health set: {num}/{num2} -> {num3}/{value}");
			}
			catch (Exception arg)
			{
				HardModePlugin.Log.LogError((object)$"Error in health patch: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")]
	public class PlayerRevivePatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerAvatar __instance, bool _revivedByTruck)
		{
			((MonoBehaviour)__instance).StartCoroutine(SetHealthAfterRevive(__instance));
		}

		private static IEnumerator SetHealthAfterRevive(PlayerAvatar avatar)
		{
			yield return (object)new WaitForSeconds(0.2f);
			try
			{
				if (!((Object)(object)avatar != (Object)null) || !((Object)(object)avatar.playerHealth != (Object)null))
				{
					yield break;
				}
				FieldInfo field = typeof(PlayerHealth).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(PlayerHealth).GetField("maxHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field != null) || !(field2 != null))
				{
					yield break;
				}
				int value = HardModePlugin.PlayerMaxHealth.Value;
				int num = (int)field.GetValue(avatar.playerHealth);
				field2.SetValue(avatar.playerHealth, value);
				if (num > value)
				{
					field.SetValue(avatar.playerHealth, value);
				}
				string arg = "Unknown";
				try
				{
					if ((Object)(object)avatar.photonView != (Object)null && avatar.photonView.Owner != null)
					{
						arg = $"{avatar.photonView.Owner.NickName} (ID: {avatar.photonView.Owner.ActorNumber})";
					}
				}
				catch
				{
				}
				HardModePlugin.Log.LogInfo((object)$"[MULTIPLAYER] Player {arg} revived with reduced health: {Mathf.Min(num, value)}/{value}");
			}
			catch (Exception arg2)
			{
				HardModePlugin.Log.LogError((object)$"Error in revive patch: {arg2}");
			}
		}
	}
	[HarmonyPatch(typeof(ValuableObject), "Awake")]
	public class ValuableFragilityPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ValuableObject __instance)
		{
			if (!PatchUtils.ShouldApplyPatch())
			{
				return;
			}
			try
			{
				if ((Object)(object)__instance.durabilityPreset != (Object)null)
				{
					Durability durabilityPreset = __instance.durabilityPreset;
					durabilityPreset.fragility *= HardModePlugin.ItemFragilityMultiplier.Value;
					Durability durabilityPreset2 = __instance.durabilityPreset;
					durabilityPreset2.durability *= HardModePlugin.ItemDurabilityMultiplier.Value;
				}
				PhysGrabObjectImpactDetector component = ((Component)__instance).GetComponent<PhysGrabObjectImpactDetector>();
				if ((Object)(object)component != (Object)null && (Object)(object)__instance.durabilityPreset != (Object)null)
				{
					component.fragility = __instance.durabilityPreset.fragility;
					component.durability = __instance.durabilityPreset.durability;
				}
			}
			catch (Exception arg)
			{
				HardModePlugin.Log.LogError((object)$"Error in fragility patch: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ValuableObject), "Awake")]
	public class ValuableWeightPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ValuableObject __instance)
		{
			if (!PatchUtils.ShouldApplyPatch())
			{
				return;
			}
			try
			{
				Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					float mass = component.mass;
					component.mass *= HardModePlugin.ItemWeightMultiplier.Value;
					HardModePlugin.Log.LogDebug((object)$"Item weight: {mass:F2} -> {component.mass:F2}");
				}
			}
			catch (Exception arg)
			{
				HardModePlugin.Log.LogError((object)$"Error in weight patch: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ValuableDirector), "Start")]
	public class ItemSpawnPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ValuableDirector __instance)
		{
			if (!PatchUtils.ShouldApplyPatch())
			{
				return;
			}
			try
			{
				FieldInfo[] fields = typeof(ValuableDirector).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!(fieldInfo.FieldType == typeof(int)))
					{
						continue;
					}
					string text = fieldInfo.Name.ToLower();
					if (text.Contains("count") || text.Contains("amount") || text.Contains("max") || text.Contains("spawn"))
					{
						int num = (int)fieldInfo.GetValue(__instance);
						if (num > 0 && num < 500)
						{
							int num2 = Mathf.RoundToInt((float)num * HardModePlugin.ItemSpawnMultiplier.Value);
							fieldInfo.SetValue(__instance, num2);
							HardModePlugin.Log.LogInfo((object)$"Spawn '{fieldInfo.Name}': {num} -> {num2}");
						}
					}
				}
			}
			catch (Exception ex)
			{
				HardModePlugin.Log.LogDebug((object)("Item spawn patch: " + ex.Message));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.gosufrutita.repohardmode";

		public const string PLUGIN_NAME = "R.E.P.O. Hard Mode";

		public const string PLUGIN_VERSION = "1.2.1";
	}
}