Decompiled source of FairBirds v1.0.1

FairBirds.dll

Decompiled 2 months 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 System.Security;
using System.Security.Permissions;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShipTurrets")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Plugin that spawns two turrets on the front and rear of the player ship that targets and neutralises enemies instead of players.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ShipTurrets")]
[assembly: AssemblyTitle("ShipTurrets")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 ShipTurrets
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "ShipTurrets";

		public const string PLUGIN_NAME = "ShipTurrets";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace FairBirds
{
	[BepInPlugin("com.woah25.FairBirdsSS", "FairBirdsHostOnly", "1.0.0")]
	public class FairBirds : BaseUnityPlugin
	{
		internal static ManualLogSource ModLogger;

		internal static ConfigEntry<bool> RandomWander;

		internal static ConfigEntry<bool> EnhancedAntiCamp;

		private void Awake()
		{
			ModLogger = ((BaseUnityPlugin)this).Logger;
			InitializeConfig();
			Harmony.CreateAndPatchAll(typeof(RadMechAIPatch), (string)null);
			ModLogger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.Name} v{((BaseUnityPlugin)this).Info.Metadata.Version} is loaded!");
		}

		private void InitializeConfig()
		{
			RandomWander = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "RandomWander", true, "Enable random wandering for OldBirds");
			EnhancedAntiCamp = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "EnhancedAntiCamp", true, "Enable enhanced anti-camping behavior");
		}
	}
	[HarmonyPatch(typeof(RadMechAI))]
	public static class RadMechAIPatch
	{
		private static readonly Random random = new Random();

		[HarmonyPatch("DoAIInterval")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> MechRoamPatch(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(EnemyAI), "ChooseFarthestNodeFromPosition", (Type[])null, (Type[])null), (string)null)
			}).Advance(3).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[6]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				CodeInstruction.Call(typeof(RadMechAIPatch), "LeaveShipPatch", (Type[])null, (Type[])null),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldloc_1, (object)null),
				CodeInstruction.Call(typeof(RadMechAIPatch), "ChooseFarNodeFromShip", (Type[])null, (Type[])null),
				new CodeInstruction(OpCodes.Stloc_1, (object)null)
			})
				.InstructionEnumeration();
		}

		public static Vector3 ChooseFarNodeFromShip(RadMechAI ai, Vector3 farPosition)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			if (!FairBirds.RandomWander.Value)
			{
				return farPosition;
			}
			Traverse val = Traverse.Create((object)ai);
			Vector3 ship = StartOfRound.Instance.elevatorTransform.position;
			Vector3 teleportBPosition = FindEntrance();
			Random localRandom = new Random(GetSeed(((Component)ai).transform.position));
			List<(Transform, float)> source = (from node in val.Field<List<Transform>>("allAINodes").Value
				select (node, Vector3.Distance(ship, node.position)) into x
				where x.Item2 >= 102f && Vector3.Distance(x.node.position, teleportBPosition) > 50f
				orderby x.Item2 + (float)localRandom.Next(-12, 12) descending
				select x).ToList();
			val.Field<Transform[]>("nodesTempArray").Value = source.Select<(Transform, float), Transform>(((Transform node, float) x) => x.node).ToArray();
			if (val.Field<Transform[]>("nodesTempArray").Value.Length == 0)
			{
				return farPosition;
			}
			double weight = CalculateWeight(CalculateWeightBase(source.Select<(Transform, float), float>(((Transform node, float) x) => x.Item2).ToArray()), val.Field<Transform[]>("nodesTempArray").Value.Length);
			return ChooseOptimalPosition(ai, farPosition, localRandom, weight);
		}

		private static Vector3 FindEntrance()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("EntranceTeleportB(Clone)");
			if (!((Object)(object)val != (Object)null))
			{
				return Vector3.zero;
			}
			return val.transform.position;
		}

		private static int GetSeed(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return RoundUpToNearestFive(position.x) + RoundUpToNearestFive(position.z);
		}

		private static float CalculateWeightBase(float[] distances)
		{
			return 0.7f * distances.Average() + 0.3f * (distances.First() + distances.Last());
		}

		private static double CalculateWeight(float weightBase, int nodeCount)
		{
			return (double)(Mathf.Clamp((weightBase < 152.5f) ? (-0.8f * (weightBase - 100f) + 50f) : (-0.125f * (weightBase - 152.5f) + 8f), 1f, 50f) * (float)Mathf.Clamp(130 - nodeCount, 50, 100)) * 0.0001;
		}

		private static Vector3 ChooseOptimalPosition(RadMechAI ai, Vector3 farPosition, Random localRandom, double weight)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			Traverse val = Traverse.Create((object)ai);
			Vector3 position = StartOfRound.Instance.elevatorTransform.position;
			Vector3 result = farPosition;
			for (int i = 1; i < val.Field<Transform[]>("nodesTempArray").Value.Length; i++)
			{
				if (localRandom.NextDouble() < weight)
				{
					break;
				}
				Vector3 position2 = val.Field<Transform[]>("nodesTempArray").Value[i].position;
				if (!val.Method("PathIsIntersectedByLineOfSight", new object[3] { position2, false, false }).GetValue<bool>())
				{
					val.Field<float>("mostOptimalDistance").Value = Vector3.Distance(position, position2);
					result = position2;
					if (i >= val.Field<Transform[]>("nodesTempArray").Value.Length - 1)
					{
						break;
					}
				}
			}
			return result;
		}

		public static void LeaveShipPatch(RadMechAI ai)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (FairBirds.EnhancedAntiCamp.Value)
			{
				FairBirds.ModLogger.LogInfo((object)"Roaming Away from Camping Areas");
				Traverse obj = Traverse.Create((object)ai);
				AISearchRoutine val = (AISearchRoutine)(((object)obj.Field<AISearchRoutine>("roamPlanet").Value) ?? ((object)new AISearchRoutine()));
				obj.Field<AISearchRoutine>("roamPlanet").Value = val;
				obj.Method("StopSearch", new object[2] { val, true }).GetValue();
				val.searchWidth = 35f;
			}
		}

		[HarmonyPatch("FinishedCurrentSearchRoutine")]
		[HarmonyPostfix]
		public static void BirdFinishSearch(RadMechAI __instance)
		{
			if (FairBirds.EnhancedAntiCamp.Value)
			{
				FairBirds.ModLogger.LogDebug((object)"OldBird Finished a Search");
				AISearchRoutine value = Traverse.Create((object)__instance).Field<AISearchRoutine>("roamPlanet").Value;
				if (value != null && value.searchWidth < 200f)
				{
					value.searchWidth = 200f;
				}
			}
		}

		private static int RoundUpToNearestFive(float value)
		{
			return Mathf.CeilToInt(value / 5f) * 5;
		}
	}
}