Decompiled source of Historical Heritage v2.0.3
plugins/Historical_Heritage.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CannonFire; using HarmonyLib; using Historical_Heritage; using ItemManager; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using PieceManager; using ServerSync; using ShipUpgrades; using Splatform; using TMPro; using UnityEngine; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; using YourModNamespace; [assembly: AssemblyFileVersion("2.0.3")] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("Historical_Heritage")] [assembly: AssemblyCompany("Dreanegade")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("Historical_Heritage")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.3.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<628ed641-12bb-4f05-bb8a-142422a5fbf6>Embedded] internal sealed class <628ed641-12bb-4f05-bb8a-142422a5fbf6>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<628ed641-12bb-4f05-bb8a-142422a5fbf6>Embedded] [CompilerGenerated] internal sealed class <1b7e9e30-9233-4cce-ab17-c3347351c0db>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <1b7e9e30-9233-4cce-ab17-c3347351c0db>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <1b7e9e30-9233-4cce-ab17-c3347351c0db>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [<628ed641-12bb-4f05-bb8a-142422a5fbf6>Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContextAttribute : Attribute { public readonly byte Flag; public <0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContextAttribute(byte P_0) { Flag = P_0; } } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] internal sealed class ConfigurationManagerAttributes { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [HarmonyPatch] public static class RandomSpeakShip { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] private static class DevLog { public const bool Enabled = false; public const bool Announcer = false; public const bool Parrot = false; public const bool Upgrades = false; public const bool Startup = false; public const bool Cycle = false; } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] private sealed class WeightedText { public readonly string text; public readonly float weight; public WeightedText(string text, float weight) { this.text = text; this.weight = weight; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] private enum UpgradeBit { Lantern, Cannon, Nest, Bell, Brazier, Hull, Sail, Barrel, Anvil, Cartography, Anchor, Seating, Quarters } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] private struct UpgradeDef { public UpgradeBit bit; public string zdoBoolKey; public List<WeightedText> lines; public string announcerInstalledLineKey; } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [HarmonyPatch] private static class Patch_UpgradeInstall { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("ShipUpgrades.ShipUpgradeTable"); if (type == null) { return null; } return AccessTools.Method(type, "RPC_RequestInstallUpgrade", new Type[3] { typeof(long), typeof(string), typeof(string) }, (Type[])null); } private static void Prefix(object __instance, long sender, string zdoKey, string itemPrefabName, ref bool __state) { __state = false; try { MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } ZNetView componentInParent = ((Component)val).GetComponentInParent<ZNetView>(); if (!((Object)(object)componentInParent == (Object)null) && componentInParent.IsValid() && string.Equals(Utils.GetPrefabName(((Component)componentInParent).gameObject), "ShipGalleonDO", StringComparison.Ordinal) && componentInParent.IsOwner()) { ZDO zDO = componentInParent.GetZDO(); if (zDO != null && !string.IsNullOrEmpty(zdoKey)) { __state = zDO.GetBool(zdoKey, false); DLogU($"Install prefix zdoKey={zdoKey} wasInstalled={__state}"); } } } catch (Exception arg) { Debug.LogError((object)string.Format("{0} UpgradeInstall prefix exception: {1}", "[RandomSpeakShip]", arg)); } } private static void Postfix(object __instance, long sender, string zdoKey, string itemPrefabName, bool __state) { try { MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } ZNetView componentInParent = ((Component)val).GetComponentInParent<ZNetView>(); if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsValid() || !string.Equals(Utils.GetPrefabName(((Component)componentInParent).gameObject), "ShipGalleonDO", StringComparison.Ordinal) || !componentInParent.IsOwner()) { return; } ZDO zDO = componentInParent.GetZDO(); if (zDO == null || string.IsNullOrEmpty(zdoKey)) { return; } bool @bool = zDO.GetBool(zdoKey, false); if (!__state && @bool) { string text = ResolveUpgradeAnnouncerKey(zdoKey); if (!string.IsNullOrEmpty(text)) { DLogU("Install detected zdoKey=" + zdoKey + " -> announce=" + text); AnnounceToEverybody(componentInParent, text); } } } catch (Exception arg) { Debug.LogError((object)string.Format("{0} UpgradeInstall postfix exception: {1}", "[RandomSpeakShip]", arg)); } } } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [HarmonyPatch] private static class Patch_SailColor { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] private struct State { public bool wasOwner; public bool sailInstalled; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(1)] public string prevColor; } private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("ShipUpgrades.ShipUpgradeTable"); if (type == null) { return null; } return AccessTools.Method(type, "RPC_SetSailColor", new Type[2] { typeof(long), typeof(string) }, (Type[])null); } private static void Prefix(object __instance, long sender, string colorId, ref State __state) { __state = new State { wasOwner = false, sailInstalled = false, prevColor = "" }; try { MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } ZNetView componentInParent = ((Component)val).GetComponentInParent<ZNetView>(); if (!((Object)(object)componentInParent == (Object)null) && componentInParent.IsValid() && string.Equals(Utils.GetPrefabName(((Component)componentInParent).gameObject), "ShipGalleonDO", StringComparison.Ordinal) && componentInParent.IsOwner()) { ZDO zDO = componentInParent.GetZDO(); if (zDO != null) { __state.wasOwner = true; __state.sailInstalled = zDO.GetBool("upgrade_sail", false); __state.prevColor = zDO.GetString("upgrade_sail_color", ""); DLogU($"SailColor prefix owner={__state.wasOwner} sailInstalled={__state.sailInstalled} prevColor={__state.prevColor}"); } } } catch (Exception arg) { Debug.LogError((object)string.Format("{0} SailColor prefix exception: {1}", "[RandomSpeakShip]", arg)); } } private static void Postfix(object __instance, long sender, string colorId, State __state) { try { if (!__state.wasOwner || !__state.sailInstalled) { return; } MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } ZNetView componentInParent = ((Component)val).GetComponentInParent<ZNetView>(); if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsValid() || !string.Equals(Utils.GetPrefabName(((Component)componentInParent).gameObject), "ShipGalleonDO", StringComparison.Ordinal)) { return; } ZDO zDO = componentInParent.GetZDO(); if (zDO == null) { return; } string @string = zDO.GetString("upgrade_sail_color", ""); string a = NormalizeColorId(__state.prevColor); string b = NormalizeColorId(@string); if (!string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { string text = ResolveSailColorAnnouncerKey(@string); if (!string.IsNullOrEmpty(text)) { DLogU("SailColor changed prev=" + __state.prevColor + " now=" + @string + " -> announce=" + text); AnnounceToEverybody(componentInParent, text); } } } catch (Exception arg) { Debug.LogError((object)string.Format("{0} SailColor postfix exception: {1}", "[RandomSpeakShip]", arg)); } } } private const string LogPrefix = "[RandomSpeakShip]"; private const string ShipParentPrefabName = "ShipGalleonDO"; private const string ParrotPath = "Interactive/UpgradeTable/Parrot"; private const string AnnouncerPath = "Interactive/UpgradeTable/Announcer"; private const string RpcAnnounce = "RPC_Announce_DO"; private const string ZdoParrotInitializedKey = "parrot_initialized"; private const string ZdoParrotCycleKey = "parrot_cycle"; private const string ZdoParrotCycleIndexKey = "parrot_cycle_index"; private const string ZdoParrotUpgradeMaskKey = "parrot_upgrade_mask"; private static readonly Dictionary<ZDOID, int> _lastSeenMaskByShip = new Dictionary<ZDOID, int>(); private const string UpgradeLantern = "upgrade_lantern"; private const string UpgradeCannon = "upgrade_cannon"; private const string UpgradeNest = "upgrade_nest"; private const string UpgradeBell = "upgrade_bell"; private const string UpgradeBrazier = "upgrade_brazier"; private const string UpgradeHull = "upgrade_hull"; private const string UpgradeSail = "upgrade_sail"; private const string UpgradeBarrel = "upgrade_barrel"; private const string UpgradeAnvil = "upgrade_anvil"; private const string UpgradeCartography = "upgrade_cartography"; private const string UpgradeAnchor = "upgrade_anchor"; private const string UpgradeSeating = "upgrade_seating"; private const string UpgradeQuarters = "upgrade_quarters"; private const string UpgradeSailColorKey = "upgrade_sail_color"; private static bool _parrotEnabled = true; private static bool _announcerEnabled = true; private static readonly WeightedText[] GeneralTexts = new WeightedText[6] { new WeightedText("$parrot_general_text_1_DO", 1f), new WeightedText("$parrot_general_text_2_DO", 1f), new WeightedText("$parrot_general_text_3_DO", 1f), new WeightedText("$parrot_general_text_4_DO", 1f), new WeightedText("$parrot_general_text_5_DO", 1f), new WeightedText("$parrot_general_text_6_DO", 1f) }; private static readonly UpgradeDef[] UpgradeDefs = new UpgradeDef[13] { new UpgradeDef { bit = UpgradeBit.Lantern, zdoBoolKey = "upgrade_lantern", announcerInstalledLineKey = "$parrot_upgrade_lantern_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_lantern_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Cannon, zdoBoolKey = "upgrade_cannon", announcerInstalledLineKey = "$parrot_upgrade_cannon_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_cannon_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Nest, zdoBoolKey = "upgrade_nest", announcerInstalledLineKey = "$parrot_upgrade_nest_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_nest_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Bell, zdoBoolKey = "upgrade_bell", announcerInstalledLineKey = "$parrot_upgrade_bell_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_bell_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Brazier, zdoBoolKey = "upgrade_brazier", announcerInstalledLineKey = "$parrot_upgrade_brazier_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_brazier_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Hull, zdoBoolKey = "upgrade_hull", announcerInstalledLineKey = "$parrot_upgrade_hull_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_hull_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Sail, zdoBoolKey = "upgrade_sail", announcerInstalledLineKey = "$parrot_upgrade_sail_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_sail_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Barrel, zdoBoolKey = "upgrade_barrel", announcerInstalledLineKey = "$parrot_upgrade_barrel_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_barrel_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Anvil, zdoBoolKey = "upgrade_anvil", announcerInstalledLineKey = "$parrot_upgrade_anvil_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_anvil_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Cartography, zdoBoolKey = "upgrade_cartography", announcerInstalledLineKey = "$parrot_upgrade_cartography_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_cartography_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Anchor, zdoBoolKey = "upgrade_anchor", announcerInstalledLineKey = "$parrot_upgrade_anchor_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_anchor_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Seating, zdoBoolKey = "upgrade_seating", announcerInstalledLineKey = "$parrot_upgrade_seating_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_seating_installed_text_DO", 1f) } }, new UpgradeDef { bit = UpgradeBit.Quarters, zdoBoolKey = "upgrade_quarters", announcerInstalledLineKey = "$parrot_upgrade_quarters_installed_text_DO", lines = new List<WeightedText> { new WeightedText("$parrot_upgrade_quarters_installed_text_DO", 1f) } } }; private static readonly Dictionary<string, string> SailColorAnnouncerLine = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "white", "$parrot_sail_color_white_text_DO" }, { "purple", "$parrot_sail_color_purple_text_DO" }, { "blue", "$parrot_sail_color_blue_text_DO" }, { "orange", "$parrot_sail_color_orange_text_DO" }, { "red", "$parrot_sail_color_red_text_DO" }, { "black", "$parrot_sail_color_black_text_DO" } }; private static void DLog(string msg) { } private static void DLogW(string msg) { } private static void DLogA(string msg) { } private static void DLogP(string msg) { } private static void DLogU(string msg) { } private static void DLogS(string msg) { } private static void DLogC(string msg) { } public static void SetParrotEnabled(bool enabled) { _parrotEnabled = enabled; DLog($"ParrotEnabled -> {enabled}"); ApplyParrotEnabledToAllShipsInScene(); ApplyParrotEnabledToShipPrefab(); } public static void SetAnnouncerEnabled(bool enabled) { _announcerEnabled = enabled; DLog($"AnnouncerEnabled -> {enabled}"); } private static bool PFail(RandomSpeak rs, string reason, ZNetView shipZnv = null, ZDO shipZdo = null) { return false; } [HarmonyPostfix] [HarmonyPatch(typeof(ZNetScene), "Awake")] private static void ZNetScene_Awake_Postfix() { ApplyParrotEnabledToShipPrefab(); } [HarmonyPatch(typeof(Ship), "Awake")] [HarmonyPostfix] private static void Ship_Awake_Postfix(Ship __instance) { try { if ((Object)(object)__instance == (Object)null) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { string prefabName = Utils.GetPrefabName(((Component)component).gameObject); if (string.Equals(prefabName, "ShipGalleonDO", StringComparison.Ordinal)) { EnsureAnnounceRpcRegistered(component); DLogS(string.Format("Ship.Awake registered RPC on {0} owner={1} id={2}", prefabName, component.IsOwner(), (component.GetZDO() != null) ? ((object)(ZDOID)(ref component.GetZDO().m_uid)).ToString() : "<nozdo>")); } } } catch (Exception arg) { Debug.LogError((object)string.Format("{0} Ship.Awake postfix exception: {1}", "[RandomSpeakShip]", arg)); } } [HarmonyPatch(typeof(RandomSpeak), "Speak")] [HarmonyPrefix] private static bool RandomSpeak_Speak_Prefix(RandomSpeak __instance) { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return true; } if (!((MonoBehaviour)__instance).IsInvoking()) { ((MonoBehaviour)__instance).InvokeRepeating("Speak", Random.Range(0f, __instance.m_interval), __instance.m_interval); DLogS($"InvokeRepeating ensured on '{((Object)__instance).name}' interval={__instance.m_interval:0.00}"); } ZNetView componentInParent = ((Component)__instance).GetComponentInParent<ZNetView>(); if ((Object)(object)componentInParent == (Object)null || !componentInParent.IsValid()) { return true; } if (!string.Equals(Utils.GetPrefabName(((Component)componentInParent).gameObject), "ShipGalleonDO", StringComparison.Ordinal)) { return true; } string relativePath = GetRelativePath(((Component)componentInParent).transform, ((Component)__instance).transform); if (string.Equals(relativePath, "Interactive/UpgradeTable/Announcer", StringComparison.Ordinal)) { return false; } if (!string.Equals(relativePath, "Interactive/UpgradeTable/Parrot", StringComparison.Ordinal)) { return true; } if (!_parrotEnabled) { return true; } if (Random.value > __instance.m_chance) { return PFail(__instance, "roll>chance", componentInParent, componentInParent.GetZDO()); } if ((Object)(object)Player.m_localPlayer == (Object)null) { return PFail(__instance, "no local player", componentInParent, componentInParent.GetZDO()); } if (Vector3.Distance(((Component)__instance).transform.position, ((Component)Player.m_localPlayer).transform.position) > __instance.m_triggerDistance) { return PFail(__instance, "too far", componentInParent, componentInParent.GetZDO()); } if (__instance.m_onlyOnItemStand && !Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponentInParent<ItemStand>())) { return PFail(__instance, "onlyOnItemStand but no ItemStand", componentInParent, componentInParent.GetZDO()); } float dayFraction = EnvMan.instance.GetDayFraction(); if (!IsTimeAllowed(__instance, dayFraction)) { return PFail(__instance, $"tod blocked dayFraction={dayFraction:0.000}", componentInParent, componentInParent.GetZDO()); } ZDO zDO = componentInParent.GetZDO(); if (zDO == null) { return PFail(__instance, "ship zdo null", componentInParent); } string text = ""; bool num = componentInParent.IsOwner(); bool flag = false; if (num) { flag = UpdateParrotStateAndCycle(zDO); text = GetNextFromCycle(zDO); if (string.IsNullOrEmpty(text)) { return PFail(__instance, "chosenText empty (owner)", componentInParent, zDO); } DLogC($"Owner choose -> {text} changed={flag}"); } else { text = ChooseReadOnlyLineWithLocalCycle(zDO); if (string.IsNullOrEmpty(text)) { return PFail(__instance, "chosenText empty (readonly)", componentInParent, zDO); } DLogC("Client choose -> " + text); } DLogP("Speak -> " + text); __instance.m_speakEffects.Create(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1); Chat.instance.SetNpcText(((Component)__instance).gameObject, __instance.m_offset, __instance.m_cullDistance, __instance.m_ttl, __instance.m_topic, text, __instance.m_useLargeDialog); return false; } catch (Exception arg) { Debug.LogError((object)string.Format("{0} Speak prefix exception: {1}", "[RandomSpeakShip]", arg)); return true; } } public static void TryAnnounceNow(ZNetView shipZnv, string localizationKey) { if (!((Object)(object)shipZnv == (Object)null) && shipZnv.IsValid() && !string.IsNullOrEmpty(localizationKey) && string.Equals(Utils.GetPrefabName(((Component)shipZnv).gameObject), "ShipGalleonDO", StringComparison.Ordinal)) { AnnounceToEverybody(shipZnv, localizationKey); } } private static void AnnounceToEverybody(ZNetView shipZnv, string localizationKey) { if (_announcerEnabled && !((Object)(object)shipZnv == (Object)null) && shipZnv.IsValid()) { EnsureAnnounceRpcRegistered(shipZnv); shipZnv.InvokeRPC(ZNetView.Everybody, "RPC_Announce_DO", new object[1] { localizationKey }); DLogA("Broadcast announce " + localizationKey); } } private static void EnsureAnnounceRpcRegistered(ZNetView shipZnv) { if ((Object)(object)shipZnv == (Object)null || !shipZnv.IsValid()) { return; } try { shipZnv.Register<string>("RPC_Announce_DO", (Action<long, string>)RPC_Announce); } catch { } } private static void RPC_Announce(long sender, string localizationKey) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) try { if (!_announcerEnabled || string.IsNullOrEmpty(localizationKey)) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ZNetView val = FindClosestShipZNetView(((Component)localPlayer).transform.position, 25f); if (!((Object)(object)val == (Object)null)) { ShowAnnounceLocally(val, localizationKey); } } } catch (Exception arg) { Debug.LogError((object)string.Format("{0} RPC_Announce exception: {1}", "[RandomSpeakShip]", arg)); } } private static ZNetView FindClosestShipZNetView(Vector3 pos, float maxDist) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) ZNetView result = null; float num = maxDist * maxDist; try { ZNetView[] array = Object.FindObjectsOfType<ZNetView>(); if (array == null) { return null; } ZNetView[] array2 = array; foreach (ZNetView val in array2) { if (!((Object)(object)val == (Object)null) && val.IsValid() && string.Equals(Utils.GetPrefabName(((Component)val).gameObject), "ShipGalleonDO", StringComparison.Ordinal)) { Vector3 val2 = ((Component)val).transform.position - pos; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val; } } } return result; } catch { return result; } } private static void ShowAnnounceLocally(ZNetView shipZnv, string localizationKey) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shipZnv == (Object)null || !shipZnv.IsValid()) { return; } Transform val = ((Component)shipZnv).transform.Find("Interactive/UpgradeTable/Announcer"); if ((Object)(object)val == (Object)null) { DLogW("Announcer path not found on ship: Interactive/UpgradeTable/Announcer"); return; } RandomSpeak component = ((Component)val).GetComponent<RandomSpeak>(); if ((Object)(object)component == (Object)null) { DLogW("Announcer has no RandomSpeak component, using fallback params"); } Vector3 position = val.position; Quaternion rotation = val.rotation; if ((Object)(object)component != (Object)null) { component.m_speakEffects.Create(position, rotation, (Transform)null, 1f, -1); } Vector3 val2 = (((Object)(object)component != (Object)null) ? component.m_offset : Vector3.zero); float num = (((Object)(object)component != (Object)null) ? component.m_cullDistance : 15f); float num2 = (((Object)(object)component != (Object)null) ? component.m_ttl : 6f); string text = (((Object)(object)component != (Object)null) ? component.m_topic : ""); bool flag = (Object)(object)component != (Object)null && component.m_useLargeDialog; Chat.instance.SetNpcText(((Component)val).gameObject, val2, num, num2, text, localizationKey, flag); DLogA("Local announce " + localizationKey); } private static bool UpdateParrotStateAndCycle(ZDO shipZdo) { int num = ComputeUpgradeMask(shipZdo); if (!shipZdo.GetBool("parrot_initialized", false)) { shipZdo.Set("parrot_initialized", true); shipZdo.Set("parrot_upgrade_mask", num); string text = BuildNewCycle(shipZdo); shipZdo.Set("parrot_cycle", text); shipZdo.Set("parrot_cycle_index", 0); DLogP($"Initialized parrot state maskNow={num} cycle='{text}'"); return true; } int @int = shipZdo.GetInt("parrot_upgrade_mask", 0); if (@int == num) { return false; } shipZdo.Set("parrot_upgrade_mask", num); string text2 = BuildNewCycle(shipZdo); shipZdo.Set("parrot_cycle", text2); shipZdo.Set("parrot_cycle_index", 0); DLogP($"Upgrades changed prevMask={@int} maskNow={num} newCycle='{text2}'"); return true; } private static string GetNextFromCycle(ZDO shipZdo) { string text = shipZdo.GetString("parrot_cycle", ""); int num = shipZdo.GetInt("parrot_cycle_index", 0); if (string.IsNullOrEmpty(text)) { text = BuildNewCycle(shipZdo); shipZdo.Set("parrot_cycle", text); num = 0; shipZdo.Set("parrot_cycle_index", 0); DLogC("Cycle was empty -> rebuilt"); } string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return ""; } if (num >= array.Length) { text = BuildNewCycle(shipZdo); shipZdo.Set("parrot_cycle", text); num = 0; shipZdo.Set("parrot_cycle_index", 0); array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return ""; } DLogC("Cycle ended -> rebuilt"); } if (!int.TryParse(array[num].Trim(), out var result)) { return ""; } shipZdo.Set("parrot_cycle_index", num + 1); List<WeightedText> localTexts = BuildLocalTexts(shipZdo); return ResolveTextByIndex(result, localTexts); } private static string ChooseReadOnlyLineWithLocalCycle(ZDO shipZdo) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (shipZdo == null) { return ""; } int num = ComputeUpgradeMask(shipZdo); ZDOID uid = shipZdo.m_uid; bool flag = true; if (_lastSeenMaskByShip.TryGetValue(uid, out var value)) { flag = value != num; } _lastSeenMaskByShip[uid] = num; List<WeightedText> list = BuildLocalTexts(shipZdo); if (flag) { DLogC(string.Format("Client pool changed id={0} lastMask={1} nowMask={2} localLines={3}", uid, _lastSeenMaskByShip.ContainsKey(uid) ? value.ToString() : "<none>", num, list.Count)); } if (flag && list != null && list.Count > 0) { return PickWeighted(list); } List<WeightedText> list2 = new List<WeightedText>(); if (list != null && list.Count > 0) { list2.AddRange(list); } for (int i = 0; i < GeneralTexts.Length; i++) { list2.Add(GeneralTexts[i]); } return PickWeighted(list2); } private static string BuildNewCycle(ZDO shipZdo) { List<WeightedText> list = BuildLocalTexts(shipZdo); List<int> list2 = new List<int>(); List<float> list3 = new List<float>(); for (int i = 0; i < list.Count; i++) { list2.Add(i); list3.Add(Mathf.Max(0.0001f, list[i].weight)); } for (int j = 0; j < GeneralTexts.Length; j++) { list2.Add(100 + j); list3.Add(Mathf.Max(0.0001f, GeneralTexts[j].weight)); } if (list2.Count == 0) { return ""; } List<int> list4 = new List<int>(); while (list2.Count > 0) { float num = 0f; for (int k = 0; k < list3.Count; k++) { num += list3[k]; } float num2 = Random.Range(0f, num); float num3 = 0f; for (int l = 0; l < list2.Count; l++) { num3 += list3[l]; if (num2 <= num3) { list4.Add(list2[l]); list2.RemoveAt(l); list3.RemoveAt(l); break; } } } StringBuilder stringBuilder = new StringBuilder(); for (int m = 0; m < list4.Count; m++) { if (m > 0) { stringBuilder.Append(","); } stringBuilder.Append(list4[m]); } return stringBuilder.ToString(); } private static string ResolveTextByIndex(int index, List<WeightedText> localTexts) { if (index >= 100) { int num = index - 100; if (num >= 0 && num < GeneralTexts.Length) { return GeneralTexts[num].text; } return ""; } if (index >= 0 && index < localTexts.Count) { return localTexts[index].text; } return ""; } private static List<WeightedText> BuildLocalTexts(ZDO shipZdo) { List<WeightedText> list = new List<WeightedText>(); UpgradeDef[] upgradeDefs = UpgradeDefs; for (int i = 0; i < upgradeDefs.Length; i++) { UpgradeDef upgradeDef = upgradeDefs[i]; if (shipZdo.GetBool(upgradeDef.zdoBoolKey, false) && upgradeDef.lines != null) { for (int j = 0; j < upgradeDef.lines.Count; j++) { list.Add(upgradeDef.lines[j]); } } } return list; } private static int ComputeUpgradeMask(ZDO shipZdo) { int num = 0; UpgradeDef[] upgradeDefs = UpgradeDefs; for (int i = 0; i < upgradeDefs.Length; i++) { UpgradeDef upgradeDef = upgradeDefs[i]; if (shipZdo.GetBool(upgradeDef.zdoBoolKey, false)) { num |= 1 << (int)upgradeDef.bit; } } return num; } private static string PickWeighted(List<WeightedText> pool) { if (pool == null || pool.Count == 0) { return ""; } float num = 0f; for (int i = 0; i < pool.Count; i++) { num += Mathf.Max(0.0001f, pool[i].weight); } float num2 = Random.Range(0f, num); float num3 = 0f; for (int j = 0; j < pool.Count; j++) { num3 += Mathf.Max(0.0001f, pool[j].weight); if (num2 <= num3) { return pool[j].text; } } return pool[pool.Count - 1].text; } private static void ApplyParrotEnabledToShipPrefab() { try { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("ShipGalleonDO"); if ((Object)(object)prefab == (Object)null) { DLogW("Ship prefab not found: ShipGalleonDO"); return; } Transform val = prefab.transform.Find("Interactive/UpgradeTable/Parrot"); if ((Object)(object)val == (Object)null) { DLogW("Parrot path not found on prefab: Interactive/UpgradeTable/Parrot"); return; } ((Component)val).gameObject.SetActive(_parrotEnabled); DLog($"Prefab parrot active -> {_parrotEnabled}"); } catch (Exception arg) { Debug.LogError((object)string.Format("{0} ApplyParrotEnabledToShipPrefab exception: {1}", "[RandomSpeakShip]", arg)); } } private static void ApplyParrotEnabledToAllShipsInScene() { try { ZNetView[] array = Object.FindObjectsOfType<ZNetView>(); int num = 0; ZNetView[] array2 = array; foreach (ZNetView val in array2) { if (!((Object)(object)val == (Object)null) && val.IsValid() && string.Equals(Utils.GetPrefabName(((Component)val).gameObject), "ShipGalleonDO", StringComparison.Ordinal)) { Transform val2 = ((Component)val).transform.Find("Interactive/UpgradeTable/Parrot"); if (!((Object)(object)val2 == (Object)null)) { ((Component)val2).gameObject.SetActive(_parrotEnabled); num++; } } } DLog($"Runtime parrot toggle applied to ships: {num}, enabled={_parrotEnabled}"); } catch (Exception arg) { Debug.LogError((object)string.Format("{0} ApplyParrotEnabledToAllShipsInScene exception: {1}", "[RandomSpeakShip]", arg)); } } private static string ResolveUpgradeAnnouncerKey(string zdoKey) { if (string.IsNullOrEmpty(zdoKey)) { return ""; } for (int i = 0; i < UpgradeDefs.Length; i++) { if (string.Equals(UpgradeDefs[i].zdoBoolKey, zdoKey, StringComparison.Ordinal)) { return UpgradeDefs[i].announcerInstalledLineKey; } } return ""; } private static string ResolveSailColorAnnouncerKey(string colorRaw) { if (string.IsNullOrEmpty(colorRaw)) { return ""; } string text = NormalizeColorId(colorRaw); if (string.IsNullOrEmpty(text)) { return ""; } if (SailColorAnnouncerLine.TryGetValue(text, out var value)) { return value; } string text2 = colorRaw.Trim().ToLowerInvariant(); if (text2.Contains("white")) { return "$parrot_sail_color_white_text_DO"; } if (text2.Contains("purple") || text2.Contains("violet")) { return "$parrot_sail_color_purple_text_DO"; } if (text2.Contains("blue")) { return "$parrot_sail_color_blue_text_DO"; } if (text2.Contains("orange") || text2.Contains("gold")) { return "$parrot_sail_color_orange_text_DO"; } if (text2.Contains("red") || text2.Contains("crimson")) { return "$parrot_sail_color_red_text_DO"; } if (text2.Contains("black")) { return "$parrot_sail_color_black_text_DO"; } return ""; } private static string NormalizeColorId(string colorRaw) { if (string.IsNullOrEmpty(colorRaw)) { return ""; } string text = colorRaw.Trim(); int num = text.IndexOfAny(new char[5] { ' ', '/', '\\', ',', '.' }); if (num > 0) { text = text.Substring(0, num); } return text.Trim().ToLowerInvariant(); } private static string GetRelativePath(Transform root, Transform t) { if ((Object)(object)root == (Object)null || (Object)(object)t == (Object)null) { return ""; } List<string> list = new List<string>(); Transform val = t; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } private static bool IsTimeAllowed(RandomSpeak rs, float dayFraction) { if (!rs.m_invertTod) { if (!(dayFraction < rs.m_minTOD)) { return !(dayFraction > rs.m_maxTOD); } return false; } if (!(dayFraction > rs.m_minTOD)) { return !(dayFraction < rs.m_maxTOD); } return false; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] public static class ExtraStats { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] private static class DevLog { public const bool Enabled = false; public const bool AttackSpeed = false; public const bool WetImmune = false; public const bool Tooltips = false; public const bool FoodStats = false; } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public enum ExtraStatType { Health, Stamina, Eitr, AttackSpeed, WetImmune } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public enum ExtraSourceType { ItemDrop, StatusEffect } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] public class ExtraStatEntry { public string PrefabName; public ExtraStatType StatType; public float Value; public float? DisplayValue; public ExtraSourceType SourceType; public ExtraStatEntry(string prefab, ExtraStatType stat, float value, ExtraSourceType source) { PrefabName = prefab; StatType = stat; Value = value; DisplayValue = null; SourceType = source; } public ExtraStatEntry(string prefab, ExtraStatType stat, float value, float? displayValue, ExtraSourceType source) { PrefabName = prefab; StatType = stat; Value = value; DisplayValue = displayValue; SourceType = source; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(Player), "GetTotalFoodValue")] public static class Player_GetTotalFoodValue_ExtraStatsPatch { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr) { if ((Object)(object)__instance == (Object)null) { return; } float num = 0f; float num2 = 0f; float num3 = 0f; try { Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory != null) { foreach (ItemData equippedItem in inventory.GetEquippedItems()) { if (equippedItem != null && !((Object)(object)equippedItem.m_dropPrefab == (Object)null)) { string name = ((Object)equippedItem.m_dropPrefab).name; GetItemDropBonusesForPrefab(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var _); if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f) { num += extraHp; num2 += extraStamina; num3 += extraEitr; DLogFood($"ItemDrop matched for food stats: {name} → +HP {extraHp}, +Stamina {extraStamina}, +Eitr {extraEitr}"); } } } } if (((Character)__instance).m_seman != null && ((Character)__instance).m_seman.m_statusEffects != null) { foreach (StatusEffect statusEffect in ((Character)__instance).m_seman.m_statusEffects) { if (!((Object)(object)statusEffect == (Object)null)) { string name2 = ((Object)statusEffect).name; GetStatusEffectBonuses(name2, out var extraHp2, out var extraStamina2, out var extraEitr2, out var _, out var _); if (extraHp2 != 0f || extraStamina2 != 0f || extraEitr2 != 0f) { num += extraHp2; num2 += extraStamina2; num3 += extraEitr2; string prefabName = Utils.GetPrefabName(name2); DLogFood($"StatusEffect matched for food stats: {name2} (clean={prefabName}) → +HP {extraHp2}, +Stamina {extraStamina2}, +Eitr {extraEitr2}"); } } } } } catch (Exception ex) { LogError("Exception in ExtraStats Player.GetTotalFoodValue Postfix: " + ex); } if (num != 0f || num2 != 0f || num3 != 0f) { DLogFood($"Total food bonuses applied to player: +HP {num}, +Stamina {num2}, +Eitr {num3}"); hp += num; stamina += num2; eitr += num3; } } } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [HarmonyPatch] public static class ItemData_StaticGetTooltip_ExtraStatsPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[5] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) }, (Type[])null); } private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result) { try { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return; } string name = ((Object)item.m_dropPrefab).name; DLogTooltip($"Static GetTooltip Postfix called for {name}, q={qualityLevel}, crafting={crafting}, worldLevel={worldLevel}, stackOverride={stackOverride}"); GetItemDropBonusesForPrefab(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var displayAttackSpeedPercent, out var wetImmune); if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f || displayAttackSpeedPercent != 0f || wetImmune) { string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune); if (!string.IsNullOrEmpty(text)) { DLogTooltip($"Appending extras for {name}: HP {extraHp}, Stamina {extraStamina}, Eitr {extraEitr}, AttackSpeed(Display)% {displayAttackSpeedPercent}, WetImmune {wetImmune}"); __result += text; } } } catch (Exception ex) { LogError("Exception in ItemData_StaticGetTooltip_ExtraStatsPatch: " + ex); } } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(SE_Stats), "GetTooltipString")] public static class SE_Stats_GetTooltipString_ExtraStatsPatch { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static void Postfix(SE_Stats __instance, ref string __result) { try { if ((Object)(object)__instance == (Object)null) { return; } string name = ((Object)__instance).name; string prefabName = Utils.GetPrefabName(name); DLogTooltip("SE GetTooltipString for " + name + " (clean=" + prefabName + ")"); GetStatusEffectBonuses(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var displayAttackSpeedPercent, out var wetImmune); if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f || displayAttackSpeedPercent != 0f || wetImmune) { string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune); if (!string.IsNullOrEmpty(text)) { DLogTooltip($"Appending SE extras for {name} (clean={prefabName}): HP {extraHp}, Stamina {extraStamina}, Eitr {extraEitr}, AttackSpeed(Display)% {displayAttackSpeedPercent}, WetImmune {wetImmune}"); __result += text; } } } catch (Exception ex) { LogError("Exception in SE_Stats_GetTooltipString_ExtraStatsPatch: " + ex); } } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] private sealed class HumanoidState { public float DesiredSpeed = 1f; public float LastAppliedSpeed = 1f; public bool HasDesiredSpeed; public bool WasInAttack; public int ActiveAttackDepth; public float ActiveAttackMul = 1f; } [HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[] { typeof(Character), typeof(bool) })] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public static class Humanoid_StartAttack_AttackSpeedPatch { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [HarmonyPostfix] private static void Postfix(Humanoid __instance, Character target, bool secondaryAttack, ref bool __result) { EnsureAttackInit(); if (!__result) { return; } HumanoidState attackState = GetAttackState(__instance); float num = ComputeTotalAttackSpeedPercentForHumanoid(__instance); if (num == 0f) { attackState.DesiredSpeed = 1f; attackState.HasDesiredSpeed = false; ApplyAnimSpeed(__instance, attackState, 1f); attackState.ActiveAttackDepth = 0; attackState.ActiveAttackMul = 1f; return; } float num2 = 1f + num / 100f; if (num2 <= 0f || float.IsNaN(num2) || float.IsInfinity(num2)) { attackState.DesiredSpeed = 1f; attackState.HasDesiredSpeed = false; ApplyAnimSpeed(__instance, attackState, 1f); attackState.ActiveAttackDepth = 0; attackState.ActiveAttackMul = 1f; } else { attackState.DesiredSpeed = num2; attackState.HasDesiredSpeed = true; ApplyAnimSpeed(__instance, attackState, num2); attackState.ActiveAttackDepth++; attackState.ActiveAttackMul = num2; DLogAttackSpeed($"StartAttack: total AttackSpeed%={num} → mul={num2} (activeDepth={attackState.ActiveAttackDepth})"); } } } [HarmonyPatch(typeof(Attack), "Stop")] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public static class Attack_Stop_AttackSpeedResetPatch { [HarmonyPostfix] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static void Postfix(Attack __instance) { try { EnsureAttackInit(); if (__instance != null) { Humanoid character = __instance.m_character; if (!((Object)(object)character == (Object)null)) { ResetForHumanoid(character); DLogAttackSpeed("Attack.Stop: ResetForHumanoid"); } } } catch (Exception) { } } } [HarmonyPatch(typeof(Humanoid), "UpdateAttack")] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public static class Humanoid_UpdateAttack_AttackSpeedDtPatch { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [HarmonyPrefix] private static void Prefix(Humanoid __instance, ref float dt) { try { EnsureAttackInit(); if ((Object)(object)__instance == (Object)null) { return; } HumanoidState attackState = GetAttackState(__instance); if (attackState.ActiveAttackDepth > 0) { float activeAttackMul = attackState.ActiveAttackMul; if (!(activeAttackMul <= 0f) && !float.IsNaN(activeAttackMul) && !float.IsInfinity(activeAttackMul)) { dt *= activeAttackMul; } } } catch (Exception ex) { LogError("Exception in Humanoid_UpdateAttack_AttackSpeedDtPatch: " + ex); } } } [HarmonyPatch(typeof(Humanoid), "CustomFixedUpdate")] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public static class Humanoid_CustomFixedUpdate_AttackSpeedPatch { [HarmonyPostfix] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static void Postfix(Humanoid __instance, float fixedDeltaTime) { EnsureAttackInit(); HumanoidState attackState = GetAttackState(__instance); bool flag = ((Character)__instance).InAttack(); if (flag) { if (attackState.HasDesiredSpeed) { ApplyAnimSpeed(__instance, attackState, attackState.DesiredSpeed); } else { ApplyAnimSpeed(__instance, attackState, 1f); } } else if (attackState.WasInAttack) { ApplyAnimSpeed(__instance, attackState, 1f); attackState.HasDesiredSpeed = false; attackState.DesiredSpeed = 1f; } attackState.WasInAttack = flag; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(Character), "RPC_Stagger")] public static class Character_RPC_Stagger_AttackSpeedResetPatch { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [HarmonyPostfix] private static void Postfix(Character __instance, long sender, Vector3 forceDirection) { try { EnsureAttackInit(); Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null); if (!((Object)(object)val == (Object)null)) { ResetForHumanoid(val); } } catch (Exception) { } } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(Character), "OnDeath")] public static class Character_OnDeath_AttackSpeedResetPatch { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [HarmonyPostfix] private static void Postfix(Character __instance) { try { EnsureAttackInit(); Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null); if (!((Object)(object)val == (Object)null)) { ResetForHumanoid(val); } } catch (Exception) { } } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(Character), "FreezeFrame")] public static class Character_FreezeFrame_AttackSpeedScalePatch { [HarmonyPrefix] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static void Prefix(Character __instance, ref float duration) { try { EnsureAttackInit(); if ((Object)(object)__instance == (Object)null || Mathf.Abs(duration - 0.15f) > 0.01f) { return; } Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null); if ((Object)(object)val == (Object)null) { return; } HumanoidState attackState = GetAttackState(val); if (!attackState.HasDesiredSpeed) { return; } float desiredSpeed = attackState.DesiredSpeed; if (!(desiredSpeed <= 1.001f) && !float.IsNaN(desiredSpeed) && !float.IsInfinity(desiredSpeed)) { float num = duration / desiredSpeed; if (num < 0.03f) { num = 0.03f; } DLogAttackSpeed($"FreezeFrame scale: {duration:F3} -> {num:F3} (mul={desiredSpeed:F3})"); duration = num; } } catch (Exception ex) { LogError("Exception in Character_FreezeFrame_AttackSpeedScalePatch: " + ex); } } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(CharacterAnimEvent), "UpdateFreezeFrame")] public static class CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch { [HarmonyPostfix] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static void Postfix(CharacterAnimEvent __instance, float dt) { try { EnsureAttackInit(); if ((Object)(object)__instance == (Object)null) { return; } Character componentInParent = ((Component)__instance).GetComponentInParent<Character>(); Humanoid val = (Humanoid)(object)((componentInParent is Humanoid) ? componentInParent : null); if (!((Object)(object)val == (Object)null)) { HumanoidState attackState = GetAttackState(val); if (attackState.HasDesiredSpeed && (attackState.ActiveAttackDepth > 0 || ((Character)val).InAttack())) { ApplyAnimSpeed(val, attackState, attackState.DesiredSpeed); } else { ApplyAnimSpeed(val, attackState, 1f); } } } catch (Exception ex) { LogError("Exception in CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch: " + ex); } } } [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(int), typeof(bool), typeof(int), typeof(float) })] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public static class SEMan_AddStatusEffect_ByHash_WetImmunePatch { [HarmonyPrefix] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static bool Prefix(SEMan __instance, int nameHash, bool resetTime, int itemLevel, float skillLevel) { try { EnsureWetInit(); if (nameHash != SEMan.s_statusEffectWet) { return true; } Character val = null; try { val = _semanCharacterRef.Invoke(__instance); } catch (Exception) { val = null; } if ((Object)(object)val != (Object)null && HasWetImmune(val)) { DLogWet("Blocked Wet (AddStatusEffect by hash) due to WetImmune"); return false; } } catch (Exception ex2) { LogError("Exception in SEMan_AddStatusEffect_ByHash_WetImmunePatch: " + ex2); } return true; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] [HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[] { typeof(StatusEffect), typeof(bool), typeof(int), typeof(float) })] public static class SEMan_AddStatusEffect_BySE_WetImmunePatch { [HarmonyPrefix] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] private static bool Prefix(SEMan __instance, StatusEffect statusEffect, bool resetTime, int itemLevel, float skillLevel, ref StatusEffect __result) { try { if ((Object)(object)statusEffect == (Object)null) { return true; } if (statusEffect.NameHash() != SEMan.s_statusEffectWet) { return true; } Character character = statusEffect.m_character; if ((Object)(object)character != (Object)null && HasWetImmune(character)) { DLogWet("Blocked Wet (AddStatusEffect by SE) due to WetImmune"); __result = null; return false; } } catch (Exception ex) { LogError("Exception in SEMan_AddStatusEffect_BySE_WetImmunePatch: " + ex); } return true; } } public static bool DEBUG = false; public static readonly List<ExtraStatEntry> ExtraStatsConfig = new List<ExtraStatEntry> { new ExtraStatEntry("SE_ShipAleBarrel_DO", ExtraStatType.Stamina, 20f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_ShipAleBarrel_DO", ExtraStatType.Health, -5f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_CaptainArmor_DO", ExtraStatType.Stamina, 30f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SE_CaptainBelt_DO", ExtraStatType.Stamina, 10f, ExtraSourceType.StatusEffect), new ExtraStatEntry("SwordCaptainCutlassDO", ExtraStatType.AttackSpeed, 90f, 50f, ExtraSourceType.ItemDrop), new ExtraStatEntry("AxeSailorDO", ExtraStatType.AttackSpeed, 50f, 50f, ExtraSourceType.ItemDrop), new ExtraStatEntry("BastardShogunKatanaDO", ExtraStatType.AttackSpeed, 50f, 50f, ExtraSourceType.ItemDrop), new ExtraStatEntry("SE_SailorArmor_DO", ExtraStatType.WetImmune, 1f, ExtraSourceType.StatusEffect) }; private static readonly ConditionalWeakTable<Humanoid, HumanoidState> _attackState = new ConditionalWeakTable<Humanoid, HumanoidState>(); private static FieldRef<Character, ZSyncAnimation> _zanimRef; private static bool _attackInit; private const float HitFreeze_Default = 0.15f; private const float HitFreeze_Epsilon = 0.01f; private const float HitFreeze_Min = 0.03f; private static FieldRef<SEMan, Character> _semanCharacterRef; private static bool _wetInit; private static void LogInfo(string msg) { } private static void LogError(string msg) { } private static void DLogAttackSpeed(string msg) { } private static void DLogWet(string msg) { } private static void DLogTooltip(string msg) { } private static void DLogFood(string msg) { } private static void GetItemDropBonusesForPrefab(string prefabName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out float displayAttackSpeedPercent, out bool wetImmune) { extraHp = 0f; extraStamina = 0f; extraEitr = 0f; extraAttackSpeedPercent = 0f; displayAttackSpeedPercent = 0f; wetImmune = false; if (string.IsNullOrEmpty(prefabName)) { return; } for (int i = 0; i < ExtraStatsConfig.Count; i++) { ExtraStatEntry extraStatEntry = ExtraStatsConfig[i]; if (extraStatEntry.SourceType == ExtraSourceType.ItemDrop && string.Equals(prefabName, extraStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase)) { switch (extraStatEntry.StatType) { case ExtraStatType.Health: extraHp += extraStatEntry.Value; break; case ExtraStatType.Stamina: extraStamina += extraStatEntry.Value; break; case ExtraStatType.Eitr: extraEitr += extraStatEntry.Value; break; case ExtraStatType.AttackSpeed: extraAttackSpeedPercent += extraStatEntry.Value; displayAttackSpeedPercent += (extraStatEntry.DisplayValue.HasValue ? extraStatEntry.DisplayValue.Value : extraStatEntry.Value); break; case ExtraStatType.WetImmune: wetImmune = true; break; } } } } private static void GetItemDropBonusesForPrefab(string prefabName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out bool wetImmune) { GetItemDropBonusesForPrefab(prefabName, out extraHp, out extraStamina, out extraEitr, out extraAttackSpeedPercent, out var _, out wetImmune); } private static void GetStatusEffectBonuses(string seRawName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out float displayAttackSpeedPercent, out bool wetImmune) { extraHp = 0f; extraStamina = 0f; extraEitr = 0f; extraAttackSpeedPercent = 0f; displayAttackSpeedPercent = 0f; wetImmune = false; if (string.IsNullOrEmpty(seRawName)) { return; } string prefabName = Utils.GetPrefabName(seRawName); for (int i = 0; i < ExtraStatsConfig.Count; i++) { ExtraStatEntry extraStatEntry = ExtraStatsConfig[i]; if (extraStatEntry.SourceType == ExtraSourceType.StatusEffect && string.Equals(prefabName, extraStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase)) { switch (extraStatEntry.StatType) { case ExtraStatType.Health: extraHp += extraStatEntry.Value; break; case ExtraStatType.Stamina: extraStamina += extraStatEntry.Value; break; case ExtraStatType.Eitr: extraEitr += extraStatEntry.Value; break; case ExtraStatType.AttackSpeed: extraAttackSpeedPercent += extraStatEntry.Value; displayAttackSpeedPercent += (extraStatEntry.DisplayValue.HasValue ? extraStatEntry.DisplayValue.Value : extraStatEntry.Value); break; case ExtraStatType.WetImmune: wetImmune = true; break; } } } } private static void GetStatusEffectBonuses(string seRawName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out bool wetImmune) { GetStatusEffectBonuses(seRawName, out extraHp, out extraStamina, out extraEitr, out extraAttackSpeedPercent, out var _, out wetImmune); } private static string BuildExtraStatsTooltipBlock(float extraHp, float extraStamina, float extraEitr, float displayAttackSpeedPercent, bool wetImmune) { if (extraHp == 0f && extraStamina == 0f && extraEitr == 0f && displayAttackSpeedPercent == 0f && !wetImmune) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); string text = "$extrastats_health_DO"; string text2 = "$extrastats_stamina_DO"; string text3 = "$extrastats_eitr_DO"; string text4 = "$extrastats_attackspeed_DO"; string text5 = "$extrastats_immune_DO"; string text6 = "$extrastats_wet_DO"; if (Localization.instance != null) { text = Localization.instance.Localize(text); text2 = Localization.instance.Localize(text2); text3 = Localization.instance.Localize(text3); text4 = Localization.instance.Localize(text4); text5 = Localization.instance.Localize(text5); text6 = Localization.instance.Localize(text6); } if (extraHp != 0f) { string arg = ((extraHp >= 0f) ? "+" : ""); stringBuilder.Append($"\n{text}: <color=#f27979>{arg}{extraHp:F0}</color>"); } if (extraStamina != 0f) { string arg2 = ((extraStamina >= 0f) ? "+" : ""); stringBuilder.Append($"\n{text2}: <color=#ffff80>{arg2}{extraStamina:F0}</color>"); } if (extraEitr != 0f) { string arg3 = ((extraEitr >= 0f) ? "+" : ""); stringBuilder.Append($"\n{text3}: <color=#8686ee>{arg3}{extraEitr:F0}</color>"); } if (displayAttackSpeedPercent != 0f) { int num = Mathf.RoundToInt(displayAttackSpeedPercent); string arg4 = ((num >= 0) ? "+" : ""); stringBuilder.Append($"\n{text4}: <color=orange>{arg4}{num}%</color>"); } if (wetImmune) { stringBuilder.Append("\n" + text5 + ": <color=orange>" + text6 + "</color>"); } return stringBuilder.ToString(); } private static bool HasWetImmune(Character c) { if ((Object)(object)c == (Object)null) { return false; } try { Player val = (Player)(object)((c is Player) ? c : null); if ((Object)(object)val != (Object)null) { Inventory inventory = ((Humanoid)val).GetInventory(); if (inventory != null) { List<ItemData> equippedItems = inventory.GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val2 = equippedItems[i]; if (val2 != null && !((Object)(object)val2.m_dropPrefab == (Object)null)) { string name = ((Object)val2.m_dropPrefab).name; GetItemDropBonusesForPrefab(name, out var _, out var _, out var _, out var _, out var _, out var wetImmune); if (wetImmune) { DLogWet("WetImmune from ItemDrop: " + name); return true; } } } } } if (c.m_seman != null && c.m_seman.m_statusEffects != null) { List<StatusEffect> statusEffects = c.m_seman.m_statusEffects; for (int j = 0; j < statusEffects.Count; j++) { StatusEffect val3 = statusEffects[j]; if (!((Object)(object)val3 == (Object)null)) { string name2 = ((Object)val3).name; GetStatusEffectBonuses(name2, out var _, out var _, out var _, out var _, out var _, out var wetImmune2); if (wetImmune2) { string prefabName = Utils.GetPrefabName(name2); DLogWet("WetImmune from StatusEffect: " + name2 + " (clean=" + prefabName + ")"); return true; } } } } } catch (Exception ex) { LogError("Exception in HasWetImmune: " + ex); } return false; } private static void EnsureAttackInit() { if (!_attackInit) { _attackInit = true; _zanimRef = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim"); } } private static HumanoidState GetAttackState(Humanoid h) { return _attackState.GetValue(h, (Humanoid _) => new HumanoidState()); } private static void ApplyAnimSpeed(Humanoid h, HumanoidState state, float speed) { ZSyncAnimation val = null; try { val = _zanimRef.Invoke((Character)(object)h); } catch (Exception) { return; } if (!((Object)(object)val == (Object)null) && !Mathf.Approximately(state.LastAppliedSpeed, speed)) { val.SetSpeed(speed); state.LastAppliedSpeed = speed; } } private static void ResetForHumanoid(Humanoid h) { if (!((Object)(object)h == (Object)null)) { EnsureAttackInit(); HumanoidState attackState = GetAttackState(h); ApplyAnimSpeed(h, attackState, 1f); attackState.HasDesiredSpeed = false; attackState.DesiredSpeed = 1f; attackState.WasInAttack = false; attackState.ActiveAttackDepth = 0; attackState.ActiveAttackMul = 1f; } } private static float ComputeTotalAttackSpeedPercentForHumanoid(Humanoid h) { float num = 0f; if ((Object)(object)h == (Object)null) { return 0f; } try { Player val = (Player)(object)((h is Player) ? h : null); if ((Object)(object)val != (Object)null) { Inventory inventory = ((Humanoid)val).GetInventory(); if (inventory != null) { List<ItemData> equippedItems = inventory.GetEquippedItems(); for (int i = 0; i < equippedItems.Count; i++) { ItemData val2 = equippedItems[i]; if (val2 != null && !((Object)(object)val2.m_dropPrefab == (Object)null)) { string name = ((Object)val2.m_dropPrefab).name; GetItemDropBonusesForPrefab(name, out var _, out var _, out var _, out var extraAttackSpeedPercent, out var _, out var _); if (extraAttackSpeedPercent != 0f) { num += extraAttackSpeedPercent; DLogAttackSpeed($"AttackSpeed from ItemDrop: {name} → {extraAttackSpeedPercent}%"); } } } } } if (((Character)h).m_seman != null && ((Character)h).m_seman.m_statusEffects != null) { List<StatusEffect> statusEffects = ((Character)h).m_seman.m_statusEffects; for (int j = 0; j < statusEffects.Count; j++) { StatusEffect val3 = statusEffects[j]; if (!((Object)(object)val3 == (Object)null)) { string name2 = ((Object)val3).name; GetStatusEffectBonuses(name2, out var _, out var _, out var _, out var extraAttackSpeedPercent2, out var _, out var _); if (extraAttackSpeedPercent2 != 0f) { num += extraAttackSpeedPercent2; string prefabName = Utils.GetPrefabName(name2); DLogAttackSpeed($"AttackSpeed from StatusEffect: {name2} (clean={prefabName}) → {extraAttackSpeedPercent2}%"); } } } } } catch (Exception ex) { LogError("Exception in ComputeTotalAttackSpeedPercentForHumanoid: " + ex); } return num; } private static void EnsureWetInit() { if (!_wetInit) { _wetInit = true; _semanCharacterRef = AccessTools.FieldRefAccess<SEMan, Character>("m_character"); } } } namespace PieceManager { [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [PublicAPI] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] public static class MaterialReplacer { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] public enum ShaderType { PieceShader, VegetationShader, RockShader, RugShader, GrassShader, CustomCreature, UseUnityShader } private static readonly Dictionary<GameObject, bool> ObjectToSwap; private static readonly Dictionary<string, Material> OriginalMaterials; private static readonly Dictionary<GameObject, ShaderType> ObjectsForShaderReplace; private static readonly HashSet<Shader> CachedShaders; private static bool hasRun; static MaterialReplacer() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown CachedShaders = new HashSet<Shader>(); hasRun = false; OriginalMaterials = new Dictionary<string, Material>(); ObjectToSwap = new Dictionary<GameObject, bool>(); ObjectsForShaderReplace = new Dictionary<GameObject, ShaderType>(); new Harmony("org.bepinex.helpers.PieceManager").Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZoneSystem), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MaterialReplacer), "ReplaceAllMaterialsWithOriginal", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static void RegisterGameObjectForShaderSwap(GameObject go, ShaderType type) { if (!ObjectsForShaderReplace.ContainsKey(go)) { ObjectsForShaderReplace.Add(go, type); } } public static void RegisterGameObjectForMatSwap(GameObject go, bool isJotunnMock = false) { if (!ObjectToSwap.ContainsKey(go)) { ObjectToSwap.Add(go, isJotunnMock); } } private static void GetAllMaterials() { Material[] array = Resources.FindObjectsOfTypeAll<Material>(); foreach (Material val in array) { OriginalMaterials[((Object)val).name] = val; } } [HarmonyPriority(700)] private static void ReplaceAllMaterialsWithOriginal() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType == 4 || hasRun) { return; } if (OriginalMaterials.Count == 0) { GetAllMaterials(); } foreach (KeyValuePair<GameObject, bool> item in ObjectToSwap) { GameObject key = item.Key; bool value = item.Value; ProcessGameObjectMaterials(key, value); } AssetBundle[] array = Resources.FindObjectsOfTypeAll<AssetBundle>(); foreach (AssetBundle val in array) { IEnumerable<Shader> enumerable3; try { IEnumerable<Shader> enumerable2; if (!val.isStreamedSceneAssetBundle || !Object.op_Implicit((Object)(object)val)) { IEnumerable<Shader> enumerable = val.LoadAllAssets<Shader>(); enumerable2 = enumerable; } else { enumerable2 = from shader in ((IEnumerable<string>)val.GetAllAssetNames()).Select((Func<string, Shader>)val.LoadAsset<Shader>) where (Object)(object)shader != (Object)null select shader; } enumerable3 = enumerable2; } catch (Exception) { continue; } if (enumerable3 == null) { continue; } foreach (Shader item2 in enumerable3) { CachedShaders.Add(item2); } } foreach (KeyValuePair<GameObject, ShaderType> item3 in ObjectsForShaderReplace) { GameObject key2 = item3.Key; ShaderType value2 = item3.Value; ProcessGameObjectShaders(key2, value2); } hasRun = true; } private static void ProcessGameObjectMaterials(GameObject go, bool isJotunnMock) { Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true); foreach (Renderer obj in componentsInChildren) { Material[] sharedMaterials = obj.sharedMaterials.Select([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Material material) => ReplaceMaterial(material, isJotunnMock)).ToArray(); obj.sharedMaterials = sharedMaterials; } } private static Material ReplaceMaterial(Material originalMaterial, bool isJotunnMock) { string text = (isJotunnMock ? "JVLmock_" : "_REPLACE_"); if (!((Object)originalMaterial).name.StartsWith(text, StringComparison.Ordinal)) { return originalMaterial; } string text2 = ((Object)originalMaterial).name.Replace(" (Instance)", "").Replace(text, ""); if (OriginalMaterials.TryGetValue(text2, out var value)) { return value; } Debug.LogWarning((object)("No suitable material found to replace: " + text2)); return originalMaterial; } private static void ProcessGameObjectShaders(GameObject go, ShaderType shaderType) { Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = componentsInChildren[i].sharedMaterials; foreach (Material val in sharedMaterials) { if ((Object)(object)val != (Object)null) { val.shader = GetShaderForType(val.shader, shaderType, ((Object)val.shader).name); } } } } private static Shader GetShaderForType(Shader orig, ShaderType shaderType, string originalShaderName) { return (Shader)(shaderType switch { ShaderType.PieceShader => FindShaderWithName(orig, "Custom/Piece"), ShaderType.VegetationShader => FindShaderWithName(orig, "Custom/Vegetation"), ShaderType.RockShader => FindShaderWithName(orig, "Custom/StaticRock"), ShaderType.RugShader => FindShaderWithName(orig, "Custom/Rug"), ShaderType.GrassShader => FindShaderWithName(orig, "Custom/Grass"), ShaderType.CustomCreature => FindShaderWithName(orig, "Custom/Creature"), ShaderType.UseUnityShader => FindShaderWithName(orig, ((Object)(object)FindShaderWithName(orig, originalShaderName) != (Object)null) ? originalShaderName : "ToonDeferredShading2017"), _ => FindShaderWithName(orig, "Standard"), }); } public static Shader FindShaderWithName(Shader origShader, string name) { foreach (Shader cachedShader in CachedShaders) { if (((Object)cachedShader).name == name) { return cachedShader; } } return origShader; } } [PublicAPI] public enum CraftingTable { None, [InternalName("piece_workbench")] Workbench, [InternalName("piece_cauldron")] Cauldron, [InternalName("forge")] Forge, [InternalName("piece_artisanstation")] ArtisanTable, [InternalName("piece_stonecutter")] StoneCutter, [InternalName("piece_magetable")] MageTable, [InternalName("blackforge")] BlackForge, [InternalName("piece_preptable")] FoodPreparationTable, [InternalName("piece_MeadCauldron")] MeadKetill, Custom } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] public class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [PublicAPI] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] public class ExtensionList { public readonly List<ExtensionConfig> ExtensionStations = new List<ExtensionConfig>(); public void Set(CraftingTable table, int maxStationDistance = 5) { ExtensionStations.Add(new ExtensionConfig { Table = table, maxStationDistance = maxStationDistance }); } public void Set(string customTable, int maxStationDistance = 5) { ExtensionStations.Add(new ExtensionConfig { Table = CraftingTable.Custom, custom = customTable, maxStationDistance = maxStationDistance }); } } public struct ExtensionConfig { public CraftingTable Table; public float maxStationDistance; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] public string custom; } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [PublicAPI] public class CraftingStationList { public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>(); public void Set(CraftingTable table) { Stations.Add(new CraftingStationConfig { Table = table }); } public void Set(string customTable) { Stations.Add(new CraftingStationConfig { Table = CraftingTable.Custom, custom = customTable }); } } public struct CraftingStationConfig { public CraftingTable Table; public int level; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] public string custom; } [PublicAPI] public enum BuildPieceCategory { Misc = 0, Crafting = 1, BuildingWorkbench = 2, BuildingStonecutter = 3, Furniture = 4, All = 100, Custom = 99 } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [PublicAPI] public class RequiredResourcesList { public readonly List<Requirement> Requirements = new List<Requirement>(); public void Add(string item, int amount, bool recover) { Requirements.Add(new Requirement { itemName = item, amount = amount, recover = recover }); } } public struct Requirement { [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(1)] public string itemName; public int amount; public bool recover; } public struct SpecialProperties { [Description("Admins should be the only ones that can build this piece.")] public bool AdminOnly; [Description("Turns off generating a config for this build piece.")] public bool NoConfig; } [PublicAPI] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] public class BuildingPieceCategory { public BuildPieceCategory Category; public string custom = ""; public void Set(BuildPieceCategory category) { Category = category; } public void Set(string customCategory) { Category = BuildPieceCategory.Custom; custom = customCategory; } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [PublicAPI] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] public class PieceTool { public readonly HashSet<string> Tools = new HashSet<string>(); public void Add(string tool) { Tools.Add(tool); } } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(1)] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] [PublicAPI] public class BuildPiece { [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] internal class PieceConfig { public ConfigEntry<string> craft; public ConfigEntry<BuildPieceCategory> category; public ConfigEntry<string> customCategory; public ConfigEntry<string> tools; public ConfigEntry<CraftingTable> extensionTable; public ConfigEntry<string> customExtentionTable; public ConfigEntry<float> maxStationDistance; public ConfigEntry<CraftingTable> table; public ConfigEntry<string> customTable; } [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] public string Category; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(new byte[] { 2, 1 })] [UsedImplicitly] public Action<ConfigEntryBase> CustomDrawer; } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(0)] private class SerializedRequirements { public readonly List<Requirement> Reqs; public SerializedRequirements(List<Requirement> reqs) { Reqs = reqs; } public SerializedRequirements(string reqs) { Reqs = reqs.Split(new char[1] { ',' }).Select([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (string r) => { string[] array = r.Split(new char[1] { ':' }); Requirement result = default(Requirement); result.itemName = array[0]; result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2); bool result3 = default(bool); result.recover = array.Length <= 2 || !bool.TryParse(array[2], out result3) || result3; return result; }).ToList(); } public override string ToString() { return string.Join(",", Reqs.Select([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Requirement r) => $"{r.itemName}:{r.amount}:{r.recover}")); } [return: <1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] public static ItemDrop fetchByName(ObjectDB objectDB, string name) { GameObject itemPrefab = objectDB.GetItemPrefab(name); ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)obj == (Object)null) { Debug.LogWarning((object)(((!string.IsNullOrWhiteSpace(((Object)plugin).name)) ? ("[" + ((Object)plugin).name + "]") : "") + " The required item '" + name + "' does not exist.")); } return obj; } public static Requirement[] toPieceReqs(SerializedRequirements craft) { return craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func<Requirement, string>)([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Requirement r) => r.itemName), (Func<Requirement, Requirement>)([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Requirement r) => { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ItemDrop val = ResItem(r); return (val != null) ? new Requirement { m_amount = r.amount, m_resItem = val, m_recover = r.recover } : ((Requirement)null); })).Values.Where([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Requirement v) => v != null).ToArray(); [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(2)] static ItemDrop ResItem(Requirement r) { return fetchByName(ObjectDB.instance, r.itemName); } } } internal static readonly List<BuildPiece> registeredPieces = new List<BuildPiece>(); private static readonly Dictionary<Piece, BuildPiece> pieceMap = new Dictionary<Piece, BuildPiece>(); internal static Dictionary<BuildPiece, PieceConfig> pieceConfigs = new Dictionary<BuildPiece, PieceConfig>(); internal List<Conversion> Conversions = new List<Conversion>(); internal List<ItemConversion> conversions = new List<ItemConversion>(); [Description("Disables generation of the configs for your pieces. This is global, this turns it off for all pieces in your mod.")] public static bool ConfigurationEnabled = true; public readonly GameObject Prefab; [Description("Specifies the resources needed to craft the piece.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the building piece should need.")] public readonly RequiredResourcesList RequiredItems = new RequiredResourcesList(); [Description("Sets the category for the building piece.")] public readonly BuildingPieceCategory Category = new BuildingPieceCategory(); [Description("Specifies the tool needed to build your piece.\nUse .Add to add a tool.")] public readonly PieceTool Tool = new PieceTool(); [Description("Specifies the crafting station needed to build your piece.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.")] public CraftingStationList Crafting = new CraftingStationList(); [Description("Makes this piece a station extension")] public ExtensionList Extension = new ExtensionList(); [Description("Change the extended/special properties of your build piece.")] public SpecialProperties SpecialProperties; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] [Description("Specifies a config entry which toggles whether a recipe is active.")] public ConfigEntryBase RecipeIsActive; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] private LocalizeKey _name; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] private LocalizeKey _description; internal string[] activeTools; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] private static object configManager; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] private static Localization _english; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] internal static BaseUnityPlugin _plugin = null; private static bool hasConfigSync = true; [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] private static object _configSync; public LocalizeKey Name { get { LocalizeKey name = _name; if (name != null) { return name; } Piece component = Prefab.GetComponent<Piece>(); if (component.m_name.StartsWith("$")) { _name = new LocalizeKey(component.m_name); } else { string text = "$piece_" + ((Object)Prefab).name.Replace(" ", "_"); _name = new LocalizeKey(text).English(component.m_name); component.m_name = text; } return _name; } } public LocalizeKey Description { get { LocalizeKey description = _description; if (description != null) { return description; } Piece component = Prefab.GetComponent<Piece>(); if (component.m_description.StartsWith("$")) { _description = new LocalizeKey(component.m_description); } else { string text = "$piece_" + ((Object)Prefab).name.Replace(" ", "_") + "_description"; _description = new LocalizeKey(text).English(component.m_description); component.m_description = text; } return _description; } } private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English")); internal static BaseUnityPlugin plugin { get { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown if (_plugin != null) { return _plugin; } IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); return _plugin; } } [<1b7e9e30-9233-4cce-ab17-c3347351c0db>Nullable(2)] private static object configSync { [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(2)] get { if (_configSync != null || !hasConfigSync) { return _configSync; } Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync"); if ((object)type != null) { _configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " PieceManager"); type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString()); type.GetProperty("IsLocked").SetValue(_configSync, true); } else { hasConfigSync = false; } return _configSync; } } public BuildPiece(string assetBundleFileName, string prefabName, string folderName = "assets") : this(PiecePrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName) { } public BuildPiece(AssetBundle bundle, string prefabName) { Prefab = PiecePrefabManager.RegisterPrefab(bundle, prefabName); registeredPieces.Add(this); } internal static void Patch_FejdStartup(FejdStartup __instance) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Expected O, but got Unknown //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Expected O, but got Unknown //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Expected O, but got Unknown //IL_0849: Unknown result type (might be due to invalid IL or missing references) //IL_0853: Expected O, but got Unknown //IL_05f6: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Expected O, but got Unknown //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_06a1: Expected O, but got Unknown //IL_08b9: Unknown result type (might be due to invalid IL or missing references) //IL_08c3: Expected O, but got Unknown //IL_0ac1: Unknown result type (might be due to invalid IL or missing references) //IL_0acb: Expected O, but got Unknown //IL_0b5a: Unknown result type (might be due to invalid IL or missing references) //IL_0b64: Expected O, but got Unknown Type configManagerType = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager"); configManager = ((configManagerType == null) ? null : Chainloader.ManagerObject.GetComponent(configManagerType)); foreach (BuildPiece registeredPiece in registeredPieces) { registeredPiece.activeTools = registeredPiece.Tool.Tools.DefaultIfEmpty("Hammer").ToArray(); if (registeredPiece.Category.Category != BuildPieceCategory.Custom) { registeredPiece.Prefab.GetComponent<Piece>().m_category = (PieceCategory)registeredPiece.Category.Category; } else { registeredPiece.Prefab.GetComponent<Piece>().m_category = PiecePrefabManager.GetCategory(registeredPiece.Category.custom); } } if (!ConfigurationEnabled) { return; } bool saveOnConfigSet = plugin.Config.SaveOnConfigSet; plugin.Config.SaveOnConfigSet = false; foreach (BuildPiece registeredPiece2 in registeredPieces) { BuildPiece piece = registeredPiece2; if (piece.SpecialProperties.NoConfig) { continue; } PieceConfig pieceConfig2 = (pieceConfigs[piece] = new PieceConfig()); PieceConfig cfg = pieceConfig2; Piece piecePrefab2 = piece.Prefab.GetComponent<Piece>(); string pieceName = piecePrefab2.m_name; string englishName = new Regex("[=\\n\\t\\\\\"\\'\\[\\]]*").Replace(english.Localize(pieceName), "").Trim(); string localizedName = Localization.instance.Localize(pieceName).Trim(); int order = 0; cfg.category = config(englishName, "Build Table Category", piece.Category.Category, new ConfigDescription("Build Category where " + localizedName + " is available.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Category = localizedName } })); ConfigurationManagerAttributes customTableAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), Browsable = (cfg.category.Value == BuildPieceCategory.Custom), Category = localizedName }; cfg.customCategory = config(englishName, "Custom Build Category", piece.Category.custom, new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); cfg.category.SettingChanged += BuildTableConfigChanged; cfg.customCategory.SettingChanged += BuildTableConfigChanged; if (cfg.category.Value == BuildPieceCategory.Custom) { piecePrefab2.m_category = PiecePrefabManager.GetCategory(cfg.customCategory.Value); } else { piecePrefab2.m_category = (PieceCategory)cfg.category.Value; } cfg.tools = config(englishName, "Tools", string.Join(", ", piece.activeTools), new ConfigDescription("Comma separated list of tools where " + localizedName + " is available.", (AcceptableValueBase)null, new object[1] { customTableAttributes })); piece.activeTools = (from s in cfg.tools.Value.Split(new char[1] { ',' }) select s.Trim()).ToArray(); cfg.tools.SettingChanged += [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (object _, EventArgs _) => { Inventory[] source = (from c in Player.s_players.Select([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Player p) => ((Humanoid)p).GetInventory()).Concat(from c in Object.FindObjectsOfType<Container>() select c.GetInventory()) where c != null select c).ToArray(); Dictionary<string, List<PieceTable>> dictionary = (from kv in (from i in (from p in ObjectDB.instance.m_items select p.GetComponent<ItemDrop>() into c where Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((Component)c).GetComponent<ZNetView>()) select c).Concat(ItemDrop.s_instances) select new KeyValuePair<string, ItemData>(Utils.GetPrefabName(((Component)i).gameObject), i.m_itemData)).Concat(from i in source.SelectMany([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (Inventory i) => i.GetAllItems()) select new KeyValuePair<string, ItemData>(((Object)i.m_dropPrefab).name, i)) where Object.op_Implicit((Object)(object)kv.Value.m_shared.m_buildPieces) group kv by kv.Key).ToDictionary([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (IGrouping<string, KeyValuePair<string, ItemData>> g) => g.Key, [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (IGrouping<string, KeyValuePair<string, ItemData>> g) => g.Select([<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (KeyValuePair<string, ItemData> kv) => kv.Value.m_shared.m_buildPieces).Distinct().ToList()); string[] array5 = piece.activeTools; foreach (string key in array5) { if (dictionary.TryGetValue(key, out var value2)) { foreach (PieceTable item3 in value2) { item3.m_pieces.Remove(piece.Prefab); } } } piece.activeTools = (from s in cfg.tools.Value.Split(new char[1] { ',' }) select s.Trim()).ToArray(); if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { array5 = piece.activeTools; foreach (string key2 in array5) { if (dictionary.TryGetValue(key2, out var value3)) { foreach (PieceTable item4 in value3) { if (!item4.m_pieces.Contains(piece.Prefab)) { item4.m_pieces.Add(piece.Prefab); } } } } if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)Player.m_localPlayer.m_buildPieces)) { PiecePrefabManager.CategoryRefreshNeeded = true; ((Humanoid)Player.m_localPlayer).SetPlaceMode(Player.m_localPlayer.m_buildPieces); } } }; StationExtension pieceExtensionComp; List<ConfigurationManagerAttributes> hideWhenNoneAttributes2; if (piece.Extension.ExtensionStations.Count > 0) { pieceExtensionComp = piece.Prefab.GetOrAddComponent<StationExtension>(); PieceConfig pieceConfig3 = cfg; string group = englishName; CraftingTable table = piece.Extension.ExtensionStations.First().Table; string text = "Crafting station that " + localizedName + " extends."; object[] array = new object[1]; ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes(); int num = order - 1; order = num; configurationManagerAttributes.Order = num; array[0] = configurationManagerAttributes; pieceConfig3.extensionTable = config(group, "Extends Station", table, new ConfigDescription(text, (AcceptableValueBase)null, array)); cfg.customExtentionTable = config(englishName, "Custom Extend Station", piece.Extension.ExtensionStations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); PieceConfig pieceConfig4 = cfg; string group2 = englishName; float maxStationDistance = piece.Extension.ExtensionStations.First().maxStationDistance; string text2 = "Distance from the station that " + localizedName + " can be placed."; object[] array2 = new object[1]; ConfigurationManagerAttributes configurationManagerAttributes2 = new ConfigurationManagerAttributes(); num = order - 1; order = num; configurationManagerAttributes2.Order = num; array2[0] = configurationManagerAttributes2; pieceConfig4.maxStationDistance = config(group2, "Max Station Distance", maxStationDistance, new ConfigDescription(text2, (AcceptableValueBase)null, array2)); hideWhenNoneAttributes2 = new List<ConfigurationManagerAttributes>(); cfg.extensionTable.SettingChanged += ExtensionTableConfigChanged; cfg.customExtentionTable.SettingChanged += ExtensionTableConfigChanged; cfg.maxStationDistance.SettingChanged += ExtensionTableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes3 = new ConfigurationManagerAttributes(); num = order - 1; order = num; configurationManagerAttributes3.Order = num; configurationManagerAttributes3.Browsable = cfg.extensionTable.Value != CraftingTable.None; ConfigurationManagerAttributes item = configurationManagerAttributes3; hideWhenNoneAttributes2.Add(item); } List<ConfigurationManagerAttributes> hideWhenNoneAttributes; if (piece.Crafting.Stations.Count > 0) { hideWhenNoneAttributes = new List<ConfigurationManagerAttributes>(); PieceConfig pieceConfig5 = cfg; string group3 = englishName; CraftingTable table2 = piece.Crafting.Stations.First().Table; string text3 = "Crafting station where " + localizedName + " is available."; object[] array3 = new object[1]; ConfigurationManagerAttributes configurationManagerAttributes4 = new ConfigurationManagerAttributes(); int num = order - 1; order = num; configurationManagerAttributes4.Order = num; array3[0] = configurationManagerAttributes4; pieceConfig5.table = config(group3, "Crafting Station", table2, new ConfigDescription(text3, (AcceptableValueBase)null, array3)); cfg.customTable = config(englishName, "Custom Crafting Station", piece.Crafting.Stations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes })); cfg.table.SettingChanged += TableConfigChanged; cfg.customTable.SettingChanged += TableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes5 = new ConfigurationManagerAttributes(); num = order - 1; order = num; configurationManagerAttributes5.Order = num; configurationManagerAttributes5.Browsable = cfg.table.Value != CraftingTable.None; ConfigurationManagerAttributes item2 = configurationManagerAttributes5; hideWhenNoneAttributes.Add(item2); } cfg.craft = itemConfig("Crafting Costs", new SerializedRequirements(piece.RequiredItems.Requirements).ToString(), "Item costs to craft " + localizedName); cfg.craft.SettingChanged += [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (object _, EventArgs _) => { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && (Object)(object)ObjectDB.instance.GetItemPrefab("YmirRemains") != (Object)null) { Requirement[] resources = SerializedRequirements.toPieceReqs(new SerializedRequirements(cfg.craft.Value)); piecePrefab2.m_resources = resources; Piece[] array4 = Object.FindObjectsOfType<Piece>(); foreach (Piece val in array4) { if (val.m_name == pieceName) { val.m_resources = resources; } } } }; for (int j = 0; j < piece.Conversions.Count; j++) { string text4 = ((piece.Conversions.Count > 1) ? $"{j + 1}. " : ""); Conversion conversion = piece.Conversions[j]; conversion.config = new Conversion.ConversionConfig(); int index = j; conversion.config.input = config(englishName, text4 + "Conversion Input Item", conversion.Input, new ConfigDescription("Conversion input item within " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName } })); conversion.config.input.SettingChanged += [<0b8b779e-e92b-4295-b4ce-c0b2d8a3a96b>NullableContext(0)] (object _, EventArgs _) => { if (index < piece.conversions.Count) { ObjectDB instance2 = ObjectDB.instance; if (instance2 != null) { ItemDrop from = SerializedRequirements.fetchByName(instance2, conversion.config.input.Value); piece.conversions[index].m_from = from; } } }; conversion.config.output = config(englishName, text4 + "Conversion Output Item", conversion.Output, new ConfigDescription("Conversion outp