Decompiled source of GordionVoidRescue v1.3.1

BepInEx/plugins/GordionVoidRescue/GordionRescue.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("GordionRescue")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GordionRescue")]
[assembly: AssemblyTitle("GordionRescue")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
[BepInPlugin("POTATOH.GordionVoidRescue", "Gordion Void Rescue", "1.3.1")]
public class GordionVoidRescue : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PlayerControllerB), "Update")]
	private static class PlayerUpdatePatch
	{
		private static readonly Dictionary<ulong, float> Cooldowns = new Dictionary<ulong, float>();

		private static readonly Dictionary<ulong, float> LastRescueTime = new Dictionary<ulong, float>();

		private static readonly Dictionary<ulong, int> RescueStreak = new Dictionary<ulong, int>();

		private static void Postfix(PlayerControllerB __instance)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || !__instance.isPlayerControlled || __instance.isPlayerDead || !((NetworkBehaviour)__instance).IsOwner || (OnlyOnGordion.Value && !IsGordionSafe()))
			{
				return;
			}
			ulong actualClientId = __instance.actualClientId;
			float time = Time.time;
			if (Cooldowns.TryGetValue(actualClientId, out var value) && time < value)
			{
				return;
			}
			float y = ((Component)__instance).transform.position.y;
			if (y >= YThreshold.Value)
			{
				return;
			}
			if (AlwaysRescueToShip.Value)
			{
				RescueToShip(__instance, y);
				RescueStreak[actualClientId] = 0;
				LastRescueTime[actualClientId] = time;
				Cooldowns[actualClientId] = time + CooldownSeconds.Value;
				return;
			}
			int num = 1;
			if (LastRescueTime.TryGetValue(actualClientId, out var value2))
			{
				num = ((!(time - value2 <= ShipRescueWindowSeconds.Value)) ? 1 : (((!RescueStreak.TryGetValue(actualClientId, out var value3)) ? 1 : value3) + 1));
			}
			LastRescueTime[actualClientId] = time;
			RescueStreak[actualClientId] = num;
			if (num >= ShipRescueAfterStreak.Value)
			{
				RescueToShip(__instance, y);
				RescueStreak[actualClientId] = 0;
			}
			else
			{
				RescueLift(__instance, y);
			}
			Cooldowns[actualClientId] = time + CooldownSeconds.Value;
		}
	}

	internal static GordionVoidRescue Instance;

	internal static ConfigEntry<float> YThreshold;

	internal static ConfigEntry<float> RescueY;

	internal static ConfigEntry<float> CooldownSeconds;

	internal static ConfigEntry<bool> OnlyOnGordion;

	internal static ConfigEntry<bool> DebugLog;

	internal static ConfigEntry<bool> AlwaysRescueToShip;

	internal static ConfigEntry<int> ShipRescueAfterStreak;

	internal static ConfigEntry<float> ShipRescueWindowSeconds;

	internal static ConfigEntry<float> ShipX;

	internal static ConfigEntry<float> ShipY;

	internal static ConfigEntry<float> ShipZ;

	private void Awake()
	{
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		YThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "YThreshold", -17f, "If player Y goes below this value, they will be rescued.");
		RescueY = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RescueY", 3.5f, "Target Y to move player to (keeps X/Z) for normal rescues (used only when AlwaysRescueToShip=false).");
		CooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CooldownSeconds", 0.5f, "Cooldown between rescues per-player (seconds). Keep small so it can react fast.");
		OnlyOnGordion = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OnlyOnGordion", true, "If true, rescue only works on Company/Gordion.");
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", false, "If true, logs rescues.");
		AlwaysRescueToShip = ((BaseUnityPlugin)this).Config.Bind<bool>("ShipRescue", "AlwaysRescueToShip", true, "If true (default), any rescue immediately teleports you to ship coords. If false, uses lift+streak logic.");
		ShipRescueAfterStreak = ((BaseUnityPlugin)this).Config.Bind<int>("ShipRescue", "ShipRescueAfterStreak", 3, "If rescues happen this many times within ShipRescueWindowSeconds, teleport to ship coords (when AlwaysRescueToShip=false).");
		ShipRescueWindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("ShipRescue", "ShipRescueWindowSeconds", 2f, "Time window for the rescue streak check (when AlwaysRescueToShip=false).");
		ShipX = ((BaseUnityPlugin)this).Config.Bind<float>("ShipRescue", "ShipX", -8f, "Ship teleport X (Gordion).");
		ShipY = ((BaseUnityPlugin)this).Config.Bind<float>("ShipRescue", "ShipY", 0f, "Ship teleport Y (Gordion).");
		ShipZ = ((BaseUnityPlugin)this).Config.Bind<float>("ShipRescue", "ShipZ", -14f, "Ship teleport Z (Gordion).");
		new Harmony("POTATOH.GordionVoidRescue").PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)($"GVR 1.3.1 loaded. YThreshold={YThreshold.Value}, OnlyOnGordion={OnlyOnGordion.Value}, " + $"AlwaysRescueToShip={AlwaysRescueToShip.Value}, ShipPos=({ShipX.Value},{ShipY.Value},{ShipZ.Value})"));
	}

	internal static bool IsGordionSafe()
	{
		SelectableLevel val = StartOfRound.Instance?.currentLevel;
		if ((Object)(object)val == (Object)null)
		{
			return true;
		}
		string text = (val.PlanetName ?? "").ToLowerInvariant();
		if (!text.Contains("gordion"))
		{
			return text.Contains("company");
		}
		return true;
	}

	internal static Vector3 GetShipPosFallback()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(ShipX.Value, ShipY.Value, ShipZ.Value);
	}

	internal static void RescueLift(PlayerControllerB p, float fromY)
	{
		//IL_0006: 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)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)p).transform.position;
		position.y = RescueY.Value;
		HardMoveAndWake(p, position);
		if (DebugLog.Value && (Object)(object)Instance != (Object)null)
		{
			ManualLogSource logger = ((BaseUnityPlugin)Instance).Logger;
			object[] obj = new object[4] { p.playerUsername, fromY, position.y, null };
			Scene activeScene = SceneManager.GetActiveScene();
			obj[3] = ((Scene)(ref activeScene)).name;
			logger.LogInfo((object)string.Format("[RescueLift] {0} y={1:F1} -> {2:F1} scene={3}", obj));
		}
	}

	internal static void RescueToShip(PlayerControllerB p, float fromY)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		Vector3 shipPosFallback = GetShipPosFallback();
		p.isInsideFactory = false;
		p.isInHangarShipRoom = true;
		try
		{
			p.TeleportPlayer(shipPosFallback, true, 0f, false, true);
		}
		catch
		{
		}
		HardMoveAndWake(p, shipPosFallback);
		if (DebugLog.Value && (Object)(object)Instance != (Object)null)
		{
			ManualLogSource logger = ((BaseUnityPlugin)Instance).Logger;
			object[] obj2 = new object[6] { p.playerUsername, fromY, shipPosFallback.x, shipPosFallback.y, shipPosFallback.z, null };
			Scene activeScene = SceneManager.GetActiveScene();
			obj2[5] = ((Scene)(ref activeScene)).name;
			logger.LogInfo((object)string.Format("[RescueShip] {0} y={1:F1} -> ship({2:F1},{3:F1},{4:F1}) scene={5}", obj2));
		}
	}

	internal static void HardMoveAndWake(PlayerControllerB p, Vector3 pos)
	{
		//IL_000c: 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_006a: 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_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		p.averageVelocity = 0f;
		p.velocityLastFrame = Vector3.zero;
		if ((Object)(object)p.thisController != (Object)null)
		{
			((Collider)p.thisController).enabled = false;
			((Component)p).transform.position = pos;
			((Collider)p.thisController).enabled = true;
			p.thisController.Move(Vector3.down * 0.2f);
		}
		else
		{
			((Component)p).transform.position = pos;
		}
	}
}