Decompiled source of FairGiantsHostOnly v1.9.0

FairBirdsLite.dll

Decompiled 3 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 Unity.Netcode;
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("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 FairGiants
{
	[BepInPlugin("com.woah25.FairGiantsSS", "FairGiantsHostOnly", "1.3.0")]
	public class FairGiantsMod : BaseUnityPlugin
	{
		internal static ManualLogSource ModLogger;

		internal static ConfigEntry<bool> RandomWander;

		internal static ConfigEntry<bool> EnhancedAntiCamp;

		internal static ConfigEntry<float> PassiveStealthDecay;

		internal static ConfigEntry<PatchApplyLevel> StealthDecaysWhen;

		internal static ConfigEntry<float> GiantSpeedMultiplier;

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

		private void InitializeConfig()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			RandomWander = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "RandomWander", true, "Enable random wandering for giants");
			EnhancedAntiCamp = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "EnhancedAntiCamp", true, "Enable enhanced anti-camping behavior");
			PassiveStealthDecay = ((BaseUnityPlugin)this).Config.Bind<float>("Stealth", "PassiveStealthDecay", 0.2f, new ConfigDescription("Rate of passive stealth decay", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			StealthDecaysWhen = ((BaseUnityPlugin)this).Config.Bind<PatchApplyLevel>("Stealth", "StealthDecaysWhen", PatchApplyLevel.Always, "When stealth decay should be applied");
			GiantSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "GiantSpeedMultiplier", 0.7f, new ConfigDescription("Multiplier for giant's movement speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
		}
	}
	public enum PatchApplyLevel
	{
		Always,
		Solo,
		Never
	}
	[HarmonyPatch(typeof(ForestGiantAI))]
	public static class ForestGiantAIPatch
	{
		private static readonly Random random = new Random();

		[HarmonyPatch("DoAIInterval")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> GiantRoamPatch(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(ForestGiantAIPatch), "LeaveShipPatch", (Type[])null, (Type[])null),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldloc_1, (object)null),
				CodeInstruction.Call(typeof(ForestGiantAIPatch), "ChooseFarNodeFromShip", (Type[])null, (Type[])null),
				new CodeInstruction(OpCodes.Stloc_1, (object)null)
			})
				.InstructionEnumeration();
		}

		public static Vector3 ChooseFarNodeFromShip(ForestGiantAI ai, Vector3 farPosition)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (!FairGiantsMod.RandomWander.Value)
			{
				return farPosition;
			}
			Vector3 ship = StartOfRound.Instance.elevatorTransform.position;
			Vector3 entranceTeleportBPos = FindEntrance();
			Random localRandom = new Random(GetSeed(((Component)ai).transform.position));
			List<(GameObject, float)> source = (from node in ((EnemyAI)ai).allAINodes
				select (node, Vector3.Distance(ship, node.transform.position)) into x
				where x.Item2 >= 102f && Vector3.Distance(entranceTeleportBPos, x.node.transform.position) > 50f
				orderby x.Item2 + (float)localRandom.Next(-12, 12) descending
				select x).ToList();
			((EnemyAI)ai).nodesTempArray = source.Select<(GameObject, float), GameObject>(((GameObject node, float) x) => x.node).ToArray();
			if (((EnemyAI)ai).nodesTempArray.Length == 0)
			{
				return farPosition;
			}
			double weight = CalculateWeight(CalculateWeightBase(source.Select<(GameObject, float), float>(((GameObject node, float) x) => x.Item2).ToArray()), ((EnemyAI)ai).nodesTempArray.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(ForestGiantAI ai, Vector3 farPosition, Random localRandom, double weight)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = StartOfRound.Instance.elevatorTransform.position;
			Vector3 result = farPosition;
			for (int i = 1; i < ((EnemyAI)ai).nodesTempArray.Length; i++)
			{
				if (localRandom.NextDouble() < weight)
				{
					break;
				}
				Vector3 position2 = ((EnemyAI)ai).nodesTempArray[i].transform.position;
				if (!((EnemyAI)ai).PathIsIntersectedByLineOfSight(position2, false, false, false))
				{
					((EnemyAI)ai).mostOptimalDistance = Vector3.Distance(position, position2);
					result = position2;
					if (i >= ((EnemyAI)ai).nodesTempArray.Length - 1)
					{
						break;
					}
				}
			}
			return result;
		}

		public static void LeaveShipPatch(ForestGiantAI ai)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (FairGiantsMod.EnhancedAntiCamp.Value)
			{
				FairGiantsMod.ModLogger.LogInfo((object)"Roaming Away");
				if (ai.roamPlanet == null)
				{
					ai.roamPlanet = new AISearchRoutine();
				}
				((EnemyAI)ai).StopSearch(ai.roamPlanet, true);
				ai.roamPlanet.searchWidth = 35f;
			}
		}

		[HarmonyPatch("FinishedCurrentSearchRoutine")]
		[HarmonyPostfix]
		public static void GiantFinishSearch(ForestGiantAI __instance)
		{
			if (FairGiantsMod.EnhancedAntiCamp.Value)
			{
				FairGiantsMod.ModLogger.LogDebug((object)"Giant Finished a Search");
				if (__instance.roamPlanet != null && __instance.roamPlanet.searchWidth < 200f)
				{
					__instance.roamPlanet.searchWidth = 200f;
				}
			}
		}

		[HarmonyPatch("LookForPlayers")]
		[HarmonyPostfix]
		public static void AggroPatch(ForestGiantAI __instance)
		{
			LowerAllAggro(__instance);
		}

		public static void LowerAllAggro(ForestGiantAI ai)
		{
			if (((EnemyAI)ai).currentBehaviourStateIndex != 0 || ShouldApplyStealthDecay())
			{
				for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++)
				{
					ai.playerStealthMeters[i] = Mathf.Clamp(ai.playerStealthMeters[i] - Time.deltaTime * FairGiantsMod.PassiveStealthDecay.Value, 0f, 1f);
				}
			}
		}

		private static bool ShouldApplyStealthDecay()
		{
			if (FairGiantsMod.StealthDecaysWhen.Value != 0)
			{
				if (FairGiantsMod.StealthDecaysWhen.Value == PatchApplyLevel.Solo)
				{
					return StartOfRound.Instance.connectedPlayersAmount <= 0;
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPrefix]
		public static void AdjustGiantSpeed(ForestGiantAI __instance)
		{
			NavMeshAgent agent = ((EnemyAI)__instance).agent;
			agent.speed *= FairGiantsMod.GiantSpeedMultiplier.Value;
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPostfix]
		public static void HandleOwnership(ForestGiantAI __instance)
		{
			if (!((EnemyAI)__instance).isEnemyDead && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && ((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId)
			{
				((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId);
			}
		}

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