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 Bobs Heretics v1.1.0
BobsHeretics.dll
Decompiled 4 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using BobsHeretics.Skins; using BobsHeretics.Skins.ArtificerSkins; using EntityStates.Missions.Arena.NullWard; using Microsoft.CodeAnalysis; using On.EntityStates.Missions.Arena.NullWard; using On.RoR2; using R2API; using RoR2; using RoR2.Achievements; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BobsHeretics")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BobsHeretics")] [assembly: AssemblyTitle("BobsHeretics")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BobsHeretics { public static class Assets { private static Shader _hgStandardShader; public static AssetBundle MainAssetBundle { get; private set; } public static Material MatAngelBody { get; private set; } public static Material MatAngelClothes { get; private set; } public static Material MatAngelFeathers { get; private set; } public static Material MatAngelEye { get; private set; } public static Material MatDecompiledBody { get; private set; } public static Material MatDecompiledClothes { get; private set; } public static Material MatDecompiledFeathers { get; private set; } public static Material MatDecompiledEye { get; private set; } public static Sprite TexAngelHereticIcon { get; private set; } public static Sprite TexDecompiledHereticIcon { get; private set; } public static SkinConfig AngelSkinConfig { get; private set; } internal static string AssemblyDir => Path.GetDirectoryName(BobsHereticsPlugin.PluginInfo.Location); public static void Init() { using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BobsHeretics.bobshereticsassets")) { MainAssetBundle = AssetBundle.LoadFromStream(stream); } if ((Object)(object)MainAssetBundle == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"Failed to load asset bundle!"); return; } MatAngelBody = MainAssetBundle.LoadAsset<Material>("matHereticAngel"); MatAngelClothes = MainAssetBundle.LoadAsset<Material>("matAngelClothes"); MatAngelFeathers = MainAssetBundle.LoadAsset<Material>("matAngelFeathers"); MatAngelEye = MainAssetBundle.LoadAsset<Material>("matAngelEye"); MatDecompiledBody = MainAssetBundle.LoadAsset<Material>("matDecompiledBody"); MatDecompiledClothes = MainAssetBundle.LoadAsset<Material>("matDecompiledClothes"); MatDecompiledFeathers = MainAssetBundle.LoadAsset<Material>("matDecompiledFeathers"); MatDecompiledEye = MainAssetBundle.LoadAsset<Material>("matDecompiledEye"); TexAngelHereticIcon = MainAssetBundle.LoadAsset<Sprite>("texAngelHereticIcon"); TexDecompiledHereticIcon = MainAssetBundle.LoadAsset<Sprite>("texDecompiledHereticIcon"); AngelSkinConfig = MainAssetBundle.LoadAsset<SkinConfig>("AngelSkinConfig"); if ((Object)(object)MatAngelBody == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matHereticAngel not found in asset bundle!"); } if ((Object)(object)MatAngelClothes == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matAngelClothes not found in asset bundle!"); } if ((Object)(object)MatAngelFeathers == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matAngelFeathers not found in asset bundle!"); } if ((Object)(object)MatAngelEye == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matAngelEye not found in asset bundle!"); } if ((Object)(object)MatDecompiledBody == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matDecompiledBody not found in asset bundle!"); } if ((Object)(object)MatDecompiledClothes == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matDecompiledClothes not found in asset bundle!"); } if ((Object)(object)MatDecompiledFeathers == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matDecompiledFeathers not found in asset bundle!"); } if ((Object)(object)MatDecompiledEye == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"matDecompiledEye not found in asset bundle!"); } } public static void FixMaterialShaders() { _hgStandardShader = Shader.Find("Hopoo Games/Deferred/Standard"); if ((Object)(object)_hgStandardShader == (Object)null) { Material val = LegacyResourcesAPI.Load<Material>("Materials/matCommando"); if ((Object)(object)val != (Object)null) { _hgStandardShader = val.shader; } } if ((Object)(object)_hgStandardShader == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"Failed to find shader - materials will appear pink!"); return; } FixShader(MatAngelBody, "MatAngelBody"); FixShader(MatAngelClothes, "MatAngelClothes"); FixShader(MatAngelFeathers, "MatAngelFeathers"); FixShader(MatAngelEye, "MatAngelEye"); FixShader(MatDecompiledBody, "MatDecompiledBody"); FixShader(MatDecompiledClothes, "MatDecompiledClothes"); FixShader(MatDecompiledFeathers, "MatDecompiledFeathers"); FixShader(MatDecompiledEye, "MatDecompiledEye"); } private static void FixShader(Material mat, string name) { if (!((Object)(object)mat == (Object)null) && ((Object)(object)mat.shader == (Object)null || ((Object)mat.shader).name == "Hidden/InternalErrorShader")) { mat.shader = _hgStandardShader; BobsHereticsPlugin.Log.LogInfo((object)("Fixed shader on " + name)); } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("bob.bobs-heretics", "bobs-heretics", "1.0.0")] public class BobsHereticsPlugin : BaseUnityPlugin { public const string PluginGUID = "bob.bobs-heretics"; public const string PluginName = "bobs-heretics"; public const string PluginVersion = "1.0.0"; public static PluginInfo PluginInfo { get; private set; } public static ManualLogSource Log { get; private set; } public static BodyIndex HereticBodyIndex { get; private set; } public void Awake() { PluginInfo = ((BaseUnityPlugin)this).Info; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"bobs-heretics v1.0.0 initializing..."); Assets.Init(); Tokens.Init(); AngelHereticSkin.RegisterUnlockable(); DecompiledHereticSkin.RegisterUnlockable(); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoad)); } private void OnGameLoad() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 HereticBodyIndex = BodyCatalog.FindBodyIndex("HereticBody"); if ((int)HereticBodyIndex == -1) { Log.LogError((object)"Could not find HereticBody! Heretic skins will not be added."); } Assets.FixMaterialShaders(); if ((int)HereticBodyIndex != -1) { SkinManager.Init(); AngelHereticSkin.SetupSkinHooks(); } ArtificerSkinBase.CacheBodyIndex(); ArtificerSkinBase.InitializeSkins(); ArtificerSkinBase.SetupSkinHooks(); Log.LogInfo((object)"bobs-heretics loaded successfully!"); } } public class SkinConfig : ScriptableObject { [Serializable] public class PrefabAttachment { public string name = "Effect"; public GameObject prefab; public string parentBoneName = "Head_M"; public Vector3 positionOffset = Vector3.zero; public Vector3 rotationOffset = Vector3.zero; public Vector3 scale = Vector3.one; } public List<string> meshesToHide = new List<string>(); public List<PrefabAttachment> prefabAttachments = new List<PrefabAttachment>(); } public static class Tokens { [CompilerGenerated] private static class <>O { public static hook_SetFolders <0>__Language_SetFolders; } public static void Init() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown object obj = <>O.<0>__Language_SetFolders; if (obj == null) { hook_SetFolders val = Language_SetFolders; <>O.<0>__Language_SetFolders = val; obj = (object)val; } Language.SetFolders += (hook_SetFolders)obj; } private static void Language_SetFolders(orig_SetFolders orig, Language self, IEnumerable<string> newFolders) { orig.Invoke(self, newFolders); if (self.name == "en") { self.SetStringByToken("BOBSHERETICS_SKIN_ANGEL_HERETIC_NAME", "Angel"); self.SetStringByToken("ACHIEVEMENT_BOBSHERETICS_ACHIEVEMENT_ANGELHERETIC_NAME", "Heretic: Ascension"); self.SetStringByToken("ACHIEVEMENT_BOBSHERETICS_ACHIEVEMENT_ANGELHERETIC_DESCRIPTION", "As Heretic, complete a run on any difficulty."); self.SetStringByToken("BOBSHERETICS_SKIN_DECOMPILED_HERETIC_NAME", "Decompiled"); self.SetStringByToken("ACHIEVEMENT_BOBSHERETICS_DECOMPILED_HERETIC_NAME", "Heretic: Assimilated"); self.SetStringByToken("ACHIEVEMENT_BOBSHERETICS_DECOMPILED_HERETIC_DESCRIPTION", "As Heretic, enter the Neural Sanctum."); } } } } namespace BobsHeretics.Skins { public static class AngelHereticSkin { [CompilerGenerated] private static class <>O { public static hook_Awake <0>__DisableAwake; public static hook_UpdateMaterials <1>__OnUpdateMaterials; } public const string SKIN_NAME = "BOBSHERETICS_SKIN_ANGEL_HERETIC"; public const string SKIN_NAME_TOKEN = "BOBSHERETICS_SKIN_ANGEL_HERETIC_NAME"; public const string UNLOCKABLE_IDENTIFIER = "Skins.AngelHeretic"; public static readonly string[] MeshesToHide = new string[3] { "Mesh_HereticTabard", "Mesh_HereticFeathersSmall", "Mesh_HereticBodyFeathers" }; public static UnlockableDef AngelHereticUnlockableDef { get; private set; } public static void RegisterUnlockable() { AngelHereticUnlockableDef = ScriptableObject.CreateInstance<UnlockableDef>(); AngelHereticUnlockableDef.cachedName = "Skins.AngelHeretic"; AngelHereticUnlockableDef.nameToken = "BOBSHERETICS_SKIN_ANGEL_HERETIC_NAME"; AngelHereticUnlockableDef.achievementIcon = Assets.TexAngelHereticIcon; ContentAddition.AddUnlockableDef(AngelHereticUnlockableDef); } public static SkinDef CreateSkin(GameObject modelObject, CharacterModel characterModel) { if ((Object)(object)Assets.MatAngelBody == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"Cannot create Angel Heretic skin: materials not loaded!"); return null; } Sprite val = Assets.TexAngelHereticIcon; if ((Object)(object)val == (Object)null) { ModelSkinController component = modelObject.GetComponent<ModelSkinController>(); if (component != null && component.skins?.Length > 0) { val = component.skins[0].icon; } } RendererInfo[] rendererInfos = CreateRendererInfos(characterModel.baseRendererInfos); return CreateSkinDef(modelObject, rendererInfos, val); } private static RendererInfo[] CreateRendererInfos(RendererInfo[] baseInfos) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_007e: Unknown result type (might be due to invalid IL or missing references) RendererInfo[] array = (RendererInfo[])(object)new RendererInfo[baseInfos.Length]; for (int i = 0; i < baseInfos.Length; i++) { array[i] = new RendererInfo { renderer = baseInfos[i].renderer, defaultMaterial = GetMaterial(baseInfos[i].renderer), defaultShadowCastingMode = baseInfos[i].defaultShadowCastingMode, ignoreOverlays = baseInfos[i].ignoreOverlays, hideOnDeath = baseInfos[i].hideOnDeath }; } return array; } private static Material GetMaterial(Renderer renderer) { string text = ((Object)((Component)renderer).gameObject).name.ToLower(); if (text.Contains("eye")) { return Assets.MatAngelEye ?? Assets.MatAngelBody; } if (text.Contains("feather")) { return Assets.MatAngelFeathers ?? Assets.MatAngelBody; } if (text.Contains("cloth") || text.Contains("cape") || text.Contains("sash") || text.Contains("tabard") || text.Contains("band")) { return Assets.MatAngelClothes ?? Assets.MatAngelBody; } return Assets.MatAngelBody; } private static SkinDef CreateSkinDef(GameObject modelObject, RendererInfo[] rendererInfos, Sprite icon) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00bf: 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_00ca: Expected O, but got Unknown object obj = <>O.<0>__DisableAwake; if (obj == null) { hook_Awake val = DisableAwake; <>O.<0>__DisableAwake = val; obj = (object)val; } SkinDef.Awake += (hook_Awake)obj; SkinDef val2 = ScriptableObject.CreateInstance<SkinDef>(); ((Object)val2).name = "BOBSHERETICS_SKIN_ANGEL_HERETIC"; val2.nameToken = "BOBSHERETICS_SKIN_ANGEL_HERETIC_NAME"; val2.icon = icon; val2.rootObject = modelObject; val2.unlockableDef = AngelHereticUnlockableDef; val2.baseSkins = Array.Empty<SkinDef>(); SkinDefParams val3 = ScriptableObject.CreateInstance<SkinDefParams>(); ((Object)val3).name = "BOBSHERETICS_SKIN_ANGEL_HERETIC_Params"; val3.rendererInfos = rendererInfos; val3.gameObjectActivations = Array.Empty<GameObjectActivation>(); val3.meshReplacements = Array.Empty<MeshReplacement>(); val3.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>(); val3.minionSkinReplacements = Array.Empty<MinionSkinReplacement>(); val2.skinDefParams = val3; object obj2 = <>O.<0>__DisableAwake; if (obj2 == null) { hook_Awake val4 = DisableAwake; <>O.<0>__DisableAwake = val4; obj2 = (object)val4; } SkinDef.Awake -= (hook_Awake)obj2; return val2; } private static void DisableAwake(orig_Awake orig, SkinDef self) { } public static void SetupSkinHooks() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown object obj = <>O.<1>__OnUpdateMaterials; if (obj == null) { hook_UpdateMaterials val = OnUpdateMaterials; <>O.<1>__OnUpdateMaterials = val; obj = (object)val; } CharacterModel.UpdateMaterials += (hook_UpdateMaterials)obj; BobsHereticsPlugin.Log.LogInfo((object)"Angel skin mesh hook ready"); } private static void OnUpdateMaterials(orig_UpdateMaterials orig, CharacterModel self) { orig.Invoke(self); if (!((Object)((Component)self).gameObject).name.ToLower().Contains("heretic")) { return; } ModelSkinController component = ((Component)self).GetComponent<ModelSkinController>(); if ((Object)(object)component == (Object)null || component.skins == null) { return; } int currentSkinIndex = component.currentSkinIndex; if (currentSkinIndex >= 0 && currentSkinIndex < component.skins.Length) { string name = ((Object)component.skins[currentSkinIndex]).name; bool flag = name == "BOBSHERETICS_SKIN_ANGEL_HERETIC"; bool flag2 = name == "BOBSHERETICS_SKIN_DECOMPILED_HERETIC"; ReEnableAllMeshes(((Component)self).transform, MeshesToHide); ReEnableAllMeshes(((Component)self).transform, DecompiledHereticSkin.MeshesToHide); if (flag) { ApplyMeshVisibility(((Component)self).transform, MeshesToHide, shouldHide: true); } else if (flag2) { ApplyMeshVisibility(((Component)self).transform, DecompiledHereticSkin.MeshesToHide, shouldHide: true); } } } private static void ReEnableAllMeshes(Transform root, string[] meshNames) { if (meshNames == null || meshNames.Length == 0) { return; } foreach (string name in meshNames) { Transform val = FindChildRecursive(root, name); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(true); Renderer component = ((Component)val).GetComponent<Renderer>(); if ((Object)(object)component != (Object)null) { component.enabled = true; } } } } private static void ApplyMeshVisibility(Transform root, string[] meshesToHide, bool shouldHide) { if (meshesToHide == null || meshesToHide.Length == 0) { return; } foreach (string name in meshesToHide) { Transform val = FindChildRecursive(root, name); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(!shouldHide); Renderer component = ((Component)val).GetComponent<Renderer>(); if ((Object)(object)component != (Object)null) { component.enabled = !shouldHide; } } } } private static Transform FindChildRecursive(Transform parent, string name) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (((Object)parent).name == name) { return parent; } foreach (Transform item in parent) { Transform parent2 = item; Transform val = FindChildRecursive(parent2, name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } public static class DecompiledHereticSkin { [CompilerGenerated] private static class <>O { public static hook_Awake <0>__DisableAwake; } public const string SKIN_NAME = "BOBSHERETICS_SKIN_DECOMPILED_HERETIC"; public const string SKIN_NAME_TOKEN = "BOBSHERETICS_SKIN_DECOMPILED_HERETIC_NAME"; public const string UNLOCKABLE_IDENTIFIER = "Skins.DecompiledHeretic"; public static readonly string[] MeshesToHide = new string[9] { "Mesh_HereticFeathersLarge", "Mesh_HereticFeathersSmall", "Mesh_HereticBodyFeathers", "Mesh_HereticClothes", "Mesh_HereticCape", "Mesh_HereticSash", "Mesh_HereticTabard", "Mesh_HereticBandArms", "Mesh_HereticBandTorso" }; public static UnlockableDef DecompiledHereticUnlockableDef { get; private set; } public static void RegisterUnlockable() { DecompiledHereticUnlockableDef = ScriptableObject.CreateInstance<UnlockableDef>(); DecompiledHereticUnlockableDef.cachedName = "Skins.DecompiledHeretic"; DecompiledHereticUnlockableDef.nameToken = "BOBSHERETICS_SKIN_DECOMPILED_HERETIC_NAME"; DecompiledHereticUnlockableDef.achievementIcon = Assets.TexDecompiledHereticIcon; ContentAddition.AddUnlockableDef(DecompiledHereticUnlockableDef); } public static SkinDef CreateSkin(GameObject modelObject, CharacterModel characterModel) { if ((Object)(object)Assets.MatDecompiledBody == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"Cannot create Decompiled Heretic skin: materials not loaded!"); return null; } Sprite val = Assets.TexDecompiledHereticIcon; if ((Object)(object)val == (Object)null) { ModelSkinController component = modelObject.GetComponent<ModelSkinController>(); if (component != null && component.skins?.Length > 0) { val = component.skins[0].icon; } } RendererInfo[] rendererInfos = CreateRendererInfos(characterModel.baseRendererInfos); return CreateSkinDef(modelObject, rendererInfos, val); } private static RendererInfo[] CreateRendererInfos(RendererInfo[] baseInfos) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_007e: Unknown result type (might be due to invalid IL or missing references) RendererInfo[] array = (RendererInfo[])(object)new RendererInfo[baseInfos.Length]; for (int i = 0; i < baseInfos.Length; i++) { array[i] = new RendererInfo { renderer = baseInfos[i].renderer, defaultMaterial = GetMaterial(baseInfos[i].renderer), defaultShadowCastingMode = baseInfos[i].defaultShadowCastingMode, ignoreOverlays = baseInfos[i].ignoreOverlays, hideOnDeath = baseInfos[i].hideOnDeath }; } return array; } private static Material GetMaterial(Renderer renderer) { string text = ((Object)((Component)renderer).gameObject).name.ToLower(); if (text.Contains("eye")) { return Assets.MatDecompiledEye ?? Assets.MatDecompiledBody; } if (text.Contains("feather")) { return Assets.MatDecompiledFeathers ?? Assets.MatDecompiledBody; } if (text.Contains("cloth") || text.Contains("cape") || text.Contains("sash") || text.Contains("tabard") || text.Contains("band")) { return Assets.MatDecompiledClothes ?? Assets.MatDecompiledBody; } return Assets.MatDecompiledBody; } private static SkinDef CreateSkinDef(GameObject modelObject, RendererInfo[] rendererInfos, Sprite icon) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00bf: 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_00ca: Expected O, but got Unknown object obj = <>O.<0>__DisableAwake; if (obj == null) { hook_Awake val = DisableAwake; <>O.<0>__DisableAwake = val; obj = (object)val; } SkinDef.Awake += (hook_Awake)obj; SkinDef val2 = ScriptableObject.CreateInstance<SkinDef>(); ((Object)val2).name = "BOBSHERETICS_SKIN_DECOMPILED_HERETIC"; val2.nameToken = "BOBSHERETICS_SKIN_DECOMPILED_HERETIC_NAME"; val2.icon = icon; val2.rootObject = modelObject; val2.unlockableDef = DecompiledHereticUnlockableDef; val2.baseSkins = Array.Empty<SkinDef>(); SkinDefParams val3 = ScriptableObject.CreateInstance<SkinDefParams>(); ((Object)val3).name = "BOBSHERETICS_SKIN_DECOMPILED_HERETIC_Params"; val3.rendererInfos = rendererInfos; val3.gameObjectActivations = Array.Empty<GameObjectActivation>(); val3.meshReplacements = Array.Empty<MeshReplacement>(); val3.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>(); val3.minionSkinReplacements = Array.Empty<MinionSkinReplacement>(); val2.skinDefParams = val3; object obj2 = <>O.<0>__DisableAwake; if (obj2 == null) { hook_Awake val4 = DisableAwake; <>O.<0>__DisableAwake = val4; obj2 = (object)val4; } SkinDef.Awake -= (hook_Awake)obj2; return val2; } private static void DisableAwake(orig_Awake orig, SkinDef self) { } } public static class SkinManager { private static bool _initialized; public static void Init() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if (_initialized) { return; } _initialized = true; GameObject bodyPrefab = BodyCatalog.GetBodyPrefab(BobsHereticsPlugin.HereticBodyIndex); if ((Object)(object)bodyPrefab == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"HereticBody prefab not found!"); return; } ModelLocator component = bodyPrefab.GetComponent<ModelLocator>(); if ((Object)(object)component == (Object)null || (Object)(object)component.modelTransform == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"ModelLocator or modelTransform not found on HereticBody!"); return; } GameObject gameObject = ((Component)component.modelTransform).gameObject; CharacterModel component2 = gameObject.GetComponent<CharacterModel>(); if ((Object)(object)component2 == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"CharacterModel not found on Heretic model!"); return; } BobsHereticsPlugin.Log.LogInfo((object)"=== HERETIC BONE HIERARCHY ==="); LogBoneHierarchy(gameObject.transform, 0); BobsHereticsPlugin.Log.LogInfo((object)"=== END BONE HIERARCHY ==="); ModelSkinController component3 = gameObject.GetComponent<ModelSkinController>(); if ((Object)(object)component3 == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"ModelSkinController not found on Heretic model!"); return; } int num = 0; SkinDef val = AngelHereticSkin.CreateSkin(gameObject, component2); if ((Object)(object)val != (Object)null) { bool flag = Skins.AddSkinToCharacter(bodyPrefab, val); BobsHereticsPlugin.Log.LogInfo((object)$"Skins.AddSkinToCharacter returned: {flag}"); if (flag) { num++; BobsHereticsPlugin.Log.LogInfo((object)"Angel Heretic skin added successfully."); UpdateSkinCatalog(val, BobsHereticsPlugin.HereticBodyIndex); UpdateDisplayPrefab(val); } else { BobsHereticsPlugin.Log.LogError((object)"Failed to add Angel Heretic skin via R2API.Skins!"); } } SkinDef val2 = DecompiledHereticSkin.CreateSkin(gameObject, component2); if ((Object)(object)val2 != (Object)null) { bool flag2 = Skins.AddSkinToCharacter(bodyPrefab, val2); BobsHereticsPlugin.Log.LogInfo((object)$"Skins.AddSkinToCharacter (Decompiled) returned: {flag2}"); if (flag2) { num++; BobsHereticsPlugin.Log.LogInfo((object)"Decompiled Heretic skin added successfully."); UpdateSkinCatalog(val2, BobsHereticsPlugin.HereticBodyIndex); UpdateDisplayPrefab(val2); } else { BobsHereticsPlugin.Log.LogError((object)"Failed to add Decompiled Heretic skin via R2API.Skins!"); } } BobsHereticsPlugin.Log.LogInfo((object)$"Successfully added {num} skin(s) to Heretic."); } private static void UpdateDisplayPrefab(SkinDef newSkin) { //IL_0032: 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) SurvivorDef val = null; foreach (SurvivorDef allSurvivorDef in SurvivorCatalog.allSurvivorDefs) { if ((Object)(object)allSurvivorDef.bodyPrefab != (Object)null && BodyCatalog.FindBodyIndex(allSurvivorDef.bodyPrefab) == BobsHereticsPlugin.HereticBodyIndex) { val = allSurvivorDef; break; } } if ((Object)(object)val == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"Could not find Heretic SurvivorDef - display prefab not updated"); return; } if ((Object)(object)val.displayPrefab == (Object)null) { BobsHereticsPlugin.Log.LogWarning((object)"Heretic SurvivorDef has no displayPrefab"); return; } BobsHereticsPlugin.Log.LogInfo((object)("Found Heretic display prefab: " + ((Object)val.displayPrefab).name)); ModelSkinController val2 = val.displayPrefab.GetComponentInChildren<ModelSkinController>(); if ((Object)(object)val2 == (Object)null) { CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(); if (!((Object)(object)componentInChildren != (Object)null)) { BobsHereticsPlugin.Log.LogWarning((object)"Could not find suitable object for ModelSkinController on display prefab"); return; } val2 = ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>(); val2.skins = (SkinDef[])(object)new SkinDef[0]; BobsHereticsPlugin.Log.LogInfo((object)"Added ModelSkinController to display prefab"); } SkinDef[] skins = val2.skins; int num = ((skins != null) ? skins.Length : 0); SkinDef[] array = (SkinDef[])(object)new SkinDef[num + 1]; for (int i = 0; i < num; i++) { array[i] = val2.skins[i]; } array[num] = newSkin; val2.skins = array; BobsHereticsPlugin.Log.LogInfo((object)$"Updated display prefab skins array from {num} to {array.Length}"); } private static void UpdateSkinCatalog(SkinDef newSkin, BodyIndex bodyIndex) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected I4, but got Unknown try { FieldInfo field = typeof(SkinCatalog).GetField("skinsByBody", BindingFlags.Static | BindingFlags.NonPublic); if (field == null) { BobsHereticsPlugin.Log.LogWarning((object)"Could not find SkinCatalog.skinsByBody field"); return; } SkinDef[][] array = (SkinDef[][])field.GetValue(null); if (array == null) { BobsHereticsPlugin.Log.LogWarning((object)"SkinCatalog.skinsByBody is null"); return; } int num = (int)bodyIndex; if (num < 0 || num >= array.Length) { BobsHereticsPlugin.Log.LogWarning((object)$"Body index {num} out of range for skinsByBody"); return; } SkinDef[] array2 = array[num]; SkinDef[] array3 = array2; foreach (SkinDef val in array3) { if ((Object)(object)val == (Object)(object)newSkin) { BobsHereticsPlugin.Log.LogInfo((object)"Skin already in SkinCatalog, skipping update"); return; } } int num2 = array2.Length; SkinDef[] array4 = (SkinDef[])(object)new SkinDef[num2 + 1]; Array.Copy(array2, array4, num2); array4[num2] = newSkin; array[num] = array4; BobsHereticsPlugin.Log.LogInfo((object)$"Updated skinsByBody[{num}] from {num2} to {array4.Length} skins"); FieldInfo field2 = typeof(SkinCatalog).GetField("allSkinDefs", BindingFlags.Static | BindingFlags.NonPublic); if (field2 != null) { SkinDef[] array5 = (SkinDef[])field2.GetValue(null); if (array5 != null) { int num3 = array5.Length; SkinDef[] array6 = (SkinDef[])(object)new SkinDef[num3 + 1]; Array.Copy(array5, array6, num3); array6[num3] = newSkin; field2.SetValue(null, array6); BobsHereticsPlugin.Log.LogInfo((object)$"Updated allSkinDefs from {num3} to {array6.Length}, new skin index: {num3}"); } } BobsHereticsPlugin.Log.LogInfo((object)"SkinCatalog updated via reflection"); } catch (Exception ex) { BobsHereticsPlugin.Log.LogError((object)("Failed to update SkinCatalog: " + ex.Message)); } } private static void LogBoneHierarchy(Transform t, int depth) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown string text = new string(' ', depth * 2); BobsHereticsPlugin.Log.LogInfo((object)(text + ((Object)t).name)); foreach (Transform item in t) { Transform t2 = item; LogBoneHierarchy(t2, depth + 1); } } } } namespace BobsHeretics.Skins.ArtificerSkins { public static class ArtificerSkinBase { [CompilerGenerated] private static class <>O { public static hook_UpdateMaterials <0>__OnUpdateMaterials; } private static bool _hooksInitialized = false; public static readonly string[] KnownMeshes = new string[0]; public static BodyIndex ArtificerBodyIndex { get; private set; } public static void CacheBodyIndex() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected I4, but got Unknown ArtificerBodyIndex = BodyCatalog.FindBodyIndex("MageBody"); if ((int)ArtificerBodyIndex == -1) { BobsHereticsPlugin.Log.LogError((object)"Could not find MageBody (Artificer)!"); } else { BobsHereticsPlugin.Log.LogInfo((object)$"Found Artificer body index: {(int)ArtificerBodyIndex}"); } } public static void InitializeSkins() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) if ((int)ArtificerBodyIndex == -1) { BobsHereticsPlugin.Log.LogError((object)"Cannot initialize Artificer skins - body index not found!"); return; } GameObject bodyPrefab = BodyCatalog.GetBodyPrefab(ArtificerBodyIndex); if ((Object)(object)bodyPrefab == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"Artificer body prefab not found!"); return; } ModelLocator component = bodyPrefab.GetComponent<ModelLocator>(); if ((Object)(object)component == (Object)null || (Object)(object)component.modelTransform == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"ModelLocator not found on Artificer!"); return; } GameObject gameObject = ((Component)component.modelTransform).gameObject; CharacterModel component2 = gameObject.GetComponent<CharacterModel>(); if ((Object)(object)component2 == (Object)null) { BobsHereticsPlugin.Log.LogError((object)"CharacterModel not found on Artificer!"); return; } BobsHereticsPlugin.Log.LogInfo((object)"=== ARTIFICER HIERARCHY ==="); LogHierarchy(gameObject.transform, 0); BobsHereticsPlugin.Log.LogInfo((object)"=== END ARTIFICER HIERARCHY ==="); BobsHereticsPlugin.Log.LogInfo((object)"=== ARTIFICER RENDERERS ==="); RendererInfo[] baseRendererInfos = component2.baseRendererInfos; foreach (RendererInfo val in baseRendererInfos) { if ((Object)(object)val.renderer != (Object)null) { BobsHereticsPlugin.Log.LogInfo((object)(" Renderer: " + ((Object)((Component)val.renderer).gameObject).name)); } } BobsHereticsPlugin.Log.LogInfo((object)"=== END ARTIFICER RENDERERS ==="); int num = 0; BobsHereticsPlugin.Log.LogInfo((object)$"Added {num} skin(s) to Artificer."); } public static bool AddSkinToCharacter(GameObject bodyPrefab, SkinDef skinDef) { bool flag = Skins.AddSkinToCharacter(bodyPrefab, skinDef); if (flag) { BobsHereticsPlugin.Log.LogInfo((object)("Added skin '" + ((Object)skinDef).name + "' to Artificer")); } else { BobsHereticsPlugin.Log.LogError((object)("Failed to add skin '" + ((Object)skinDef).name + "' to Artificer")); } return flag; } public static void SetupSkinHooks() { //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_002d: Expected O, but got Unknown if (!_hooksInitialized) { _hooksInitialized = true; object obj = <>O.<0>__OnUpdateMaterials; if (obj == null) { hook_UpdateMaterials val = OnUpdateMaterials; <>O.<0>__OnUpdateMaterials = val; obj = (object)val; } CharacterModel.UpdateMaterials += (hook_UpdateMaterials)obj; BobsHereticsPlugin.Log.LogInfo((object)"Artificer skin hooks initialized"); } } private static void OnUpdateMaterials(orig_UpdateMaterials orig, CharacterModel self) { orig.Invoke(self); if (!((Object)((Component)self).gameObject).name.ToLower().Contains("mage")) { return; } ModelSkinController component = ((Component)self).GetComponent<ModelSkinController>(); if (!((Object)(object)component == (Object)null) && component.skins != null) { int currentSkinIndex = component.currentSkinIndex; if (currentSkinIndex >= 0 && currentSkinIndex < component.skins.Length) { string name = ((Object)component.skins[currentSkinIndex]).name; } } } private static void ApplyMeshVisibility(Transform root, string[] meshesToHide, bool shouldHide) { if (meshesToHide == null || meshesToHide.Length == 0) { return; } foreach (string name in meshesToHide) { Transform val = FindChildRecursive(root, name); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(!shouldHide); Renderer component = ((Component)val).GetComponent<Renderer>(); if ((Object)(object)component != (Object)null) { component.enabled = !shouldHide; } } } } private static Transform FindChildRecursive(Transform parent, string name) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (((Object)parent).name == name) { return parent; } foreach (Transform item in parent) { Transform parent2 = item; Transform val = FindChildRecursive(parent2, name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void LogHierarchy(Transform t, int depth) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown string text = new string(' ', depth * 2); BobsHereticsPlugin.Log.LogInfo((object)(text + ((Object)t).name)); foreach (Transform item in t) { Transform t2 = item; LogHierarchy(t2, depth + 1); } } } public static class ExampleArtificerSkin { [CompilerGenerated] private static class <>O { public static hook_Awake <0>__DisableAwake; } public const string SKIN_NAME = "BOBSHERETICS_SKIN_EXAMPLE_ARTIFICER"; public const string SKIN_NAME_TOKEN = "BOBSHERETICS_SKIN_EXAMPLE_ARTIFICER_NAME"; public const string UNLOCKABLE_IDENTIFIER = "Skins.ExampleArtificer"; public static readonly string[] MeshesToHide = new string[0]; public static UnlockableDef UnlockableDef { get; private set; } public static void RegisterUnlockable() { } public static SkinDef CreateSkin(GameObject modelObject, CharacterModel characterModel) { return null; } private static RendererInfo[] CreateRendererInfos(RendererInfo[] baseInfos) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_007e: Unknown result type (might be due to invalid IL or missing references) RendererInfo[] array = (RendererInfo[])(object)new RendererInfo[baseInfos.Length]; for (int i = 0; i < baseInfos.Length; i++) { array[i] = new RendererInfo { renderer = baseInfos[i].renderer, defaultMaterial = GetMaterial(baseInfos[i].renderer), defaultShadowCastingMode = baseInfos[i].defaultShadowCastingMode, ignoreOverlays = baseInfos[i].ignoreOverlays, hideOnDeath = baseInfos[i].hideOnDeath }; } return array; } private static Material GetMaterial(Renderer renderer) { string text = ((Object)((Component)renderer).gameObject).name.ToLower(); return null; } private static SkinDef CreateSkinDef(GameObject modelObject, RendererInfo[] rendererInfos, Sprite icon) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00bf: 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_00ca: Expected O, but got Unknown object obj = <>O.<0>__DisableAwake; if (obj == null) { hook_Awake val = DisableAwake; <>O.<0>__DisableAwake = val; obj = (object)val; } SkinDef.Awake += (hook_Awake)obj; SkinDef val2 = ScriptableObject.CreateInstance<SkinDef>(); ((Object)val2).name = "BOBSHERETICS_SKIN_EXAMPLE_ARTIFICER"; val2.nameToken = "BOBSHERETICS_SKIN_EXAMPLE_ARTIFICER_NAME"; val2.icon = icon; val2.rootObject = modelObject; val2.unlockableDef = UnlockableDef; val2.baseSkins = Array.Empty<SkinDef>(); SkinDefParams val3 = ScriptableObject.CreateInstance<SkinDefParams>(); ((Object)val3).name = "BOBSHERETICS_SKIN_EXAMPLE_ARTIFICER_Params"; val3.rendererInfos = rendererInfos; val3.gameObjectActivations = Array.Empty<GameObjectActivation>(); val3.meshReplacements = Array.Empty<MeshReplacement>(); val3.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>(); val3.minionSkinReplacements = Array.Empty<MinionSkinReplacement>(); val2.skinDefParams = val3; object obj2 = <>O.<0>__DisableAwake; if (obj2 == null) { hook_Awake val4 = DisableAwake; <>O.<0>__DisableAwake = val4; obj2 = (object)val4; } SkinDef.Awake -= (hook_Awake)obj2; BobsHereticsPlugin.Log.LogInfo((object)"Created skin: BOBSHERETICS_SKIN_EXAMPLE_ARTIFICER"); return val2; } private static void DisableAwake(orig_Awake orig, SkinDef self) { } } } namespace BobsHeretics.Achievements { [RegisterAchievement("BOBSHERETICS_ACHIEVEMENT_ANGELHERETIC", "Skins.AngelHeretic", null, 5u, null)] public class AngelHereticAchievement : BaseEndingAchievement { public const string ACHIEVEMENT_ID = "BOBSHERETICS_ACHIEVEMENT_ANGELHERETIC"; public const string UNLOCKABLE_IDENTIFIER = "Skins.AngelHeretic"; public override BodyIndex LookUpRequiredBodyIndex() { //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_000e: Unknown result type (might be due to invalid IL or missing references) return BodyCatalog.FindBodyIndex("HereticBody"); } public override bool ShouldGrant(RunReport runReport) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (runReport == null || (Object)(object)runReport.gameEnding == (Object)null) { return false; } if (!runReport.gameEnding.isWin) { return false; } if (((BaseAchievement)this).localUser == null || (Object)(object)((BaseAchievement)this).localUser.cachedBody == (Object)null) { return false; } if (((BaseAchievement)this).localUser.cachedBody.bodyIndex != ((BaseAchievement)this).requiredBodyIndex) { return false; } return true; } } [RegisterAchievement("BOBSHERETICS_DECOMPILED_HERETIC", "Skins.DecompiledHeretic", null, 5u, null)] public class DecompiledHereticAchievement : BaseAchievement { public override BodyIndex LookUpRequiredBodyIndex() { //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_000e: Unknown result type (might be due to invalid IL or missing references) return BodyCatalog.FindBodyIndex("HereticBody"); } public override void OnInstall() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown ((BaseAchievement)this).OnInstall(); ArenaMissionController.EndRound += new hook_EndRound(OnEndRound); Active.FixedUpdate += new hook_FixedUpdate(OnNullWardUpdate); VoidSurvivorController.OnInventoryChanged += new hook_OnInventoryChanged(OnVoidSurvivorInventoryChanged); BobsHereticsPlugin.Log.LogInfo((object)"DecompiledHereticAchievement installed"); } public override void OnUninstall() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ArenaMissionController.EndRound -= new hook_EndRound(OnEndRound); Active.FixedUpdate -= new hook_FixedUpdate(OnNullWardUpdate); VoidSurvivorController.OnInventoryChanged -= new hook_OnInventoryChanged(OnVoidSurvivorInventoryChanged); ((BaseAchievement)this).OnUninstall(); } private void OnEndRound(orig_EndRound orig, ArenaMissionController self) { orig.Invoke(self); CheckAchievement(); } private void OnNullWardUpdate(orig_FixedUpdate orig, Active self) { orig.Invoke(self); CheckAchievement(); } private void OnVoidSurvivorInventoryChanged(orig_OnInventoryChanged orig, VoidSurvivorController self) { orig.Invoke(self); CheckAchievement(); } private void CheckAchievement() { //IL_002d: 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) LocalUser localUser = ((BaseAchievement)this).localUser; if (!((Object)(object)((localUser != null) ? localUser.cachedBody : null) == (Object)null) && ((BaseAchievement)this).localUser.cachedBody.bodyIndex == ((BaseAchievement)this).requiredBodyIndex) { SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); string text = ((sceneDefForCurrentScene != null) ? sceneDefForCurrentScene.baseSceneName : null) ?? ""; if (text.ToLower().Contains("neuralsanctum") || text.ToLower().Contains("neural") || text.ToLower().Contains("sanctum") || text.ToLower().Contains("collective")) { BobsHereticsPlugin.Log.LogInfo((object)("Heretic on Neural Sanctum: " + text + ", granting achievement!")); ((BaseAchievement)this).Grant(); } } } } public class DecompiledHereticEndingAchievement : BaseEndingAchievement { public override BodyIndex LookUpRequiredBodyIndex() { //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_000e: Unknown result type (might be due to invalid IL or missing references) return BodyCatalog.FindBodyIndex("HereticBody"); } public override bool ShouldGrant(RunReport runReport) { if (runReport == null) { return false; } if ((Object)(object)runReport.gameEnding != (Object)null) { string text = runReport.gameEnding.cachedName?.ToLower() ?? ""; BobsHereticsPlugin.Log.LogInfo((object)("Run ended with ending: " + text)); if (text.Contains("collective") || text.Contains("neural") || text.Contains("alloyed") || text.Contains("sanctum")) { return true; } } return false; } } }