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 Snatcher over Anima Harvester boss v1.0.1
HatKidSoulbound.dll
Decompiled 12 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; 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.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HG.GeneralSerializer; using HarmonyLib; using Microsoft.CodeAnalysis; using R2API; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.ConVar; using RoR2.Projectile; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.Rendering; using UnityEngine.Rendering.PostProcessing; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.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 HatKidSoulbound { internal static class BossEffects { private const string BossFolder = "RoR2/DLC4/ReaperBoss/"; private static readonly string[] ExtraPrefabs = new string[9] { "RoR2/DLC4/champrush/ReaperRevivalFX.prefab", "RoR2/DLC4/champrush/ChampRushReaperSpawnVFX.prefab", "RoR2/DLC4/MalachiteSpikeEffect.prefab", "RoR2/DLC4/MalachiteSpikeGroundEffect.prefab", "RoR2/DLC4/MalachiteSpikeGrower.prefab", "RoR2/DLC4/MalachiteSpikeGrowerProjectileInitialGhost.prefab", "RoR2/DLC4/MalachiteSpikePredictionEffect.prefab", "RoR2/DLC4/ReaperBossAssailSlashMalachiteProjectile.prefab", "RoR2/DLC4/ReaperBossAssailSlashMalachiteProjectileRightVariant.prefab" }; private static readonly string[] BossBodies = new string[2] { "RoR2/Junk_DLC4/WightProjectile/WightProjectileReaper.prefab", "RoR2/DLC4/ReaperBoss/ReaperBossSoulBody.prefab" }; private static readonly string[] SharedProjectiles = new string[2] { "RoR2/Base/ElitePoison/PoisonStakeProjectile.prefab", "RoR2/Base/ElitePoison/UrchinSeekingProjectile.prefab" }; private const string StageFolder = "RoR2/DLC4/champrush/"; private static readonly string[] StagePrefixes = new string[14] { "CR_", "ChampRushOrb", "ChamprushOrb", "ChampRushReaper", "ChampRushRitual", "ChampRushPurgatory", "ChamprushFireNado", "ChamprushPitFire", "ReaperRevivalFX", "TeleportOutBoom", "AcoWightSkullCS_VFX", "Champrush_DoorPortal", "PortalToUltima", "Holder_ Quadrant" }; private static readonly Regex Guid = new Regex("^[0-9a-f]{32}$"); private static readonly List<GameObject> held = new List<GameObject>(); private static readonly Dictionary<GameObject, GameObject> copies = new Dictionary<GameObject, GameObject>(); internal static readonly HashSet<string> sharedProjectileNames = new HashSet<string>(); public static void Setup() { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) Stopwatch stopwatch = Stopwatch.StartNew(); HashSet<string> hashSet = new HashSet<string>(); foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators) { foreach (object key in resourceLocator.Keys) { if (key is string text && text.StartsWith("RoR2/DLC4/")) { hashSet.Add(text); } } } HashSet<GameObject> hashSet2 = new HashSet<GameObject>(); foreach (string item2 in from k in hashSet.Where((string k) => k.EndsWith(".prefab") && k.StartsWith("RoR2/DLC4/ReaperBoss/")).Concat(ExtraPrefabs) orderby k select k) { Add(hashSet2, TryLoad(item2)); } foreach (string item3 in hashSet.Where((string k) => k.EndsWith(".asset") && (k.StartsWith("RoR2/DLC4/ReaperBoss/EntityStates.") || k.Contains("/EntityStates.ChampRushReaper.")))) { EntityStateConfiguration val = null; try { val = Addressables.LoadAssetAsync<EntityStateConfiguration>((object)item3).WaitForCompletion(); } catch { } if (!Object.op_Implicit((Object)(object)val)) { continue; } SerializedField[] serializedFields = val.serializedFieldsCollection.serializedFields; foreach (SerializedField val2 in serializedFields) { Object objectValue = val2.fieldValue.objectValue; GameObject val3 = (GameObject)(object)((objectValue is GameObject) ? objectValue : null); if (val3 != null) { Add(hashSet2, val3); } else if (val2.fieldValue.stringValue != null && Guid.IsMatch(val2.fieldValue.stringValue)) { Add(hashSet2, TryLoad(val2.fieldValue.stringValue)); } } } int num2 = 0; foreach (GameObject item4 in hashSet2) { if (Purple.All(item4)) { num2++; } } string[] bossBodies = BossBodies; for (int num = 0; num < bossBodies.Length; num++) { GameObject val4 = TryLoad(bossBodies[num]); if (Object.op_Implicit((Object)(object)val4)) { held.Add(val4); PurpleBody(val4); num2++; if (Object.op_Implicit((Object)(object)val4.GetComponent<ProjectileController>())) { hashSet2.Add(val4); } } } int num3 = 0; foreach (string item5 in hashSet.Where((string k) => k.StartsWith("RoR2/DLC4/champrush/") && k.EndsWith(".prefab") && StagePrefixes.Any((string p) => k.Substring("RoR2/DLC4/champrush/".Length).StartsWith(p)))) { GameObject val5 = TryLoad(item5); if (!Object.op_Implicit((Object)(object)val5) || hashSet2.Contains(val5)) { continue; } held.Add(val5); Renderer[] componentsInChildren = val5.GetComponentsInChildren<Renderer>(true); foreach (Renderer r in componentsInChildren) { Purple.Renderer(r, !IsEffect(r)); } ParticleSystem[] componentsInChildren2 = val5.GetComponentsInChildren<ParticleSystem>(true); for (int num = 0; num < componentsInChildren2.Length; num++) { Purple.Particles(componentsInChildren2[num]); } Light[] componentsInChildren3 = val5.GetComponentsInChildren<Light>(true); foreach (Light val6 in componentsInChildren3) { if (Purple.IsColoured(val6.color)) { val6.color = Purple.Shift(val6.color); } } num3++; } int num4 = 0; foreach (GameObject item6 in hashSet2.Where((GameObject g) => Object.op_Implicit((Object)(object)g.GetComponent<ProjectileController>())).ToList()) { foreach (var (obj2, fieldInfo, val7) in EffectFields(item6).ToList()) { if (!hashSet2.Contains(val7) && !Object.op_Implicit((Object)(object)val7.GetComponent<ProjectileController>()) && !Object.op_Implicit((Object)(object)val7.GetComponent<CharacterBody>())) { GameObject val8 = Copy(val7); if ((Object)(object)val8 != (Object)(object)val7) { fieldInfo.SetValue(obj2, val8); num4++; } } } ProjectileController component = item6.GetComponent<ProjectileController>(); GameObject val9 = Ghost(component); if (Object.op_Implicit((Object)(object)val9) && !hashSet2.Contains(val9)) { GameObject val10 = Copy(val9); if ((Object)(object)val10 != (Object)(object)val9) { SetGhost(component, val10); num4++; } } } bossBodies = SharedProjectiles; for (int num = 0; num < bossBodies.Length; num++) { GameObject val11 = TryLoad(bossBodies[num]); ProjectileController val12 = (Object.op_Implicit((Object)(object)val11) ? val11.GetComponent<ProjectileController>() : null); if (!Object.op_Implicit((Object)(object)val12)) { continue; } held.Add(val11); sharedProjectileNames.Add(((Object)val11).name); foreach (var item7 in EffectFields(val11).ToList()) { GameObject item = item7.Item3; if (!Object.op_Implicit((Object)(object)item.GetComponent<ProjectileController>()) && !Object.op_Implicit((Object)(object)item.GetComponent<CharacterBody>())) { Copy(item); } } GameObject val13 = Ghost(val12); if (Object.op_Implicit((Object)(object)val13)) { Copy(val13); } } HatKidSoulboundPlugin.Log.LogInfo((object)($"Purple boss effects: {hashSet2.Count} boss prefabs ({num2} recoloured), {num4} shared effects copied, " + $"{num3} stage effects, {sharedProjectileNames.Count} shared projectiles ({stopwatch.ElapsedMilliseconds} ms)")); } internal static bool IsEffect(Renderer r) { if (!(r is ParticleSystemRenderer) && !(r is TrailRenderer) && !(r is LineRenderer)) { return r.sharedMaterials.Any((Material m) => Object.op_Implicit((Object)(object)m) && Object.op_Implicit((Object)(object)m.shader) && ((Object)m.shader).name.Contains("/FX/")); } return true; } private static IEnumerable<(Component, FieldInfo, GameObject)> EffectFields(GameObject go) { Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true); foreach (Component c in componentsInChildren) { if (!Object.op_Implicit((Object)(object)c) || c is Transform || ((object)c).GetType().Namespace == null || !((object)c).GetType().Namespace.StartsWith("RoR2")) { continue; } FieldInfo[] fields = ((object)c).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType != typeof(GameObject)) { continue; } object? value = fieldInfo.GetValue(c); GameObject val = (GameObject)((value is GameObject) ? value : null); if (Object.op_Implicit((Object)(object)val)) { Scene scene = val.scene; if (!((Scene)(ref scene)).IsValid() && !val.transform.IsChildOf(go.transform)) { yield return (c, fieldInfo, val); } } } } } internal static void BeforeStart(ProjectileController pc) { foreach (var (obj, fieldInfo, val) in EffectFields(((Component)pc).gameObject).ToList()) { if (copies.TryGetValue(val, out var value) && (Object)(object)value != (Object)(object)val) { fieldInfo.SetValue(obj, value); } } GameObject val2 = Ghost(pc); if (Object.op_Implicit((Object)(object)val2) && copies.TryGetValue(val2, out var value2) && (Object)(object)value2 != (Object)(object)val2) { SetGhost(pc, value2, log: false); } } internal static void AfterStart(ProjectileController pc) { Purple.All(((Component)pc).gameObject); } internal static void PurpleBody(GameObject body) { Purple.All(body); ColorParticlesWithBodyColor[] componentsInChildren = body.GetComponentsInChildren<ColorParticlesWithBodyColor>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } ModelLocator component = body.GetComponent<ModelLocator>(); Transform val = ((component != null) ? component.modelTransform : null); CharacterModel val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<CharacterModel>() : null); if (!Object.op_Implicit((Object)(object)val2)) { return; } for (int j = 0; j < val2.baseRendererInfos.Length; j++) { if (Object.op_Implicit((Object)(object)val2.baseRendererInfos[j].defaultMaterial)) { val2.baseRendererInfos[j].defaultMaterial = Purple.Material(val2.baseRendererInfos[j].defaultMaterial); } } } private static void Add(HashSet<GameObject> set, GameObject go) { if (Object.op_Implicit((Object)(object)go) && !Object.op_Implicit((Object)(object)go.GetComponent<CharacterBody>()) && !Object.op_Implicit((Object)(object)go.GetComponent<CharacterMaster>()) && set.Add(go)) { held.Add(go); } } private static GameObject TryLoad(string key) { //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) try { return Addressables.LoadAssetAsync<GameObject>((object)key).WaitForCompletion(); } catch { return null; } } private static GameObject Copy(GameObject original) { if (copies.TryGetValue(original, out var value)) { return value; } if (copies.ContainsValue(original)) { return original; } GameObject val = original; GameObject val2 = PrefabAPI.InstantiateClone(original, ((Object)original).name + "HatKidPurple", false); if (Purple.All(val2) && (!Object.op_Implicit((Object)(object)val2.GetComponent<EffectComponent>()) || ContentAddition.AddEffect(val2))) { val = val2; } else { Object.Destroy((Object)(object)val2); } copies[original] = val; return val; } private static void SetGhost(ProjectileController pc, GameObject ghost, bool log = true) { pc.ghostPrefab = ghost; FieldInfo[] fields = typeof(ProjectileController).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.Name.IndexOf("ghost", StringComparison.OrdinalIgnoreCase) >= 0 && typeof(AssetReference).IsAssignableFrom(fieldInfo.FieldType)) { fieldInfo.SetValue(pc, Activator.CreateInstance(fieldInfo.FieldType, "")); } } if (log) { HatKidSoulboundPlugin.Log.LogInfo((object)("Boss projectile " + ((Object)pc).name + ": purple copy of its shared ghost (" + ((Object)ghost).name + ")")); } } private static GameObject Ghost(ProjectileController pc) { if (Object.op_Implicit((Object)(object)pc.ghostPrefab)) { return pc.ghostPrefab; } FieldInfo[] fields = typeof(ProjectileController).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.Name.IndexOf("ghost", StringComparison.OrdinalIgnoreCase) >= 0) { object? value = fieldInfo.GetValue(pc); AssetReference val = (AssetReference)((value is AssetReference) ? value : null); if (val != null && val.RuntimeKeyIsValid()) { return TryLoad(val.RuntimeKey.ToString()); } } } return null; } } internal static class BossFight { private const string NameToken = "CHAZ_HATKIDSOULBOUND_BOSS_NAME"; private const string SubtitleToken = "CHAZ_HATKIDSOULBOUND_BOSS_SUBTITLE"; private const string MusicRtpc = "Volume_MSX"; private const int BossTrack = 0; private const int TimePieceTrack = 1; private const float PhaseGap = 30f; private const float RiffLength = 7.2f; private const float BossFadeOut = 0.4f; private const float SongFadeOut = 3f; internal static byte[] spawnVoice; internal static byte[] deathRiff; private static readonly Dictionary<string, (string name, string subtitle)> originalTokens = new Dictionary<string, (string, string)>(); private static float lastBossSeen = -999f; private static float killedAt = -1f; private static bool finalPhaseSeen; private static bool finalPhaseAlive; private static bool mutedGameMusic; private static bool ownCall; private static float reportAt = -1f; private static float gameMusicVolume = 1f; private static float dim = 1f; private static long framesAtStart; private static uint musicRtpcId; public static void Setup(Harmony harmony) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown LanguageAPI.Add("CHAZ_HATKIDSOULBOUND_BOSS_NAME", "The Snatcher"); LanguageAPI.Add("CHAZ_HATKIDSOULBOUND_BOSS_SUBTITLE", "The Soulbound Contractor"); CharacterBody.onBodyStartGlobal += OnBodyStart; SceneManager.activeSceneChanged += delegate { lastBossSeen = -999f; killedAt = -1f; finalPhaseSeen = (finalPhaseAlive = false); }; if (LoadTrack(0, "your_contract_has_expired.snm") & LoadTrack(1, "timepiece_released.snm")) { MusicPlayer.Start(); } HarmonyMethod val = new HarmonyMethod(typeof(BossFight).GetMethod("SetRtpcPrefix", BindingFlags.Static | BindingFlags.NonPublic)); int num = 0; MethodInfo[] methods = typeof(AkSoundEngine).GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "SetRTPCValue") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length >= 2 && !(parameters[1].Name != "in_value") && !(parameters[1].ParameterType != typeof(float))) { try { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch (Exception ex) { HatKidSoulboundPlugin.Log.LogWarning((object)("Couldn't hook a music volume call: " + ex.Message)); } } } HatKidSoulboundPlugin.Log.LogInfo((object)$"Music: hooked {num} music volume calls"); } private static bool LoadTrack(int slot, string resource) { using (Stream stream = typeof(Assets).Assembly.GetManifestResourceStream(resource)) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); if (MusicPlayer.Load(slot, memoryStream.ToArray())) { return true; } } HatKidSoulboundPlugin.Log.LogError((object)("Couldn't read " + resource)); return false; } public static void Shutdown() { MusicPlayer.Wanted = false; MusicPlayer.Stop(); RestoreGameMusic(); } internal static bool IsBoss(CharacterBody b) { if (Object.op_Implicit((Object)(object)b) && ((Object)b).name.StartsWith("ReaperBoss")) { return !((Object)b).name.StartsWith("ReaperBossSoul"); } return false; } private static void OnBodyStart(CharacterBody body) { if (IsBoss(body)) { Title(body); if (((Object)body).name.StartsWith("ReaperBossBody") && HatKidSoulboundPlugin.SnatcherVoice) { Voice.Play(spawnVoice, HatKidSoulboundPlugin.FoolVolume * 1.035f); } } } private static void Title(CharacterBody body) { string key = ((Object)body).name.Replace("(Clone)", ""); if (!originalTokens.TryGetValue(key, out (string, string) value)) { if (body.baseNameToken == "CHAZ_HATKIDSOULBOUND_BOSS_NAME") { return; } value = (originalTokens[key] = (body.baseNameToken, body.subtitleNameToken)); } bool replaceBossTitle = HatKidSoulboundPlugin.ReplaceBossTitle; object baseNameToken; if (!replaceBossTitle) { (baseNameToken, _) = value; } else { baseNameToken = "CHAZ_HATKIDSOULBOUND_BOSS_NAME"; } body.baseNameToken = (string)baseNameToken; body.subtitleNameToken = (replaceBossTitle ? "CHAZ_HATKIDSOULBOUND_BOSS_SUBTITLE" : value.Item2); } public static void Update() { bool inSoulbound = BossRuntime.InSoulbound; bool flag = false; bool flag2 = false; if (inSoulbound) { foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { if (IsBoss(readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.healthComponent) && readOnlyInstances.healthComponent.alive) { flag = true; if (((Object)readOnlyInstances).name.Contains("Malachite")) { finalPhaseSeen = true; flag2 = true; } Title(readOnlyInstances); } } } if (flag) { lastBossSeen = Time.time; } if (finalPhaseAlive && !flag2 && killedAt < 0f) { killedAt = Time.time; HatKidSoulboundPlugin.Log.LogInfo((object)"Snatcher defeated: boss-death riff"); if (HatKidSoulboundPlugin.ReplaceMusic) { Voice.PlayAt(deathRiff, MusicVolume()); } } finalPhaseAlive = flag2; bool flag3 = inSoulbound && killedAt < 0f && (flag || (!finalPhaseSeen && Time.time - lastBossSeen < 30f)); bool flag4 = inSoulbound && killedAt >= 0f; bool replaceMusic = HatKidSoulboundPlugin.ReplaceMusic; bool flag5 = replaceMusic && (flag3 || (flag4 && Time.time >= killedAt + 7.2f)); int num = (flag4 ? 1 : 0); if (flag5 != MusicPlayer.Wanted || (flag5 && num != MusicPlayer.WantedTrack)) { HatKidSoulboundPlugin.Log.LogInfo((object)((!flag5) ? "Music: stopping" : ((num == 0) ? "Music: Your Contract Has Expired" : "Music: Time Piece"))); if (flag5) { reportAt = Time.unscaledTime + 5f; framesAtStart = MusicPlayer.FramesWritten; } } if (reportAt > 0f && Time.unscaledTime >= reportAt) { reportAt = -1f; HatKidSoulboundPlugin.Log.LogInfo((object)($"Music: {(float)(MusicPlayer.FramesWritten - framesAtStart) / 44100f:0.0} s streamed, " + $"peak {MusicPlayer.LastPeak}, volume {MusicPlayer.Volume:0.00} (music setting {HatKidSoulboundPlugin.MusicVolume:0.00}, " + string.Format("master {0:0.00}, game music {1:0.00}, dimmed {2:0.00})", Voice.GameVolume("volume_master"), gameMusicVolume, dim))); } MusicPlayer.FadeOutSeconds = (flag4 ? 0.4f : 3f); MusicPlayer.WantedTrack = num; MusicPlayer.Wanted = flag5; MusicPlayer.Paused = PauseManager.isPaused; if (!mutedGameMusic) { gameMusicVolume = Voice.GameVolume("volume_music"); } MusicPlayer.Volume = MusicVolume() * dim; if (MusicPlayer.Wanted || MusicPlayer.Playing || (replaceMusic && flag4)) { if (!mutedGameMusic) { dim = 1f; } mutedGameMusic = true; SetMusicRtpc(0f); } else { RestoreGameMusic(); } } private static float MusicVolume() { return HatKidSoulboundPlugin.MusicVolume * Voice.GameVolume("volume_master") * gameMusicVolume; } private static void RestoreGameMusic() { if (mutedGameMusic) { mutedGameMusic = false; dim = 1f; SetMusicRtpc(gameMusicVolume * 100f); } } private static void SetMusicRtpc(float value) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ownCall = true; try { AkSoundEngine.SetRTPCValue("Volume_MSX", value); } finally { ownCall = false; } } private static void SetRtpcPrefix(object[] __args, ref float in_value) { if (ownCall || !mutedGameMusic) { return; } bool num2; if (!(__args[0] is string text)) { if (!(__args[0] is uint num)) { return; } num2 = num == ((musicRtpcId != 0) ? musicRtpcId : (musicRtpcId = AkSoundEngine.GetIDFromString("Volume_MSX"))); } else { num2 = text == "Volume_MSX"; } if (num2) { float num3 = ((gameMusicVolume > 0.001f) ? Mathf.Clamp01(in_value / (gameMusicVolume * 100f)) : 1f); if (Mathf.Abs(num3 - dim) > 0.01f) { HatKidSoulboundPlugin.Log.LogInfo((object)$"Music: another mod set the game's music to {in_value:0}; kept muted, song at {num3:0%}"); } dim = num3; in_value = 0f; } } } internal static class BossRuntime { [HarmonyPatch(typeof(ProjectileController), "Start")] private static class ProjectilePatches { private static void Prefix(ProjectileController __instance, out bool __state) { __state = false; try { if (Object.op_Implicit((Object)(object)__instance) && Shared(__instance)) { Once(string.Format("shared projectile {0} owner={1} bossSide={2}", ((Object)__instance).name, Object.op_Implicit((Object)(object)__instance.owner) ? ((Object)__instance.owner).name : "none", BossSide(__instance.owner))); if (BossSide(__instance.owner)) { __state = true; BossEffects.BeforeStart(__instance); } } } catch (Exception ex) { HatKidSoulboundPlugin.Log.LogWarning((object)("Purple projectile: " + ex.Message)); } } private static void Postfix(ProjectileController __instance, bool __state) { if (__state && Object.op_Implicit((Object)(object)__instance)) { BossEffects.AfterStart(__instance); } } } private const string ScreamEvent = "Play_Champ_Reaper_Phase2Transistion"; private const float ScreamDelay = 5f; internal const float VoiceGain = 1.035f; internal static byte[] foolVoice; private static float foolAt = -1f; private static readonly HashSet<string> logged = new HashSet<string>(); internal static bool InSoulbound { get { //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) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name == "champrush"; } } public static void Setup(Harmony harmony) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (HatKidSoulboundPlugin.RecolouredEffects) { harmony.PatchAll(typeof(ProjectilePatches)); } HarmonyMethod val = new HarmonyMethod(typeof(BossRuntime).GetMethod("PostEventPrefix", BindingFlags.Static | BindingFlags.NonPublic)); int num = 0; MethodInfo[] methods = typeof(AkSoundEngine).GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "PostEvent") && !(methodInfo.ReturnType != typeof(uint))) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length >= 2 && !(parameters[0].ParameterType != typeof(string))) { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } } } HatKidSoulboundPlugin.Log.LogInfo((object)$"Scream replacement: hooked {num} sound calls"); if (HatKidSoulboundPlugin.RecolouredEffects) { CharacterBody.onBodyStartGlobal += OnBodyStart; } } private static bool PostEventPrefix(object[] __args, ref uint __result) { if (!(__args[0] is string a) || !string.Equals(a, "Play_Champ_Reaper_Phase2Transistion", StringComparison.OrdinalIgnoreCase) || !HatKidSoulboundPlugin.SnatcherVoice) { return true; } foolAt = Time.time + 5f; __result = 0u; return false; } public static void Update() { if (!(foolAt < 0f) && !(Time.time < foolAt)) { foolAt = -1f; HatKidSoulboundPlugin.Log.LogInfo((object)"Phase 2: FOOOOOOOOL instead of the scream"); Voice.Play(foolVoice, HatKidSoulboundPlugin.FoolVolume * 1.035f); } } private static bool BossAlive() { return CharacterBody.readOnlyInstancesList.Any((CharacterBody b) => Object.op_Implicit((Object)(object)b) && IsBoss(b) && Object.op_Implicit((Object)(object)b.healthComponent) && b.healthComponent.alive); } private static bool IsBoss(CharacterBody b) { if (((Object)b).name.StartsWith("ReaperBoss")) { return !((Object)b).name.StartsWith("ReaperBossSoul"); } return false; } private static bool BossSide(GameObject owner) { CharacterBody val = (Object.op_Implicit((Object)(object)owner) ? owner.GetComponent<CharacterBody>() : null); if (Object.op_Implicit((Object)(object)val)) { if (!IsBoss(val)) { return Object.op_Implicit((Object)(object)((Component)val).GetComponent<PurpleMinion>()); } return true; } return false; } private static void OnBodyStart(CharacterBody body) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (((Object)body).name.StartsWith("UrchinTurretBody")) { bool flag = InSoulbound && BossAlive() && !Object.op_Implicit((Object)(object)((Component)body).GetComponent<PurpleMinion>()); string[] obj = new string[6] { "urchin ", flag.ToString(), " scene=", null, null, null }; Scene activeScene = SceneManager.GetActiveScene(); obj[3] = ((Scene)(ref activeScene)).name; obj[4] = " boss="; obj[5] = BossAlive().ToString(); Once(string.Concat(obj)); if (flag) { ((Component)body).gameObject.AddComponent<PurpleMinion>(); } } } private static void Once(string what) { if (logged.Add(what)) { HatKidSoulboundPlugin.Log.LogInfo((object)("Purple: " + what)); } } private static bool Shared(ProjectileController pc) { GameObject projectilePrefab = ProjectileCatalog.GetProjectilePrefab(pc.catalogIndex); if (Object.op_Implicit((Object)(object)projectilePrefab)) { return BossEffects.sharedProjectileNames.Contains(((Object)projectilePrefab).name); } return false; } } [DefaultExecutionOrder(10000)] public class PurpleMinion : MonoBehaviour { private CharacterModel model; private MaterialPropertyBlock block; private float nextScan; private void Start() { CharacterBody component = ((Component)this).GetComponent<CharacterBody>(); object obj; if (component == null) { obj = null; } else { ModelLocator modelLocator = component.modelLocator; obj = ((modelLocator != null) ? modelLocator.modelTransform : null); } Transform val = (Transform)obj; model = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<CharacterModel>() : null); } private void LateUpdate() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)model)) { RendererInfo[] baseRendererInfos = model.baseRendererInfos; for (int i = 0; i < baseRendererInfos.Length; i++) { if (Object.op_Implicit((Object)(object)baseRendererInfos[i].defaultMaterial)) { baseRendererInfos[i].defaultMaterial = Purple.Material(baseRendererInfos[i].defaultMaterial); } } } block = (MaterialPropertyBlock)(((object)block) ?? ((object)new MaterialPropertyBlock())); Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { Purple.Renderer(val); if (val.HasPropertyBlock()) { Purple.Block(val, block); } } if (!(Time.time >= nextScan)) { return; } nextScan = Time.time + 0.5f; ParticleSystem[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<ParticleSystem>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { Purple.Particles(componentsInChildren2[j]); } Light[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Light>(true); foreach (Light val2 in componentsInChildren3) { if (Purple.IsColoured(val2.color)) { val2.color = Purple.Shift(val2.color); } } } } [DefaultExecutionOrder(10000)] public class BossSnatcher : MonoBehaviour { internal static Material snatcherMaterial; internal static Mesh emptyMesh; private static readonly string[] hiddenParts = new string[11] { "cyrstals", "horns", "inner_cloak", "Harvester_Head_Main", "Harvester_Head_Main_Eyes", "Harvester_Head_False", "Harvester_Head_False_Eyes", "Harvester_Weapon", "Harvester_Weapon_blade", "Symbol", "ring" }; public Mesh snatcherMesh; private CharacterModel characterModel; private SkinnedMeshRenderer body; private SkinnedMeshRenderer[] hidden; private MaterialPropertyBlock block; private float nextEffectScan; private readonly HashSet<int> recoloured = new HashSet<int>(); private void Awake() { characterModel = ((Component)this).GetComponent<CharacterModel>(); body = Find("Harvester_Body"); hidden = (from r in hiddenParts.Select(Find) where Object.op_Implicit((Object)(object)r) select r).ToArray(); } private SkinnedMeshRenderer Find(string path) { Transform val = ((Component)this).transform.Find(path); if (!Object.op_Implicit((Object)(object)val)) { return null; } return ((Component)val).GetComponent<SkinnedMeshRenderer>(); } private void LateUpdate() { if (!Object.op_Implicit((Object)(object)body)) { return; } if (Object.op_Implicit((Object)(object)snatcherMesh) && (Object)(object)body.sharedMesh != (Object)(object)snatcherMesh) { body.sharedMesh = snatcherMesh; } SkinnedMeshRenderer[] array = hidden; foreach (SkinnedMeshRenderer val in array) { if ((Object)(object)val.sharedMesh != (Object)(object)emptyMesh) { val.sharedMesh = emptyMesh; } } RendererInfo[] array2 = (Object.op_Implicit((Object)(object)characterModel) ? characterModel.baseRendererInfos : null); if (array2 != null) { for (int j = 0; j < array2.Length; j++) { Renderer renderer = array2[j].renderer; if ((Object)(object)renderer == (Object)(object)body && (Object)(object)array2[j].defaultMaterial != (Object)(object)snatcherMaterial) { array2[j].defaultMaterial = snatcherMaterial; ((Renderer)body).sharedMaterial = snatcherMaterial; } else if (HatKidSoulboundPlugin.RecolouredEffects && Object.op_Implicit((Object)(object)renderer) && (Object)(object)renderer != (Object)(object)body && !(renderer is SkinnedMeshRenderer) && Object.op_Implicit((Object)(object)array2[j].defaultMaterial)) { array2[j].defaultMaterial = Purple.Material(array2[j].defaultMaterial); } } } if (HatKidSoulboundPlugin.RecolouredEffects) { KeepPurple((Renderer)(object)body); if (Time.time >= nextEffectScan) { nextEffectScan = Time.time + 0.2f; RecolourAttachedEffects(); } } } private void KeepPurple(Renderer r) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) Material[] sharedMaterials = r.sharedMaterials; bool flag = false; for (int i = 0; i < sharedMaterials.Length; i++) { if (Object.op_Implicit((Object)(object)sharedMaterials[i]) && !((Object)(object)sharedMaterials[i] == (Object)(object)snatcherMaterial)) { Material val = Purple.Material(sharedMaterials[i]); if ((Object)(object)val != (Object)(object)sharedMaterials[i]) { sharedMaterials[i] = val; flag = true; } } } if (flag) { r.sharedMaterials = sharedMaterials; } if (r.HasPropertyBlock()) { block = (MaterialPropertyBlock)(((object)block) ?? ((object)new MaterialPropertyBlock())); Purple.Block(r, block); r.GetPropertyBlock(block); if (block.HasFloat("_EliteIndex") && block.GetFloat("_EliteIndex") != 0f) { block.SetFloat("_EliteIndex", 0f); r.SetPropertyBlock(block); } } } private void RecolourAttachedEffects() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) CharacterBody val = (Object.op_Implicit((Object)(object)characterModel) ? characterModel.body : null); Transform val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).transform : ((Component)this).transform); Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren) { if (recoloured.Add(((Object)val3).GetInstanceID()) && (val3 is ParticleSystemRenderer || val3 is TrailRenderer || val3 is LineRenderer || Object.op_Implicit((Object)(object)((Component)val3).GetComponentInParent<EffectComponent>()) || Object.op_Implicit((Object)(object)((Component)val3).GetComponentInParent<VFXAttributes>()))) { Purple.All(((Component)val3).gameObject); } } Light[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Light>(true); foreach (Light val4 in componentsInChildren2) { if (recoloured.Add(((Object)val4).GetInstanceID()) && Purple.IsColoured(val4.color)) { val4.color = Purple.Shift(val4.color); } } } } [BepInPlugin("com.chaz.hatkidsoulbound", "Snatcher over Anima Harvester (boss)", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class HatKidSoulboundPlugin : BaseUnityPlugin { public const string PluginGUID = "com.chaz.hatkidsoulbound"; public const string PluginName = "Snatcher over Anima Harvester (boss)"; public const string PluginVersion = "1.0.1"; private const string StageScene = "champrush"; private const float HatKidScale = 0.9f; private const float ChainedScale = 1f; internal static ManualLogSource Log; internal static ConfigEntry<bool> replaceMusic; internal static ConfigEntry<bool> replaceBossTitle; internal static ConfigEntry<bool> recolouredEffects; internal static ConfigEntry<bool> snatcherVoice; internal static ConfigEntry<float> musicVolume; internal static ConfigEntry<float> voiceVolume; private static Dictionary<string, Matrix4x4> acolyteBindposes; private static Dictionary<string, Matrix4x4> harvesterBindposes; private static Material bodyMat; private static Material faceMat; private static Material umbrellaMat; internal static bool ReplaceMusic => replaceMusic.Value; internal static bool ReplaceBossTitle => replaceBossTitle.Value; internal static bool SnatcherVoice => snatcherVoice.Value; internal static float MusicVolume => musicVolume.Value; internal static float FoolVolume => voiceVolume.Value; internal static bool RecolouredEffects { get; private set; } private void Awake() { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Expected O, but got Unknown //IL_028b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; replaceMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Replace music", true, "Play A Hat in Time's \"Your Contract Has Expired\" during the boss fight instead of the normal boss music, the boss-death riff on the killing blow, and the Time Piece's calm music after the fight."); replaceBossTitle = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Replace boss title", true, "Show the boss as \"The Snatcher\" with the subtitle \"The Soulbound Contractor\" instead of \"Anima Harvester\" / \"Avatar of N'kuhana\"."); recolouredEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Recoloured effects", true, "The boss's attacks and the stage's ritual, cutscene, pit and door effects in Hat Kid's purple. Off: the usual green. Takes effect after restarting the game."); RecolouredEffects = recolouredEffects.Value; snatcherVoice = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Snatcher voice lines", true, "\"Ahahaa, FOOOOOL\" when the Snatcher appears, and \"FOOOOOOOOL\" instead of the Anima Harvester's scream when his second phase starts."); voiceVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Voice volume", 1f, new ConfigDescription("Volume of the Snatcher's lines (0-1), multiplied by the game's Master and SFX volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); musicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Music volume", 1f, new ConfigDescription("Volume of the music (0-1), multiplied by the game's Master and Music volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { try { ModSettings.Register(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Couldn't add the mod settings page: " + ex.Message)); } } try { LoadHatKid(); HatKidify(HatKidSoulboundPlugin.Load<GameObject>("RoR2/DLC4/champrush/UnlockableAcolyteInteractable.prefab").transform, "revivable Acolyte", 0.9f); SceneManager.sceneLoaded += OnSceneLoaded; } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Hat Kid NPC setup failed: " + ex2)); } if (RecolouredEffects) { try { BossEffects.Setup(); } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogError((object)("Boss effects setup failed: " + ex3)); } } try { using (Stream s = typeof(Assets).Assembly.GetManifestResourceStream("snatcher_fool.wav")) { BossRuntime.foolVoice = Voice.Load(s); } using (Stream s2 = typeof(Assets).Assembly.GetManifestResourceStream("snatcher_ahahaa_fool.wav")) { BossFight.spawnVoice = Voice.Load(s2); } using (Stream s3 = typeof(Assets).Assembly.GetManifestResourceStream("boss_death_riff.wav")) { BossFight.deathRiff = Voice.Load(s3); } Harmony val = new Harmony("com.chaz.hatkidsoulbound"); BossRuntime.Setup(val); BossFight.Setup(val); } catch (Exception ex4) { ((BaseUnityPlugin)this).Logger.LogError((object)("Boss runtime setup failed: " + ex4)); } RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate { try { SetUpBosses(); } catch (Exception ex5) { ((BaseUnityPlugin)this).Logger.LogError((object)("Snatcher boss setup failed: " + ex5)); } }); } private void Update() { Voice.Cleanup(); BossRuntime.Update(); BossFight.Update(); } private void OnDestroy() { Voice.StopAll(); BossFight.Shutdown(); } private void LoadHatKid() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown acolyteBindposes = Assets.ReadBindposes("bindposes.bin"); harvesterBindposes = Assets.ReadBindposes("harvester_bindposes.bin"); Material template = HatKidSoulboundPlugin.Load<Material>("RoR2/DLC4/Acolyte/matAcolyteBody.mat"); bodyMat = Assets.MakeMaterial(template, "matHatKidBody", Assets.ReadTexture("hatkid_body.png"), cutout: false); faceMat = Assets.MakeMaterial(template, "matHatKidFace", Assets.ReadTexture("hatkid_face.png"), cutout: true); umbrellaMat = Assets.MakeMaterial(template, "matHatKidUmbrella", Assets.ReadTexture("umbrella.png"), cutout: false); Material val = Assets.MakeMaterial(template, "matSnatcher", Assets.ReadTexture("snatcher_albedo.png"), cutout: false); val.SetTexture("_EmTex", (Texture)(object)Assets.ReadTexture("snatcher_glow.png")); val.SetColor("_EmColor", Color.white); val.SetFloat("_EmPower", 2f); Texture texture = val.GetTexture("_FresnelRamp"); if (Object.op_Implicit((Object)(object)texture)) { val.SetTexture("_FresnelRamp", Purple.Texture(texture)); } BossSnatcher.snatcherMaterial = val; BossSnatcher.emptyMesh = new Mesh { name = "HatKidSoulboundEmpty" }; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (((Scene)(ref scene)).name != "champrush") { return; } int num = 0; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Transform[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "mdlAcolyte" && !Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<CharacterModel>()) && !Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<CharacterBody>())) { Transform parent = val.parent; HatKidify(val, "chained Acolyte (" + ((parent != null) ? ((Object)parent).name : null) + ")", 1f); num++; } } } if (num == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No Acolyte found in Soulbound Threshold"); } if (!RecolouredEffects) { return; } try { StagePurple.Apply(scene); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Stage purple failed: " + ex)); } } internal static void HatKidify(Transform mdlAcolyte, string what, float scale) { //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) if (((Object)mdlAcolyte).name != "mdlAcolyte") { mdlAcolyte = ((IEnumerable<Transform>)((Component)mdlAcolyte).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "mdlAcolyte")); } if (!Object.op_Implicit((Object)(object)mdlAcolyte)) { throw new Exception("No mdlAcolyte in " + what); } if (Object.op_Implicit((Object)(object)((Component)mdlAcolyte).GetComponent<HatKidNpc>())) { return; } HatKidNpc hatKidNpc = ((Component)mdlAcolyte).gameObject.AddComponent<HatKidNpc>(); hatKidNpc.scale = scale; SkinnedMeshRenderer[] componentsInChildren = ((Component)mdlAcolyte).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (((Object)val).name == "acolyte_geo") { hatKidNpc.Add(val, Assets.ReadSkinnedMesh("hatkid_body.hkm", val, acolyteBindposes), bodyMat, face: false); } else if (((Object)val).name.StartsWith("acolyte_eyes")) { hatKidNpc.Add(val, Assets.ReadSkinnedMesh("hatkid_face.hkm", val, acolyteBindposes), faceMat, face: true); } else if (((Object)val).name == "Acolyte_Weapon_geo") { hatKidNpc.Add(val, Assets.ReadSkinnedMesh("umbrella.hkm", val, acolyteBindposes), Object.op_Implicit((Object)(object)((Renderer)val).sharedMaterial) ? umbrellaMat : null, face: false); } } hatKidNpc.Apply(); mdlAcolyte.localScale = Vector3.one * scale; Log.LogInfo((object)$"Hat Kid: {what} ({hatKidNpc.Count} parts)"); } private void SetUpBosses() { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (GameObject allBodyPrefab in BodyCatalog.allBodyPrefabs) { if (!Object.op_Implicit((Object)(object)allBodyPrefab) || !((Object)allBodyPrefab).name.StartsWith("ReaperBoss") || ((Object)allBodyPrefab).name.StartsWith("ReaperBossSoul")) { continue; } ModelLocator component = allBodyPrefab.GetComponent<ModelLocator>(); Transform val = ((component != null) ? component.modelTransform : null); object obj; if (!Object.op_Implicit((Object)(object)val)) { obj = null; } else { Transform obj2 = val.Find("Harvester_Body"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<SkinnedMeshRenderer>() : null); } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)obj; if (Object.op_Implicit((Object)(object)val2)) { if (!Object.op_Implicit((Object)(object)((Component)val).GetComponent<BossSnatcher>())) { ((Component)val).gameObject.AddComponent<BossSnatcher>().snatcherMesh = Assets.ReadSkinnedMesh("snatcher.hkm", val2, harvesterBindposes); } num++; ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Snatcher boss: {((Object)allBodyPrefab).name} (model scale {val.localScale.x})"); } } if (num == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Soulbound Threshold boss body not found"); } } internal static T Load<T>(string key) where T : Object { //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) T val = Addressables.LoadAssetAsync<T>((object)key).WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val)) { throw new Exception("Missing addressable " + key); } return val; } } [DefaultExecutionOrder(10000)] public class HatKidNpc : MonoBehaviour { public float scale = 1f; private readonly List<(SkinnedMeshRenderer renderer, Mesh mesh, Material material, bool face)> parts = new List<(SkinnedMeshRenderer, Mesh, Material, bool)>(); public int Count => parts.Count; private void Awake() { if (parts.Count > 0) { return; } SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val.sharedMesh) && (((Object)val.sharedMesh).name.StartsWith("hatkid_") || ((Object)val.sharedMesh).name == "umbrella")) { Add(val, val.sharedMesh, ((Renderer)val).sharedMaterial, ((Object)val).name.StartsWith("acolyte_eyes")); } } } public void Add(SkinnedMeshRenderer r, Mesh mesh, Material material, bool face) { r.updateWhenOffscreen = true; parts.Add((r, mesh, material, face)); } public void Apply() { foreach (var (val, val2, val3, flag) in parts) { if (Object.op_Implicit((Object)(object)val)) { if ((Object)(object)val.sharedMesh != (Object)(object)val2) { val.sharedMesh = val2; } if (Object.op_Implicit((Object)(object)val3) && (((Renderer)val).sharedMaterials.Length != 1 || (Object)(object)((Renderer)val).sharedMaterial != (Object)(object)val3)) { ((Renderer)val).sharedMaterials = (Material[])(object)new Material[1] { val3 }; } if (flag && ((Renderer)val).HasPropertyBlock()) { ((Renderer)val).SetPropertyBlock((MaterialPropertyBlock)null); } } } } private void LateUpdate() { //IL_000c: 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_002f: Unknown result type (might be due to invalid IL or missing references) Apply(); if (((Component)this).transform.localScale.x != scale) { ((Component)this).transform.localScale = Vector3.one * scale; } } } internal static class Assets { private static readonly Dictionary<string, Mesh> meshes = new Dictionary<string, Mesh>(); private static Stream Open(string name) { return typeof(Assets).Assembly.GetManifestResourceStream(name) ?? throw new FileNotFoundException("Embedded resource missing: " + name); } public static Dictionary<string, Matrix4x4> ReadBindposes(string name) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) using BinaryReader binaryReader = new BinaryReader(Open(name)); Dictionary<string, Matrix4x4> dictionary = new Dictionary<string, Matrix4x4>(); int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { string key = ReadString(binaryReader); Matrix4x4 value = default(Matrix4x4); for (int j = 0; j < 16; j++) { ((Matrix4x4)(ref value))[j / 4, j % 4] = binaryReader.ReadSingle(); } dictionary[key] = value; } return dictionary; } public static Mesh ReadSkinnedMesh(string name, SkinnedMeshRenderer target, Dictionary<string, Matrix4x4> bindposes) { //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown Transform[] bones = target.bones; string key = name + "|" + string.Join(",", bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name)); if (meshes.TryGetValue(key, out var value)) { return value; } using BinaryReader binaryReader = new BinaryReader(Open(name)); if (new string(binaryReader.ReadChars(4)) != "HKM1") { throw new InvalidDataException(name); } int num = binaryReader.ReadInt32(); string[] array = new string[num]; for (int num2 = 0; num2 < num; num2++) { array[num2] = ReadString(binaryReader); } Dictionary<string, int> byName = new Dictionary<string, int>(); for (int num3 = 0; num3 < bones.Length; num3++) { if (Object.op_Implicit((Object)(object)bones[num3]) && !byName.ContainsKey(((Object)bones[num3]).name)) { byName[((Object)bones[num3]).name] = num3; } } Matrix4x4 value2; int[] array2 = array.Select(delegate(string b) { if (!byName.TryGetValue(b, out value2)) { throw new Exception(name + ": bone " + b + " not on " + ((Object)target).name); } return value2; }).ToArray(); int num4 = binaryReader.ReadInt32(); Vector3[] array3 = (Vector3[])(object)new Vector3[num4]; Vector3[] array4 = (Vector3[])(object)new Vector3[num4]; Vector2[] array5 = (Vector2[])(object)new Vector2[num4]; for (int num5 = 0; num5 < num4; num5++) { array3[num5] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); } for (int num6 = 0; num6 < num4; num6++) { array4[num6] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); } for (int num7 = 0; num7 < num4; num7++) { array5[num7] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()); } int[] array6 = new int[num4 * 4]; for (int num8 = 0; num8 < array6.Length; num8++) { array6[num8] = array2[binaryReader.ReadInt32()]; } BoneWeight[] array7 = (BoneWeight[])(object)new BoneWeight[num4]; for (int num9 = 0; num9 < num4; num9++) { float weight = binaryReader.ReadSingle(); float weight2 = binaryReader.ReadSingle(); float weight3 = binaryReader.ReadSingle(); float weight4 = binaryReader.ReadSingle(); int num10 = num9; BoneWeight val = default(BoneWeight); ((BoneWeight)(ref val)).boneIndex0 = array6[num9 * 4]; ((BoneWeight)(ref val)).boneIndex1 = array6[num9 * 4 + 1]; ((BoneWeight)(ref val)).boneIndex2 = array6[num9 * 4 + 2]; ((BoneWeight)(ref val)).boneIndex3 = array6[num9 * 4 + 3]; ((BoneWeight)(ref val)).weight0 = weight; ((BoneWeight)(ref val)).weight1 = weight2; ((BoneWeight)(ref val)).weight2 = weight3; ((BoneWeight)(ref val)).weight3 = weight4; array7[num10] = val; } int num11 = binaryReader.ReadInt32(); int[] array8 = new int[num11]; for (int num12 = 0; num12 < num11; num12++) { array8[num12] = binaryReader.ReadInt32(); } Mesh val2 = new Mesh { name = Path.GetFileNameWithoutExtension(name) }; if (num4 > 65535) { val2.indexFormat = (IndexFormat)1; } val2.vertices = array3; val2.normals = array4; val2.uv = array5; val2.SetIndices(array8, (MeshTopology)0, 0); val2.boneWeights = array7; val2.bindposes = bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b) || !bindposes.TryGetValue(((Object)b).name, out value2)) ? Matrix4x4.identity : value2).ToArray(); val2.RecalculateTangents(); val2.RecalculateBounds(); meshes[key] = val2; return val2; } public static Texture2D ReadTexture(string name) { //IL_0018: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown using Stream stream = Open(name); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true) { name = Path.GetFileNameWithoutExtension(name) }; ImageConversion.LoadImage(val, memoryStream.ToArray()); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)2; val.Apply(true, true); return val; } public static Material MakeMaterial(Material template, string name, Texture2D tex, bool cutout) { //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_000e: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(template) { name = name }; val.SetTexture("_MainTex", (Texture)(object)tex); val.SetTexture("_NormalTex", (Texture)null); val.SetFloat("_NormalStrength", 0f); val.SetColor("_EmColor", Color.black); val.SetTexture("_EmTex", (Texture)null); val.SetFloat("_LimbRemovalOn", 0f); val.DisableKeyword("LIMBREMOVAL"); val.SetFloat("_EnableCutout", cutout ? 1f : 0f); if (cutout) { val.EnableKeyword("CUTOUT"); } else { val.DisableKeyword("CUTOUT"); } return val; } private static string ReadString(BinaryReader r) { return Encoding.UTF8.GetString(r.ReadBytes(r.ReadInt32())); } } internal static class ModSettings { public const string RiskOfOptionsGUID = "com.rune580.riskofoptions"; public static void Register() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown ModSettingsManager.SetModDescription("Soulbound Threshold with Hat Kid and the Snatcher."); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(HatKidSoulboundPlugin.replaceMusic)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(HatKidSoulboundPlugin.replaceBossTitle)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(HatKidSoulboundPlugin.recolouredEffects, new CheckBoxConfig { restartRequired = true })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(HatKidSoulboundPlugin.snatcherVoice)); ModSettingsManager.AddOption((BaseOption)new SliderOption(HatKidSoulboundPlugin.voiceVolume, new SliderConfig { min = 0f, max = 1f, formatString = "{0:0%}" })); ModSettingsManager.AddOption((BaseOption)new SliderOption(HatKidSoulboundPlugin.musicVolume, new SliderConfig { min = 0f, max = 1f, formatString = "{0:0%}" })); } } internal static class MusicPlayer { private struct WaveFormat { public short wFormatTag; public short nChannels; public int nSamplesPerSec; public int nAvgBytesPerSec; public short nBlockAlign; public short wBitsPerSample; public short cbSize; } private struct WaveHeader { public IntPtr lpData; public int dwBufferLength; public int dwBytesRecorded; public IntPtr dwUser; public int dwFlags; public int dwLoops; public IntPtr lpNext; public IntPtr reserved; } private class Channel { public int start; public int value; public int index; public int startValue; public int startIndex; public void Reset() { value = startValue; index = startIndex; } public short Next(byte[] data, int frame) { int num = data[start + (frame >> 1)]; int num2 = (((frame & 1) == 0) ? (num >> 4) : (num & 0xF)); int num3 = Steps[index]; index = Math.Min(88, Math.Max(0, index + IndexStep[num2])); int num4 = num3 >> 3; if ((num2 & 4) != 0) { num4 += num3; } if ((num2 & 2) != 0) { num4 += num3 >> 1; } if ((num2 & 1) != 0) { num4 += num3 >> 2; } value = (((num2 & 8) != 0) ? (value - num4) : (value + num4)); value = Math.Max(-32768, Math.Min(32767, value)); return (short)value; } } private class Track { public byte[] data; public int headFrames; public int loopFrames; public Channel headL; public Channel headR; public Channel loopL; public Channel loopR; } private const int BufferFrames = 2205; private const int BufferCount = 8; private const int WAVE_MAPPER = -1; private const int CALLBACK_EVENT = 327680; private const int WHDR_DONE = 1; private static readonly int headerSize = Marshal.SizeOf(typeof(WaveHeader)); private static readonly int flagsOffset = (int)Marshal.OffsetOf(typeof(WaveHeader), "dwFlags"); private static readonly short[] Steps = new short[89] { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; private static readonly sbyte[] IndexStep = new sbyte[16] { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; public static volatile bool Wanted; public static volatile bool Paused; public static volatile int WantedTrack; public static volatile float Volume; public static volatile float FadeInSeconds = 0.5f; public static volatile float FadeOutSeconds = 3f; public static volatile bool Playing; public static long FramesWritten; public static volatile int LastPeak; public static volatile int OpenError; private static readonly Track[] tracks = new Track[4]; private static int rate = 44100; private static Thread thread; private static volatile bool quit; [DllImport("winmm.dll")] private static extern int waveOutOpen(out IntPtr handle, int deviceId, ref WaveFormat format, IntPtr callback, IntPtr instance, int flags); [DllImport("winmm.dll")] private static extern int waveOutPrepareHeader(IntPtr handle, IntPtr header, int size); [DllImport("winmm.dll")] private static extern int waveOutWrite(IntPtr handle, IntPtr header, int size); [DllImport("winmm.dll")] private static extern int waveOutUnprepareHeader(IntPtr handle, IntPtr header, int size); [DllImport("winmm.dll")] private static extern int waveOutPause(IntPtr handle); [DllImport("winmm.dll")] private static extern int waveOutRestart(IntPtr handle); [DllImport("winmm.dll")] private static extern int waveOutReset(IntPtr handle); [DllImport("winmm.dll")] private static extern int waveOutClose(IntPtr handle); public static bool Load(int slot, byte[] snm) { if (snm == null || snm.Length < 32 || snm[0] != 83 || snm[1] != 78 || snm[2] != 77 || snm[3] != 52) { return false; } rate = BitConverter.ToInt32(snm, 4); short num = BitConverter.ToInt16(snm, 8); int num2 = BitConverter.ToInt32(snm, 18); int num3 = BitConverter.ToInt32(snm, 22); if (num != 2 || num3 <= 0 || snm.Length < 32 + 2 * num2 + 2 * num3) { return false; } tracks[slot] = new Track { data = snm, headFrames = Math.Min(BitConverter.ToInt32(snm, 10), num2 * 2), loopFrames = Math.Min(BitConverter.ToInt32(snm, 14), num3 * 2), headL = new Channel { start = 32 }, headR = new Channel { start = 32 + num2 }, loopL = new Channel { start = 32 + 2 * num2, startValue = BitConverter.ToInt16(snm, 26), startIndex = (sbyte)snm[28] }, loopR = new Channel { start = 32 + 2 * num2 + num3, startValue = BitConverter.ToInt16(snm, 29), startIndex = (sbyte)snm[31] } }; return true; } public static void Start() { if (thread == null) { quit = false; thread = new Thread(Run) { IsBackground = true, Name = "HatKidSoulboundMusic" }; thread.Start(); } } public static void Stop() { quit = true; thread?.Join(500); thread = null; } private static void Run() { AutoResetEvent autoResetEvent = new AutoResetEvent(initialState: false); IntPtr[] array = new IntPtr[8]; IntPtr[] array2 = new IntPtr[8]; bool[] array3 = new bool[8]; byte[] array4 = new byte[8820]; for (int i = 0; i < 8; i++) { array[i] = Marshal.AllocHGlobal(headerSize); array2[i] = Marshal.AllocHGlobal(array4.Length); } IntPtr handle = IntPtr.Zero; Track track = null; bool flag = false; bool flag2 = false; int num = 0; float num2 = 0f; float num3 = 0f; try { while (!quit) { autoResetEvent.WaitOne(20); Track track2 = (Wanted ? tracks[Math.Max(0, Math.Min(tracks.Length - 1, WantedTrack))] : null); bool flag3 = track2 != null && (handle == IntPtr.Zero || track2 == track); if (handle == IntPtr.Zero) { if (!flag3) { Playing = false; continue; } track = track2; WaveFormat format = new WaveFormat { wFormatTag = 1, nChannels = 2, nSamplesPerSec = rate, wBitsPerSample = 16, nBlockAlign = 4, nAvgBytesPerSec = rate * 4 }; int num4 = waveOutOpen(out handle, -1, ref format, autoResetEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, 327680); if (num4 != 0) { if (OpenError != num4) { HatKidSoulboundPlugin.Log.LogWarning((object)("Music: couldn't open the audio device (waveOut error " + num4 + ")")); } OpenError = num4; handle = IntPtr.Zero; Thread.Sleep(1000); continue; } for (int j = 0; j < 8; j++) { Marshal.StructureToPtr(new WaveHeader { lpData = array2[j], dwBufferLength = array4.Length }, array[j], fDeleteOld: false); waveOutPrepareHeader(handle, array[j], headerSize); array3[j] = false; } num = 0; flag2 = track.headFrames <= 0; track.headL.Reset(); track.headR.Reset(); track.loopL.Reset(); track.loopR.Reset(); num2 = (num3 = 0f); flag = false; Playing = true; } if (Paused != flag) { flag = Paused; if (flag) { waveOutPause(handle); } else { waveOutRestart(handle); } } bool flag4 = false; for (int k = 0; k < 8; k++) { if (array3[k] && (Marshal.ReadInt32(array[k], flagsOffset) & 1) == 0) { flag4 = true; continue; } array3[k] = false; if (!flag3 && num2 <= 0f) { continue; } float num5 = 2205f / (float)rate; num2 = (flag3 ? Math.Min(1f, num2 + num5 / Math.Max(0.01f, FadeInSeconds)) : Math.Max(0f, num2 - num5 / Math.Max(0.01f, FadeOutSeconds))); float num6 = Volume * num2 * num2; for (int l = 0; l < 2205; l++) { float num7 = num3 + (num6 - num3) * ((float)l + 1f) / 2205f; int val; int val2; if (!flag2) { val = (int)((float)track.headL.Next(track.data, num) * num7); val2 = (int)((float)track.headR.Next(track.data, num) * num7); if (++num >= track.headFrames) { num = 0; flag2 = true; } } else { val = (int)((float)track.loopL.Next(track.data, num) * num7); val2 = (int)((float)track.loopR.Next(track.data, num) * num7); if (++num >= track.loopFrames) { num = 0; track.loopL.Reset(); track.loopR.Reset(); } } val = Math.Max(-32768, Math.Min(32767, val)); val2 = Math.Max(-32768, Math.Min(32767, val2)); array4[l * 4] = (byte)val; array4[l * 4 + 1] = (byte)(val >> 8); array4[l * 4 + 2] = (byte)val2; array4[l * 4 + 3] = (byte)(val2 >> 8); } num3 = num6; int num8 = 0; for (int m = 0; m < array4.Length; m += 2) { num8 = Math.Max(num8, Math.Abs((int)(short)(array4[m] | (array4[m + 1] << 8)))); } LastPeak = num8; FramesWritten += 2205L; Marshal.Copy(array4, 0, array2[k], array4.Length); waveOutWrite(handle, array[k], headerSize); flag4 = (array3[k] = true); } if (!flag3 && num2 <= 0f && !flag4) { Close(ref handle, array); } } } catch (Exception ex) { HatKidSoulboundPlugin.Log.LogWarning((object)("Music stream stopped: " + ex)); } finally { Close(ref handle, array); for (int n = 0; n < 8; n++) { Marshal.FreeHGlobal(array[n]); Marshal.FreeHGlobal(array2[n]); } autoResetEvent.Close(); Playing = false; } } private static void Close(ref IntPtr handle, IntPtr[] headers) { if (!(handle == IntPtr.Zero)) { waveOutReset(handle); foreach (IntPtr header in headers) { waveOutUnprepareHeader(handle, header, headerSize); } waveOutClose(handle); handle = IntPtr.Zero; Playing = false; } } } internal static class Purple { private const float TargetHue = 0.78f; private static readonly Dictionary<Texture, Texture> textures = new Dictionary<Texture, Texture>(); private static readonly Dictionary<Material, Material> materials = new Dictionary<Material, Material>(); private static readonly Dictionary<Material, Material> glowMaterials = new Dictionary<Material, Material>(); private const float SkyMinSaturation = 0.3f; private const float SkyMinShift = 0.04f; private static readonly Dictionary<Texture, Texture> skyTextures = new Dictionary<Texture, Texture>(); private static readonly Dictionary<Material, Material> skyMaterials = new Dictionary<Material, Material>(); private static readonly string[] blockColours = new string[7] { "_EmColor", "_Color", "_TintColor", "_FlashColor", "_EmissionColor", "_MainColor", "_GlowColor" }; private static readonly string[] blockTextures = new string[4] { "_FresnelRamp", "_RemapTex", "_EmTex", "_MainTex" }; public static bool IsColoured(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(c, ref num, ref num2, ref num3); if (num2 > 0.25f && num3 > 0.03f) { return Mathf.Abs(num - 0.78f) > 0.002f; } return false; } public static Color Shift(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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) if (!IsColoured(c)) { return c; } float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(c, ref num, ref num2, ref num3); Color result = Color.HSVToRGB(0.78f, num2, num3, true); result.a = c.a; return result; } public static Color Force(Color c, float minSaturation, float minSaturationToShift = 0f) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(c, ref num, ref num2, ref num3); if (num2 < minSaturationToShift) { return c; } Color result = Color.HSVToRGB(0.78f, Mathf.Max(num2, minSaturation), num3, true); result.a = c.a; return result; } public static Gradient Shift(Gradient g) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown if (g == null) { return null; } GradientColorKey[] colorKeys = g.colorKeys; bool flag = false; for (int i = 0; i < colorKeys.Length; i++) { if (IsColoured(colorKeys[i].color)) { colorKeys[i].color = Shift(colorKeys[i].color); flag = true; } } if (!flag) { return g; } Gradient val = new Gradient { mode = g.mode }; val.SetKeys(colorKeys, g.alphaKeys); return val; } public static MinMaxGradient Shift(MinMaxGradient m) { //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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ParticleSystemGradientMode mode = ((MinMaxGradient)(ref m)).mode; switch ((int)mode) { case 0: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).color)); case 2: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).colorMin), Shift(((MinMaxGradient)(ref m)).colorMax)); case 1: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).gradient)); case 3: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).gradientMin), Shift(((MinMaxGradient)(ref m)).gradientMax)); case 4: { MinMaxGradient result = default(MinMaxGradient); ((MinMaxGradient)(ref result))..ctor(Shift(((MinMaxGradient)(ref m)).gradient)); ((MinMaxGradient)(ref result)).mode = (ParticleSystemGradientMode)4; return result; } default: return m; } } public static Texture Texture(Texture t) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)t) || !(t is Texture2D) || (int)t.dimension != 2) { return t; } if (textures.TryGetValue(t, out var value)) { return value; } Texture val = t; try { int w; int h; Color32[] array = Read(t, out w, out h); int num = 0; for (int i = 0; i < array.Length; i++) { Color c = Color32.op_Implicit(array[i]); if (IsColoured(c)) { array[i] = Color32.op_Implicit(Shift(c)); num++; } } if (num > array.Length / 200) { Texture2D val2 = new Texture2D(w, h, (TextureFormat)4, t.mipmapCount > 1) { name = ((Object)t).name + "_Purple", wrapMode = t.wrapMode, filterMode = t.filterMode, anisoLevel = t.anisoLevel }; val2.SetPixels32(array); val2.Apply(true, true); val = (Texture)val2; } } catch (Exception ex) { HatKidSoulboundPlugin.Log.LogWarning((object)("Couldn't recolour " + ((Object)t).name + ": " + ex.Message)); } textures[t] = val; return val; } private static Color32[] Read(Texture t, out int w, out int h) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Color32[] array = Blit(t, 64, 64); bool flag = false; Color32[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (IsColoured(Color32.op_Implicit(array2[i]))) { flag = true; break; } } if (!flag) { w = 64; h = 64; return (Color32[])(object)new Color32[0]; } w = Mathf.Min(t.width, 1024); h = Mathf.Min(t.height, 1024); return Blit(t, w, h); } private static Color32[] Blit(Texture t, int w, int h) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown RenderTexture temporary = RenderTexture.GetTemporary(w, h, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); Graphics.Blit(t, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(w, h, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)w, (float)h), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); Color32[] pixels = val.GetPixels32(); Object.Destroy((Object)val); return pixels; } public static Material Material(Material m, bool glowOnly = false) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)m)) { return m; } if (((Object)m).name.Contains("TeamAreaIndicator")) { return m; } Dictionary<Material, Material> dictionary = (glowOnly ? glowMaterials : materials); if (dictionary.TryGetValue(m, out var value)) { return value; } Material val = null; Shader shader = m.shader; for (int i = 0; i < shader.GetPropertyCount(); i++) { string propertyName = shader.GetPropertyName(i); ShaderPropertyType propertyType = shader.GetPropertyType(i); if ((int)propertyType != 0) { if ((int)propertyType == 4 && !propertyName.Contains("Normal") && !propertyName.Contains("Bump") && (!glowOnly || propertyName.Contains("Ramp") || propertyName.Contains("Remap") || propertyName.Contains("Em") || propertyName.Contains("Glow"))) { Texture texture = m.GetTexture(propertyName); Texture val2 = Texture(texture); if ((Object)(object)val2 != (Object)(object)texture) { val = (Material)(((object)val) ?? ((object)new Material(m) { name = ((Object)m).name + "_Purple" })); val.SetTexture(propertyName, val2); } } } else { Color color = m.GetColor(propertyName); if (IsColoured(color)) { val = (Material)(((object)val) ?? ((object)new Material(m) { name = ((Object)m).name + "_Purple" })); val.SetColor(propertyName, Shift(color)); } } } dictionary[m] = val ?? m; dictionary[val ?? m] = val ?? m; return val ?? m; } public static Color Sky(Color c) { //IL_0000: 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) return Force(c, 0.3f, 0.04f); } private static Gradient Sky(Gradient g) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_003c: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if (g == null) { return null; } GradientColorKey[] colorKeys = g.colorKeys; for (int i = 0; i < colorKeys.Length; i++) { colorKeys[i].color = Sky(colorKeys[i].color); } Gradient val = new Gradient { mode = g.mode }; val.SetKeys(colorKeys, g.alphaKeys); return val; } private static MinMaxGradient Sky(MinMaxGradient m) { //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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ParticleSystemGradientMode mode = ((MinMaxGradient)(ref m)).mode; switch ((int)mode) { case 0: return new MinMaxGradient(Sky(((MinMaxGradient)(ref m)).color)); case 2: return new MinMaxGradient(Sky(((MinMaxGradient)(ref m)).colorMin), Sky(((MinMaxGradient)(ref m)).colorMax)); case 1: return new MinMaxGradient(Sky(((MinMaxGradient)(ref m)).gradient)); case 3: return new MinMaxGradient(Sky(((MinMaxGradient)(ref m)).gradientMin), Sky(((MinMaxGradient)(ref m)).gradientMax)); case 4: { MinMaxGradient result = default(MinMaxGradient); ((MinMaxGradient)(ref result))..ctor(Sky(((MinMaxGradient)(ref m)).gradient)); ((MinMaxGradient)(ref result)).mode = (ParticleSystemGradientMode)4; return result; } default: return m; } } private static Texture SkyTexture(Texture t) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)t) || !(t is Texture2D) || (int)t.dimension != 2) { return t; } if (skyTextures.TryGetValue(t, out var value)) { return value; } Texture val = t; try { int num = Mathf.Min(t.width, 1024); int num2 = Mathf.Min(t.height, 1024); Color32[] array = Blit(t, num, num2); int num3 = 0; for (int i = 0; i < array.Length; i++) { Color val2 = Color32.op_Implicit(array[i]); Color val3 = Sky(val2); if (val3 != val2) { array[i] = Color32.op_Implicit(val3); num3++; } } if (num3 > array.Length / 200) { Texture2D val4 = new Texture2D(num, num2, (TextureFormat)4, t.mipmapCount > 1) { name = ((Object)t).name + "_SkyPurple", wrapMode = t.wrapMode, filterMode = t.filterMode, anisoLevel = t.anisoLevel }; val4.SetPixels32(array); val4.Apply(true, true); val = (Texture)val4; } } catch (Exception ex) { HatKidSoulboundPlugin.Log.LogWarning((object)("Couldn't recolour " + ((Object)t).name + ": " + ex.Message)); } skyTextures[t] = val; return val; } private static Material SkyMaterial(Material m) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)m)) { return m; } if (skyMaterials.TryGetValue(m, out var value)) { return value; } Material val = new Material(m) { name = ((Object)m).name + "_SkyPurple" }; Shader shader = m.shader; for (int i = 0; i < shader.GetPropertyCount(); i++) { string propertyName = shader.GetPropertyName(i); ShaderPropertyType propertyType = shader.GetPropertyType(i); if ((int)propertyType != 0) { if ((int)propertyType == 4 && !propertyName.Contains("Normal") && !propertyName.Contains("Bump")) { val.SetTexture(propertyName, SkyTexture(m.GetTexture(propertyName))); } } else { val.SetColor(propertyName, Sky(m.GetColor(propertyName))); } } skyMaterials[m] = val; skyMaterials[val] = val; return val; } public static void SkyRenderer(Renderer r) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) Material[] sharedMaterials = r.sharedMaterials; for (int i = 0; i < sharedMaterials.Length; i++) { sharedMaterials[i] = SkyMaterial(sharedMaterials[i]); } r.sharedMaterials = sharedMaterials; ParticleSystemRenderer val = (ParticleSystemRenderer)(object)((r is ParticleSystemRenderer) ? r : null); if (val != null && Object.op_Implicit((Object)(object)val.trailMaterial)) { val.trailMaterial = SkyMaterial(val.trailMaterial); } ParticleSystem component = ((Component)r).GetComponent<ParticleSystem>(); if (Object.op_Implicit((Object)(object)component)) { MainModule main = component.main; ((MainModule)(ref main)).startColor = Sky(((MainModule)(ref main)).startColor); ColorOverLifetimeModule colorOverLifetime = component.colorOverLifetime; if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled) { ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = Sky(((ColorOverLifetimeModule)(ref colorOverLifetime)).color); } } } public static bool All(GameObject root, bool glowOnly = false) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer r in componentsInChildren) { flag |= Renderer(r, glowOnly); } ParticleSystem[] componentsInChildren2 = root.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem ps in componentsInChildren2) { flag |= Particles(ps); } Light[] componentsInChildren3 = root.GetComponentsInChildren<Light>(true); foreach (Light val in componentsInChildren3) { if (IsColoured(val.color)) { val.color = Shift(val.color); flag = true; } } return flag; } public static bool Renderer(Renderer r, bool glowOnly = false) { bool flag = false; Material[] sharedMaterials = r.sharedMaterials; for (int i = 0; i < sharedMaterials.Length; i++) { Material val = Material(sharedMaterials[i], glowOnly); if ((Object)(object)val != (Object)(object)sharedMaterials[i]) { sharedMaterials[i] = val; flag = true; } } if (flag) { r.sharedMaterials = sharedMaterials; } ParticleSystemRenderer val2 = (ParticleSystemRenderer)(object)((r is ParticleSystemRenderer) ? r : null); if (val2 != null && Object.op_Implicit((Object)(object)val2.trailMaterial)) { Material val3 = Material(val2.trailMaterial); if ((Object)(object)val3 != (Object)(object)val2.trailMaterial) { val2.trailMaterial = val3; flag = true; } } TrailRenderer val4 = (TrailRenderer)(object)((r is TrailRenderer) ? r : null); if (val4 != null) { Gradient val5 = Shift(val4.colorGradient); if (val5 != val4.colorGradient) { val4.colorGradient = val5; flag = true; } } LineRenderer val6 = (LineRenderer)(object)((r is LineRenderer) ? r : null); if (val6 != null) { Gradient val7 = Shift(val6.colorGradient); if (val7 != val6.colorGradient) { val6.colorGradient = val7; flag = true; } } return flag; } public static void Block(Renderer r, MaterialPropertyBlock block) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0034: 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) r.GetPropertyBlock(block); bool flag = false; string[] array = blockColours; foreach (string text in array) { if (block.HasColor(text)) { Color color = block.GetColor(text); if (IsColoured(color)) { block.SetColor(text, Shift(color)); flag = true; } } } array = blockTextures; foreach (string text2 in array) { if (block.HasTexture(text2)) { Texture texture = block.GetTexture(text2); Texture val = Texture(texture); if ((Object)(object)val != (Object)(object)texture) { block.SetTexture(text2, val); flag = true; } } } if (flag) { r.SetPropertyBlock(block); } } public static bool Particles(ParticleSystem ps) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0020: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) //IL_0066: 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_0056: 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) //IL_0087: Unknown result type (might be due to invalid IL or