Decompiled source of EnemyVariety v0.2.1

EnemyVariety.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Local.Enemy.Variety
{
	[BepInPlugin("local.enemy.variety", "EnemyVariety", "0.2.1")]
	internal class Plugin : BaseUnityPlugin
	{
		public const string version = "0.2.1";

		public const string identifier = "local.enemy.variety";

		private static ConfigEntry<bool> boss;

		private static ConfigEntry<float> horde;

		protected async void Awake()
		{
			Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			boss = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Apply to Teleporter Boss", true, "If enabled, multiple types of bosses may appear for the teleporter event.");
			horde = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Horde of Many", 5f, new ConfigDescription("Percent chance for a different type of enemy to be chosen instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			CombatDirector[] componentsInChildren = (await Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC2/ShrineHalcyonite.prefab").Task).GetComponentsInChildren<CombatDirector>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].resetMonsterCardIfFailed = false;
			}
		}

		[HarmonyPatch(typeof(CombatDirector), "AttemptSpawnOnTarget")]
		[HarmonyPrefix]
		private static void ResetMonsterCard(CombatDirector __instance, ref bool __state)
		{
			//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_003a: 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)
			ref DirectorCard currentMonsterCard = ref __instance.currentMonsterCard;
			WeightedSelection<DirectorCard> finalMonsterCardsSelection = __instance.finalMonsterCardsSelection;
			__state = false;
			if (!__instance.resetMonsterCardIfFailed || currentMonsterCard == null || finalMonsterCardsSelection == null)
			{
				return;
			}
			ChoiceInfo<DirectorCard>[] choices = finalMonsterCardsSelection.choices;
			for (int i = 0; i < choices.Length; i++)
			{
				ChoiceInfo<DirectorCard> val = choices[i];
				if (!object.Equals(currentMonsterCard, val.value) || val.weight <= 0f || currentMonsterCard.cost <= 0)
				{
					continue;
				}
				int spawnCountInCurrentWave = __instance.spawnCountInCurrentWave;
				int cost = currentMonsterCard.cost;
				Xoroshiro128Plus rng = __instance.rng;
				do
				{
					if ((Object)(object)__instance == (Object)(object)TeleporterInteraction.instance?.bossDirector)
					{
						if (!boss.Value)
						{
							break;
						}
						__instance.SetNextSpawnAsBoss();
						__state = spawnCountInCurrentWave == 0 || (float)currentMonsterCard.cost <= __instance.monsterCredit;
					}
					else
					{
						float num = Mathf.Min(800f, __instance.monsterCredit);
						do
						{
							currentMonsterCard = finalMonsterCardsSelection.Evaluate(rng.nextNormalizedFloat);
						}
						while ((float)currentMonsterCard.cost < rng.nextNormalizedFloat * num);
						__instance.PrepareNewMonsterWave(currentMonsterCard);
					}
				}
				while (currentMonsterCard.cost > cost && (float)currentMonsterCard.cost > __instance.monsterCredit);
				__instance.spawnCountInCurrentWave = spawnCountInCurrentWave;
				break;
			}
		}

		[HarmonyPatch(typeof(CombatDirector), "AttemptSpawnOnTarget")]
		[HarmonyPostfix]
		private static void RetryIfNodePlacementFailed(bool __state, ref bool __result)
		{
			__result |= __state;
		}

		[HarmonyPatch(typeof(ChargingState), "OnEnter")]
		[HarmonyPostfix]
		private static void SummonTheHorde(ChargingState __instance)
		{
			//IL_004e: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			CombatDirector bossDirector = __instance.bossDirector;
			if (!Object.op_Implicit((Object)(object)bossDirector))
			{
				return;
			}
			WeightedSelection<DirectorCard> finalMonsterCardsSelection = bossDirector.finalMonsterCardsSelection;
			if (finalMonsterCardsSelection == null || bossDirector.rng.nextNormalizedFloat >= horde.Value / 100f)
			{
				return;
			}
			WeightedSelection<DirectorCard> val = new WeightedSelection<DirectorCard>(8);
			for (int i = 0; i < finalMonsterCardsSelection.Count; i++)
			{
				ChoiceInfo<DirectorCard> choice = finalMonsterCardsSelection.GetChoice(i);
				DirectorCard value = choice.value;
				if (value.IsAvailable() && !value.spawnCard.prefab.GetComponent<CharacterMaster>().bodyPrefab.GetComponent<CharacterBody>().isChampion)
				{
					val.AddChoice(choice);
				}
			}
			if (val.totalWeight > 0f && val.Count > 0)
			{
				bossDirector.currentMonsterCard = null;
				bossDirector.monsterCardsSelection = val;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Chat), "SendBroadcastChat", new Type[] { typeof(ChatMessageBase) })]
		private static void ChangeMessage(ChatMessageBase message)
		{
			SubjectFormatChatMessage val = (SubjectFormatChatMessage)(object)((message is SubjectFormatChatMessage) ? message : null);
			if (val != null)
			{
				bool? flag = val.paramTokens?.Any();
				if (flag.HasValue && flag.GetValueOrDefault() && ((SubjectChatMessage)val).baseToken == "SHRINE_COMBAT_USE_MESSAGE")
				{
					val.paramTokens[0] = Language.GetString("LOGBOOK_CATEGORY_MONSTER").ToLower();
				}
			}
		}

		[HarmonyPatch(typeof(BossGroup), "UpdateBossMemories")]
		[HarmonyPostfix]
		private static void UpdateTitle(BossGroup __instance)
		{
			if (!boss.Value)
			{
				return;
			}
			Dictionary<(string, string), float> dictionary = new Dictionary<(string, string), float>();
			float num = 0f;
			for (int i = 0; i < __instance.bossMemoryCount; i++)
			{
				CharacterBody cachedBody = __instance.bossMemories[i].cachedBody;
				if (!Object.op_Implicit((Object)(object)cachedBody))
				{
					continue;
				}
				HealthComponent healthComponent = cachedBody.healthComponent;
				if (!(((healthComponent != null) ? new bool?(healthComponent.alive) : null) ?? true))
				{
					continue;
				}
				string bestBodyName = Util.GetBestBodyName(((Component)cachedBody).gameObject);
				string text = cachedBody.GetSubtitle();
				(string, string) key = (bestBodyName, text);
				if (!dictionary.ContainsKey(key))
				{
					dictionary[key] = 0f;
				}
				dictionary[key] += healthComponent.combinedHealth + healthComponent.missingCombinedHealth * 4f;
				if (dictionary[key] > num)
				{
					num = dictionary[key];
					if (string.IsNullOrEmpty(text))
					{
						text = Language.GetString("NULL_SUBTITLE");
					}
					__instance.bestObservedName = bestBodyName;
					__instance.bestObservedSubtitle = "<sprite name=\"CloudLeft\" tint=1> " + text + " <sprite name=\"CloudRight\" tint=1>";
				}
			}
		}

		[HarmonyPatch(typeof(CombatDirector), "SpendAllCreditsOnMapSpawns")]
		[HarmonyPrefix]
		private static void PopulateScene(CombatDirector __instance, ref bool __state)
		{
			__state = __instance.resetMonsterCardIfFailed;
			if (SceneCatalog.mostRecentSceneDef.stageOrder > Run.stagesPerLoop)
			{
				__instance.resetMonsterCardIfFailed = false;
			}
		}

		[HarmonyPatch(typeof(CombatDirector), "SpendAllCreditsOnMapSpawns")]
		[HarmonyPostfix]
		private static void RestoreValue(CombatDirector __instance, bool __state)
		{
			__instance.resetMonsterCardIfFailed = __state;
		}
	}
}