Decompiled source of EngineerWithFourTurrets v1.1.1

plugins/EngineerFourTurrets.dll

Decompiled 4 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.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 NormalAIPeople.EngineerFourTurrets
{
	[BepInPlugin("normalAIPeople.EngineerFourTurrets", "Engineer Four Turrets", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class EngineerFourTurretsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "normalAIPeople.EngineerFourTurrets";

		public const string PluginName = "Engineer Four Turrets";

		public const string PluginVersion = "1.1.1";

		private static ConfigEntry<int> turretLimit;

		private static ConfigEntry<int> tr90InitialStocks;

		private static ConfigEntry<float> tr90PlacementRecharge;

		private static ConfigEntry<float> tr90AttackInterval;

		private static ManualLogSource log;

		private static DeployableSlot aerosBigTurretSlot;

		private static bool hasAerosBigTurretSlot;

		private void Awake()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			log = ((BaseUnityPlugin)this).Logger;
			turretLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Engineer", "Turret Limit", 4, "Maximum simultaneous turrets for the vanilla Engineer turret slot and AerosSkills TR90 Railgun Turret slot.");
			tr90InitialStocks = ((BaseUnityPlugin)this).Config.Bind<int>("TR90 Railgun Turret", "Initial Placement Stocks", 1, "TR90 placement charges available when entering a run. The skill starts full, so this also sets its maximum stock.");
			tr90PlacementRecharge = ((BaseUnityPlugin)this).Config.Bind<float>("TR90 Railgun Turret", "Placement Recharge Time", 25f, "Seconds required to recharge one TR90 placement stock.");
			tr90AttackInterval = ((BaseUnityPlugin)this).Config.Bind<float>("TR90 Railgun Turret", "Base Attack Interval", 8f, "Base seconds between TR90 shots before the turret's attack-speed multiplier is applied.");
			Harmony val = new Harmony("normalAIPeople.EngineerFourTurrets");
			MethodInfo methodInfo = AccessTools.Method(typeof(CharacterMaster), "GetDeployableSameSlotLimit", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(EngineerFourTurretsPlugin), "DeployableLimitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			InstallAerosCompatibility(val);
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(ApplyTR90SkillConfig));
		}

		private void OnDestroy()
		{
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(ApplyTR90SkillConfig));
		}

		private static void ApplyTR90SkillConfig()
		{
			Type type = AccessTools.TypeByName("AerosSkills.EngiSpecial");
			Type type2 = AccessTools.TypeByName("AerosSkills.EngiTurretPrimary");
			int num = 0;
			int num2 = 0;
			foreach (SkillDef allSkillDef in SkillCatalog.allSkillDefs)
			{
				Type type3 = (((Object)(object)allSkillDef != (Object)null) ? ((SerializableEntityStateType)(ref allSkillDef.activationState)).stateType : null);
				if (type3 == type)
				{
					allSkillDef.baseMaxStock = Math.Max(1, tr90InitialStocks.Value);
					allSkillDef.baseRechargeInterval = Math.Max(0.05f, tr90PlacementRecharge.Value);
					allSkillDef.rechargeStock = 1;
					num++;
				}
				else if (type3 == type2)
				{
					allSkillDef.baseRechargeInterval = Math.Max(0.05f, tr90AttackInterval.Value);
					num2++;
				}
			}
			log.LogInfo((object)("Configured " + num + " TR90 placement skill(s) and " + num2 + " attack skill(s)."));
		}

		private static void InstallAerosCompatibility(Harmony harmony)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("AerosSkills.Prefabs");
			if (type == null)
			{
				log.LogInfo((object)"AerosSkills is not loaded; vanilla Engineer turret support remains active.");
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(type, "bigTurret");
			if (fieldInfo != null)
			{
				object value = fieldInfo.GetValue(null);
				if (value is DeployableSlot)
				{
					aerosBigTurretSlot = (DeployableSlot)value;
					hasAerosBigTurretSlot = true;
				}
			}
			FieldInfo fieldInfo2 = AccessTools.Field(type, "turret");
			GameObject val = (GameObject)((fieldInfo2 != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null)
			{
				NormalizeNetworkIdentities(val);
			}
			Type type2 = AccessTools.TypeByName("AerosSkills.EngiSpecial");
			MethodInfo methodInfo = ((type2 != null) ? AccessTools.Method(type2, "OnEnter", (Type[])null, (Type[])null) : null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(EngineerFourTurretsPlugin), "AerosOnEnterPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo2 = ((type2 != null) ? AccessTools.Method(type2, "Summon", (Type[])null, (Type[])null) : null);
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(EngineerFourTurretsPlugin), "AerosSummonPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				log.LogInfo((object)"Installed AerosSkills TR90 host/client placement compatibility.");
			}
		}

		private static void AerosOnEnterPostfix(object __instance)
		{
			try
			{
				GameObject value = Traverse.Create(__instance).Property("gameObject", (object[])null).GetValue<GameObject>();
				EntityStateMachine value2 = Traverse.Create(__instance).Field("outer").GetValue<EntityStateMachine>();
				CharacterBody val = (((Object)(object)value != (Object)null) ? value.GetComponent<CharacterBody>() : null);
				if ((Object)(object)value2 != (Object)null && (Object)(object)val != (Object)null)
				{
					FieldInfo fieldInfo = AccessTools.Field(typeof(EntityStateMachine), "commonComponents");
					object obj = ((fieldInfo != null) ? fieldInfo.GetValue(value2) : null);
					FieldInfo fieldInfo2 = ((obj != null) ? AccessTools.Field(obj.GetType(), "characterBody") : null);
					if (fieldInfo != null && fieldInfo2 != null)
					{
						fieldInfo2.SetValue(obj, val);
						fieldInfo.SetValue(value2, obj);
					}
				}
				Type type = AccessTools.TypeByName("AerosSkills.Prefabs");
				FieldInfo fieldInfo3 = ((type != null) ? AccessTools.Field(type, "turretMaster") : null);
				GameObject val2 = (GameObject)((fieldInfo3 != null) ? /*isinst with value type is only supported in some contexts*/: null);
				Type type2 = AccessTools.TypeByName("EntityStates.Engi.EngiWeapon.PlaceTurret");
				FieldInfo fieldInfo4 = ((type2 != null) ? AccessTools.Field(type2, "turretMasterPrefab") : null);
				if ((Object)(object)val2 != (Object)null && fieldInfo4 != null)
				{
					fieldInfo4.SetValue(__instance, val2);
				}
			}
			catch (Exception ex)
			{
				log.LogWarning((object)("Could not initialize TR90 placement compatibility: " + ex.Message));
			}
		}

		private static void NormalizeNetworkIdentities(GameObject turretBody)
		{
			NetworkIdentity[] components = turretBody.GetComponents<NetworkIdentity>();
			NetworkIdentity val = ((components.Length != 0) ? components[0] : null);
			int num = 0;
			for (int i = 1; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
				num++;
			}
			NetworkIdentity[] componentsInChildren = turretBody.GetComponentsInChildren<NetworkIdentity>(true);
			NetworkIdentity[] array = componentsInChildren;
			foreach (NetworkIdentity val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val && (Object)(object)((Component)val2).gameObject != (Object)(object)turretBody)
				{
					Object.DestroyImmediate((Object)(object)val2);
					num++;
				}
			}
			if (num > 0)
			{
				log.LogInfo((object)"Removed duplicate NetworkIdentity components from AerosBigTurretBody.");
			}
		}

		private static void DeployableLimitPostfix(DeployableSlot slot, ref int __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (int)slot == 1;
			bool flag2 = hasAerosBigTurretSlot && slot == aerosBigTurretSlot;
			if (flag || flag2)
			{
				__result = Math.Max(__result, Math.Max(1, turretLimit.Value));
			}
		}

		private static bool AerosSummonPrefix(object __instance)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = AccessTools.TypeByName("EntityStates.Engi.EngiWeapon.PlaceTurret");
				FieldInfo fieldInfo = ((type != null) ? AccessTools.Field(type, "currentPlacementInfo") : null);
				object obj = ((fieldInfo != null) ? fieldInfo.GetValue(__instance) : null);
				if (obj == null)
				{
					return true;
				}
				Type type2 = obj.GetType();
				FieldInfo fieldInfo2 = AccessTools.Field(type2, "position");
				FieldInfo fieldInfo3 = AccessTools.Field(type2, "rotation");
				if (fieldInfo2 == null || fieldInfo3 == null)
				{
					return true;
				}
				Vector3 val = (Vector3)fieldInfo2.GetValue(obj);
				Quaternion val2 = (Quaternion)fieldInfo3.GetValue(obj);
				GameObject value = Traverse.Create(__instance).Property("gameObject", (object[])null).GetValue<GameObject>();
				Type type3 = AccessTools.TypeByName("AerosSkills.TurretSpawner");
				Component val3 = (((Object)(object)value != (Object)null && type3 != null) ? value.GetComponent(type3) : null);
				string text = (NetworkServer.active ? "CmdSpawn" : "CallCmdSpawn");
				MethodInfo methodInfo = ((type3 != null) ? AccessTools.Method(type3, text, (Type[])null, (Type[])null) : null);
				if ((Object)(object)val3 == (Object)null || methodInfo == null)
				{
					return true;
				}
				methodInfo.Invoke(val3, new object[2] { val, val2 });
				return false;
			}
			catch (Exception ex)
			{
				log.LogWarning((object)("TR90 placement compatibility fell back to AerosSkills: " + ex.Message));
				return true;
			}
		}
	}
}