Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TrialSpawnGuard v0.3.0
BepInEx/plugins/TrialSpawnGuard/TrialSpawnGuard.dll
Decompiled 15 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Artifacts; using RoR2.Quests; using RoR2.Quests.TrialQuests; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; 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("TrialSpawnGuard")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: AssemblyInformationalVersion("0.3.0")] [assembly: AssemblyProduct("TrialSpawnGuard")] [assembly: AssemblyTitle("TrialSpawnGuard")] [assembly: AssemblyVersion("0.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 TrialSpawnGuard { internal static class Localization { [Serializable] private sealed class Translation { public string language; public string[] strings; } [HarmonyPatch(typeof(Language), "GetString", new Type[] { typeof(string) })] private static class LanguagePatch { private static void Postfix([HarmonyArgument(0)] string token, ref string __result) { if (TryGet(token, Language.currentLanguageName, out var value)) { __result = value; } } } [HarmonyPatch(typeof(Language), "GetString", new Type[] { typeof(string), typeof(string) })] private static class ExplicitLanguagePatch { private static void Postfix([HarmonyArgument(0)] string token, [HarmonyArgument(1)] string language, ref string __result) { if (TryGet(token, language, out var value)) { __result = value; } } } [HarmonyPatch(typeof(Language), "TokenIsRegistered", new Type[] { typeof(string) })] private static class TokenValidationPatch { private static void Postfix([HarmonyArgument(0)] string token, ref bool __result) { if (token != null && Tokens.ContainsKey(token)) { __result = true; } } } private static readonly Dictionary<string, string[]> Languages = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, int> Tokens = new Dictionary<string, int>(StringComparer.Ordinal); private static Texture2D iconTexture; private static Sprite iconSprite; internal const string ModNameToken = "RISK_OF_OPTIONS.LOCAL.TRIALSPAWNGUARD.MOD_LIST_BUTTON.NAME"; internal static string Token(int index) { return "TRIAL_SPAWN_GUARD_" + index; } internal static void Initialize() { //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) Assembly assembly = typeof(Localization).Assembly; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (!text.EndsWith(".json", StringComparison.Ordinal)) { continue; } using Stream stream = assembly.GetManifestResourceStream(text); using StreamReader streamReader = new StreamReader(stream); Translation translation = JsonUtility.FromJson<Translation>(streamReader.ReadToEnd()); if (translation == null || translation.strings?.Length != 13 || Array.Exists(translation.strings, string.IsNullOrWhiteSpace)) { throw new InvalidDataException("Incomplete translation: " + text); } Languages.Add(translation.language, translation.strings); } if (!Languages.ContainsKey("en")) { throw new InvalidDataException("English translation missing."); } for (int j = 0; j < 13; j++) { Tokens.Add(Token(j), j); } Tokens.Add("RISK_OF_OPTIONS.LOCAL.TRIALSPAWNGUARD.MOD_LIST_BUTTON.NAME", 0); Tokens.Add("RISK_OF_OPTIONS.local.trialspawnguard.mod_list_button.name".ToUpper(CultureInfo.GetCultureInfo("tr")), 0); ModSettingsManager.SetModDescriptionToken(Token(2), "local.trialspawnguard", "Trial Spawn Guard"); using Stream stream2 = assembly.GetManifestResourceStream("TrialSpawnGuard.icon.png"); using MemoryStream memoryStream = new MemoryStream(); stream2.CopyTo(memoryStream); iconTexture = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(iconTexture, memoryStream.ToArray())) { throw new InvalidDataException("Invalid mod icon."); } iconSprite = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), new Vector2(0.5f, 0.5f)); ModSettingsManager.SetModIcon(iconSprite, "local.trialspawnguard", "Trial Spawn Guard"); } internal static bool TryGet(string token, string language, out string value) { value = null; if (token == null || !Tokens.TryGetValue(token, out var value2)) { return false; } if (!Languages.TryGetValue(language ?? "en", out var value3)) { value3 = Languages["en"]; } value = value3[value2]; return true; } internal static void Dispose() { if (Object.op_Implicit((Object)(object)iconSprite)) { Object.Destroy((Object)(object)iconSprite); } if (Object.op_Implicit((Object)(object)iconTexture)) { Object.Destroy((Object)(object)iconTexture); } } } [HarmonyPatch(typeof(TrialController), "set_NetworkvariantIndex")] internal static class VariantIndexPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(TrialController __instance, int value) { if (value >= 0 && value < __instance.trialVariants.Length) { Plugin.InspectVariant(__instance.trialVariants[value]); } } } [HarmonyPatch(typeof(TrialVariantEventRelay), "OnVariantChosen")] internal static class VariantPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(TrialVariantEventRelay __instance) { Plugin.InspectVariant(__instance); } } [HarmonyPatch(typeof(QuestRunner), "SetNewQuest")] internal static class QuestPatch { private static void Prefix(QuestRunner __instance, BaseQuest newQuest) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (newQuest != null) { Plugin.Activate(((object)newQuest).GetType(), ((Component)__instance).gameObject.scene, "quest scheduled"); } } } [HarmonyPatch] internal static class EnterPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(TrialQuestSurvivorMonstersIntoRifts), "OnEnter", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(TrialQuestSurvivorMonstersOffMap), "OnEnter", (Type[])null, (Type[])null); } private static void Prefix(BaseQuest __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Plugin.Activate(((object)__instance).GetType(), SceneManager.GetActiveScene(), "quest entered"); QuotaSync.Apply(__instance); } } [HarmonyPatch(typeof(CombatDirector), "get_finalMonsterCardsSelection")] internal static class PoolPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CombatDirector __instance, ref WeightedSelection<DirectorCard> __result) { if (SpawnPolicy.Protect(__instance)) { __result = SpawnPolicy.Filter(__result); } } } [HarmonyPatch(typeof(CombatDirector), "PrepareNewMonsterWave")] internal static class WavePatch { private static void Prefix(CombatDirector __instance, ref DirectorCard monsterCard) { if (SpawnPolicy.Protect(__instance)) { monsterCard = SpawnPolicy.SafeDirectorCard(monsterCard); } } private static void Postfix(CombatDirector __instance) { SpawnPolicy.Normalize(__instance, replaceCard: true); } } [HarmonyPatch(typeof(CombatDirector), "ResetEliteType")] internal static class ResetElitePatch { private static void Postfix(CombatDirector __instance) { SpawnPolicy.Normalize(__instance, replaceCard: false); } } [HarmonyPatch(typeof(CombatDirector), "AttemptSpawnOnTarget")] internal static class AttemptPatch { private static void Prefix(CombatDirector __instance) { SpawnPolicy.Normalize(__instance, replaceCard: true); } } [HarmonyPatch(typeof(CombatDirector), "GetNextActiveEliteMultiplier")] internal static class CostPatch { private static bool Prefix(CombatDirector __instance, ref float __result) { if (!SpawnPolicy.Protect(__instance) || !Plugin.SuppressElites) { return true; } __result = 1f; return false; } } [HarmonyPatch(typeof(CombatDirector), "get_mostExpensiveMonsterCostInDeck")] internal static class DeckCostPatch { private static bool Prefix(CombatDirector __instance, ref int __result) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (!SpawnPolicy.Protect(__instance) || !Plugin.SuppressElites) { return true; } WeightedSelection<DirectorCard> val = (WeightedSelection<DirectorCard>)AccessTools.Property(typeof(CombatDirector), "finalMonsterCardsSelection").GetValue(__instance); __result = 1; for (int i = 0; i < val.Count; i++) { __result = Math.Max(__result, val.GetChoice(i).value.cost); } return false; } } [HarmonyPatch(typeof(CombatDirector), "Spawn", new Type[] { typeof(SpawnArgs) })] internal static class DirectorSpawnPatch { private static readonly FieldInfo halcyon = AccessTools.Field(typeof(CombatDirector), "isHalcyonShrineSpawn"); private static void Prefix(CombatDirector __instance, ref SpawnArgs spawnArgs, out bool? __state) { __state = null; if (SpawnPolicy.Protect(__instance)) { spawnArgs.spawnCard = (SpawnCard)(object)SpawnPolicy.SafeCard(spawnArgs.spawnCard); if (Plugin.SuppressElites) { spawnArgs.eliteDef = null; spawnArgs.valueMultiplier = 1f; __state = (bool)halcyon.GetValue(__instance); halcyon.SetValue(__instance, false); } } } private static void Finalizer(CombatDirector __instance, bool? __state) { if (__state.HasValue && Object.op_Implicit((Object)(object)__instance)) { halcyon.SetValue(__instance, __state.Value); } } } [HarmonyPatch(typeof(DirectorCore), "TrySpawnObject")] internal static class RequestPatch { private static void Prefix(DirectorSpawnRequest directorSpawnRequest) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (Plugin.Active && directorSpawnRequest != null && directorSpawnRequest.spawnCard is CharacterSpawnCard && Plugin.Hostile(Plugin.TeamFor(directorSpawnRequest.spawnCard.prefab, directorSpawnRequest.teamIndexOverride, directorSpawnRequest.summonerBodyObject))) { directorSpawnRequest.spawnCard = (SpawnCard)(object)SpawnPolicy.SafeCard(directorSpawnRequest.spawnCard); } } } [HarmonyPatch(typeof(MasterSummon), "Perform")] internal static class SummonPatch { private static void Prefix(MasterSummon __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (Plugin.Active && Plugin.Hostile(Plugin.TeamFor(__instance.masterPrefab, __instance.teamIndexOverride, __instance.summonerBodyObject)) && !SpawnPolicy.Suitable(__instance.masterPrefab)) { Plugin.Trace("SUMMON_REPLACE " + (Object.op_Implicit((Object)(object)__instance.masterPrefab) ? ((Object)__instance.masterPrefab).name : "null")); __instance.masterPrefab = SpawnPolicy.FallbackMaster(); __instance.loadout = null; } } } [HarmonyPatch] internal static class PromotionPatch { private static IEnumerable<MethodBase> TargetMethods() { string[] array = new string[3] { "PromoteIfHonor", "PromoteIfHonorAndApplyStats", "PromoteAndApplyStats" }; foreach (string text in array) { yield return AccessTools.Method(typeof(EliteOnlyArtifactManager), text, (Type[])null, (Type[])null); } } private static bool Prefix(CharacterMaster __0) { if (!Plugin.SuppressElites || !Plugin.Hostile(__0)) { return true; } Plugin.Trace("ELITE_PROMOTION_BLOCKED " + ((Object)__0).name); return false; } } [HarmonyPatch] internal static class EquipmentPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Inventory), "SetEquipmentInternal", new Type[2] { typeof(EquipmentState).MakeByRefType(), typeof(EquipmentLocation).MakeByRefType() }, (Type[])null); } private unsafe static bool Prefix(Inventory __instance, in EquipmentState __0, ref bool __result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) if (!Plugin.SuppressElites || !SpawnPolicy.IsEliteEquipment(__0.equipmentIndex) || !Plugin.Hostile(__instance)) { return true; } EquipmentIndex equipmentIndex = __0.equipmentIndex; Plugin.Trace("ELITE_EQUIPMENT_BLOCKED " + ((object)(*(EquipmentIndex*)(&equipmentIndex))/*cast due to .constrained prefix*/).ToString()); __result = false; return false; } } [HarmonyPatch(typeof(CharacterBody), "SetBuffCount")] internal static class EliteBuffPatch { private static void Prefix(CharacterBody __instance, BuffIndex buffType, ref int newCount) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (Plugin.SuppressElites && newCount > 0 && Object.op_Implicit((Object)(object)__instance.teamComponent) && Plugin.Hostile(__instance.teamComponent.teamIndex) && !__instance.isPlayerControlled) { BuffDef buffDef = BuffCatalog.GetBuffDef(buffType); if (Object.op_Implicit((Object)(object)buffDef) && buffDef.isElite) { newCount = 0; } } } } [BepInPlugin("local.trialspawnguard", "Trial Spawn Guard", "0.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "local.trialspawnguard"; public const string Version = "0.3.0"; internal ConfigEntry<bool> Enabled; internal ConfigEntry<bool> Rifts; internal ConfigEntry<bool> OffMap; internal ConfigEntry<bool> Diagnostics; internal ConfigEntry<string> AllowedBodies; internal ConfigEntry<bool> BalanceQuota; internal ConfigEntry<bool> AllowElites; internal ConfigEntry<bool> AllowFlying; internal ConfigEntry<bool> AllowOther; internal bool SceneEnabled; internal bool SceneBalance; internal bool SceneElites; internal bool SceneFlying; internal bool SceneOther; private bool ready; private Harmony harmony; private int sceneHandle = -1; public static Plugin Instance { get; private set; } public string TaskKind { get; private set; } public static bool Active { get { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Instance) && Instance.ready && Instance.SceneEnabled && NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance)) { int num = Instance.sceneHandle; Scene activeScene = SceneManager.GetActiveScene(); return num == ((Scene)(ref activeScene)).handle; } return false; } } internal static bool SuppressElites { get { if (Active) { return !Instance.SceneElites; } return false; } } private void Awake() { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown Instance = this; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "开关整个 Mod。房主设置决定规则;下一次进入试炼生效,当前关卡不变。"); Rifts = ((BaseUnityPlugin)this).Config.Bind<bool>("Tasks", "MonstersIntoRifts", true, "使用仪式头盔将敌人击入裂隙。"); OffMap = ((BaseUnityPlugin)this).Config.Bind<bool>("Tasks", "MonstersOffMap", true, "深渊试炼:将敌人献祭给迷雾。"); AllowedBodies = ((BaseUnityPlugin)this).Config.Bind<string>("Monsters", "AllowedBodyNames", "BeetleBody,LemurianBody,ImpBody", "可用地面怪物的内部 Body 名称,逗号分隔。仍执行飞行/不可移动检查。修改后重开游戏。"); Diagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "VerboseLogging", false, "输出过滤、替换和精英化拦截日志。"); BalanceQuota = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "增加任务需求数量", true, "将原生目标数量提高 50%,通常为 20 → 30,以补偿安全刷怪池降低的难度。关闭使用原版数量。下一次试炼生效。"); AllowElites = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "允许生成精英怪物", false, "开启后恢复原版精英生成和荣耀神器的正常效果、属性及费用;不强制每只都是精英。下一次试炼生效。"); AllowFlying = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "允许生成飞行怪物", false, "允许原怪物池中的常规飞行怪物,不额外添加原池没有的怪物。此类敌人可能无法献祭给迷雾。下一次试炼生效。"); AllowOther = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "允许生成其他怪物", false, "允许三种安全名单以外的其他常规地面怪物,仍排除明显不可移动和首领单位。飞行怪由独立选项控制。下一次试炼生效。"); Localization.Initialize(); AddSetting(Enabled, 3); AddSetting(BalanceQuota, 5); AddSetting(AllowElites, 7); AddSetting(AllowFlying, 9); AddSetting(AllowOther, 11); try { SpawnPolicy.Initialize(AllowedBodies.Value); harmony = new Harmony("local.trialspawnguard"); harmony.PatchAll(typeof(Plugin).Assembly); ready = true; SceneManager.activeSceneChanged += SceneChanged; Run.onRunDestroyGlobal += RunDestroyed; RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoaded)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Trial Spawn Guard 0.3.0 ready. Task-scoped server rules; Honor state is never changed."); } catch (Exception ex) { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ready = false; ((BaseUnityPlugin)this).Logger.LogError((object)("Plugin initialization failed; patches removed: " + ex)); } } private static void AddSetting(ConfigEntry<bool> entry, int nameIndex) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0027: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown CheckBoxOption val = new CheckBoxOption(entry, new CheckBoxConfig { name = ((ConfigEntryBase)entry).Definition.Key, category = "Trial settings" }); ModSettingsManager.AddOption((BaseOption)(object)val, "local.trialspawnguard", "Trial Spawn Guard", Localization.Token(nameIndex), Localization.Token(nameIndex + 1)); ModSettingsManager.SetCategoryNameToken("local.trialspawnguard", (BaseOption)(object)val, Localization.Token(1)); } private void Update() { QuotaSync.Tick(); } private void OnGameLoaded() { SpawnPolicy.BeginFallbackLoad(); } private void SceneChanged(Scene oldScene, Scene newScene) { ResetScope("scene changed"); } private void RunDestroyed(Run run) { ResetScope("run ended"); } private void ResetScope(string reason) { if (sceneHandle != -1) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Trial restriction ended: " + reason)); } sceneHandle = -1; TaskKind = null; SpawnPolicy.ClearScene(); } internal static bool Matches(Type type) { if (Object.op_Implicit((Object)(object)Instance)) { if (!(type == typeof(TrialQuestSurvivorMonstersIntoRifts)) || !Instance.Rifts.Value) { if (type == typeof(TrialQuestSurvivorMonstersOffMap)) { return Instance.OffMap.Value; } return false; } return true; } return false; } internal static void Activate(Type type, Scene scene, string source) { //IL_003d: 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) if (Object.op_Implicit((Object)(object)Instance) && Instance.ready && NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance) && Matches(type)) { if (!((Scene)(ref scene)).IsValid()) { scene = SceneManager.GetActiveScene(); } if (Instance.sceneHandle != ((Scene)(ref scene)).handle) { Instance.ResetScope("new trial"); Instance.sceneHandle = ((Scene)(ref scene)).handle; Instance.SceneEnabled = Instance.Enabled.Value; Instance.SceneBalance = Instance.BalanceQuota.Value; Instance.SceneElites = Instance.AllowElites.Value; Instance.SceneFlying = Instance.AllowFlying.Value; Instance.SceneOther = Instance.AllowOther.Value; Instance.TaskKind = type.Name; ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Trial restriction active: " + type.Name + " scene=" + ((Scene)(ref scene)).name + " source=" + source)); } } } internal static void InspectVariant(TrialVariantEventRelay relay) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00fc: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)relay) || !NetworkServer.active) { return; } if (relay.trialVariantNotificationInfo.nameToken == "QUEST_TRIAL_SURVIVORMONSTERSOFFMAP_NAME") { Activate(typeof(TrialQuestSurvivorMonstersOffMap), ((Component)relay).gameObject.scene, "variant token"); } if (relay.customName == "MonstersIntoRiftsVariant") { Activate(typeof(TrialQuestSurvivorMonstersIntoRifts), ((Component)relay).gameObject.scene, "variant id"); } string[] array = new string[2] { "onVariantBegin", "prepareSceneForVariant" }; foreach (string text in array) { object? obj = AccessTools.Field(typeof(TrialVariantEventRelay), text)?.GetValue(relay); UnityEventBase val = (UnityEventBase)((obj is UnityEventBase) ? obj : null); if (val == null) { continue; } for (int j = 0; j < val.GetPersistentEventCount(); j++) { Object persistentTarget = val.GetPersistentTarget(j); QuestStarter val2 = (QuestStarter)(object)((persistentTarget is QuestStarter) ? persistentTarget : null); if (val2 != null && Matches((Type)val2.quest)) { Activate((Type)val2.quest, ((Component)relay).gameObject.scene, "variant event"); } } } } internal static bool Hostile(TeamIndex team) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if ((int)team != 2 && (int)team != 3) { return (int)team == 4; } return true; } internal static bool Hostile(CharacterMaster master) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)master) && !Object.op_Implicit((Object)(object)master.playerCharacterMasterController)) { return Hostile(master.teamIndex); } return false; } internal static bool Hostile(Inventory inventory) { if (!Object.op_Implicit((Object)(object)inventory)) { return false; } return Hostile(((Component)inventory).GetComponent<CharacterMaster>()); } internal static TeamIndex TeamFor(GameObject prefab, TeamIndex? requested, GameObject summoner) { //IL_000b: 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_0061: Unknown result type (might be due to invalid IL or missing references) if (requested.HasValue) { return requested.Value; } CharacterBody val = (Object.op_Implicit((Object)(object)summoner) ? summoner.GetComponent<CharacterBody>() : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.teamComponent)) { return val.teamComponent.teamIndex; } CharacterMaster val2 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<CharacterMaster>() : null); if (!Object.op_Implicit((Object)(object)val2)) { return (TeamIndex)(-1); } return val2.teamIndex; } internal static void Trace(string message) { if (Object.op_Implicit((Object)(object)Instance) && Instance.Diagnostics.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)message); } } internal static void Warn(string message) { if (Object.op_Implicit((Object)(object)Instance)) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)message); } } private void OnDestroy() { SceneManager.activeSceneChanged -= SceneChanged; Run.onRunDestroyGlobal -= RunDestroyed; RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnGameLoaded)); ResetScope("plugin stopped"); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } SpawnPolicy.Dispose(); Localization.Dispose(); Instance = null; } } internal static class QuotaSync { private sealed class Empty : MessageBase { public override void Serialize(NetworkWriter writer) { } public override void Deserialize(NetworkReader reader) { } } private sealed class Payload : MessageBase { public NetworkInstanceId runnerId; public int quota; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(runnerId); writer.Write(quota); } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) runnerId = reader.ReadNetworkId(); quota = reader.ReadInt32(); } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static NetworkMessageDelegate <>9__11_0; public static NetworkMessageDelegate <>9__11_1; internal void <Tick>b__11_0(NetworkMessage message) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) foreach (QuestRunner instances in InstanceTracker.GetInstancesList<QuestRunner>()) { int num = Get(instances.quest); if (num > 0) { message.conn.Send((short)29874, (MessageBase)(object)new Payload { runnerId = ((NetworkBehaviour)instances).netId, quota = num }); } } } internal void <Tick>b__11_1(NetworkMessage message) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) Payload payload = message.ReadMessage<Payload>(); if (payload.quota >= 1 && payload.quota <= 1000000) { GameObject val = ClientScene.FindLocalObject(payload.runnerId); QuestRunner val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<QuestRunner>() : null); if (Object.op_Implicit((Object)(object)val2) && Get(val2.quest) > 0) { Set(val2.quest, payload.quota); } } } } private const short Request = 29873; private const short Response = 29874; private static readonly ConditionalWeakTable<BaseQuest, object> applied = new ConditionalWeakTable<BaseQuest, object>(); private static readonly HashSet<NetworkClient> registered = new HashSet<NetworkClient>(); private static bool serverRegistered; private static float next; internal static int Get(BaseQuest quest) { return ((TrialQuestSurvivorMonstersOffMap)(((quest is TrialQuestSurvivorMonstersOffMap) ? quest : null)?)).killQuota ?? ((TrialQuestSurvivorMonstersIntoRifts)(((quest is TrialQuestSurvivorMonstersIntoRifts) ? quest : null)?)).killsRequired ?? 0; } private static void Set(BaseQuest quest, int quota) { TrialQuestSurvivorMonstersOffMap val = (TrialQuestSurvivorMonstersOffMap)(object)((quest is TrialQuestSurvivorMonstersOffMap) ? quest : null); if (val != null) { val.killQuota = quota; } TrialQuestSurvivorMonstersIntoRifts val2 = (TrialQuestSurvivorMonstersIntoRifts)(object)((quest is TrialQuestSurvivorMonstersIntoRifts) ? quest : null); if (val2 != null) { val2.killsRequired = quota; } } internal static void Apply(BaseQuest quest) { if (Plugin.Active && Plugin.Instance.SceneBalance && Get(quest) > 0 && !applied.TryGetValue(quest, out var _)) { applied.Add(quest, new object()); Set(quest, (int)Math.Min(1000000L, ((long)Get(quest) * 3L + 1) / 2)); Plugin.Trace("QUOTA " + Get(quest)); } } internal static void Tick() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //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_00bb: Expected O, but got Unknown if (Time.unscaledTime < next) { return; } next = Time.unscaledTime + 1f; if (!NetworkServer.active) { serverRegistered = false; } else if (!serverRegistered) { object obj = <>c.<>9__11_0; if (obj == null) { NetworkMessageDelegate val = delegate(NetworkMessage message) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) foreach (QuestRunner instances in InstanceTracker.GetInstancesList<QuestRunner>()) { int num = Get(instances.quest); if (num > 0) { message.conn.Send((short)29874, (MessageBase)(object)new Payload { runnerId = ((NetworkBehaviour)instances).netId, quota = num }); } } }; <>c.<>9__11_0 = val; obj = (object)val; } NetworkServer.RegisterHandler((short)29873, (NetworkMessageDelegate)obj); serverRegistered = true; } if (!NetworkClient.active) { registered.Clear(); return; } foreach (NetworkClient allClient in NetworkClient.allClients) { if (registered.Add(allClient)) { object obj2 = <>c.<>9__11_1; if (obj2 == null) { NetworkMessageDelegate val2 = delegate(NetworkMessage message) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) Payload payload = message.ReadMessage<Payload>(); if (payload.quota >= 1 && payload.quota <= 1000000) { GameObject val3 = ClientScene.FindLocalObject(payload.runnerId); QuestRunner val4 = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<QuestRunner>() : null); if (Object.op_Implicit((Object)(object)val4) && Get(val4.quest) > 0) { Set(val4.quest, payload.quota); } } }; <>c.<>9__11_1 = val2; obj2 = (object)val2; } allClient.RegisterHandler((short)29874, (NetworkMessageDelegate)obj2); } if (allClient.isConnected && Object.op_Implicit((Object)(object)Run.instance) && !NetworkServer.active) { allClient.Send((short)29873, (MessageBase)(object)new Empty()); } } } } internal static class SpawnPolicy { private static HashSet<string> allowed; private static readonly Dictionary<SpawnCard, CharacterSpawnCard> copies = new Dictionary<SpawnCard, CharacterSpawnCard>(); private static readonly Dictionary<GameObject, bool> suitability = new Dictionary<GameObject, bool>(); private static readonly Dictionary<WeightedSelection<DirectorCard>, WeightedSelection<DirectorCard>> pools = new Dictionary<WeightedSelection<DirectorCard>, WeightedSelection<DirectorCard>>(); private static readonly HashSet<SpawnCard> generated = new HashSet<SpawnCard>(); private static readonly MethodInfo clone = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); private static CharacterSpawnCard fallbackSource; private static AsyncOperationHandle<CharacterSpawnCard> fallbackHandle; private static bool fallbackLoaded; internal static readonly EliteTierDef NormalTier = new EliteTierDef { costMultiplier = 1f, eliteTypes = (EliteDef[])(object)new EliteDef[1], canSelectWithoutAvailableEliteDef = true, isAvailable = (EliteRules rules) => true }; private static readonly FieldInfo currentCard = AccessTools.Field(typeof(CombatDirector), "currentMonsterCard"); private static readonly FieldInfo currentTier = AccessTools.Field(typeof(CombatDirector), "currentActiveEliteTier"); private static readonly FieldInfo currentElite = AccessTools.Field(typeof(CombatDirector), "currentActiveEliteDef"); internal static void Initialize(string bodies) { allowed = new HashSet<string>(from s in bodies.Split(',') select s.Trim() into s where s.Length > 0 select s, StringComparer.Ordinal); } internal static void BeginFallbackLoad() { //IL_0012: 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) if (fallbackHandle.IsValid()) { return; } fallbackHandle = Addressables.LoadAssetAsync<CharacterSpawnCard>((object)"RoR2/Base/Lemurian/cscLemurian.asset"); fallbackHandle.Completed += delegate(AsyncOperationHandle<CharacterSpawnCard> handle) { fallbackSource = handle.Result; fallbackLoaded = Object.op_Implicit((Object)(object)fallbackSource); if (!fallbackLoaded) { Plugin.Warn("Native fallback card could not be loaded."); } }; } internal static void LoadFallback() { if (!fallbackLoaded) { BeginFallbackLoad(); fallbackSource = fallbackHandle.WaitForCompletion(); fallbackLoaded = Object.op_Implicit((Object)(object)fallbackSource); if (!fallbackLoaded) { throw new InvalidOperationException("Could not load the native Lemurian fallback card."); } } } internal static bool Suitable(GameObject masterPrefab, bool fallback = false) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)masterPrefab)) { return false; } if (!fallback && suitability.TryGetValue(masterPrefab, out var value)) { return value; } CharacterMaster component = masterPrefab.GetComponent<CharacterMaster>(); CharacterBody val = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.bodyPrefab)) ? component.bodyPrefab.GetComponent<CharacterBody>() : null); CharacterMotor val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<CharacterMotor>() : null); ModelLocator val3 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ModelLocator>() : null); RigidbodyMotor val4 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<RigidbodyMotor>() : null); int num; if (Object.op_Implicit((Object)(object)val)) { if (Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val4)) { if (Object.op_Implicit((Object)(object)val2)) { if (!val2.isFlying) { CharacterFlightParameters flightParameters = val2.flightParameters; num = (((CharacterFlightParameters)(ref flightParameters)).CheckShouldUseFlight() ? 1 : 0); } else { num = 1; } } else { num = 0; } } else { num = 1; } } else { num = 0; } bool flag = (byte)num != 0; bool flag2 = (Object.op_Implicit((Object)(object)val2) ? (val2.mass > 0f) : (Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)((Component)val).GetComponent<Rigidbody>()) && ((Component)val).GetComponent<Rigidbody>().mass > 0f)); bool flag3 = Object.op_Implicit((Object)(object)val) && flag2 && (fallback || !flag || Plugin.Instance.SceneFlying) && !val.isChampion && (val.bodyFlags & 0x10000) == 0 && Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val3.modelTransform) && Object.op_Implicit((Object)(object)((Component)val3.modelTransform).GetComponentInChildren<HurtBoxGroup>(true)) && (fallback || (flag ? Plugin.Instance.SceneFlying : (Plugin.Instance.SceneOther || allowed.Contains(((Object)val).name)))); if (!fallback) { suitability[masterPrefab] = flag3; } return flag3; } internal static bool Suitable(SpawnCard card) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (card is CharacterSpawnCard && ((int)card.nodeGraphType == 0 || Plugin.Instance.SceneFlying)) { return Suitable(card.prefab); } return false; } internal static bool IsEliteEquipment(EquipmentIndex index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0006: Unknown result type (might be due to invalid IL or missing references) if ((int)index == -1) { return false; } EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(index); if (Object.op_Implicit((Object)(object)equipmentDef) && Object.op_Implicit((Object)(object)equipmentDef.passiveBuffDef)) { return equipmentDef.passiveBuffDef.isElite; } return false; } internal static CharacterSpawnCard SafeCard(SpawnCard source) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (generated.Contains(source)) { return (CharacterSpawnCard)source; } if (Object.op_Implicit((Object)(object)source) && copies.TryGetValue(source, out var value)) { return value; } CharacterSpawnCard val = (CharacterSpawnCard)((!Suitable(source)) ? ((object)Fallback()) : ((object)(CharacterSpawnCard)source)); CharacterSpawnCard val2 = Object.Instantiate<CharacterSpawnCard>(val); ((Object)val2).name = ((Object)val).name + "_TrialSpawnGuard"; val2.noElites = !Plugin.Instance.SceneElites || val.noElites; val2.equipmentToGrant = val.equipmentToGrant.Select((EquipmentDef e) => (Plugin.Instance.SceneElites || !Object.op_Implicit((Object)(object)e) || !IsEliteEquipment(e.equipmentIndex)) ? e : null).ToArray(); generated.Add((SpawnCard)(object)val2); if (Object.op_Implicit((Object)(object)source)) { copies[source] = val2; } Plugin.Trace("CARD " + (Object.op_Implicit((Object)(object)source) ? ((Object)source).name : "empty") + " -> " + ((Object)val2).name); return val2; } private static CharacterSpawnCard Fallback() { if (!fallbackLoaded) { LoadFallback(); } if (!Suitable(((SpawnCard)fallbackSource).prefab, fallback: true)) { throw new InvalidOperationException("Native fallback does not satisfy movement checks."); } return fallbackSource; } internal static GameObject FallbackMaster() { return ((SpawnCard)Fallback()).prefab; } internal static DirectorCard SafeDirectorCard(DirectorCard source) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (source == null) { return new DirectorCard { spawnCard = (SpawnCard)(object)SafeCard(null), selectionWeight = 1, spawnDistance = (MonsterSpawnDistance)0 }; } DirectorCard val = (DirectorCard)clone.Invoke(source, null); val.spawnCard = (SpawnCard)(object)SafeCard(source.GetSpawnCard()); if (!Plugin.Instance.SceneElites) { val.isExclusivelyElite = false; val.eliteDef = null; } return val; } internal static WeightedSelection<DirectorCard> Filter(WeightedSelection<DirectorCard> original) { //IL_0024: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) if (original != null && pools.TryGetValue(original, out var value)) { return value; } WeightedSelection<DirectorCard> val = new WeightedSelection<DirectorCard>(8); if (original != null) { for (int i = 0; i < original.Count; i++) { ChoiceInfo<DirectorCard> choice = original.GetChoice(i); if (choice.weight > 0f && choice.value != null && choice.value.IsAvailable() && Suitable(choice.value.GetSpawnCard())) { val.AddChoice(SafeDirectorCard(choice.value), choice.weight); } } } if (val.Count == 0) { val.AddChoice(SafeDirectorCard(null), 1f); Plugin.Trace("EMPTY_POOL: using native ground Lemurian"); } if (original != null) { pools[original] = val; } return val; } internal static bool Protect(CombatDirector director) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (Plugin.Active && Object.op_Implicit((Object)(object)director)) { return Plugin.Hostile(director.teamIndex); } return false; } internal static void Normalize(CombatDirector director, bool replaceCard) { if (!Protect(director)) { return; } if (replaceCard) { object? value = currentCard.GetValue(director); DirectorCard val = (DirectorCard)((value is DirectorCard) ? value : null); if (val != null && (!generated.Contains(val.GetSpawnCard()) || val.isExclusivelyElite || Object.op_Implicit((Object)(object)val.eliteDef))) { currentCard.SetValue(director, SafeDirectorCard(val)); } } if (Plugin.SuppressElites) { currentTier.SetValue(director, NormalTier); currentElite.SetValue(director, null); director.ActiveEliteDefOverride = null; director.ActiveEliteDefOverrideCostMultiplier = -1f; } } internal static void ClearScene() { pools.Clear(); copies.Clear(); suitability.Clear(); foreach (SpawnCard item in generated) { if (Object.op_Implicit((Object)(object)item)) { Object.Destroy((Object)(object)item); } } generated.Clear(); } internal static void Dispose() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ClearScene(); if (fallbackHandle.IsValid()) { Addressables.Release<CharacterSpawnCard>(fallbackHandle); } fallbackLoaded = false; fallbackSource = null; } } }