Decompiled source of Ascent8 v1.0.1

BepInEx/plugins/Ascent8/Ascent8.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Ascent8")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Ascent8")]
[assembly: AssemblyTitle("Ascent8")]
[assembly: AssemblyVersion("1.0.0.0")]
[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.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;
		}
	}
	[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 Ascent8
{
	[BepInPlugin("com.shuhia.peak.ascent8", "Ascent 8", "1.0.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(BoardingPass), "UpdateAscent")]
		private static class BoardingPassUpdateAscentPatch
		{
			private static void Prefix(BoardingPass __instance)
			{
				object? value = BoardingPassAscentDataField.GetValue(__instance);
				AscentData val = (AscentData)((value is AscentData) ? value : null);
				if (val != null)
				{
					Instance?.EnsureAscentEntry(val);
				}
				else
				{
					Instance?.EnsureAscentEntry();
				}
				if (!RunSettings.IsCustomRun)
				{
					BoardingPassMaxAscentField.SetValue(__instance, 8);
					int boardingPassAscentIndex = GetBoardingPassAscentIndex(__instance);
					if (boardingPassAscentIndex > 8)
					{
						SetBoardingPassAscentIndex(__instance, 8);
					}
					else if (boardingPassAscentIndex < -1)
					{
						SetBoardingPassAscentIndex(__instance, -1);
					}
				}
			}
		}

		[HarmonyPatch(typeof(AchievementManager), "GetMaxAscent")]
		private static class AchievementManagerGetMaxAscentPatch
		{
			private static void Postfix(ref int __result)
			{
				__result = 8;
			}
		}

		[HarmonyPatch(typeof(AchievementManager), "SetSteamStat")]
		private static class AchievementManagerSetSteamStatPatch
		{
			private static void Prefix(STEAMSTATTYPE steamStatType, ref int value)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: Invalid comparison between Unknown and I4
				if ((int)steamStatType == 13 && value > 8)
				{
					value = 8;
				}
			}
		}

		[HarmonyPatch(typeof(BoardingPass), "StartGame")]
		private static class BoardingPassStartGamePatch
		{
			private static bool Prefix(BoardingPass __instance)
			{
				Instance?.EnsureAscentEntry();
				Instance?.AdvertiseSupport(force: true);
				if (RunSettings.IsCustomRun || GetBoardingPassAscentIndex(__instance) != 8)
				{
					return true;
				}
				if (Instance == null || Instance.AreAllPlayersCompatible(out string missingPlayers))
				{
					return true;
				}
				Instance.ShowCompatibilityWarning(missingPlayers);
				return false;
			}
		}

		[HarmonyPatch(typeof(AscentUI), "Start")]
		private static class AscentUiStartPatch
		{
			private static void Prefix()
			{
				Instance?.EnsureAscentEntry();
			}

			private static void Postfix(AscentUI __instance)
			{
				if (IsAscent8Active())
				{
					object? value = AscentUiTextField.GetValue(__instance);
					TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
					if (val != null)
					{
						val.text = "ASCENT 8";
					}
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_fallDamageMultiplier")]
		private static class FallDamagePatch
		{
			private static void Postfix(ref float __result)
			{
				if (IsAscent8Active())
				{
					__result = 3f;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_etcDamageMultiplier")]
		private static class EtcDamagePatch
		{
			private static void Postfix(ref float __result)
			{
				if (IsAscent8Active())
				{
					__result = 2.5f;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_hungerRateMultiplier")]
		private static class HungerPatch
		{
			private static void Postfix(ref float __result)
			{
				if (IsAscent8Active())
				{
					__result = 2f;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_itemWeightModifier")]
		private static class ItemWeightPatch
		{
			private static void Postfix(ref int __result)
			{
				if (IsAscent8Active())
				{
					__result = 2;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_shouldSpawnFlare")]
		private static class SpawnFlarePatch
		{
			private static void Postfix(ref bool __result)
			{
				if (IsAscent8Active())
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_isNightCold")]
		private static class NightColdPatch
		{
			private static void Postfix(ref bool __result)
			{
				if (IsAscent8Active())
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_canReviveDead")]
		private static class ReviveDeadPatch
		{
			private static void Postfix(ref bool __result)
			{
				if (IsAscent8Active())
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Ascents), "get_climbStaminaMultiplier")]
		private static class ClimbStaminaPatch
		{
			private static void Postfix(ref float __result)
			{
				if (IsAscent8Active())
				{
					__result = 1.8f;
				}
			}
		}

		[HarmonyPatch]
		private static class AscentEntryLocalizedTitlePatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(AscentInstanceType, "get_localizedTitle", (Type[])null, (Type[])null);
			}

			private static void Postfix(object __instance, ref string __result)
			{
				if (IsAscent8Entry(__instance))
				{
					__result = "ASCENT 8";
				}
			}
		}

		[HarmonyPatch]
		private static class AscentEntryLocalizedDescriptionPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(AscentInstanceType, "get_localizedDescription", (Type[])null, (Type[])null);
			}

			private static void Postfix(object __instance, ref string __result)
			{
				if (IsAscent8Entry(__instance))
				{
					__result = "3x fall damage. 2.5x other damage. 2x hunger. +2 item weight. 1.8x climb stamina. No flares. Night cold. No revives.";
				}
			}
		}

		[HarmonyPatch]
		private static class AscentEntryLocalizedRewardPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(AscentInstanceType, "get_localizedReward", (Type[])null, (Type[])null);
			}

			private static void Postfix(object __instance, ref string __result)
			{
				if (IsAscent8Entry(__instance))
				{
					__result = string.Empty;
				}
			}
		}

		public const string PluginGuid = "com.shuhia.peak.ascent8";

		public const string PluginName = "Ascent 8";

		public const string PluginVersion = "1.0.1";

		private const int Ascent8Index = 8;

		private const string Ascent8EntryKey = "SHUHIA_ASCENT_8";

		private const string Ascent8Title = "ASCENT 8";

		private const string Ascent8Description = "3x fall damage. 2.5x other damage. 2x hunger. +2 item weight. 1.8x climb stamina. No flares. Night cold. No revives.";

		private const string SupportPropertyKey = "Shuhia_Ascent8Support";

		private const int SupportPropertyValue = 1;

		private const float FallDamageMultiplier = 3f;

		private const float EtcDamageMultiplier = 2.5f;

		private const float HungerRateMultiplier = 2f;

		private const int ItemWeightModifier = 2;

		private const float ClimbStaminaMultiplier = 1.8f;

		private static readonly Harmony Harmony = new Harmony("com.shuhia.peak.ascent8");

		private static readonly FieldInfo AscentDataAscentsField = AccessTools.Field(typeof(AscentData), "ascents");

		private static readonly Type AscentInstanceType = AccessTools.Inner(typeof(AscentData), "AscentInstanceData");

		private static readonly FieldInfo AscentTitleField = AccessTools.Field(AscentInstanceType, "title");

		private static readonly FieldInfo AscentRewardTitleField = AccessTools.Field(AscentInstanceType, "titleReward");

		private static readonly FieldInfo AscentDescriptionField = AccessTools.Field(AscentInstanceType, "description");

		private static readonly FieldInfo AscentColorField = AccessTools.Field(AscentInstanceType, "color");

		private static readonly FieldInfo AscentSashSpriteField = AccessTools.Field(AscentInstanceType, "sashSprite");

		private static readonly FieldInfo BoardingPassAscentIndexField = AccessTools.Field(typeof(BoardingPass), "_ascentIndex");

		private static readonly FieldInfo BoardingPassAscentDataField = AccessTools.Field(typeof(BoardingPass), "ascentData");

		private static readonly FieldInfo BoardingPassMaxAscentField = AccessTools.Field(typeof(BoardingPass), "maxAscent");

		private static readonly FieldInfo AscentUiTextField = AccessTools.Field(typeof(AscentUI), "text");

		private object? _ascent8Entry;

		private AscentData? _ascentData;

		private float _lastAdvertiseAttempt;

		private bool _loggedEntryAppend;

		internal static Plugin? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Harmony.PatchAll(typeof(Plugin));
			EnsureAscentEntry();
			AdvertiseSupport(force: true);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ascent 8 loaded.");
		}

		private void OnDestroy()
		{
			Harmony.UnpatchSelf();
			if (Instance == this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			EnsureAscentEntry();
			AdvertiseSupport(force: false);
		}

		internal void EnsureAscentEntry()
		{
			EnsureAscentEntry(TryGetAscentData());
		}

		internal void EnsureAscentEntry(AscentData? ascentData)
		{
			if (ascentData == null || !(AscentDataAscentsField.GetValue(ascentData) is IList list))
			{
				return;
			}
			if ((Object)(object)_ascentData != (Object)(object)ascentData)
			{
				_ascentData = ascentData;
				_ascent8Entry = null;
			}
			object obj = FindExistingAscent8Entry(list);
			if (obj != null)
			{
				int num = list.IndexOf(obj);
				int num2 = list.Count - 1;
				if (num != num2)
				{
					list.RemoveAt(num);
					list.Add(obj);
				}
				_ascent8Entry = obj;
			}
			else if (list.Count != 0)
			{
				object obj2 = list[list.Count - 1];
				object obj3 = Activator.CreateInstance(AscentInstanceType);
				AscentTitleField.SetValue(obj3, "SHUHIA_ASCENT_8");
				AscentRewardTitleField.SetValue(obj3, string.Empty);
				AscentDescriptionField.SetValue(obj3, "3x fall damage. 2.5x other damage. 2x hunger. +2 item weight. 1.8x climb stamina. No flares. Night cold. No revives.");
				AscentColorField.SetValue(obj3, AscentColorField.GetValue(obj2));
				AscentSashSpriteField.SetValue(obj3, AscentSashSpriteField.GetValue(obj2));
				list.Add(obj3);
				_ascent8Entry = obj3;
				if (!_loggedEntryAppend)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Appended Ascent 8 entry to ascent data. Total entries: {list.Count}.");
					_loggedEntryAppend = true;
				}
			}
		}

		private static object? FindExistingAscent8Entry(IList ascentEntries)
		{
			foreach (object ascentEntry in ascentEntries)
			{
				if (IsAscent8Entry(ascentEntry))
				{
					return ascentEntry;
				}
			}
			return null;
		}

		private AscentData? TryGetAscentData()
		{
			try
			{
				AscentData instance = SingletonAsset<AscentData>.Instance;
				if (instance != null)
				{
					return instance;
				}
			}
			catch
			{
			}
			return Resources.FindObjectsOfTypeAll<AscentData>().FirstOrDefault();
		}

		private void AdvertiseSupport(bool force)
		{
			//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)
			//IL_006e: Expected O, but got Unknown
			//IL_0075: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null && (force || !(Time.unscaledTime - _lastAdvertiseAttempt < 1f)))
			{
				_lastAdvertiseAttempt = Time.unscaledTime;
				if (!((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Shuhia_Ascent8Support", out object value) || ConvertToInt(value) != 1)
				{
					Player localPlayer = PhotonNetwork.LocalPlayer;
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"Shuhia_Ascent8Support", (object)1);
					localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				}
			}
		}

		private static bool IsAscent8Active()
		{
			if (!RunSettings.IsCustomRun)
			{
				return Ascents.currentAscent == 8;
			}
			return false;
		}

		private bool AreAllPlayersCompatible(out string missingPlayers)
		{
			if (!PhotonNetwork.InRoom)
			{
				missingPlayers = string.Empty;
				return true;
			}
			List<string> list = new List<string>();
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (!PlayerSupportsAscent8(val))
				{
					string text = val.NickName;
					if (string.IsNullOrWhiteSpace(text))
					{
						text = val.UserId;
					}
					if (string.IsNullOrWhiteSpace(text))
					{
						text = $"Player {val.ActorNumber}";
					}
					list.Add(text);
				}
			}
			missingPlayers = string.Join(", ", list);
			return list.Count == 0;
		}

		private static bool PlayerSupportsAscent8(Player? player)
		{
			if (player != null && player == PhotonNetwork.LocalPlayer)
			{
				return true;
			}
			if (((player != null) ? player.CustomProperties : null) == null)
			{
				return false;
			}
			if (((Dictionary<object, object>)(object)player.CustomProperties).TryGetValue((object)"Shuhia_Ascent8Support", out object value))
			{
				return ConvertToInt(value) == 1;
			}
			return false;
		}

		private void ShowCompatibilityWarning(string missingPlayers)
		{
			string text = "ASCENT 8 REQUIRES ALL PLAYERS TO HAVE THE MOD";
			if (!string.IsNullOrWhiteSpace(missingPlayers))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Blocked Ascent 8 start. Missing support from: " + missingPlayers));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Blocked Ascent 8 start because not all players advertise support.");
			}
			if (GUIManager.instance != null)
			{
				GUIManager.instance.SetHeroTitle(text, (AudioClip)null);
			}
		}

		private static int GetBoardingPassAscentIndex(BoardingPass instance)
		{
			return (int)BoardingPassAscentIndexField.GetValue(instance);
		}

		private static void SetBoardingPassAscentIndex(BoardingPass instance, int value)
		{
			BoardingPassAscentIndexField.SetValue(instance, value);
		}

		private static bool IsAscent8Entry(object? entry)
		{
			if (entry != null)
			{
				return string.Equals(AscentTitleField.GetValue(entry) as string, "SHUHIA_ASCENT_8", StringComparison.Ordinal);
			}
			return false;
		}

		private static int ConvertToInt(object? value)
		{
			if (!(value is byte result))
			{
				if (!(value is short result2))
				{
					if (!(value is int result3))
					{
						if (!(value is long num))
						{
							if (value is bool flag)
							{
								return flag ? 1 : 0;
							}
							return 0;
						}
						return (int)num;
					}
					return result3;
				}
				return result2;
			}
			return result;
		}
	}
}