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 Raincoat v2.0.0
RaincoatMod.dll
Decompiled 11 hours 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.Text; using BepInEx; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; 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("RaincoatMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RaincoatMod")] [assembly: AssemblyTitle("RaincoatMod")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RaincoatMod { [BepInPlugin("yourname.valheim.raincoat", "Raincoat", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class RaincoatMod : BaseUnityPlugin { public const string PluginGUID = "yourname.valheim.raincoat"; public const string PluginName = "Raincoat"; public const string PluginVersion = "1.0.0"; private static readonly Color TintMultiplier = new Color(0.6f, 1.15f, 0.5f, 1f); private const string StatusEffectName = "SE_RainResistant"; private const string TranslationResourceName = "RaincoatMod.English.json"; private static readonly Color NeckSkinTintMultiplier = new Color(0.3f, 0.75f, 0.3f, 1f); private const string NeckSkinIconResourceName = "RaincoatMod.NeckSkin.png"; private static readonly Color NeckTailTintMultiplier = new Color(0.3f, 0.75f, 0.3f, 1f); private const string NeckTailIconResourceName = "RaincoatMod.NeckTail.png"; private const string BodyIconResourceName = "RaincoatMod.RaincoatBody.png"; private const string HoodIconResourceName = "RaincoatMod.RaincoatHood.png"; private static StatusEffect RaincoatStatusEffect; private void Awake() { AddLocalizations(); PrefabManager.OnVanillaPrefabsAvailable += CreateRaincoatSet; Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "yourname.valheim.raincoat"); } private void AddLocalizations() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); try { using Stream stream = executingAssembly.GetManifestResourceStream("RaincoatMod.English.json"); if (stream == null) { string text = string.Join(", ", executingAssembly.GetManifestResourceNames()); Logger.LogError((object)("[Raincoat] Embedded resource 'RaincoatMod.English.json' not found. Resources actually in this DLL: [" + text + "]. Make sure English.json has an <EmbeddedResource> entry in the .csproj with LogicalName 'RaincoatMod.English.json'.")); return; } using StreamReader streamReader = new StreamReader(stream); string text2 = streamReader.ReadToEnd(); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); localization.AddJsonFile("English", text2); Logger.LogInfo((object)"[Raincoat] Loaded translations from embedded resource."); } catch (Exception arg) { Logger.LogError((object)$"[Raincoat] Failed to load/parse embedded translation JSON: {arg}"); } } private static void ExportMeshToObj(string prefabName, string outputPath) { //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_00fe: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)("[Raincoat][MeshExport] Could not find prefab '" + prefabName + "'.")); return; } SkinnedMeshRenderer componentInChildren = prefab.GetComponentInChildren<SkinnedMeshRenderer>(true); Mesh val = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.sharedMesh : null); if ((Object)(object)val == (Object)null) { MeshFilter componentInChildren2 = prefab.GetComponentInChildren<MeshFilter>(true); val = (((Object)(object)componentInChildren2 != (Object)null) ? componentInChildren2.sharedMesh : null); } if ((Object)(object)val == (Object)null) { Logger.LogError((object)("[Raincoat][MeshExport] No mesh found on '" + prefabName + "' or its children.")); return; } try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Exported from Valheim prefab '" + prefabName + "' by RaincoatMod"); stringBuilder.AppendLine("o " + prefabName); Vector3[] vertices = val.vertices; Vector3[] array = vertices; foreach (Vector3 val2 in array) { stringBuilder.AppendLine($"v {0f - val2.x} {val2.y} {val2.z}"); } Vector3[] normals = val.normals; Vector3[] array2 = normals; foreach (Vector3 val3 in array2) { stringBuilder.AppendLine($"vn {0f - val3.x} {val3.y} {val3.z}"); } Vector2[] uv = val.uv; Vector2[] array3 = uv; foreach (Vector2 val4 in array3) { stringBuilder.AppendLine($"vt {val4.x} {val4.y}"); } bool hasNormals = normals != null && normals.Length == vertices.Length; bool hasUVs = uv != null && uv.Length == vertices.Length; int[] triangles = val.triangles; for (int l = 0; l < triangles.Length; l += 3) { int idx = triangles[l] + 1; int idx2 = triangles[l + 1] + 1; int idx3 = triangles[l + 2] + 1; stringBuilder.AppendLine("f " + FaceVertex(idx) + " " + FaceVertex(idx3) + " " + FaceVertex(idx2)); } File.WriteAllText(outputPath, stringBuilder.ToString()); Logger.LogInfo((object)$"[Raincoat][MeshExport] Wrote '{prefabName}' ({vertices.Length} verts, {triangles.Length / 3} tris) to: {outputPath}"); string FaceVertex(int num) { return (hasUVs && hasNormals) ? $"{num}/{num}/{num}" : (hasUVs ? $"{num}/{num}" : (hasNormals ? $"{num}//{num}" : $"{num}")); } } catch (Exception arg) { Logger.LogError((object)$"[Raincoat][MeshExport] Failed to export '{prefabName}': {arg}"); } } private void CreateRaincoatSet() { try { CreateStatusEffect(); } catch (Exception arg) { Logger.LogError((object)$"[Raincoat] CreateStatusEffect failed: {arg}"); } try { CreateNeckSkinItem(); AddNeckDropTableEntry(); } catch (Exception arg2) { Logger.LogError((object)$"[Raincoat] Failed to set up Neck Skin: {arg2}"); } try { CloneArmorPiece("CapeTrollHide", "RaincoatBody", "$item_raincoat_body", "$item_raincoat_body_desc", "RaincoatMod.RaincoatBody.png", 5, 2, "piece_workbench", 2); } catch (Exception arg3) { Logger.LogError((object)$"[Raincoat] Failed to register RaincoatBody: {arg3}"); } try { CloneArmorPiece("HelmetTrollLeather", "RaincoatHood", "$item_raincoat_hood", "$item_raincoat_hood_desc", "RaincoatMod.RaincoatHood.png", 3, 1, "piece_workbench", 2); } catch (Exception arg4) { Logger.LogError((object)$"[Raincoat] Failed to register RaincoatHood: {arg4}"); } PrefabManager.OnVanillaPrefabsAvailable -= CreateRaincoatSet; } private void CreateNeckSkinItem() { //IL_0087: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab("LeatherScraps"); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)"[Raincoat] Could not find source prefab 'LeatherScraps' for Neck Skin."); return; } GameObject val = PrefabManager.Instance.CreateClonedPrefab("NeckSkin", prefab); Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val2 in array) { Material[] materials = val2.materials; foreach (Material val3 in materials) { if (val3.HasProperty("_Color")) { val3.color *= NeckSkinTintMultiplier; } } } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)"[Raincoat] Cloned 'NeckSkin' prefab has no ItemDrop component."); return; } SharedData shared = component.m_itemData.m_shared; shared.m_name = "$item_neckskin"; shared.m_description = "$item_neckskin_desc"; if (shared.m_icons != null && shared.m_icons.Length != 0) { Sprite val4 = LoadEmbeddedIconSprite("RaincoatMod.NeckSkin.png", shared.m_icons[0]); Sprite[] array2 = (Sprite[])(object)new Sprite[shared.m_icons.Length]; for (int k = 0; k < array2.Length; k++) { array2[k] = val4; } shared.m_icons = array2; } ItemConfig val5 = new ItemConfig { Amount = 1 }; CustomItem val6 = new CustomItem(val, false, val5); ItemManager.Instance.AddItem(val6); Logger.LogInfo((object)"[Raincoat] Registered NeckSkin item."); } private void AddNeckDropTableEntry() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0096: 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) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab("Neck"); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)"[Raincoat] Could not find 'Neck' prefab to add Neck Skin drop."); return; } CharacterDrop component = prefab.GetComponent<CharacterDrop>(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)"[Raincoat] 'Neck' prefab has no CharacterDrop component."); return; } GameObject prefab2 = PrefabManager.Instance.GetPrefab("NeckSkin"); if ((Object)(object)prefab2 == (Object)null) { Logger.LogError((object)"[Raincoat] Could not find the newly created 'NeckSkin' prefab to add as a drop."); return; } Drop item = new Drop { m_prefab = prefab2, m_amountMin = 1, m_amountMax = 3, m_chance = 1f, m_onePerPlayer = false, m_levelMultiplier = true }; component.m_drops.Add(item); Logger.LogInfo((object)"[Raincoat] Added NeckSkin to Neck's drop table."); } private static Sprite LoadEmbeddedIconSprite(string resourceName, Sprite referenceSprite) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_00f9: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: 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_0176: Unknown result type (might be due to invalid IL or missing references) Assembly executingAssembly = Assembly.GetExecutingAssembly(); try { using Stream stream = executingAssembly.GetManifestResourceStream(resourceName); if (stream == null) { string text = string.Join(", ", executingAssembly.GetManifestResourceNames()); Logger.LogError((object)("[Raincoat] Embedded icon resource '" + resourceName + "' not found. Resources actually in this DLL: [" + text + "]. Falling back to the original icon.")); return referenceSprite; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); byte[] array = memoryStream.ToArray(); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { Logger.LogError((object)("[Raincoat] Failed to decode embedded icon PNG '" + resourceName + "'. Falling back to the original icon.")); return referenceSprite; } Vector2 val2; if ((Object)(object)referenceSprite != (Object)null) { Rect rect = referenceSprite.rect; if (((Rect)(ref rect)).width > 0f) { rect = referenceSprite.rect; if (((Rect)(ref rect)).height > 0f) { float x = referenceSprite.pivot.x; rect = referenceSprite.rect; float num = x / ((Rect)(ref rect)).width; float y = referenceSprite.pivot.y; rect = referenceSprite.rect; val2 = new Vector2(num, y / ((Rect)(ref rect)).height); goto IL_013b; } } } val2 = new Vector2(0.5f, 0.5f); goto IL_013b; IL_013b: Vector2 val3 = val2; float num2 = (((Object)(object)referenceSprite != (Object)null) ? referenceSprite.pixelsPerUnit : 100f); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), val3, num2); } catch (Exception arg) { Logger.LogError((object)$"[Raincoat] Failed to load embedded icon '{resourceName}': {arg}. Falling back to the original icon."); return referenceSprite; } } private static Requirement[] GetSourceRecipeRequirements(string sourcePrefabName, ItemDrop sourceItemDrop) { if ((Object)(object)sourceItemDrop == (Object)null) { Logger.LogWarning((object)("[Raincoat] sourceItemDrop was null when looking up recipe for '" + sourcePrefabName + "'.")); return null; } Recipe[] array = Resources.FindObjectsOfTypeAll<Recipe>(); Recipe[] array2 = array; foreach (Recipe val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)val.m_item == (Object)(object)sourceItemDrop) { return val.m_resources; } } Logger.LogWarning((object)("[Raincoat] No loaded Recipe found whose m_item is '" + sourcePrefabName + "' " + $"(searched {array.Length} Recipe objects in memory).")); return null; } private void CloneArmorPiece(string sourcePrefabName, string newPrefabName, string displayName, string description, string iconResourceName, int recipeAmount, int recipeAmountPerLevel, string stationName, int stationLevel) { //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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Expected O, but got Unknown //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Expected O, but got Unknown //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab(sourcePrefabName); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)("[Raincoat] Could not find source prefab '" + sourcePrefabName + "'. Check that the prefab name matches your game version.")); return; } GameObject val = PrefabManager.Instance.CreateClonedPrefab(newPrefabName, prefab); Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); Renderer[] array = componentsInChildren; foreach (Renderer val2 in array) { Material[] materials = val2.materials; foreach (Material val3 in materials) { if (val3.HasProperty("_Color")) { val3.color *= TintMultiplier; } } } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)("[Raincoat] Cloned prefab '" + newPrefabName + "' has no ItemDrop component - source prefab '" + sourcePrefabName + "' may not be a valid item prefab.")); return; } SharedData shared = component.m_itemData.m_shared; shared.m_name = displayName; shared.m_description = description; if (shared.m_icons != null && shared.m_icons.Length != 0) { Sprite val4 = LoadEmbeddedIconSprite(iconResourceName, shared.m_icons[0]); Sprite[] array2 = (Sprite[])(object)new Sprite[shared.m_icons.Length]; for (int k = 0; k < array2.Length; k++) { array2[k] = val4; } shared.m_icons = array2; } shared.m_setName = "$item_set_raincoat"; shared.m_setSize = 2; if ((Object)(object)RaincoatStatusEffect == (Object)null) { Logger.LogWarning((object)("[Raincoat] RaincoatStatusEffect was not created before cloning '" + newPrefabName + "' - set bonus will not have an effect assigned.")); } else { shared.m_setStatusEffect = Object.Instantiate<StatusEffect>(RaincoatStatusEffect); ((Object)shared.m_setStatusEffect).name = "SE_RainResistant"; } ItemConfig val5 = new ItemConfig { Amount = 1, CraftingStation = stationName, MinStationLevel = stationLevel }; val5.AddRequirement(new RequirementConfig("NeckSkin", recipeAmount, recipeAmountPerLevel, true)); val5.AddRequirement(new RequirementConfig("LeatherScraps", recipeAmount, recipeAmountPerLevel, true)); val5.AddRequirement(new RequirementConfig("TrollHide", recipeAmount, recipeAmountPerLevel, true)); CustomItem val6 = new CustomItem(val, false, val5); ItemManager.Instance.AddItem(val6); Logger.LogInfo((object)("[Raincoat] Registered " + newPrefabName)); } private void CreateStatusEffect() { StatusEffect val = ScriptableObject.CreateInstance<StatusEffect>(); ((Object)val).name = "SE_RainResistant"; val.m_name = "$se_raincoat_name"; val.m_tooltip = "$se_raincoat_tooltip"; GameObject prefab = PrefabManager.Instance.GetPrefab("CapeTrollHide"); SharedData val2 = ((prefab == null) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData.m_shared); if (val2 != null && val2.m_icons != null && val2.m_icons.Length != 0) { val.m_icon = LoadEmbeddedIconSprite("RaincoatMod.RaincoatBody.png", val2.m_icons[0]); } RaincoatStatusEffect = val; } } internal static class RaincoatSEUtil { internal static bool HasRaincoatEffect(SEMan seman) { List<StatusEffect> value = Traverse.Create((object)seman).Field<List<StatusEffect>>("m_statusEffects").Value; if (value == null) { return false; } foreach (StatusEffect item in value) { if ((Object)(object)item != (Object)null && ((Object)item).name.StartsWith("SE_RainResistant")) { return true; } } return false; } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(StatusEffect), typeof(bool), typeof(int), typeof(float) })] public static class WetBlockPatch { private static bool Prefix(SEMan __instance, StatusEffect statusEffect) { if ((Object)(object)statusEffect == (Object)null) { return true; } if (((Object)statusEffect).name != "Wet") { return true; } if (!RaincoatSEUtil.HasRaincoatEffect(__instance)) { return true; } Character value = Traverse.Create((object)__instance).Field<Character>("m_character").Value; if ((Object)(object)value != (Object)null && value.IsSwimming()) { return true; } return false; } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(float) })] public static class WetBlockByHashPatch { private static bool Prefix(SEMan __instance, int nameHash) { if (nameHash != SEMan.s_statusEffectWet) { return true; } if (!RaincoatSEUtil.HasRaincoatEffect(__instance)) { return true; } Character value = Traverse.Create((object)__instance).Field<Character>("m_character").Value; if ((Object)(object)value != (Object)null && value.IsSwimming()) { return true; } return false; } } }