Decompiled source of Soulcatcher tility stones fix v1.0.0

SoulcatcherUtilityStonesFix.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SoulcatcherTickBlobFix")]
[assembly: AssemblyConfiguration("release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SoulcatcherTickBlobFix")]
[assembly: AssemblyTitle("SoulcatcherTickBlobFix")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 SoulcatcherTickBlobFix
{
	[BepInPlugin("ru.gerbesh.soulcatcher.tickblobfix", "Soulcatcher Tick + Blob Fix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "ru.gerbesh.soulcatcher.tickblobfix";

		public const string PluginName = "Soulcatcher Tick + Blob Fix";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private bool _jumpTranspilerUnpatched;

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			UnpatchSoulcatcherJumpTranspiler();
			_harmony = new Harmony("ru.gerbesh.soulcatcher.tickblobfix");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
		}

		private void UnpatchSoulcatcherJumpTranspiler()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (_jumpTranspilerUnpatched)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Character), "Jump", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					new Harmony("Soulcatcher").Unpatch((MethodBase)methodInfo, (HarmonyPatchType)3, "Soulcatcher");
					_jumpTranspilerUnpatched = true;
				}
			}
			catch
			{
			}
		}

		private void Start()
		{
			UnpatchSoulcatcherJumpTranspiler();
		}

		private void OnDestroy()
		{
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}
	}
	internal static class ReflectionExtensions
	{
		internal static Type[] GetTypesSafe(this Assembly asm)
		{
			try
			{
				return asm.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.Where((Type t) => t != null).ToArray();
			}
			catch
			{
				return Array.Empty<Type>();
			}
		}
	}
	internal static class EffectConfigTypeCache
	{
		private static readonly object LockObj = new object();

		private static readonly Dictionary<string, Type> Cache = new Dictionary<string, Type>(StringComparer.Ordinal);

		internal static Type GetConfigType(string declaringTypeName)
		{
			lock (LockObj)
			{
				if (Cache.TryGetValue(declaringTypeName, out var value))
				{
					return value;
				}
				value = FindConfigType(declaringTypeName);
				Cache[declaringTypeName] = value;
				return value;
			}
		}

		private static Type FindConfigType(string declaringTypeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type[] typesSafe = assemblies[i].GetTypesSafe();
				foreach (Type type in typesSafe)
				{
					if (!(type == null) && !(type.Name != "Config") && type.IsNested && type.DeclaringType?.Name == declaringTypeName)
					{
						return type;
					}
				}
			}
			return null;
		}
	}
	internal static class JewelcraftingApi
	{
		private static readonly object LockObj = new object();

		private static MethodInfo _getEffectPowerGeneric;

		private static Type _defaultPowerType;

		private static void EnsureApi()
		{
			if (_getEffectPowerGeneric != null && _defaultPowerType != null)
			{
				return;
			}
			lock (LockObj)
			{
				if (_getEffectPowerGeneric != null && _defaultPowerType != null)
				{
					return;
				}
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					Type[] typesSafe = assemblies[i].GetTypesSafe();
					foreach (Type type in typesSafe)
					{
						if (type == null || !type.IsAbstract || !type.IsSealed)
						{
							continue;
						}
						MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						foreach (MethodInfo methodInfo in methods)
						{
							if (!(methodInfo.Name == "GetEffectPower") || !methodInfo.IsGenericMethodDefinition)
							{
								continue;
							}
							ParameterInfo[] parameters = methodInfo.GetParameters();
							if (parameters.Length != 2 || !(parameters[1].ParameterType == typeof(string)))
							{
								continue;
							}
							_getEffectPowerGeneric = methodInfo;
							if (!(_defaultPowerType == null))
							{
								return;
							}
							Assembly assembly = methodInfo.DeclaringType?.Assembly;
							if (assembly != null)
							{
								_defaultPowerType = assembly.GetTypesSafe().FirstOrDefault((Type x) => x != null && x.Name == "DefaultPower" && x.IsValueType);
							}
							return;
						}
					}
				}
			}
		}

		internal static float GetEffectValue(Player player, string effectName, string declaringTypeName)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0f;
			}
			EnsureApi();
			if (_getEffectPowerGeneric == null)
			{
				return 0f;
			}
			Type configType = EffectConfigTypeCache.GetConfigType(declaringTypeName);
			if (configType != null)
			{
				float num = TryGetEffectValue(player, effectName, configType);
				if (num != 0f)
				{
					return num;
				}
			}
			if (_defaultPowerType != null)
			{
				float num2 = TryGetEffectValue(player, effectName, _defaultPowerType);
				if (num2 != 0f)
				{
					return num2;
				}
			}
			return 0f;
		}

		private static float TryGetEffectValue(Player player, string effectName, Type cfgType)
		{
			if (cfgType == null)
			{
				return 0f;
			}
			try
			{
				object obj = _getEffectPowerGeneric.MakeGenericMethod(cfgType).Invoke(null, new object[2] { player, effectName });
				if (obj == null)
				{
					return 0f;
				}
				FieldInfo fieldInfo = cfgType.GetField("Value", BindingFlags.Instance | BindingFlags.Public) ?? cfgType.GetField("Power", BindingFlags.Instance | BindingFlags.Public);
				if (fieldInfo != null)
				{
					return Convert.ToSingle(fieldInfo.GetValue(obj));
				}
				PropertyInfo propertyInfo = cfgType.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public) ?? cfgType.GetProperty("Power", BindingFlags.Instance | BindingFlags.Public);
				if (propertyInfo != null)
				{
					return Convert.ToSingle(propertyInfo.GetValue(obj, null));
				}
			}
			catch
			{
			}
			return 0f;
		}
	}
	[HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")]
	internal static class TickGemEitrRegenPatch
	{
		private const string EffectName = "Tick Soul Power";

		private const string DeclaringTypeName = "Tick_Soul_Power";

		private static void Postfix(Player __instance, ref float __result)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				float effectValue = JewelcraftingApi.GetEffectValue(__instance, "Tick Soul Power", "Tick_Soul_Power");
				if (effectValue > 0f)
				{
					__result += effectValue / 100f;
				}
			}
		}
	}
	internal static class BlobVfxCache
	{
		private static bool _searched;

		private static GameObject _vfx;

		internal static GameObject GetVfx()
		{
			if (_searched)
			{
				return _vfx;
			}
			_searched = true;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type[] typesSafe = assemblies[i].GetTypesSafe();
				foreach (Type type in typesSafe)
				{
					if (!(type?.Name != "Blob_Soul_Power"))
					{
						FieldInfo field = type.GetField("VFX", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						if (field != null && typeof(GameObject).IsAssignableFrom(field.FieldType))
						{
							object? value = field.GetValue(null);
							return _vfx = (GameObject)((value is GameObject) ? value : null);
						}
					}
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Character), "Jump")]
	internal static class BlobGemJumpPatch
	{
		private const string EffectName = "Blob Soul Power";

		private const string DeclaringTypeName = "Blob_Soul_Power";

		private static readonly FieldRef<Character, ZNetView> NViewRef = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview");

		private static readonly FieldRef<Character, Rigidbody> BodyRef = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");

		private static void Prefix(Character __instance, ref bool __state)
		{
			__state = (Object)(object)__instance != (Object)null && __instance.IsOnGround();
		}

		private static void Postfix(Character __instance, bool __state)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || !__state)
			{
				return;
			}
			ZNetView val2 = NViewRef.Invoke((Character)(object)val);
			if ((Object)(object)val2 == (Object)null || !val2.IsOwner())
			{
				return;
			}
			Rigidbody val3 = BodyRef.Invoke((Character)(object)val);
			if ((Object)(object)val3 == (Object)null)
			{
				return;
			}
			float effectValue = JewelcraftingApi.GetEffectValue(val, "Blob Soul Power", "Blob_Soul_Power");
			if (!(effectValue <= 0f))
			{
				Vector3 val4 = Vector3.up * effectValue * 0.5f + ((Component)val).transform.forward * effectValue * 6f;
				val3.AddForce(val4, (ForceMode)2);
				GameObject vfx = BlobVfxCache.GetVfx();
				if ((Object)(object)vfx != (Object)null)
				{
					Object.Instantiate<GameObject>(vfx, ((Component)val).transform.position, Quaternion.identity);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SEMan), "ModifySkillLevel")]
	internal static class DvergerBloodMageSkillPatch
	{
		private const string EffectName = "Dverger Blood Mage Soul Power";

		private const string DeclaringTypeName = "Dverger_BloodMage_Soul_Power";

		private static readonly FieldRef<SEMan, Character> CharacterRef = AccessTools.FieldRefAccess<SEMan, Character>("m_character");

		private static void Postfix(SEMan __instance, SkillType skill, ref float level)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			if ((int)skill != 10 || __instance == null)
			{
				return;
			}
			Character obj = CharacterRef.Invoke(__instance);
			Player val = (Player)(object)((obj is Player) ? obj : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer))
			{
				float effectValue = JewelcraftingApi.GetEffectValue(val, "Dverger Blood Mage Soul Power", "Dverger_BloodMage_Soul_Power");
				if (effectValue > 0f)
				{
					level += effectValue;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class DvergerBloodMageCompendiumPatch
	{
		private const string EffectNameKey = "$jc_effect_dverger_blood_mage_soul_power";

		private const string SkillNameKey = "$skill_bloodmagic";

		private const string EffectName = "Dverger Blood Mage Soul Power";

		private const string DeclaringTypeName = "Dverger_BloodMage_Soul_Power";

		private static readonly FieldInfo TextAreaField = AccessTools.Field(typeof(TextsDialog), "m_textArea");

		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Jewelcrafting.CompendiumDisplay+DisplayGemEffectOverview");
			if (!(type == null))
			{
				return AccessTools.Method(type, "Render", (Type[])null, (Type[])null);
			}
			return null;
		}

		private static void Postfix(TextsDialog compendium)
		{
			if ((Object)(object)compendium == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || JewelcraftingApi.GetEffectValue(localPlayer, "Dverger Blood Mage Soul Power", "Dverger_BloodMage_Soul_Power") <= 0f)
			{
				return;
			}
			string value = LocalizationHelper.Localize("$jc_effect_dverger_blood_mage_soul_power");
			string text = LocalizationHelper.Localize("$skill_bloodmagic");
			string text2 = "\n<color=yellow>" + text + "</color>: " + Mathf.FloorToInt(((Character)localPlayer).GetSkillLevel((SkillType)10));
			object? obj = TextAreaField?.GetValue(compendium);
			Component val = (Component)((obj is Component) ? obj : null);
			Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.parent : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Component[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Component>(true);
			foreach (Component target in componentsInChildren)
			{
				string text3 = TextComponentAccess.GetText(target);
				if (!string.IsNullOrEmpty(text3) && text3.Contains(value) && !text3.Contains(text))
				{
					TextComponentAccess.SetText(target, text3 + text2);
				}
			}
		}
	}
	[HarmonyPatch(typeof(TextsDialog), "AddActiveEffects")]
	internal static class DvergerBloodMageActiveEffectsPatch
	{
		private const string EffectName = "Dverger Blood Mage Soul Power";

		private const string DeclaringTypeName = "Dverger_BloodMage_Soul_Power";

		private const string SkillNameKey = "$skill_bloodmagic";

		private static readonly FieldInfo TextsField = AccessTools.Field(typeof(TextsDialog), "m_texts");

		private static void Postfix(TextsDialog __instance)
		{
			if ((Object)(object)__instance == (Object)null || !(TextsField?.GetValue(__instance) is IList list) || list.Count == 0)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || JewelcraftingApi.GetEffectValue(localPlayer, "Dverger Blood Mage Soul Power", "Dverger_BloodMage_Soul_Power") <= 0f)
			{
				return;
			}
			string text = LocalizationHelper.Localize("$skill_bloodmagic");
			int num = Mathf.FloorToInt(((Character)localPlayer).GetSkillLevel((SkillType)10));
			string value = "\n" + text + ":";
			string text2 = "\n" + text + ": " + num;
			object target = list[0];
			string text3 = TextComponentAccess.GetText(target);
			if (string.IsNullOrEmpty(text3))
			{
				return;
			}
			int num2 = text3.IndexOf(value, StringComparison.Ordinal);
			if (num2 >= 0)
			{
				int num3 = text3.IndexOf('\n', num2 + 1);
				if (num3 < 0)
				{
					num3 = text3.Length;
				}
				text3 = text3.Remove(num2, num3 - num2);
			}
			text3 += text2;
			TextComponentAccess.SetText(target, text3);
		}
	}
	internal static class LocalizationHelper
	{
		private static Type _type;

		private static PropertyInfo _instanceProp;

		private static MethodInfo _localizeMethod;

		internal static string Localize(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return key;
			}
			Ensure();
			if (_instanceProp == null || _localizeMethod == null)
			{
				return key;
			}
			try
			{
				object value = _instanceProp.GetValue(null, null);
				if (value == null)
				{
					return key;
				}
				return (_localizeMethod.Invoke(value, new object[1] { key }) as string) ?? key;
			}
			catch
			{
				return key;
			}
		}

		private static void Ensure()
		{
			if (!(_localizeMethod != null))
			{
				_type = typeof(Player).Assembly.GetTypesSafe().FirstOrDefault((Type t) => t != null && t.Name == "Localization");
				if (!(_type == null))
				{
					_instanceProp = _type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public);
					_localizeMethod = _type.GetMethod("Localize", new Type[1] { typeof(string) });
				}
			}
		}
	}
	internal static class TextComponentAccess
	{
		internal static string GetText(object target)
		{
			if (target == null)
			{
				return null;
			}
			PropertyInfo property = target.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property.PropertyType == typeof(string))
			{
				return property.GetValue(target, null) as string;
			}
			FieldInfo field = target.GetType().GetField("m_text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(string))
			{
				return field.GetValue(target) as string;
			}
			return null;
		}

		internal static void SetText(object target, string value)
		{
			if (target == null)
			{
				return;
			}
			PropertyInfo property = target.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public);
			if (property != null && property.PropertyType == typeof(string))
			{
				property.SetValue(target, value, null);
				return;
			}
			FieldInfo field = target.GetType().GetField("m_text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(string))
			{
				field.SetValue(target, value);
			}
		}
	}
}