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;
}
}
}