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 GhostMead v1.8.2
plugins/GhostMeadMod.dll
Decompiled 12 hours agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = "")] [assembly: AssemblyCompany("GhostMeadMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GhostMeadMod")] [assembly: AssemblyTitle("GhostMeadMod")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 GhostMeadMod { [BepInPlugin("alairaheim.ghostmead", "GhostMead", "1.8.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class GhostMeadMod : BaseUnityPlugin { public const string PluginGUID = "alairaheim.ghostmead"; public const string PluginName = "GhostMead"; public const string PluginVersion = "1.8.1"; private ConfigEntry<float>? configGhostDuration; private ConfigEntry<string>? configCraftingStation; private ConfigEntry<int>? configMinStationLevel; private ConfigEntry<int>? configMeadYield; private ConfigEntry<string>? configIngredient1Item; private ConfigEntry<int>? configIngredient1Amount; private ConfigEntry<string>? configIngredient2Item; private ConfigEntry<int>? configIngredient2Amount; private ConfigEntry<string>? configIngredient3Item; private ConfigEntry<int>? configIngredient3Amount; private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) InitConfiguration(); RegisterLocalizations(); PrefabManager.OnPrefabsRegistered += RegisterGhostMead; new Harmony("alairaheim.ghostmead").PatchAll(); Logger.LogInfo((object)"[GhostMead] Plugin awake and Harmony patches applied successfully."); } private void InitConfiguration() { configGhostDuration = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Effect", "GhostDuration", 300f, "Duration of the Ghost Form status effect in seconds."); configCraftingStation = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Production", "CraftingStation", "piece_MeadCauldron", "Prefab name of the crafting station needed to make the mead base (e.g., piece_MeadCauldron, piece_workbench)."); configMinStationLevel = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Production", "MinStationLevel", 1, "Minimum level required for the crafting station."); configMeadYield = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Production", "FermentationYield", 5, "Number of Ghost Meads produced per fermentation batch."); configIngredient1Item = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Recipe Ingredients", "Ingredient1_Prefab", "Ectoplasm", "Prefab name for the first ingredient."); configIngredient1Amount = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Recipe Ingredients", "Ingredient1_Amount", 1, "Amount required for the first ingredient."); configIngredient2Item = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Recipe Ingredients", "Ingredient2_Prefab", "Honey", "Prefab name for the second ingredient."); configIngredient2Amount = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Recipe Ingredients", "Ingredient2_Amount", 10, "Amount required for the second ingredient."); configIngredient3Item = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Recipe Ingredients", "Ingredient3_Prefab", "BoneFragments", "Prefab name for the third ingredient."); configIngredient3Amount = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Recipe Ingredients", "Ingredient3_Amount", 5, "Amount required for the third ingredient."); } private void RegisterLocalizations() { LocalizationManager.Instance.AddToken("$item_meadbase_ghost", "Mead base: Ghost", false); LocalizationManager.Instance.AddToken("$item_meadbase_ghost_desc", "Needs to be fermented.", false); LocalizationManager.Instance.AddToken("$item_mead_ghost", "Ghost Mead", false); LocalizationManager.Instance.AddToken("$item_mead_ghost_desc", "A frothy, ethereal brew that sends a shiver down your spine.", false); LocalizationManager.Instance.AddToken("$se_ghostform_name", "Ghost Form", false); LocalizationManager.Instance.AddToken("$se_ghostform_desc", "You are undetectable to all monsters", false); } private static Sprite? LoadEmbeddedSprite(string resourceName) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) { if (stream == null) { Logger.LogWarning((object)("[GhostMead] Could not find embedded resource stream: " + resourceName)); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); bool flag = false; Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("UnityEngine.ImageConversion"); if (type != null) { break; } } if (type != null) { MethodInfo method = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (method != null) { flag = (bool)(method.Invoke(null, new object[2] { val, array }) ?? ((object)false)); } } if (flag) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } } Logger.LogWarning((object)("[GhostMead] Failed to convert embedded resource into Texture2D: " + resourceName)); return null; } private void RegisterGhostMead() { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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) //IL_0203: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Expected O, but got Unknown //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Expected O, but got Unknown //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Expected O, but got Unknown //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Expected O, but got Unknown //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04d5: Expected O, but got Unknown //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Expected O, but got Unknown //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Expected O, but got Unknown //IL_05d4: Unknown result type (might be due to invalid IL or missing references) //IL_05d9: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_0606: Expected O, but got Unknown PrefabManager.OnPrefabsRegistered -= RegisterGhostMead; Color darkColor = default(Color); ((Color)(ref darkColor))..ctor(0.18f, 0.23f, 0.27f, 1f); Color darkColor2 = default(Color); ((Color)(ref darkColor2))..ctor(0.25f, 0.32f, 0.38f, 1f); Color tealColor = default(Color); ((Color)(ref tealColor))..ctor(0.1f, 0.64f, 0.57f, 1f); Sprite val = LoadEmbeddedSprite("GhostMeadMod.ghost_mead_icon.png"); Sprite val2 = LoadEmbeddedSprite("GhostMeadMod.ghost_mead_base_icon.png"); SE_GhostMead sE_GhostMead = ScriptableObject.CreateInstance<SE_GhostMead>(); ((Object)sE_GhostMead).name = "SE_GhostMead"; ((StatusEffect)sE_GhostMead).m_name = "$se_ghostform_name"; ((StatusEffect)sE_GhostMead).m_tooltip = "$se_ghostform_desc"; ((StatusEffect)sE_GhostMead).m_ttl = configGhostDuration?.Value ?? 300f; ((StatusEffect)sE_GhostMead).m_startMessageType = (MessageType)2; ((StatusEffect)sE_GhostMead).m_startMessage = "You fade from the perception of monsters..."; ((StatusEffect)sE_GhostMead).m_stopMessageType = (MessageType)2; ((StatusEffect)sE_GhostMead).m_stopMessage = "Monsters can see and hear you again."; GameObject prefab = PrefabManager.Instance.GetPrefab("MeadFrostResist"); if ((Object)(object)prefab != (Object)null) { ItemDrop component = prefab.GetComponent<ItemDrop>(); if (component != null) { StatusEffect consumeStatusEffect = component.m_itemData.m_shared.m_consumeStatusEffect; if (consumeStatusEffect != null) { ((StatusEffect)sE_GhostMead).m_startEffects = consumeStatusEffect.m_startEffects; ((StatusEffect)sE_GhostMead).m_stopEffects = consumeStatusEffect.m_stopEffects; if (((StatusEffect)sE_GhostMead).m_startEffects?.m_effectPrefabs != null) { EffectData[] effectPrefabs = ((StatusEffect)sE_GhostMead).m_startEffects.m_effectPrefabs; foreach (EffectData val3 in effectPrefabs) { if ((Object)(object)val3.m_prefab != (Object)null) { ApplyTealParticleTint(val3.m_prefab, tealColor); } } } } } } if ((Object)(object)val != (Object)null) { ((StatusEffect)sE_GhostMead).m_icon = val; } else { GameObject prefab2 = PrefabManager.Instance.GetPrefab("TrophyGhost"); if ((Object)(object)prefab2 != (Object)null) { ItemDrop component2 = prefab2.GetComponent<ItemDrop>(); if (component2 != null) { ((StatusEffect)sE_GhostMead).m_icon = component2.m_itemData.GetIcon(); } } } ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)sE_GhostMead, false)); CustomItem val4 = new CustomItem("MeadGhost", "MeadFrostResist"); ItemDrop itemDrop = val4.ItemDrop; itemDrop.m_itemData.m_shared.m_name = "$item_mead_ghost"; itemDrop.m_itemData.m_shared.m_description = "$item_mead_ghost_desc"; itemDrop.m_itemData.m_shared.m_consumeStatusEffect = (StatusEffect)(object)sE_GhostMead; itemDrop.m_itemData.m_shared.m_weight = 1f; GameObject prefab3 = PrefabManager.Instance.GetPrefab("Tankard_dvergr"); if ((Object)(object)prefab3 != (Object)null) { MeshFilter componentInChildren = prefab3.GetComponentInChildren<MeshFilter>(); MeshRenderer componentInChildren2 = prefab3.GetComponentInChildren<MeshRenderer>(); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren2 != (Object)null && (Object)(object)val4.ItemPrefab != (Object)null) { MeshFilter componentInChildren3 = val4.ItemPrefab.GetComponentInChildren<MeshFilter>(); MeshRenderer componentInChildren4 = val4.ItemPrefab.GetComponentInChildren<MeshRenderer>(); if ((Object)(object)componentInChildren3 != (Object)null && (Object)(object)componentInChildren4 != (Object)null) { componentInChildren3.sharedMesh = componentInChildren.sharedMesh; ((Renderer)componentInChildren4).sharedMaterials = ((Renderer)componentInChildren2).sharedMaterials; } } } if ((Object)(object)val != (Object)null) { itemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; } ApplyDarkSilveryTint(val4.ItemPrefab, darkColor); ApplyTealParticleTint(val4.ItemPrefab, tealColor); ItemManager.Instance.AddItem(val4); CustomItem val5 = new CustomItem("MeadBaseGhost", "MeadBasePoisonResist"); ItemDrop itemDrop2 = val5.ItemDrop; itemDrop2.m_itemData.m_shared.m_name = "$item_meadbase_ghost"; itemDrop2.m_itemData.m_shared.m_description = "$item_meadbase_ghost_desc"; itemDrop2.m_itemData.m_shared.m_consumeStatusEffect = null; itemDrop2.m_itemData.m_shared.m_weight = 1f; if ((Object)(object)val2 != (Object)null) { itemDrop2.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 }; } ApplyDarkSilveryTint(val5.ItemPrefab, darkColor2); ItemManager.Instance.AddItem(val5); RequirementConfig[] requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = (configIngredient1Item?.Value ?? "Ectoplasm"), Amount = (configIngredient1Amount?.Value ?? 1) }, new RequirementConfig { Item = (configIngredient2Item?.Value ?? "Honey"), Amount = (configIngredient2Amount?.Value ?? 10) }, new RequirementConfig { Item = (configIngredient3Item?.Value ?? "BoneFragments"), Amount = (configIngredient3Amount?.Value ?? 5) } }; CustomRecipe val6 = new CustomRecipe(new RecipeConfig { Name = "Recipe_MeadBaseGhost", Item = "MeadBaseGhost", Amount = 1, CraftingStation = (configCraftingStation?.Value ?? "piece_MeadCauldron"), MinStationLevel = (configMinStationLevel?.Value ?? 1), Requirements = requirements }); ItemManager.Instance.AddRecipe(val6); GameObject val7 = PrefabManager.Instance.GetPrefab("piece_fermenter") ?? PrefabManager.Instance.GetPrefab("fermenter"); if (!((Object)(object)val7 != (Object)null)) { return; } Fermenter component3 = val7.GetComponent<Fermenter>(); if (component3 != null) { GameObject itemPrefab = val5.ItemPrefab; ItemDrop val8 = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); GameObject itemPrefab2 = val4.ItemPrefab; ItemDrop val9 = ((itemPrefab2 != null) ? itemPrefab2.GetComponent<ItemDrop>() : null); if ((Object)(object)val8 != (Object)null && (Object)(object)val9 != (Object)null) { component3.m_conversion.Add(new ItemConversion { m_from = val8, m_to = val9, m_producedItems = (configMeadYield?.Value ?? 5) }); Logger.LogInfo((object)"[GhostMead] Added Ghost Mead conversion to Fermenter."); } } } private static void ApplyDarkSilveryTint(GameObject? prefab, Color darkColor) { //IL_0050: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return; } Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] materials = componentsInChildren[i].materials; foreach (Material val in materials) { if (!((Object)(object)val == (Object)null)) { if (val.HasProperty("_Color")) { val.SetColor("_Color", darkColor); } if (val.HasProperty("_Tint")) { val.SetColor("_Tint", darkColor); } if (val.HasProperty("_SpecColor")) { val.SetColor("_SpecColor", new Color(0.4f, 0.45f, 0.5f, 1f)); } if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", Color.black); } } } } } private static void ApplyTealParticleTint(GameObject? prefab, Color tealColor) { //IL_0019: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return; } ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true); for (int i = 0; i < componentsInChildren.Length; i++) { MainModule main = componentsInChildren[i].main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(tealColor); } ParticleSystemRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<ParticleSystemRenderer>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Material[] materials = ((Renderer)componentsInChildren2[i]).materials; foreach (Material val in materials) { if (!((Object)(object)val == (Object)null)) { if (val.HasProperty("_Color")) { val.SetColor("_Color", tealColor); } if (val.HasProperty("_TintColor")) { val.SetColor("_TintColor", tealColor); } } } } } } public class SE_GhostMead : StatusEffect { private GameObject? glowLightObject; public override void Setup(Character character) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) ((StatusEffect)this).Setup(character); if ((Object)(object)character != (Object)null) { glowLightObject = new GameObject("GhostMeadTealGlow"); glowLightObject.transform.SetParent(((Component)character).transform, false); glowLightObject.transform.localPosition = new Vector3(0f, 1.2f, 0f); Light obj = glowLightObject.AddComponent<Light>(); obj.type = (LightType)2; obj.color = new Color(0.2f, 0.85f, 0.77f, 1f); obj.range = 4.5f; obj.intensity = 1.8f; obj.shadows = (LightShadows)0; } } public override void Stop() { if ((Object)(object)glowLightObject != (Object)null) { Object.Destroy((Object)(object)glowLightObject); } ((StatusEffect)this).Stop(); } } [HarmonyPatch] public static class StealthPatches { private static bool IsPlayerGhosted(Character? target) { if ((Object)(object)target != (Object)null && target.IsPlayer()) { Player val = (Player)(object)((target is Player) ? target : null); if (val != null) { SEMan sEMan = ((Character)val).GetSEMan(); if (sEMan != null) { foreach (StatusEffect statusEffect in sEMan.GetStatusEffects()) { if (statusEffect is SE_GhostMead) { return true; } } } } } return false; } [HarmonyPatch(typeof(BaseAI), "CanSeeTarget", new Type[] { typeof(Character) })] [HarmonyPrefix] public static bool Prefix_CanSeeTarget(Character target, ref bool __result) { if (IsPlayerGhosted(target)) { __result = false; return false; } return true; } [HarmonyPatch(typeof(BaseAI), "CanSenseTarget", new Type[] { typeof(Character) })] [HarmonyPrefix] public static bool Prefix_CanSenseTarget(Character target, ref bool __result) { if (IsPlayerGhosted(target)) { __result = false; return false; } return true; } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] [HarmonyPrefix] public static bool Prefix_IsEnemy(Character a, Character b, ref bool __result) { if (IsPlayerGhosted(a) || IsPlayerGhosted(b)) { __result = false; return false; } return true; } } }