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 WolfStars v1.8.18
WolfStars.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace WolfStars; [BepInPlugin("wick.wolfstars", "WolfStars", "1.8.18")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private class SizeEntries { public ConfigEntry<bool> grow; public ConfigEntry<float> perStar; public ConfigEntry<float> max; public ConfigEntry<int> dropStars; public ConfigEntry<int> maxStars; public ConfigEntry<string> tintStyle; public ConfigEntry<float> furHue; public ConfigEntry<float> furSaturation; } public const string Guid = "wick.wolfstars"; public const string Version = "1.8.18"; internal static ManualLogSource Log; private static readonly string[] KnownCreatures = new string[9] { "Wolf", "Boar", "Lox", "Hen", "Asksvin", "Deer", "Neck", "Bjorn", "Hare" }; private const string DefaultTints = "3:0.02,0.03,0.08; 5:0,0.065,0.065; 7:0.02,0.08,0.01; 9:0.085,0.07,0; 11:0.1,0.02,0.01; 13:0.085,0,0.08; 15:0.05,0.01,0.1; 17:0.07,0.07,0.085; 19:0.32,0.12,0"; internal static ConfigEntry<string> extraCreatures; internal static ConfigEntry<string> tints; internal static ConfigEntry<int> maxDropStars; internal static ConfigEntry<float> scalePerStar; internal static ConfigEntry<float> maxScale; internal static ConfigEntry<float> glowStrength; internal static ConfigEntry<bool> naturalFur; internal static ConfigEntry<bool> limitStars; internal static ConfigEntry<bool> butcherStars; internal static ConfigEntry<bool> butcherOneHit; internal static ConfigEntry<bool> keepModelSize; internal static ConfigEntry<bool> tintAllParts; internal static ConfigEntry<bool> addMissingLooks; internal static ConfigEntry<string> eggExclude; internal static ConfigEntry<float> butcherMult; internal static ConfigEntry<bool> radarAbbreviate; internal static ConfigEntry<bool> longNames; internal static ConfigEntry<bool> eggFix; internal static ConfigEntry<bool> zeroEggFix; internal static ConfigEntry<bool> controlBreeding; internal static ConfigEntry<bool> separateEggs; internal static ConfigEntry<bool> drawerEggs; internal static ConfigEntry<bool> tameNoStructureDamage; internal static ConfigEntry<bool> babyDrops; internal static ConfigEntry<int> nameLength; internal static ConfigEntry<int> eggMaxQuality; internal static ConfigEntry<int> breedMaxLevel; internal static ConfigEntry<int> breedMaxCreatures; internal static ConfigEntry<int> incubationDelay; internal static ConfigEntry<float> breedLevelUpChance; internal static ConfigEntry<int> radarFrom; private static readonly Dictionary<string, ConfigEntry<bool>> toggles = new Dictionary<string, ConfigEntry<bool>>(); private static readonly Dictionary<string, SizeEntries> sizes = new Dictionary<string, SizeEntries>(StringComparer.OrdinalIgnoreCase); private static HashSet<string> creatureSet = new HashSet<string>(); private static List<KeyValuePair<int, Color>> tintList = new List<KeyValuePair<int, Color>>(); private static readonly Dictionary<string, string> Babies = new Dictionary<string, string> { { "Chicken", "Hen" }, { "Wolf_cub", "Wolf" }, { "Boar_piggy", "Boar" }, { "Lox_Calf", "Lox" }, { "Asksvin_hatchling", "Asksvin" } }; private static readonly HashSet<string> reportedTames = new HashSet<string>(); private static string DefaultStyle(string name) { if (!(name == "Bjorn") && !(name == "Lox")) { return "Glow"; } return "Fur"; } private static int DefaultDropStars(string name) { switch (name) { default: return 3; case "Hen": case "Lox": case "Bjorn": return 1; } } private void Awake() { //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Expected O, but got Unknown //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Expected O, but got Unknown //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Expected O, but got Unknown //IL_0596: Unknown result type (might be due to invalid IL or missing references) //IL_05a0: Expected O, but got Unknown //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_05d3: Expected O, but got Unknown //IL_05fb: Unknown result type (might be due to invalid IL or missing references) //IL_0605: Expected O, but got Unknown //IL_064e: Unknown result type (might be due to invalid IL or missing references) //IL_0658: Expected O, but got Unknown //IL_0704: Unknown result type (might be due to invalid IL or missing references) //IL_070e: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Expected O, but got Unknown //IL_0798: Unknown result type (might be due to invalid IL or missing references) //IL_079d: Unknown result type (might be due to invalid IL or missing references) //IL_07b2: Unknown result type (might be due to invalid IL or missing references) //IL_07b8: Expected O, but got Unknown //IL_07b8: Unknown result type (might be due to invalid IL or missing references) //IL_07be: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; string[] knownCreatures = KnownCreatures; foreach (string text in knownCreatures) { ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Creatures", text, true, "Apply WolfStars looks and drop cap to " + text + "."); val.SettingChanged += delegate { ParseCreatures(); }; toggles[text] = val; string text2 = text; sizes[text] = new SizeEntries { grow = ((BaseUnityPlugin)this).Config.Bind<bool>(text2, "GrowWithStars", true, "true = " + text + " gets bigger with every star above 2; false = it stays at the game's 2-star size (colours and the drop cap still apply)."), perStar = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "ScalePerStar", 0.05f, "Extra size per star above 2 for " + text + " (0.05 = +5%), added to its 2-star size."), max = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "MaxScale", 1.5f, "Largest size for " + text + ", as a multiple of a 0-star " + text + "."), dropStars = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "MaxDropStars", DefaultDropStars(text), new ConfigDescription("A " + text + " with more stars than this drops like one with exactly this many (3 stars = 8x the 0-star drops, 2 = 4x, 0 = like a 0-star).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), Array.Empty<object>())), maxStars = ((BaseUnityPlugin)this).Config.Bind<int>(text2, "MaxStars", 19, new ConfigDescription("Highest star count a " + text + " can get when [Breeding] LimitStars is on (19 = level 20). Only lowers levels - raising the limit is the breeding mod's job.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())), tintStyle = ((BaseUnityPlugin)this).Config.Bind<string>(text2, "TintStyle", DefaultStyle(text), new ConfigDescription("How " + text + "'s star colour is shown: Glow = a faint glow in the [Looks] Tints colour (needs fur that can glow - wolf, boar); Fur = the fur itself is shifted towards that colour (for fur that can't glow - the bear).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Glow", "Fur" }), Array.Empty<object>())), furHue = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "FurHue", 0.07f, new ConfigDescription("TintStyle Fur only: " + text + "'s own fur hue (0-1; 0.07 = brown). Used to work out how far to turn the hue to reach each band's colour.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())), furSaturation = ((BaseUnityPlugin)this).Config.Bind<float>(text2, "FurSaturation", 0.4f, new ConfigDescription("TintStyle Fur only: extra colour strength for " + text + "'s tinted fur (0 = only the hue turns, 1 = very vivid).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>())) }; } extraCreatures = ((BaseUnityPlugin)this).Config.Bind<string>("Creatures", "ExtraCreatures", "", "More prefab names to include (comma separated), e.g. creatures from other mods."); maxDropStars = ((BaseUnityPlugin)this).Config.Bind<int>("Drops", "MaxDropStars", 3, new ConfigDescription("Creatures with more stars than this drop like one with exactly this many (3 stars = 8x the 0-star drops). Vanilla doubles drops with every star. Used for ExtraCreatures - the listed creatures have their own MaxDropStars in their [<name>] section.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), Array.Empty<object>())); babyDrops = ((BaseUnityPlugin)this).Config.Bind<bool>("Drops", "BabiesLikeAdults", true, "true = the game's babies (chick, wolf cub, piglet, lox calf, asksvin hatchling) drop with their adult's MaxDropStars cap. They are born at their parent's level, so a 9-star hen's chick otherwise drops 512x. Their looks are not changed."); scalePerStar = ((BaseUnityPlugin)this).Config.Bind<float>("Looks", "ScalePerStar", 0.05f, "Extra size per star above 2 (0.05 = +5%), added to the 2-star size. Used for ExtraCreatures - the listed creatures have their own [<name>] sections."); maxScale = ((BaseUnityPlugin)this).Config.Bind<float>("Looks", "MaxScale", 1.5f, "Largest size, as a multiple of a 0-star creature. Used for ExtraCreatures - the listed creatures have their own [<name>] sections."); tints = ((BaseUnityPlugin)this).Config.Bind<string>("Looks", "Tints", "3:0.02,0.03,0.08; 5:0,0.065,0.065; 7:0.02,0.08,0.01; 9:0.085,0.07,0; 11:0.1,0.02,0.01; 13:0.085,0,0.08; 15:0.05,0.01,0.1; 17:0.07,0.07,0.085; 19:0.32,0.12,0", "Colour bands as 'fromStars:R,G,B' separated by ';' - each band glows that colour from that many stars until the next band starts. The glow lights the whole body evenly, so keep values low (0.1-0.2 tints, 0.3+ looks painted). Default: 3 blue, 5 teal, 7 green, 9 yellow, 11 red, 13 magenta, 15 purple, 17 silver, 19 orange (level 20)."); glowStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Looks", "GlowStrength", 1f, "Multiplies every Tints colour - 0.5 = half as strong, 1.5 = half again stronger. Takes effect on the next game start."); naturalFur = ((BaseUnityPlugin)this).Config.Bind<bool>("Looks", "NaturalFurUnderTints", true, "true = tinted creatures keep their plain fur colour so the tint reads cleanly; false = they keep the game's bluish 2-star fur under the tint."); keepModelSize = ((BaseUnityPlugin)this).Config.Bind<bool>("Looks", "KeepModelSize", true, "true = creatures whose model is built at a size other than 1 (the hen: 2x) keep that size when they get stars. The game's star sizes replace the model size, so a 1-star hen shrinks to about half."); addMissingLooks = ((BaseUnityPlugin)this).Config.Bind<bool>("Looks", "AddMissingLooks", true, "true = listed creatures the game gave no star looks at all (the lox) get them added, so they grow and get star colours like the others. Takes effect on the next game start."); tintAllParts = ((BaseUnityPlugin)this).Config.Bind<bool>("Looks", "TintAllParts", true, "true = creatures whose body is split into several meshes (the bear) get the star colour on every part, not only the one the game picks."); limitStars = ((BaseUnityPlugin)this).Config.Bind<bool>("Breeding", "LimitStars", false, "true = no listed creature can get more stars than its own MaxStars setting (applies when a level is set: births, growing up, spawns). Leave false when another mod (e.g. BreedingTweaks) handles max levels."); butcherMult = ((BaseUnityPlugin)this).Config.Bind<float>("ButcherKnife", "DamageMultiplier", 2f, "Butcher knife damage against tamed creatures, as a multiple of normal (1 = vanilla)."); butcherStars = ((BaseUnityPlugin)this).Config.Bind<bool>("ButcherKnife", "ScaleWithStars", true, "true = the butcher knife also multiplies its damage by the tame's level, so a high-star tame takes as many hits as a 0-star one (tames have level x the health)."); butcherOneHit = ((BaseUnityPlugin)this).Config.Bind<bool>("ButcherKnife", "OneHitKill", true, "true = every butcher knife hit kills the tame outright (the knife only hurts tamed creatures anyway); DamageMultiplier and ScaleWithStars are then not used."); radarAbbreviate = ((BaseUnityPlugin)this).Config.Bind<bool>("ValheimRadar", "AbbreviateStars", true, "When ValheimRadar is installed: show many stars on its minimap pins as '19x★' instead of 19 star characters - the same way BetterUI shows them above the creature."); radarFrom = ((BaseUnityPlugin)this).Config.Bind<int>("ValheimRadar", "AbbreviateFrom", 5, new ConfigDescription("Star count from which radar pins switch to the short '<n>x★' form (5 = like BetterUI).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 100), Array.Empty<object>())); longNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Names", "LongTameNames", true, "true = the rename box for tamed creatures accepts names up to NameLength characters (vanilla: 10). Applies to every tame, not just the listed creatures."); nameLength = ((BaseUnityPlugin)this).Config.Bind<int>("Names", "NameLength", 30, new ConfigDescription("Longest tame name you can type when LongTameNames is on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>())); controlBreeding = ((BaseUnityPlugin)this).Config.Bind<bool>("Breeding", "ControlBreeding", false, "true = WolfStars does what BreedingTweaks does, for anyone using WolfStars on its own: a newborn can get one level more than its parent (LevelUpChance) up to MaxLevel, and MaxCreatures can raise how many animals breed in one area. Leave false when BreedingTweaks (or another breeding mod) is installed."); breedLevelUpChance = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "LevelUpChance", 5f, new ConfigDescription("Percent chance that a newborn (or laid egg) is one level higher than its parent (vanilla: 0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); breedMaxLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Breeding", "MaxLevel", 20, new ConfigDescription("Highest level breeding can reach through LevelUpChance (level 20 = 19 stars; vanilla parents top out at level 3).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); breedMaxCreatures = ((BaseUnityPlugin)this).Config.Bind<int>("Breeding", "MaxCreatures", 0, new ConfigDescription("Animals of a kind nearby before they stop breeding. 0 = keep the game's own value (about 4 for most animals).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); eggFix = ((BaseUnityPlugin)this).Config.Bind<bool>("Eggs", "FixHighStarEggs", true, "true = eggs laid by high-star animals still work in recipes. An egg's quality is the parent's level, and crafting only counts an ingredient up to the item's max quality - so with breeding past 2 stars the eggs stop counting. This raises the max quality of every egg item (anything that hatches)."); eggMaxQuality = ((BaseUnityPlugin)this).Config.Bind<int>("Eggs", "MaxEggQuality", 25, new ConfigDescription("Max quality given to egg items - keep it at or above the highest creature level (BreedingTweaks' Max Creature Level, default here 20).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 100), Array.Empty<object>())); zeroEggFix = ((BaseUnityPlugin)this).Config.Bind<bool>("Eggs", "FixZeroQualityEggs", true, "true = plain eggs stored with quality 0 count as normal (quality 1) eggs. The recipe list counts them, but crafting only accepts quality 1 and up, so they could never be used. They are corrected whenever an inventory, chest or dropped egg loads, and new eggs never get quality 0."); separateEggs = ((BaseUnityPlugin)this).Config.Bind<bool>("Eggs", "ChestsKeepQualities", true, "With BetrValheim: its auto-collect only puts an egg into a chest that already holds that egg at the same quality (an egg's quality = the stars it hatches with). Put a quality-2 egg in a chest and it collects only quality-2 eggs."); drawerEggs = ((BaseUnityPlugin)this).Config.Bind<bool>("Eggs", "DrawersKeepQualities", false, "With BetrValheim: each drawer remembers the quality of the eggs in it - an empty drawer takes any quality, a filled one only the same - and eggs taken out keep it. false = BetrValheim's own drawers, which keep no quality: starred eggs put in come out as plain quality-1 eggs."); tameNoStructureDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Tames", "NoStructureDamage", true, "true = tamed creatures do no damage to build pieces (walls, floors, ships...) - e.g. a swing at an enemy that also catches a wall, or a lox stomping next to the base. Applies to every tame, not just the listed creatures. Enemies, players and wild creatures are not affected."); incubationDelay = ((BaseUnityPlugin)this).Config.Bind<int>("Eggs", "IncubationDelaySeconds", 60, new ConfigDescription("Seconds an egg must lie on the ground before it can start warming up (vanilla: 0). Gives BetrValheim's auto-collect time to put freshly laid eggs into a chest before they start to hatch; an egg you drop to hatch on purpose just starts this much later. Counted from when the egg was dropped or laid, also across restarts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3600), Array.Empty<object>())); eggExclude = ((BaseUnityPlugin)this).Config.Bind<string>("Eggs", "ExcludeItems", "DragonEgg", "Hatching items the [Eggs] fixes leave alone, comma separated prefab names. DragonEgg only hatches because LetMeTameYou makes it, and is not bred from a parent."); extraCreatures.SettingChanged += delegate { ParseCreatures(); }; tints.SettingChanged += delegate { ParseTints(); }; ParseCreatures(); ParseTints(); Harmony val2 = new Harmony("wick.wolfstars"); val2.PatchAll(typeof(Plugin).Assembly); RadarCompat.TryPatch(val2); BetrEggs.PatchFindDrawer(val2); List<string> list = new List<string>(); foreach (MethodBase patchedMethod in val2.GetPatchedMethods()) { if (patchedMethod.DeclaringType != null && patchedMethod.DeclaringType.FullName.StartsWith("BetrValheim.", StringComparison.Ordinal)) { list.Add(patchedMethod.DeclaringType.Name + "." + patchedMethod.Name); } } if (list.Count > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[wolfstars] BetrValheim egg handling on: " + string.Join(", ", list))); } if (controlBreeding.Value) { foreach (PluginInfo value in Chainloader.PluginInfos.Values) { if (value.Metadata.Name.IndexOf("BreedingTweaks", StringComparison.OrdinalIgnoreCase) >= 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[wolfstars] [Breeding] ControlBreeding is on while " + value.Metadata.Name + " is installed - both change breeding; switch one of them off")); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[wolfstars] ready 1.8.18 for " + string.Join(",", creatureSet))); } private static void ParseCreatures() { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, ConfigEntry<bool>> toggle in toggles) { if (toggle.Value.Value) { hashSet.Add(toggle.Key); } } string[] array = extraCreatures.Value.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { hashSet.Add(text); } } creatureSet = hashSet; } private static void ParseTints() { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<int, Color>> list = new List<KeyValuePair<int, Color>>(); CultureInfo invariantCulture = CultureInfo.InvariantCulture; string[] array = tints.Value.Split(';'); foreach (string text in array) { string[] array2 = text.Split(':'); if (array2.Length != 2) { continue; } string[] array3 = array2[1].Split(','); if (array3.Length == 3 && int.TryParse(array2[0].Trim(), out var result)) { if (!float.TryParse(array3[0].Trim(), NumberStyles.Float, invariantCulture, out var result2) || !float.TryParse(array3[1].Trim(), NumberStyles.Float, invariantCulture, out var result3) || !float.TryParse(array3[2].Trim(), NumberStyles.Float, invariantCulture, out var result4)) { Log.LogWarning((object)("[wolfstars] skipped bad tint band: " + text.Trim())); } else { list.Add(new KeyValuePair<int, Color>(result, new Color(result2, result3, result4, 1f))); } } } list.Sort((KeyValuePair<int, Color> a, KeyValuePair<int, Color> b) => a.Key.CompareTo(b.Key)); tintList = list; } internal static string BaseName(string prefab) { if (string.IsNullOrEmpty(prefab)) { return null; } if (creatureSet.Contains(prefab)) { return prefab; } if (prefab.StartsWith("Mini", StringComparison.Ordinal) && creatureSet.Contains(prefab.Substring(4))) { return prefab.Substring(4); } return null; } internal static int MaxStarsFor(string prefab) { if (!sizes.TryGetValue(BaseName(prefab) ?? prefab, out var value)) { return 100; } return value.maxStars.Value; } internal static int DropStarsFor(string prefab) { if (!sizes.TryGetValue(DropName(prefab) ?? prefab, out var value)) { return maxDropStars.Value; } return value.dropStars.Value; } internal static string DropName(string prefab) { string text = BaseName(prefab); if (text != null || prefab == null || !babyDrops.Value) { return text; } if (!Babies.TryGetValue(prefab, out var value) || !creatureSet.Contains(value)) { return null; } return value; } internal static bool AppliesDrops(Component c) { if ((Object)(object)c != (Object)null) { return DropName(Utils.GetPrefabName(c.gameObject)) != null; } return false; } internal static void SizeFor(string prefab, out bool grow, out float perStar, out float max) { if (sizes.TryGetValue(BaseName(prefab) ?? prefab, out var value)) { grow = value.grow.Value; perStar = value.perStar.Value; max = value.max.Value; } else { grow = true; perStar = scalePerStar.Value; max = maxScale.Value; } } internal static bool FurTint(string prefab, Color band, out float hue, out float saturation) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) hue = (saturation = 0f); if (!sizes.TryGetValue(BaseName(prefab) ?? prefab, out var value) || value.tintStyle.Value != "Fur") { return false; } float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(band, ref num, ref num2, ref num3); hue = num - value.furHue.Value; if (hue > 0.5f) { hue -= 1f; } if (hue < -0.5f) { hue += 1f; } saturation = value.furSaturation.Value; return true; } internal static bool TintFor(int stars, out Color color) { //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_0031: 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) color = Color.black; bool result = false; foreach (KeyValuePair<int, Color> tint in tintList) { if (tint.Key > stars) { break; } color = tint.Value; result = true; } return result; } internal static IEnumerable<string> CreatureNames() { return creatureSet; } internal static bool Applies(Component c) { if ((Object)(object)c != (Object)null) { return BaseName(Utils.GetPrefabName(c.gameObject)) != null; } return false; } internal static bool EggExcluded(string prefab) { string[] array = eggExclude.Value.Split(','); for (int i = 0; i < array.Length; i++) { if (string.Equals(array[i].Trim(), prefab, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } internal static void ReportUncovered(Character c, string where) { if (!((Object)(object)c == (Object)null) && !c.IsPlayer() && c.IsTamed() && !((where == "drops") ? AppliesDrops((Component)(object)c) : Applies((Component)(object)c))) { string prefabName = Utils.GetPrefabName(((Component)c).gameObject); if (reportedTames.Add(prefabName)) { Log.LogInfo((object)$"[wolfstars] tame not covered ({where}): prefab '{prefabName}', level {c.GetLevel()} - add it to [Creatures] ExtraCreatures to include it"); } } } } [HarmonyPatch(typeof(LevelEffects), "SetupLevelVisualization")] internal static class LooksPatch { private static readonly Dictionary<string, List<LevelSetup>> vanilla = new Dictionary<string, List<LevelSetup>>(); private static readonly Dictionary<string, float> modelSize = new Dictionary<string, float>(); private static float ModelSize(string prefab) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (modelSize.TryGetValue(prefab, out var value)) { return value; } value = 1f; GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(prefab) : null); LevelEffects val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponentInChildren<LevelEffects>(true) : null); if ((Object)(object)val2 != (Object)null) { value = ((Component)val2).transform.localScale.x; } modelSize[prefab] = value; if (!Mathf.Approximately(value, 1f)) { Plugin.Log.LogInfo((object)$"[wolfstars] {prefab} model size {value} - star sizes are multiplied by it"); } return value; } private static void Postfix(LevelEffects __instance, int level, Material __state) { //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) if (level <= 1 || __instance.m_levelSetups == null || __instance.m_levelSetups.Count < level - 1) { return; } Character componentInParent = ((Component)__instance).GetComponentInParent<Character>(); if (!Plugin.Applies((Component)(object)componentInParent)) { return; } if (Plugin.keepModelSize.Value) { float num = ModelSize(Utils.GetPrefabName(((Component)componentInParent).gameObject)); if (!Mathf.Approximately(num, 1f)) { ((Component)__instance).transform.localScale = ((Component)__instance).transform.localScale * num; } } Renderer mainRender = __instance.m_mainRender; if (!Plugin.tintAllParts.Value || !((Object)(object)mainRender != (Object)null) || !((Object)(object)__state != (Object)null) || !((Object)(object)mainRender.sharedMaterial != (Object)(object)__state)) { return; } Material sharedMaterial = mainRender.sharedMaterial; Renderer[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)(object)mainRender && (Object)(object)val.sharedMaterial == (Object)(object)__state) { val.sharedMaterial = sharedMaterial; } } } private static void Prefix(LevelEffects __instance, int level, out Material __state) { //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01da: 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_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) __state = (((Object)(object)__instance.m_mainRender != (Object)null) ? __instance.m_mainRender.sharedMaterial : null); List<LevelSetup> levelSetups = __instance.m_levelSetups; Character componentInParent = ((Component)__instance).GetComponentInParent<Character>(); Plugin.ReportUncovered(componentInParent, "looks"); if (levelSetups == null || levelSetups.Count == 0 || level - 1 <= levelSetups.Count || !Plugin.Applies((Component)(object)componentInParent)) { return; } string prefabName = Utils.GetPrefabName(((Component)componentInParent).gameObject); if (!vanilla.TryGetValue(prefabName, out var value)) { value = new List<LevelSetup>(levelSetups); vanilla[prefabName] = value; for (int i = 0; i < value.Count; i++) { Plugin.Log.LogInfo((object)($"[wolfstars] {prefabName} vanilla level {i + 2}: scale {value[i].m_scale} hue {value[i].m_hue} " + $"sat {value[i].m_saturation} value {value[i].m_value} emissive {value[i].m_setEmissiveColor}")); } } LevelSetup val = value[value.Count - 1]; Plugin.SizeFor(prefabName, out var grow, out var perStar, out var max); int num = value.Count + 1; while (levelSetups.Count < level - 1) { int num2 = levelSetups.Count + 2; int num3 = num2 - num; int stars = num2 - 1; LevelSetup val2 = new LevelSetup { m_scale = (grow ? Mathf.Min(max, val.m_scale + perStar * (float)num3) : val.m_scale), m_hue = val.m_hue, m_saturation = val.m_saturation, m_value = val.m_value, m_setEmissiveColor = val.m_setEmissiveColor, m_emissiveColor = val.m_emissiveColor, m_enableObject = val.m_enableObject }; Color color2; if (Plugin.TintFor(stars, out var color) && Plugin.FurTint(prefabName, color, out var hue, out var saturation)) { val2.m_hue = hue; val2.m_saturation = saturation; val2.m_value = 0f; val2.m_setEmissiveColor = false; } else if (Plugin.TintFor(stars, out color2)) { if (Plugin.naturalFur.Value) { val2.m_hue = 0f; val2.m_saturation = 0f; val2.m_value = 0f; } color2 *= Plugin.glowStrength.Value; color2.a = 1f; val2.m_setEmissiveColor = true; val2.m_emissiveColor = color2; } levelSetups.Add(val2); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class AddLooksPatch { private static void Postfix(ZNetScene __instance) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown if (!Plugin.addMissingLooks.Value) { return; } List<string> list = new List<string>(); foreach (string item in Plugin.CreatureNames()) { GameObject prefab = __instance.GetPrefab(item); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<Character>() == (Object)null || (Object)(object)prefab.GetComponentInChildren<LevelEffects>(true) != (Object)null) { continue; } Transform val = prefab.transform.Find("Visual") ?? prefab.transform; Renderer val2 = null; int num = -1; SkinnedMeshRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val3 in componentsInChildren) { int num2 = (Object.op_Implicit((Object)(object)val3.sharedMesh) ? val3.sharedMesh.vertexCount : 0); if (num2 > num) { num = num2; val2 = (Renderer)(object)val3; } } if (!((Object)(object)val2 == (Object)null)) { LevelEffects obj = ((Component)val).gameObject.AddComponent<LevelEffects>(); obj.m_mainRender = val2; float x = val.localScale.x; obj.m_levelSetups = new List<LevelSetup> { new LevelSetup { m_scale = 1.1f }, new LevelSetup { m_scale = 1.2f } }; list.Add($"{item} (on '{((Object)val).name}', main '{((Object)val2).name}', model size {x})"); } } if (list.Count > 0) { Plugin.Log.LogInfo((object)("[wolfstars] added star looks to: " + string.Join(", ", list))); } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class TestCommand { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; internal void <Postfix>b__1_0(ConsoleEventArgs args) { //IL_005b: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } int num = args.TryParameterInt(1, 1); Character val = null; float num2 = 30f; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer() && Plugin.Applies((Component)(object)allCharacter)) { float num3 = Vector3.Distance(((Component)allCharacter).transform.position, ((Component)localPlayer).transform.position); if (num3 < num2) { num2 = num3; val = allCharacter; } } } if ((Object)(object)val == (Object)null) { args.Context.AddString("no WolfStars creature within 30 m"); return; } val.SetLevel(Mathf.Max(1, num)); args.Context.AddString($"{Utils.GetPrefabName(((Component)val).gameObject)} set to level {val.GetLevel()} ({val.GetLevel() - 1} stars)"); } } private static bool added; private static void Postfix() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0037: Expected O, but got Unknown if (added) { return; } added = true; object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_005b: 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) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { int num = args.TryParameterInt(1, 1); Character val2 = null; float num2 = 30f; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer() && Plugin.Applies((Component)(object)allCharacter)) { float num3 = Vector3.Distance(((Component)allCharacter).transform.position, ((Component)localPlayer).transform.position); if (num3 < num2) { num2 = num3; val2 = allCharacter; } } } if ((Object)(object)val2 == (Object)null) { args.Context.AddString("no WolfStars creature within 30 m"); } else { val2.SetLevel(Mathf.Max(1, num)); args.Context.AddString($"{Utils.GetPrefabName(((Component)val2).gameObject)} set to level {val2.GetLevel()} ({val2.GetLevel() - 1} stars)"); } } }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("wolfstars_level", "[level] - set the level of the nearest WolfStars creature within 30 m (stars = level - 1)", (ConsoleEvent)obj, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } [HarmonyPatch(typeof(Procreation), "Procreate")] internal static class BreedLevelPatch { private static void Prefix(Procreation __instance, Character ___m_character, out int __state) { __state = -1; if (!Plugin.controlBreeding.Value || (Object)(object)___m_character == (Object)null) { return; } int level = ___m_character.GetLevel(); if (level < Plugin.breedMaxLevel.Value && !(Random.value * 100f >= Plugin.breedLevelUpChance.Value)) { __state = __instance.m_minOffspringLevel; if (level + 1 > __instance.m_minOffspringLevel) { __instance.m_minOffspringLevel = level + 1; } } } private static void Finalizer(Procreation __instance, int __state) { if (__state >= 0) { __instance.m_minOffspringLevel = __state; } } } [HarmonyPatch(typeof(Procreation), "Awake")] internal static class BreedCountPatch { private static void Postfix(Procreation __instance) { if (Plugin.controlBreeding.Value && Plugin.breedMaxCreatures.Value > 0) { __instance.m_maxCreatures = Plugin.breedMaxCreatures.Value; } } } [HarmonyPatch] internal static class EggQualityPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(ObjectDB), "CopyOtherDB", (Type[])null, (Type[])null); } [HarmonyPriority(0)] private static void Postfix(ObjectDB __instance) { if (!Plugin.eggFix.Value || (Object)(object)__instance == (Object)null || __instance.m_items == null) { return; } int value = Plugin.eggMaxQuality.Value; List<string> list = new List<string>(); foreach (GameObject item in __instance.m_items) { if ((Object)(object)item == (Object)null || (Object)(object)item.GetComponent<EggGrow>() == (Object)null || Plugin.EggExcluded(((Object)item).name)) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null && component.m_itemData.m_shared != null) { SharedData shared = component.m_itemData.m_shared; if (shared.m_maxQuality < value) { list.Add($"{((Object)item).name} {shared.m_maxQuality}->{value}"); shared.m_maxQuality = value; } } } if (list.Count > 0) { Plugin.Log.LogInfo((object)("[wolfstars] egg max quality raised: " + string.Join(", ", list))); } } } internal static class ZeroEggs { [HarmonyPatch] private static class InventoryLoadPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Inventory), "Load", new Type[1] { typeof(ZPackage) }, (Type[])null); yield return AccessTools.Method(typeof(Inventory), "Load", new Type[2] { typeof(ZPackage), typeof(bool) }, (Type[])null); } private static void Postfix(Inventory __instance) { if (!Plugin.zeroEggFix.Value) { return; } foreach (ItemData allItem in __instance.GetAllItems()) { Fix(allItem); } } } [HarmonyPatch(typeof(ItemDrop), "LoadFromZDO")] private static class DropLoadPatch { private static void Postfix(ItemData itemData) { Fix(itemData); } } [HarmonyPatch(typeof(ItemDrop), "SetQuality")] private static class SetQualityPatch { private static void Prefix(ItemDrop __instance, ref int quality) { if (Plugin.zeroEggFix.Value && quality < 1 && (Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<EggGrow>() != (Object)null && !Plugin.EggExcluded(Utils.GetPrefabName(((Component)__instance).gameObject))) { quality = 1; } } } private static readonly Dictionary<string, bool> isEgg = new Dictionary<string, bool>(); internal static bool IsEgg(ItemData item) { GameObject val = item?.m_dropPrefab; if ((Object)(object)val == (Object)null) { return false; } if (!isEgg.TryGetValue(((Object)val).name, out var value)) { value = (Object)(object)val.GetComponent<EggGrow>() != (Object)null && !Plugin.EggExcluded(((Object)val).name); isEgg[((Object)val).name] = value; } return value; } internal static void Fix(ItemData item) { if (Plugin.zeroEggFix.Value && item != null && item.m_quality < 1 && IsEgg(item)) { item.m_quality = 1; } } } internal static class BetrEggs { [HarmonyPatch] private static class UseItemPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Drawers.Drawer", "UseItem", typeof(Humanoid), typeof(ItemData)); } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static bool Prefix(object __instance, Humanoid user, ItemData item, ref bool __result, out int __state) { __state = 0; if (!Egg(item)) { return true; } __state = Mathf.Max(1, item.m_quality); if (Accepts(__instance, __state)) { return true; } if (user != null) { ((Character)user).Message((MessageType)2, $"This drawer holds quality {QualityOf(__instance)} eggs", 0, (Sprite)null, false); } __result = false; return false; } private static void Postfix(object __instance, bool __result, int __state) { if (__state > 0 && __result) { Remember(__instance, __state); } } } [HarmonyPatch] private static class DepositFromPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Drawers.Drawer", "DepositFrom", typeof(Inventory), typeof(string)); } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static bool Prefix(object __instance, Inventory inventory, string prefabName, ref int __result) { if (inventory == null || !EggPrefab(prefabName)) { return true; } int num = 0; foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (!item.m_equipped && !((Object)(object)item.m_dropPrefab == (Object)null) && !(((Object)item.m_dropPrefab).name != prefabName)) { num += Store(__instance, inventory, item, prefabName, item.m_stack); } } __result = num; return false; } } [HarmonyPatch] private static class IntoDrawersPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Storage.QuickStack", "IntoDrawers", typeof(Inventory), typeof(ItemData)); } private static bool Prepare() { if (TargetMethod() != null && Ready()) { return quickDrawers != null; } return false; } private static bool Prefix(Inventory source, ItemData item, ref int __result) { if (!Egg(item) || (Object)(object)item.m_dropPrefab == (Object)null) { return true; } string name = ((Object)item.m_dropPrefab).name; int num = item.m_stack; int num2 = 0; if (quickDrawers.GetValue(null) is IList list) { foreach (object item2 in list) { if (num <= 0) { break; } Object val = (Object)((item2 is Object) ? item2 : null); if (val != null && !(val == (Object)null) && !(Name(item2) != name) && Free(item2) > 0) { int num3 = Store(item2, source, item, name, num); num -= num3; num2 += num3; } } } __result = num2; return false; } } [HarmonyPatch] private static class FromDrawersPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Storage.QuickStack", "FromDrawers", typeof(ItemData), typeof(int)); } private static bool Prepare() { return TargetMethod() != null; } private static bool Prefix(ItemData __0, ref int __result) { if (!Egg(__0)) { return true; } __result = 0; return false; } } [HarmonyPatch] private static class TryStorePatch { internal static ItemDrop current; private static MethodBase TargetMethod() { return M("BetrValheim.Collect.Collector", "TryStore", typeof(ItemDrop)); } private static bool Prepare() { return TargetMethod() != null; } private static void Prefix(ItemDrop drop) { current = drop; } private static void Finalizer() { current = null; } } [HarmonyPatch] private static class StoreInDrawerPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("BetrValheim.Collect.Collector"); if (!(type == null)) { return AccessTools.FirstMethod(type, (Func<MethodInfo, bool>)((MethodInfo m) => m.Name == "StoreInDrawer")); } return null; } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static bool Prefix(object __0, ItemDrop __1, ref bool __result, out int __state) { __state = 0; if (__0 == null || (Object)(object)__1 == (Object)null || !Egg(__1.m_itemData)) { return true; } __state = Mathf.Max(1, __1.m_itemData.m_quality); if (Accepts(__0, __state)) { return true; } __result = false; return false; } private static void Postfix(object __0, bool __result, int __state) { if (__state > 0 && __result && __0 != null) { Remember(__0, __state); } } } [HarmonyPatch] private static class GiveToPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("BetrValheim.Drawers.Drawer"); if (!(type == null)) { return AccessTools.FirstMethod(type, (Func<MethodInfo, bool>)((MethodInfo m) => m.Name == "GiveTo")); } return null; } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static void Prefix(object __instance, ItemDrop __1, out int __state) { __state = 0; if (!((Object)(object)__1 == (Object)null) && EggPrefab(Utils.GetPrefabName(((Component)__1).gameObject))) { __state = __1.m_itemData.m_quality; __1.m_itemData.m_quality = QualityOf(__instance); } } private static void Finalizer(ItemDrop __1, int __state) { if (__state > 0 && (Object)(object)__1 != (Object)null) { __1.m_itemData.m_quality = __state; } } } [HarmonyPatch] private static class DropContentsPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Drawers.Drawer", "DropContents"); } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static void Prefix(object __instance) { dropQuality = ((Count(__instance) > 0) ? QualityOf(__instance) : 0); } private static void Finalizer() { if ((Object)(object)dropTemplate != (Object)null) { dropTemplate.m_itemData.m_quality = dropTemplateQuality; } dropTemplate = null; dropQuality = 0; } } [HarmonyPatch] private static class DropForPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Drawers.Drawer", "DropFor", typeof(string)); } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(ItemDrop __result) { if (dropQuality > 1 && !((Object)(object)__result == (Object)null) && !((Object)(object)dropTemplate != (Object)null) && EggPrefab(Utils.GetPrefabName(((Component)__result).gameObject))) { dropTemplate = __result; dropTemplateQuality = __result.m_itemData.m_quality; __result.m_itemData.m_quality = dropQuality; } } } [HarmonyPatch] private static class HoverPatch { private static MethodBase TargetMethod() { return M("BetrValheim.Drawers.Drawer", "GetHoverText"); } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static void Postfix(object __instance, ref string __result) { if (__result != null && Count(__instance) > 0 && EggPrefab(Name(__instance))) { int num = QualityOf(__instance); if (num > 1) { __result += $"\n<color=yellow>quality {num}</color>"; } } } } [HarmonyPatch] private static class HoverNamePatch { private static MethodBase TargetMethod() { return M("BetrValheim.Drawers.Drawer", "GetHoverName"); } private static bool Prepare() { if (TargetMethod() != null) { return Ready(); } return false; } private static void Postfix(object __instance, ref string __result) { if (__result != null && Count(__instance) > 0 && EggPrefab(Name(__instance))) { int num = QualityOf(__instance); if (num > 1) { __result += $" (quality {num})"; } } } } [HarmonyPatch] private static class SuitsPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("BetrValheim.Storage.ChestRules"); if (!(type == null)) { return AccessTools.FirstMethod(type, (Func<MethodInfo, bool>)((MethodInfo m) => m.Name == "Suits")); } return null; } private static bool Prepare() { return TargetMethod() != null; } private static void Postfix(Inventory inventory, ItemData item, ref bool __result) { if (!__result || !Plugin.separateEggs.Value || inventory == null || item == null || !ZeroEggs.IsEgg(item)) { return; } bool flag = false; foreach (ItemData allItem in inventory.GetAllItems()) { if (!(allItem.m_shared.m_name != item.m_shared.m_name)) { if (allItem.m_quality == item.m_quality) { return; } flag = true; } } if (flag) { __result = false; } } } private const string QualityKey = "wolfstars_egg_q"; private static bool looked; private static bool ready; private static MethodInfo zdoOf; private static MethodInfo deposit; private static MethodInfo countOf; private static MethodInfo nameOf; private static MethodInfo freeOf; private static FieldInfo quickDrawers; private static int dropQuality; private static ItemDrop dropTemplate; private static int dropTemplateQuality; private static MethodInfo M(string type, string name, params Type[] args) { if (!(AccessTools.TypeByName(type) == null)) { return AccessTools.Method(AccessTools.TypeByName(type), name, args, (Type[])null); } return null; } private static bool Ready() { if (looked) { return ready; } looked = true; Type type = AccessTools.TypeByName("BetrValheim.Drawers.Drawer"); if (type == null) { return false; } zdoOf = AccessTools.Method(type, "Zdo", (Type[])null, (Type[])null); deposit = AccessTools.Method(type, "Deposit", new Type[2] { typeof(string), typeof(int) }, (Type[])null); countOf = AccessTools.PropertyGetter(type, "Count"); nameOf = AccessTools.PropertyGetter(type, "ItemName"); freeOf = AccessTools.PropertyGetter(type, "FreeSpace"); Type type2 = AccessTools.TypeByName("BetrValheim.Storage.QuickStack"); quickDrawers = ((type2 != null) ? AccessTools.Field(type2, "Drawers") : null); ready = zdoOf != null && deposit != null && countOf != null && nameOf != null && freeOf != null; return ready; } internal static bool Egg(ItemData item) { if (Plugin.drawerEggs.Value && item != null) { return ZeroEggs.IsEgg(item); } return false; } private static bool EggPrefab(string prefab) { if (!Plugin.drawerEggs.Value || string.IsNullOrEmpty(prefab)) { return false; } GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null); if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<EggGrow>() != (Object)null) { return !Plugin.EggExcluded(prefab); } return false; } private static ZDO Zdo(object drawer) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return (ZDO)zdoOf.Invoke(drawer, null); } private static int Count(object drawer) { return (int)countOf.Invoke(drawer, null); } private static string Name(object drawer) { return (string)nameOf.Invoke(drawer, null); } private static int Free(object drawer) { return (int)freeOf.Invoke(drawer, null); } internal static int QualityOf(object drawer) { ZDO val = Zdo(drawer); if (val != null) { return Mathf.Max(1, val.GetInt("wolfstars_egg_q", 1)); } return 1; } private static bool Accepts(object drawer, int quality) { if (Count(drawer) > 0) { return QualityOf(drawer) == Mathf.Max(1, quality); } return true; } private static void Remember(object drawer, int quality) { ZDO val = Zdo(drawer); if (val != null) { val.Set("wolfstars_egg_q", Mathf.Max(1, quality)); } } private static int Store(object drawer, Inventory inv, ItemData item, string prefab, int amount) { if (amount <= 0 || !Accepts(drawer, item.m_quality)) { return 0; } int quality = item.m_quality; int num = (int)deposit.Invoke(drawer, new object[2] { prefab, amount }); if (num > 0) { Remember(drawer, quality); if (inv != null) { inv.RemoveItem(item, num); } } return num; } internal static void PatchFindDrawer(Harmony harmony) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Type type = AccessTools.TypeByName("BetrValheim.Collect.Collector"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.FirstMethod(type, (Func<MethodInfo, bool>)((MethodInfo m) => m.Name == "FindDrawer"))); if (methodInfo == null || !Ready()) { return; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(BetrEggs), "FindDrawerPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[wolfstars] could not patch BetrValheim FindDrawer (" + ex.Message + ") - an egg next to a drawer of another quality stays on the ground")); } } private static void FindDrawerPostfix(ref object __result) { ItemDrop current = TryStorePatch.current; if (__result != null && !((Object)(object)current == (Object)null) && Egg(current.m_itemData) && !Accepts(__result, current.m_itemData.m_quality)) { __result = null; } } } [HarmonyPatch(typeof(TextInput), "RequestText")] internal static class TameNamePatch { private static void Prefix(TextReceiver __0, ref int __2) { if (Plugin.longNames.Value && __0 is Tameable && __2 < Plugin.nameLength.Value) { __2 = Plugin.nameLength.Value; } } } internal static class RadarCompat { internal const string RadarGuid = "HampusToft.ValheimRadar"; private const char Star = '★'; internal static void TryPatch(Harmony harmony) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("HampusToft.ValheimRadar")) { MethodInfo methodInfo = AccessTools.Method("ValheimRadar.PinManager:ApplyPinName", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning((object)"[wolfstars] ValheimRadar found but PinManager.ApplyPinName is missing - radar stars left as they are"); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(RadarCompat), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"[wolfstars] ValheimRadar found - long star runs on its pins are shortened"); } } private static void Prefix(ref string name) { if (Plugin.radarAbbreviate.Value && !string.IsNullOrEmpty(name) && name.IndexOf('★') >= 0) { name = Shorten(name, Plugin.radarFrom.Value); } } internal static string Shorten(string text, int from) { StringBuilder stringBuilder = new StringBuilder(text.Length); int i = 0; while (i < text.Length) { if (text[i] != '★') { stringBuilder.Append(text[i++]); continue; } int num = 0; for (; i < text.Length && text[i] == '★'; i++) { num++; } if (num >= from) { stringBuilder.Append(num).Append('x').Append('★'); } else { stringBuilder.Append('★', num); } } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(Character), "SetLevel")] internal static class MaxStarsPatch { private static void Prefix(Character __instance, ref int level) { if (Plugin.limitStars.Value && Plugin.Applies((Component)(object)__instance)) { int num = Plugin.MaxStarsFor(Utils.GetPrefabName(((Component)__instance).gameObject)) + 1; if (level > num) { level = num; } } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class ButcherPatch { private static bool reported; private static void Prefix(Character __instance, HitData hit) { if (hit == null || (Object)(object)__instance == (Object)null || __instance.IsPlayer() || !__instance.IsTamed()) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)hit.GetAttacker() != (Object)(object)localPlayer) { return; } ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.m_shared == null || !currentWeapon.m_shared.m_tamedOnly) { return; } float totalDamage = hit.GetTotalDamage(); if (Plugin.butcherOneHit.Value) { float num = __instance.GetMaxHealth() * 2f + 10f; if (hit.m_damage.m_damage < num) { hit.m_damage.m_damage = num; } } else { float num2 = Plugin.butcherMult.Value; if (Plugin.butcherStars.Value) { num2 *= (float)Mathf.Max(1, __instance.GetLevel()); } if (num2 != 1f) { hit.ApplyModifier(num2); } } if (!reported) { reported = true; Plugin.Log.LogInfo((object)($"[wolfstars] butcher knife on {Utils.GetPrefabName(((Component)__instance).gameObject)} level {__instance.GetLevel()} " + $"(max health {__instance.GetMaxHealth():0}): damage {totalDamage:0} -> {hit.GetTotalDamage():0}")); } } } [HarmonyPatch(typeof(EggGrow), "CanGrow")] internal static class IncubationDelayPatch { private static readonly HashSet<string> reported = new HashSet<string>(); private static void Postfix(EggGrow __instance, ref bool __result) { int value = Plugin.incubationDelay.Value; if (!__result || value <= 0 || (Object)(object)__instance == (Object)null) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val == null || (Object)(object)ZNet.instance == (Object)null) { return; } string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); if (Plugin.EggExcluded(prefabName)) { return; } long num = val.GetLong(ZDOVars.s_spawnTime, 0L); if (num == 0L) { return; } double totalSeconds = (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds; if (!(totalSeconds >= (double)value)) { __result = false; if (reported.Add(prefabName)) { Plugin.Log.LogInfo((object)$"[wolfstars] incubation delay: {prefabName} waits until {value} s on the ground (now {totalSeconds:0} s)"); } } } } [HarmonyPatch(typeof(WearNTear), "Damage")] internal static class TameStructurePatch { private static bool reported; private static bool Prefix(WearNTear __instance, HitData hit) { if (!Plugin.tameNoStructureDamage.Value || hit == null) { return true; } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker == (Object)null || attacker.IsPlayer() || !attacker.IsTamed()) { return true; } if (!reported) { reported = true; Plugin.Log.LogInfo((object)("[wolfstars] tame hit on a build piece ignored: " + Utils.GetPrefabName(((Component)attacker).gameObject) + " " + $"-> {Utils.GetPrefabName(((Component)__instance).gameObject)} ({hit.GetTotalDamage():0} damage)")); } return false; } } [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] internal static class DropsPatch { private static readonly HashSet<string> cappedOnce = new HashSet<string>(); private static readonly FieldRef<Character, int> levelRef = AccessTools.FieldRefAccess<Character, int>("m_level"); private static void Prefix(CharacterDrop __instance, out int __state) { __state = 0; Character component = ((Component)__instance).GetComponent<Character>(); Plugin.ReportUncovered(component, "drops"); if (!Plugin.AppliesDrops((Component)(object)component)) { return; } int num = Plugin.DropStarsFor(Utils.GetPrefabName(((Component)component).gameObject)) + 1; int num2 = levelRef.Invoke(component); if (num2 > num) { __state = num2; levelRef.Invoke(component) = num; string prefabName = Utils.GetPrefabName(((Component)component).gameObject); if (cappedOnce.Add(prefabName)) { Plugin.Log.LogInfo((object)$"[wolfstars] drops capped: {prefabName} level {num2} ({num2 - 1} stars) rolls drops as level {num} ({num - 1} stars)"); } } } private static void Finalizer(CharacterDrop __instance, int __state) { if (__state != 0) { Character component = ((Component)__instance).GetComponent<Character>(); if ((Object)(object)component != (Object)null) { levelRef.Invoke(component) = __state; } } } }