Decompiled source of SummonTweaks v1.0.0

SummonTweaks.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
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.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SummonTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2cc35a509d0cd09739fcf2c5e7c5808891b1751a")]
[assembly: AssemblyProduct("SummonTweaks")]
[assembly: AssemblyTitle("SummonTweaks")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SummonTweaks
{
	[BepInPlugin("com.koendertjh.summontweaks", "SummonTweaks", "1.0.0")]
	public class SummonTweaksPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.koendertjh.summontweaks";

		public const string ModName = "SummonTweaks";

		public const string ModVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> WalkThroughSummons;

		internal static ConfigEntry<string> SolidSummons;

		internal static ConfigEntry<bool> SmartSpiritCaller;

		private static HashSet<string> s_solid = new HashSet<string>();

		private Harmony _harmony;

		private void Awake()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			WalkThroughSummons = ((BaseUnityPlugin)this).Config.Bind<bool>("Collision", "WalkThroughSummons", true, "Players walk through summons instead of bumping into them. Attacks and projectiles still hit.");
			SolidSummons = ((BaseUnityPlugin)this).Config.Bind<string>("Collision", "SolidSummons", "Troll_Summoned", "Comma-separated creature prefab names that stay solid for players.");
			SmartSpiritCaller = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "SmartSpiritCaller", true, "Summoning staffs with several creatures (Spirit Caller) only roll creatures you can add without unsummoning one you already have. When every kind is at its limit, the game's normal roll is used.");
			ParseSolid();
			SolidSummons.SettingChanged += delegate
			{
				ParseSolid();
			};
			_harmony = new Harmony("com.koendertjh.summontweaks");
			_harmony.PatchAll(typeof(SummonTweaksPlugin).Assembly);
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void ParseSolid()
		{
			s_solid = new HashSet<string>(from s in SolidSummons.Value.Split(new char[1] { ',' })
				select s.Trim() into s
				where s.Length > 0
				select s, StringComparer.OrdinalIgnoreCase);
		}

		internal static bool IsSolid(string prefabName)
		{
			return s_solid.Contains(prefabName);
		}
	}
	[HarmonyPatch]
	internal static class SpiritCallerPatches
	{
		private static readonly FieldRef<SpawnAbility, Character> s_owner = AccessTools.FieldRefAccess<SpawnAbility, Character>("m_owner");

		private static readonly FieldRef<SpawnAbility, ItemData> s_weapon = AccessTools.FieldRefAccess<SpawnAbility, ItemData>("m_weapon");

		private static MethodBase TargetMethod()
		{
			return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(SpawnAbility), "Spawn", (Type[])null, (Type[])null));
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			FieldInfo fieldInfo = AccessTools.Field(typeof(SpawnAbility), "m_spawnPrefab");
			MethodInfo methodInfo = AccessTools.Method(typeof(Random), "Range", new Type[2]
			{
				typeof(int),
				typeof(int)
			}, (Type[])null);
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[6]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction _) => true), (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldlen, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Conv_I4, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldelem_Ref, (object)null, (string)null)
			});
			if (val.IsInvalid)
			{
				SummonTweaksPlugin.Log.LogWarning((object)"SpawnAbility.Spawn has changed; SmartSpiritCaller is disabled.");
				return val.InstructionEnumeration();
			}
			CodeInstruction instruction = val.Instruction;
			return val.Advance(4).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(instruction.opcode, instruction.operand)
			}).SetInstruction(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(SpiritCallerPatches), "PickIndex", (Type[])null, (Type[])null)))
				.InstructionEnumeration();
		}

		private static int PickIndex(int min, int max, SpawnAbility ability)
		{
			if (SummonTweaksPlugin.SmartSpiritCaller.Value && max - min > 1)
			{
				Character obj = s_owner.Invoke(ability);
				Player val = (Player)(object)((obj is Player) ? obj : null);
				if (val != null)
				{
					int maxInstances = GetMaxInstances(ability, val);
					List<int> list = new List<int>();
					for (int i = min; i < max; i++)
					{
						if (CanAdd(ability, ability.m_spawnPrefab[i], val, maxInstances))
						{
							list.Add(i);
						}
					}
					if (list.Count <= 0)
					{
						return Random.Range(min, max);
					}
					return list[Random.Range(0, list.Count)];
				}
			}
			return Random.Range(min, max);
		}

		private static bool CanAdd(SpawnAbility ability, GameObject prefab, Player player, int maxInstances)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return false;
			}
			if (ability.m_maxSpawned > 0 && SpawnSystem.GetNrOfInstances(prefab, Vector3.zero, 0f, false, false) >= ability.m_maxSpawned)
			{
				return false;
			}
			if (maxInstances <= 0)
			{
				return true;
			}
			Character component = prefab.GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			string playerName = player.GetPlayerName();
			int num = 0;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!(allCharacter.m_name != component.m_name))
				{
					ZNetView component2 = ((Component)allCharacter).GetComponent<ZNetView>();
					ZDO val = (((Object)(object)component2 != (Object)null && component2.IsValid()) ? component2.GetZDO() : null);
					if (val != null && val.GetString(ZDOVars.s_follow, "") == playerName)
					{
						num++;
					}
				}
			}
			return num < maxInstances;
		}

		private static int GetMaxInstances(SpawnAbility ability, Player player)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Skills skills = ((Character)player).GetSkills();
			if ((Object)(object)skills == (Object)null || ability.m_levelUpSettings == null)
			{
				return 0;
			}
			for (int num = ability.m_levelUpSettings.Count - 1; num >= 0; num--)
			{
				LevelUpSettings val = ability.m_levelUpSettings[num];
				if (!(skills.GetSkillLevel(val.m_skill) < (float)val.m_skillLevel))
				{
					ItemData val2 = s_weapon.Invoke(ability);
					if (!ability.m_setMaxInstancesFromWeaponLevel)
					{
						return val.m_maxSpawns;
					}
					return val2?.m_quality ?? 0;
				}
			}
			return 0;
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class SummonPatches
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance)
		{
			Tameable component = ((Component)__instance).GetComponent<Tameable>();
			if (!((Object)(object)component == (Object)null) && (!(component.m_unsummonDistance <= 0f) || !(component.m_unsummonOnOwnerLogoutSeconds <= 0f)))
			{
				((Component)__instance).gameObject.AddComponent<PlayerPassThrough>();
			}
		}
	}
	internal class PlayerPassThrough : MonoBehaviour
	{
		private const float Interval = 1f;

		private Collider[] _colliders;

		private string _prefabName;

		private float _timer;

		private void Awake()
		{
			_colliders = (from c in ((Component)this).GetComponentsInChildren<Collider>()
				where !c.isTrigger
				select c).ToArray();
			_prefabName = ((Object)((Component)this).gameObject).name.Replace("(Clone)", "").Trim();
		}

		private void Update()
		{
			_timer -= Time.deltaTime;
			if (_timer > 0f)
			{
				return;
			}
			_timer = 1f;
			bool flag = SummonTweaksPlugin.WalkThroughSummons.Value && !SummonTweaksPlugin.IsSolid(_prefabName);
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				Collider val = (Collider)(object)(((Object)(object)allPlayer != (Object)null) ? ((Character)allPlayer).GetCollider() : null);
				if ((Object)(object)val == (Object)null || !val.enabled)
				{
					continue;
				}
				Collider[] colliders = _colliders;
				foreach (Collider val2 in colliders)
				{
					if ((Object)(object)val2 != (Object)null && val2.enabled && ((Component)val2).gameObject.activeInHierarchy)
					{
						Physics.IgnoreCollision(val2, val, flag);
					}
				}
			}
		}
	}
	internal static class PluginInfo
	{
		public const string Version = "1.0.0";
	}
}