Decompiled source of LastStand v1.0.3

RepoLastStandMod.dll

Decompiled 2 months 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.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using RepoLastStandMod.Utility;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RepoLastStandMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RepoLastStandMod")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3c62d521-f165-4e05-bf57-5cde43a5541d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[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 RepoLastStandMod
{
	internal record Prefab(string Name, string Path)
	{
		internal GameObject GameObject => Resources.Load<GameObject>(Path);

		[CompilerGenerated]
		protected virtual bool PrintMembers(StringBuilder builder)
		{
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("Name = ");
			builder.Append((object?)Name);
			builder.Append(", Path = ");
			builder.Append((object?)Path);
			return true;
		}
	}
	internal class StateManager
	{
		internal bool LastStandActive;

		internal IEnumerable<ProbabilityItem<Prefab>> PityWeapons;

		internal static StateManager Instance { get; } = new StateManager();

	}
	[BepInPlugin("umbreon222.repo.laststand", "Repo Last Stand Mod", "1.0.0")]
	public class RepoLastStandMod : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <BuildPityWeapons>d__7 : IEnumerable<ProbabilityItem<Prefab>>, IEnumerable, IEnumerator<ProbabilityItem<Prefab>>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private ProbabilityItem<Prefab> <>2__current;

			private int <>l__initialThreadId;

			public RepoLastStandMod <>4__this;

			private ConfigEntry<float> <pistolProbability>5__1;

			private ConfigEntry<float> <tranquilizerProbability>5__2;

			private ConfigEntry<float> <ductTapedGrenadeProbability>5__3;

			private ConfigEntry<float> <grenadeProbability>5__4;

			private ConfigEntry<float> <shotgunProbability>5__5;

			private ConfigEntry<float> <baseballBatProbability>5__6;

			private ConfigEntry<float> <fryingPanProbability>5__7;

			private ConfigEntry<float> <inflatableHammerProbability>5__8;

			private ConfigEntry<float> <sledgeHammerProbability>5__9;

			private ConfigEntry<float> <swordProbability>5__10;

			private ConfigEntry<float> <explosiveMineProbability>5__11;

			private ConfigEntry<float> <rubberDuckProbability>5__12;

			private ConfigEntry<float> <clownBombProbability>5__13;

			ProbabilityItem<Prefab> IEnumerator<ProbabilityItem<Prefab>>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <BuildPityWeapons>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<pistolProbability>5__1 = null;
				<tranquilizerProbability>5__2 = null;
				<ductTapedGrenadeProbability>5__3 = null;
				<grenadeProbability>5__4 = null;
				<shotgunProbability>5__5 = null;
				<baseballBatProbability>5__6 = null;
				<fryingPanProbability>5__7 = null;
				<inflatableHammerProbability>5__8 = null;
				<sledgeHammerProbability>5__9 = null;
				<swordProbability>5__10 = null;
				<explosiveMineProbability>5__11 = null;
				<rubberDuckProbability>5__12 = null;
				<clownBombProbability>5__13 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<pistolProbability>5__1 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "HandgunProbability", 0.15f, "Probability between 0 and 1 of spawning a handgun");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Handgun", "items/Item Gun Handgun"), <pistolProbability>5__1.Value);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<tranquilizerProbability>5__2 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "TranqGunProbability", 0.3f, "Probability between 0 and 1 of spawning a tranq gun");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Tranq Gun", "items/Item Gun Tranq"), <tranquilizerProbability>5__2.Value);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<ductTapedGrenadeProbability>5__3 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "DuctTapedGrenadeProbability", 0.4f, "Probability between 0 and 1 of spawning a duct taped grenade");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Duct Taped Grenade", "items/Item Grenade Duct Taped"), <ductTapedGrenadeProbability>5__3.Value);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<grenadeProbability>5__4 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "GrenadeProbability", 0.5f, "Probability between 0 and 1 of spawning a grenade");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Grenade", "items/Item Grenade Explosive"), <grenadeProbability>5__4.Value);
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<shotgunProbability>5__5 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "ShotgunProbability", 0.05f, "Probability between 0 and 1 of spawning a shotgun");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Shotgun", "items/Item Gun Shotgun"), <shotgunProbability>5__5.Value);
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					<baseballBatProbability>5__6 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "BaseballBatProbability", 0.5f, "Probability between 0 and 1 of spawning a baseball bat");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Baseball Bat", "items/Item Melee Baseball Bat"), <baseballBatProbability>5__6.Value);
					<>1__state = 6;
					return true;
				case 6:
					<>1__state = -1;
					<fryingPanProbability>5__7 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "FryingPanProbability", 0.5f, "Probability between 0 and 1 of spawning a frying pan");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Frying Pan", "items/Item Melee Frying Pan"), <fryingPanProbability>5__7.Value);
					<>1__state = 7;
					return true;
				case 7:
					<>1__state = -1;
					<inflatableHammerProbability>5__8 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "InflatableHammerProbability", 0.4f, "Probability between 0 and 1 of spawning an inflatable hammer");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Inflatable Hammer", "items/Item Melee Inflatable Hammer"), <inflatableHammerProbability>5__8.Value);
					<>1__state = 8;
					return true;
				case 8:
					<>1__state = -1;
					<sledgeHammerProbability>5__9 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "SledgeHammerProbability", 0.3f, "Probability between 0 and 1 of spawning a sledge hammer");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Sledge Hammer", "items/Item Melee Sledge Hammer"), <sledgeHammerProbability>5__9.Value);
					<>1__state = 9;
					return true;
				case 9:
					<>1__state = -1;
					<swordProbability>5__10 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "SwordProbability", 0.3f, "Probability between 0 and 1 of spawning a sword");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Sword", "items/Item Melee Sword"), <swordProbability>5__10.Value);
					<>1__state = 10;
					return true;
				case 10:
					<>1__state = -1;
					<explosiveMineProbability>5__11 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "ExplosiveMineProbability", 0.5f, "Probability between 0 and 1 of spawning an explosive mine");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Mine", "items/Item Mine Explosive"), <explosiveMineProbability>5__11.Value);
					<>1__state = 11;
					return true;
				case 11:
					<>1__state = -1;
					<rubberDuckProbability>5__12 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "RubberDuckProbability", 0.01f, "Probability between 0 and 1 of spawning a rubber duck");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Rubber Duck", "items/Item Rubber Duck"), <rubberDuckProbability>5__12.Value);
					<>1__state = 12;
					return true;
				case 12:
					<>1__state = -1;
					<clownBombProbability>5__13 = ((BaseUnityPlugin)<>4__this).Config.Bind<float>("General", "ValuableClownProbability", 0.1f, "Probability between 0 and 1 of spawning a valuable clown");
					<>2__current = new ProbabilityItem<Prefab>(new Prefab("Valuable Clown", "valuables/03 medium/Valuable Clown"), <clownBombProbability>5__13.Value);
					<>1__state = 13;
					return true;
				case 13:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<ProbabilityItem<Prefab>> IEnumerable<ProbabilityItem<Prefab>>.GetEnumerator()
			{
				<BuildPityWeapons>d__7 result;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					result = this;
				}
				else
				{
					result = new <BuildPityWeapons>d__7(0)
					{
						<>4__this = <>4__this
					};
				}
				return result;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<ProbabilityItem<Prefab>>)this).GetEnumerator();
			}
		}

		private const string pluginGuid = "umbreon222.repo.laststand";

		private const string pluginName = "Repo Last Stand Mod";

		private const string pluginVersion = "1.0.0";

		internal static ManualLogSource LoggerInstance;

		private readonly Harmony _harmony = new Harmony("umbreon222.repo.laststand");

		public void Awake()
		{
			LoggerInstance = ((BaseUnityPlugin)this).Logger;
			InitializeState();
			_harmony.PatchAll();
			LoggerInstance.LogInfo((object)"Repo Last Stand Mod has loaded!");
		}

		private void InitializeState()
		{
			StateManager.Instance.LastStandActive = false;
			StateManager instance = StateManager.Instance;
			List<ProbabilityItem<Prefab>> list = new List<ProbabilityItem<Prefab>>();
			list.AddRange(BuildPityWeapons());
			instance.PityWeapons = new <>z__ReadOnlyList<ProbabilityItem<Prefab>>(list);
		}

		[IteratorStateMachine(typeof(<BuildPityWeapons>d__7))]
		private IEnumerable<ProbabilityItem<Prefab>> BuildPityWeapons()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BuildPityWeapons>d__7(-2)
			{
				<>4__this = this
			};
		}
	}
}
namespace RepoLastStandMod.Patches
{
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector))]
	public static class PhysGrabObjectImpactDetectorPatches
	{
		[HarmonyPatch("BreakRPC")]
		[HarmonyPostfix]
		public static void BreakRPCPostfix()
		{
			if (SemiFunc.RunIsLevel())
			{
				AfterValuableObjectBreak();
			}
		}

		private static void AfterValuableObjectBreak()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			int internalHaulGoal = RoundDirector.instance.GetInternalHaulGoal();
			int num = internalHaulGoal / RoundDirector.instance.GetInternalExtractionPoints();
			int num2 = RoundDirector.instance.GetInternalExtractionPointsCompleted() * num;
			float levelValuablesValue = GetLevelValuablesValue();
			float num3 = levelValuablesValue + (float)num2;
			bool flag = num3 >= (float)internalHaulGoal;
			RepoLastStandMod.LoggerInstance.LogInfo((object)$"Can still extract: {flag}");
			if (flag || StateManager.Instance.LastStandActive)
			{
				RepoLastStandMod.LoggerInstance.LogDebug((object)"Round is still completable or last stand is already active");
				return;
			}
			StateManager.Instance.LastStandActive = true;
			RepoLastStandMod.LoggerInstance.LogInfo((object)"Last stand activated!");
			SemiFunc.UIBigMessage("LAST STAND ACTIVATED", "{!}", 25f, Color.red, Color.red);
			SemiFunc.UIFocusText("Not enough loot to complete the level! Take your last stand!", Color.red, Color.red, 3f);
			Prefab prefab = ProbabilitySelector.SelectRandomItem(StateManager.Instance.PityWeapons);
			if ((object)prefab == null)
			{
				RepoLastStandMod.LoggerInstance.LogError((object)"Couldn't randomly select a pity weapon. Are probabilities all 0?");
				return;
			}
			RepoLastStandMod.LoggerInstance.LogInfo((object)("Rolled a \"" + prefab.Name + "\" as a pity weapon; Spawning..."));
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				RepoLastStandMod.LoggerInstance.LogError((object)("Failed to spawn \"" + prefab.Name + "\". You are not the host."));
				return;
			}
			Vector3 val = ((Component)PlayerController.instance).transform.position + ((Component)PlayerController.instance).transform.up + ((Component)PlayerController.instance).transform.forward;
			if (SemiFunc.IsMultiplayer())
			{
				PhotonNetwork.InstantiateRoomObject(prefab.Path, val, ((Component)PlayerController.instance).transform.rotation, (byte)0, (object[])null);
			}
			else
			{
				Object.Instantiate<GameObject>(prefab.GameObject, val, ((Component)PlayerController.instance).transform.rotation);
			}
			GameDirector.instance.CameraImpact.ShakeDistance(3f, 3f, 8f, val, 0.1f);
			GameDirector.instance.CameraShake.ShakeDistance(3f, 3f, 8f, val, 0.1f);
		}

		private static float GetLevelValuablesValue()
		{
			return Object.FindObjectsOfType<ValuableObject>().Aggregate(0f, (float sum, ValuableObject valuable) => sum + valuable.dollarValueCurrent);
		}
	}
	[HarmonyPatch(typeof(RoundDirector))]
	public static class RoundDirectorPatches
	{
		[HarmonyPatch("StartRoundLogic")]
		[HarmonyPrefix]
		public static void StartRoundLogicPrefix(int value)
		{
			StateManager.Instance.LastStandActive = false;
		}
	}
}
namespace RepoLastStandMod.Utility
{
	internal record ProbabilityItem<T>(T Item, double Probability);
	internal static class ProbabilitySelector
	{
		private static readonly Random _random = new Random();

		public static T SelectRandomItem<T>(IEnumerable<ProbabilityItem<T>> items)
		{
			if (items == null || !items.Any())
			{
				return default(T);
			}
			double num = items.Sum((ProbabilityItem<T> i) => i.Probability);
			if (num <= 0.0)
			{
				return default(T);
			}
			double num2 = _random.NextDouble() * num;
			double num3 = 0.0;
			foreach (ProbabilityItem<T> item in items)
			{
				num3 += item.Probability;
				if (num2 <= num3)
				{
					return item.Item;
				}
			}
			return items.Last().Item;
		}
	}
	internal static class Extensions
	{
		public static int GetInternalHaulGoal(this RoundDirector roundDirector)
		{
			FieldInfo field = typeof(RoundDirector).GetField("haulGoal", BindingFlags.Instance | BindingFlags.NonPublic);
			return (int)field.GetValue(roundDirector);
		}

		public static int GetInternalExtractionPoints(this RoundDirector roundDirector)
		{
			FieldInfo field = typeof(RoundDirector).GetField("extractionPoints", BindingFlags.Instance | BindingFlags.NonPublic);
			return (int)field.GetValue(roundDirector);
		}

		public static int GetInternalExtractionPointsCompleted(this RoundDirector roundDirector)
		{
			FieldInfo field = typeof(RoundDirector).GetField("extractionPointsCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
			return (int)field.GetValue(roundDirector);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	internal static class IsExternalInit
	{
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlyList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Count;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Count;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Count;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyList(List<T> items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return _items.Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		_items.CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return _items.IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}