using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WoodcutterNPC { internal static class ModUi { private static bool _waitForMouseRelease; internal static bool IsOpen { get { if (!WoodcutterSettingsWindow.IsOpen) { return WoodcutterPostWindow.IsOpen; } return true; } } internal static bool BlocksGameInput { get { if (IsOpen) { return true; } if (_waitForMouseRelease && !Input.GetMouseButton(0) && !Input.GetMouseButton(1) && !Input.GetMouseButton(2)) { _waitForMouseRelease = false; } return _waitForMouseRelease; } } internal static void NotifyClosed() { _waitForMouseRelease = true; } } [HarmonyPatch(typeof(Container), "GetHoverText")] internal static class Container_GetHoverText_Post_Patch { private static void Postfix(Container __instance, ref string __result) { WoodcutterHirePost component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { __result = component.BuildHoverText(); } } } [HarmonyPatch(typeof(Character), "GetHoverText")] internal static class Character_GetHoverText_Patch { private static void Postfix(Character __instance, ref string __result) { WoodcutterInteraction component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { __result = component.BuildHoverText(); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetScene_Awake_LogTreeSpecies_Patch { private static void Postfix() { TreeSpecies.LogKnownPrefabs(); } } [HarmonyPatch(typeof(Container), "Interact")] internal static class Container_Interact_Patch { private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result) { WoodcutterHirePost component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { if (!alt) { return true; } if (!hold && (Object)(object)character == (Object)(object)Player.m_localPlayer) { WoodcutterPostWindow.Open(component); } __result = !hold; return false; } WoodcutterInteraction component2 = ((Component)__instance).GetComponent(); if ((Object)(object)component2 == (Object)null) { return true; } if (hold) { __result = false; return false; } if (!alt) { return true; } WoodcutterSettingsWindow.Open(component2); __result = true; return false; } } [HarmonyPatch(typeof(Character), "OnDeath")] internal static class Character_OnDeath_DropLootChest_Patch { private const string ChestPrefabName = "piece_chest_wood"; private static void Prefix(Character __instance) { //IL_005d: 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) //IL_0094: Unknown result type (might be due to invalid IL or missing references) WoodcutterInteraction component = ((Component)__instance).GetComponent(); Container component2 = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { return; } Inventory inventory = component2.GetInventory(); if (inventory == null || inventory.NrOfItems() == 0) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("piece_chest_wood"); if ((Object)(object)prefab == (Object)null) { Logger.LogWarning((object)"WoodcutterNPC: could not find 'piece_chest_wood' prefab to drop a loot chest on death."); return; } GameObject obj = Object.Instantiate(prefab, ((Component)__instance).transform.position, Quaternion.identity); WoodcutterLootChest.Mark(obj); Container component3 = obj.GetComponent(); if (component3 != null) { Inventory inventory2 = component3.GetInventory(); if (inventory2 != null) { inventory2.MoveAll(inventory); } } WoodcutterDeathPin.Add(obj.transform.position); } } [HarmonyPatch(typeof(Container), "CheckForChanges")] internal static class Container_CheckForChanges_BreakEmptyLootChest_Patch { private static void Postfix(Container __instance) { if (WoodcutterLootChest.ShouldBreak(__instance)) { WoodcutterLootChest.Break(__instance); } } } [HarmonyPatch(typeof(Container), "OnContainerChanged")] internal static class Container_OnContainerChanged_RemoveDeathPin_Patch { private static void Postfix(Container __instance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = __instance.GetInventory(); if (inventory != null && inventory.NrOfItems() == 0 && (Object)(object)((Component)__instance).GetComponent() == (Object)null) { WoodcutterDeathPin.RemoveAt(((Component)__instance).transform.position); } } } internal static class WoodcutterLootChest { private const string ZdoKey = "WoodcutterNPC_LootChest"; private static readonly FieldRef LastRevisionRef = AccessTools.FieldRefAccess("m_lastRevision"); internal static void Mark(GameObject chest) { ZNetView component = chest.GetComponent(); ZDO obj = ((component != null) ? component.GetZDO() : null); if (obj != null) { obj.Set("WoodcutterNPC_LootChest", true); } } internal static bool ShouldBreak(Container container) { ZNetView component = ((Component)container).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || !component.GetZDO().GetBool("WoodcutterNPC_LootChest", false)) { return false; } Inventory inventory = container.GetInventory(); if (inventory != null && inventory.NrOfItems() == 0 && !container.IsInUse()) { return LastRevisionRef.Invoke(container) != uint.MaxValue; } return false; } internal static void Break(Container container) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) WoodcutterDeathPin.RemoveAt(((Component)container).transform.position); WearNTear component = ((Component)container).GetComponent(); if ((Object)(object)component != (Object)null) { component.Remove(true); } else { ((Component)container).GetComponent().Destroy(); } } } internal static class WoodcutterDeathPin { private const float MatchRadius = 1f; private static readonly FieldRef> PinsRef = AccessTools.FieldRefAccess>("m_pins"); internal static void Add(Vector3 position) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Minimap.instance == (Object)null)) { Minimap.instance.AddPin(position, (PinType)4, WoodcutterTexts.T("npc_name"), true, false, 0L, default(PlatformUserID)); } } internal static void RemoveAt(Vector3 position) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Minimap.instance == (Object)null)) { HashSet names = new HashSet(WoodcutterTexts.AllLanguages("npc_name")); PinData val = PinsRef.Invoke(Minimap.instance).Find((PinData pin) => (int)pin.m_type == 4 && names.Contains(pin.m_name) && Vector3.Distance(pin.m_pos, position) <= 1f); if (val != null) { Minimap.instance.RemovePin(val); } } } } [HarmonyPatch(typeof(InventoryGui), "Show")] internal static class InventoryGui_Show_HideSidePanels_Patch { private static void Postfix(InventoryGui __instance, Container container) { bool flag = (Object)(object)container != (Object)null && (Object)(object)((Component)container).GetComponent() != (Object)null; InventoryGuiPanels.SetVisible(__instance, !flag); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryGui_Hide_RestoreSidePanels_Patch { private static void Postfix(InventoryGui __instance) { InventoryGuiPanels.SetVisible(__instance, visible: true); } } [HarmonyPatch(typeof(InventoryGrid), "DropItem")] internal static class InventoryGrid_DropItem_AxeSlotPatch { private static bool Prefix(InventoryGrid __instance, ItemData item, Vector2i pos, ref bool __result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = __instance.GetInventory(); if (!WoodcutterAxeSlot.IsAxeCell(inventory, pos.x, pos.y) || WoodcutterAxeSlot.IsAxe(item)) { return true; } if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, WoodcutterTexts.T(WoodcutterAxeSlot.IsPost(inventory) ? "drop_post_axerow" : "drop_axeslot"), 0, (Sprite)null, false); } __result = false; return false; } } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] internal static class Inventory_MoveItemToThis_AxeSlotPatch { private static void Postfix(Inventory __instance, ItemData item) { if (WoodcutterAxeSlot.IsManaged(__instance)) { WoodcutterAxeSlot.Rearrange(__instance, item); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class InventoryGrid_UpdateGui_AxeSlotPatch { private sealed class Changes { public readonly List Icons = new List(); public readonly List> Backgrounds = new List>(); } private static readonly Color GhostTint = new Color(1f, 1f, 1f, 0.25f); private static readonly Color AxeCellTint = new Color(1f, 0.72f, 0.3f, 1f); private static readonly MethodInfo GetElementMethod = AccessTools.Method(typeof(InventoryGrid), "GetElement", (Type[])null, (Type[])null); private static readonly Dictionary ByGrid = new Dictionary(); private static void Postfix(InventoryGrid __instance) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) if (!ByGrid.TryGetValue(__instance, out var value)) { value = new Changes(); ByGrid[__instance] = value; } Undo(value); Inventory inventory = __instance.GetInventory(); if (!WoodcutterAxeSlot.IsManaged(inventory) || GetElementMethod == null) { return; } Sprite ghostIcon = WoodcutterAxeSlot.GhostIcon; int width = inventory.GetWidth(); for (int i = 0; i < inventory.GetHeight(); i++) { for (int j = 0; j < width; j++) { if (!WoodcutterAxeSlot.IsAxeCell(inventory, j, i)) { continue; } object? obj = GetElementMethod.Invoke(__instance, new object[3] { j, i, width }); InventoryElement val = (InventoryElement)((obj is InventoryElement) ? obj : null); if (!((Object)(object)val == (Object)null)) { Image val2 = (((Object)(object)val.m_button != (Object)null) ? ((Selectable)val.m_button).image : null); if ((Object)(object)val2 != (Object)null) { value.Backgrounds.Add(new KeyValuePair(val2, ((Graphic)val2).color)); ((Graphic)val2).color = ((Graphic)val2).color * AxeCellTint; } if ((Object)(object)ghostIcon != (Object)null && (Object)(object)val.m_icon != (Object)null && inventory.GetItemAt(j, i) == null) { val.m_icon.sprite = ghostIcon; ((Graphic)val.m_icon).color = GhostTint; ((Behaviour)val.m_icon).enabled = true; value.Icons.Add(val.m_icon); } } } } } private static void Undo(Changes changes) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) foreach (Image icon in changes.Icons) { if ((Object)(object)icon != (Object)null) { ((Graphic)icon).color = Color.white; } } changes.Icons.Clear(); foreach (KeyValuePair background in changes.Backgrounds) { if ((Object)(object)background.Key != (Object)null) { ((Graphic)background.Key).color = background.Value; } } changes.Backgrounds.Clear(); } } [HarmonyPatch(typeof(Player), "TakeInput")] internal static class Player_TakeInput_Patch { private static void Postfix(ref bool __result) { if (ModUi.BlocksGameInput) { __result = false; } } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] internal static class PlayerController_TakeInput_Patch { private static void Postfix(ref bool __result) { if (ModUi.BlocksGameInput) { __result = false; } } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] internal static class GameCamera_UpdateMouseCapture_Patch { private static bool Prefix() { if (!ModUi.IsOpen) { return true; } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); return false; } } internal static class InventoryGuiPanels { internal static void SetVisible(InventoryGui gui, bool visible) { if ((Object)(object)gui.m_crafting != (Object)null) { ((Component)gui.m_crafting).gameObject.SetActive(visible); } if ((Object)(object)gui.m_info != (Object)null) { ((Component)gui.m_info).gameObject.SetActive(visible); } } } [BepInPlugin("com.roman.woodcutternpc", "WoodcutterNPC", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string PluginGUID = "com.roman.woodcutternpc"; private const string PluginName = "WoodcutterNPC"; private const string PluginVersion = "1.1.0"; private const string BaseCreatureName = "Skeleton"; internal const string CreatureName = "WoodcutterNPC"; internal const int InventoryWidth = 6; internal const int InventoryHeight = 3; private const string BasePostPieceName = "piece_workbench_ext1"; private const string PostPieceName = "piece_woodcutter_post"; private const string RuntimeHostName = "WoodcutterNPC_RuntimeHost"; private static ConfigEntry _useDurability; private static ConfigEntry _chopDamageMultiplier; private static ConfigEntry _chopInterval; private static ConfigEntry _defaultZoneRadius; private static ConfigEntry _showMapPins; private static ConfigEntry _notifications; private static ConfigEntry _language; private static ConfigEntry _hirePrice1; private static ConfigEntry _hirePrice2; private static ConfigEntry _hirePrice3; private static ConfigEntry _rehireDiscount; private static ConfigEntry _level2Cores; private static ConfigEntry _level3Cores; private static ConfigEntry _maxHealth; private static ConfigEntry _regenAmount; private static ConfigEntry _regenInterval; private static ConfigEntry _pathfinding; private static ConfigEntry _repairCostPercent; private static ConfigEntry _skillGainRate; private static ConfigEntry _skillStartLevel; private Harmony _harmony; internal static bool UseDurability { get { if (_useDurability != null) { return _useDurability.Value; } return true; } } internal static float ChopDamageMultiplier { get { if (_chopDamageMultiplier == null) { return 1f; } return _chopDamageMultiplier.Value; } } internal static float ChopInterval { get { if (_chopInterval == null) { return 1.5f; } return _chopInterval.Value; } } internal static bool ShowMapPins { get { if (_showMapPins != null) { return _showMapPins.Value; } return true; } } internal static bool Notifications { get { if (_notifications != null) { return _notifications.Value; } return true; } } internal static float MaxHealth { get { if (_maxHealth == null) { return 300f; } return _maxHealth.Value; } } internal static float RegenAmount { get { if (_regenAmount == null) { return 5f; } return _regenAmount.Value; } } internal static float RegenInterval { get { if (_regenInterval == null) { return 2.5f; } return _regenInterval.Value; } } internal static float SkillGainRate { get { if (_skillGainRate == null) { return 1f; } return _skillGainRate.Value; } } internal static int SkillStartLevel { get { if (_skillStartLevel == null) { return 0; } return _skillStartLevel.Value; } } internal static int RepairCostPercent { get { if (_repairCostPercent == null) { return 30; } return _repairCostPercent.Value; } } internal static bool UsePathfinding { get { if (_pathfinding != null) { return _pathfinding.Value; } return true; } } internal static int HirePrice1 { get { if (_hirePrice1 == null) { return 50; } return _hirePrice1.Value; } } internal static int HirePrice2 { get { if (_hirePrice2 == null) { return 100; } return _hirePrice2.Value; } } internal static int HirePrice3 { get { if (_hirePrice3 == null) { return 200; } return _hirePrice3.Value; } } internal static int RehireDiscountPercent { get { if (_rehireDiscount == null) { return 50; } return _rehireDiscount.Value; } } internal static int Level2Cores { get { if (_level2Cores == null) { return 10; } return _level2Cores.Value; } } internal static int Level3Cores { get { if (_level3Cores == null) { return 20; } return _level3Cores.Value; } } internal static float DefaultZoneRadius { get { if (_defaultZoneRadius == null) { return 100f; } return _defaultZoneRadius.Value; } } internal static void ApplyLanguage() { string gameLanguage = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : null); WoodcutterTexts.Current = WoodcutterTexts.Resolve((_language != null) ? _language.Value : "Auto", gameLanguage); } private void Awake() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Expected O, but got Unknown //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Expected O, but got Unknown //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Expected O, but got Unknown //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Expected O, but got Unknown //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Expected O, but got Unknown //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Expected O, but got Unknown //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Expected O, but got Unknown //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Expected O, but got Unknown //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Expected O, but got Unknown //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Expected O, but got Unknown _useDurability = ((BaseUnityPlugin)this).Config.Bind("Axe", "UseDurability", true, "Whether the axe in the woodcutter's axe slot loses durability while it works. A worn-out axe stops the NPC until the player repairs it; it is never destroyed."); _chopDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind("Axe", "ChopDamageMultiplier", 1f, new ConfigDescription("Multiplier on top of the damage a player with the woodcutter's skill level would do with that same axe. 1.0 = exactly like such a player.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), Array.Empty())); _chopInterval = ((BaseUnityPlugin)this).Config.Bind("Axe", "ChopInterval", 1.5f, new ConfigDescription("Seconds between swings.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 10f), Array.Empty())); _defaultZoneRadius = ((BaseUnityPlugin)this).Config.Bind("WorkZone", "DefaultRadius", 100f, new ConfigDescription("Radius in meters of a new Woodcutter's Post work zone. Its woodcutters only chop and collect inside it. Each post's radius can be changed in-game from the post's window (alt interact on the post).", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 300f), Array.Empty())); _showMapPins = ((BaseUnityPlugin)this).Config.Bind("Map", "ShowWoodcutterPins", true, "Show a live pin with an axe icon on the map where each woodcutter currently is."); _language = ((BaseUnityPlugin)this).Config.Bind("General", "Language", "Auto", new ConfigDescription("Language of the mod's texts. Auto follows the game's language (English if it isn't one of the others). The names of the woodcutter and the post are set when the game starts, so changing this needs a restart for those; the windows switch right away.", (AcceptableValueBase)(object)new AcceptableValueList(new string[4] { "Auto", "English", "Ukrainian", "Russian" }), Array.Empty())); _notifications = ((BaseUnityPlugin)this).Config.Bind("Notifications", "Enabled", true, "Show a message when a woodcutter's axe drops to 5% durability and when it breaks."); _maxHealth = ((BaseUnityPlugin)this).Config.Bind("Health", "MaxHealth", 300f, new ConfigDescription("Woodcutter's max health. Falling trees hit hard, so it is well above a skeleton's.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 10000f), Array.Empty())); _regenAmount = ((BaseUnityPlugin)this).Config.Bind("Health", "RegenAmount", 5f, new ConfigDescription("Health restored every RegenInterval seconds while below max (0 = no regeneration).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1000f), Array.Empty())); _regenInterval = ((BaseUnityPlugin)this).Config.Bind("Health", "RegenInterval", 2.5f, new ConfigDescription("Seconds between regeneration ticks.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 60f), Array.Empty())); _skillGainRate = ((BaseUnityPlugin)this).Config.Bind("Skill", "GainRate", 1f, new ConfigDescription("How fast woodcutters get better at woodcutting. Each swing counts like a player's (the world's skill gain modifier applies too); 1.0 = as fast as a player, 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); _skillStartLevel = ((BaseUnityPlugin)this).Config.Bind("Skill", "StartLevel", 0, new ConfigDescription("Woodcutting skill of a newly hired woodcutter (and of ones hired before skills existed). A player's damage with an axe goes from about 40% at 0 to 100% at 100.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); _repairCostPercent = ((BaseUnityPlugin)this).Config.Bind("Repair", "CostPercent", 30, new ConfigDescription("When a post has automatic axe repair ticked, a woodcutter whose axe breaks repairs it there, paying this share of the axe's main crafting material - the one its recipe takes the most of, handle wood not counted - from the post's storage (at least 1).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), Array.Empty())); _pathfinding = ((BaseUnityPlugin)this).Config.Bind("Movement", "Pathfinding", true, "Woodcutters find their way around rocks, trees, buildings and cliffs, the way the game's creatures do. Off: they walk in straight lines and give up on whatever is in the way."); AcceptableValueRange val = new AcceptableValueRange(0, 99999); _hirePrice1 = ((BaseUnityPlugin)this).Config.Bind("Hire", "Price1", 50, new ConfigDescription("Coins for the 1st woodcutter in the world (post level 1).", (AcceptableValueBase)(object)val, Array.Empty())); _hirePrice2 = ((BaseUnityPlugin)this).Config.Bind("Hire", "Price2", 100, new ConfigDescription("Coins for the 2nd woodcutter (needs post level 2).", (AcceptableValueBase)(object)val, Array.Empty())); _hirePrice3 = ((BaseUnityPlugin)this).Config.Bind("Hire", "Price3", 200, new ConfigDescription("Coins for the 3rd woodcutter (needs post level 3).", (AcceptableValueBase)(object)val, Array.Empty())); _rehireDiscount = ((BaseUnityPlugin)this).Config.Bind("Hire", "RehireThirdDiscountPercent", 50, new ConfigDescription("Discount on hiring a 3rd woodcutter again, once one has been hired in this world before (after it died or was dismissed).", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); AcceptableValueRange val2 = new AcceptableValueRange(0, 9999); _level2Cores = ((BaseUnityPlugin)this).Config.Bind("Upgrade", "Level2SurtlingCores", 10, new ConfigDescription("Surtling cores to upgrade the Woodcutter's Post to level 2 (one-off per world).", (AcceptableValueBase)(object)val2, Array.Empty())); _level3Cores = ((BaseUnityPlugin)this).Config.Bind("Upgrade", "Level3SurtlingCores", 20, new ConfigDescription("Surtling cores to upgrade the Woodcutter's Post to level 3 (one-off per world).", (AcceptableValueBase)(object)val2, Array.Empty())); _harmony = new Harmony("com.roman.woodcutternpc"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); GameObject val3 = new GameObject("WoodcutterNPC_RuntimeHost"); val3.AddComponent(); val3.AddComponent(); val3.AddComponent(); val3.AddComponent(); val3.AddComponent(); Object.DontDestroyOnLoad((Object)val3); CreatureManager.OnVanillaCreaturesAvailable += RegisterWoodcutterCreature; PrefabManager.OnVanillaPrefabsAvailable += RegisterHirePost; } private void RegisterHirePost() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) ApplyLanguage(); PrefabManager.OnVanillaPrefabsAvailable -= RegisterHirePost; PieceConfig val = new PieceConfig(); val.Name = WoodcutterHirePost.DisplayName; val.Description = WoodcutterTexts.T("post_desc"); val.PieceTable = PieceTables.Hammer; val.Category = PieceCategories.Crafting; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig("Wood", 10, 0, true) }; PieceConfig val2 = val; CustomPiece val3 = new CustomPiece("piece_woodcutter_post", "piece_workbench_ext1", val2); if ((Object)(object)val3.PiecePrefab == (Object)null) { Logger.LogError((object)"WoodcutterNPC: could not clone base piece 'piece_workbench_ext1'"); return; } GameObject piecePrefab = val3.PiecePrefab; val3.Piece.m_craftingStation = null; StationExtension component = piecePrefab.GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } Container obj = piecePrefab.AddComponent(); obj.m_name = WoodcutterHirePost.DisplayName; obj.m_width = 5; obj.m_height = 5; obj.m_privacy = (PrivacySetting)2; obj.m_checkGuardStone = true; obj.m_autoDestroyEmpty = false; piecePrefab.AddComponent(); PieceManager.Instance.AddPiece(val3); } private void RegisterWoodcutterCreature() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) ApplyLanguage(); CreatureManager.OnVanillaCreaturesAvailable -= RegisterWoodcutterCreature; CreatureConfig val = new CreatureConfig { Name = "WoodcutterNPC", Faction = (Faction)11 }; CustomCreature val2 = new CustomCreature("WoodcutterNPC", "Skeleton", val); if ((Object)(object)val2.Prefab == (Object)null) { Logger.LogError((object)"WoodcutterNPC: could not clone base prefab 'Skeleton'"); return; } GameObject prefab = val2.Prefab; MonsterAI component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; component.m_sleeping = false; } Character component2 = prefab.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_speed = 2f; component2.m_walkSpeed = 2f; component2.m_runSpeed = 2f; component2.m_health = MaxHealth; component2.m_name = WoodcutterTexts.T("npc_name"); } Container val3 = prefab.AddComponent(); val3.m_name = WoodcutterTexts.T("npc_name"); val3.m_width = 6; val3.m_height = 3; val3.m_privacy = (PrivacySetting)2; val3.m_checkGuardStone = false; val3.m_autoDestroyEmpty = false; prefab.AddComponent().Inventory = val3; prefab.AddComponent(); Logger.LogInfo((object)(CreatureManager.Instance.AddCreature(val2) ? "WoodcutterNPC: 'WoodcutterNPC' registered. Spawn with 'devcommands' then 'spawn WoodcutterNPC 1'." : "WoodcutterNPC: 'WoodcutterNPC' failed validation, see warnings above.")); } } internal static class TreeSpecies { internal const int AllMask = -1; private static readonly Dictionary IndexByPrefab = new Dictionary(); internal static int Count => WoodcutterLogic.SpeciesCount; internal static int IndexOf(MonoBehaviour treeOrLog) { string prefabName = Utils.GetPrefabName(((Component)treeOrLog).gameObject); if (!IndexByPrefab.TryGetValue(prefabName, out var value)) { value = WoodcutterLogic.ClassifySpecies(prefabName); IndexByPrefab[prefabName] = value; } return value; } internal static bool IsAllowed(MonoBehaviour treeOrLog, int mask) { return WoodcutterLogic.IsSpeciesAllowed(mask, IndexOf(treeOrLog)); } internal static void LogKnownPrefabs() { if (!((Object)(object)ZNetScene.instance == (Object)null)) { IEnumerable values = from p in ZNetScene.instance.m_prefabs where (Object)(object)p != (Object)null && ((Object)(object)p.GetComponent() != (Object)null || (Object)(object)p.GetComponent() != (Object)null) select ((Object)p).name + " -> " + WoodcutterTexts.Species[0][WoodcutterLogic.ClassifySpecies(((Object)p).name)] into line orderby line select line; Logger.LogInfo((object)("WoodcutterNPC: tree species by prefab:\n " + string.Join("\n ", values))); } } } internal static class UiTheme { internal sealed class WindowState { internal float Height; internal float Scale; internal void Reset() { Height = 0f; Scale = 0f; } } private const float ReferenceHeight = 1080f; internal static readonly Color Panel = Hex(1973015); internal static readonly Color PanelBorder = Hex(4866100); internal static readonly Color Card = Hex(2762272); internal static readonly Color CardBorder = Hex(3814444); internal static readonly Color Accent = Hex(14723146); internal static readonly Color AccentHover = Hex(15776866); internal static readonly Color AccentPressed = Hex(12618804); internal static readonly Color Text = Hex(15656664); internal static readonly Color TextMuted = Hex(11116432); internal static readonly Color TextOnAccent = Hex(1973015); internal static readonly Color Button = Hex(3748651); internal static readonly Color ButtonHover = Hex(4866616); internal static readonly Color ButtonPressed = Hex(3090979); internal static readonly Color Success = Hex(6200919); internal static readonly Color SuccessHover = Hex(7189094); internal static readonly Color Danger = Hex(12145471); internal static readonly Color DangerHover = Hex(13460560); internal static GUIStyle PanelStyle; internal static GUIStyle CardStyle; internal static GUIStyle RowStyle; internal static GUIStyle RowTitle; internal static GUIStyle Title; internal static GUIStyle SectionHeader; internal static GUIStyle Label; internal static GUIStyle LabelMuted; internal static GUIStyle Hint; internal static GUIStyle BigValue; internal static GUIStyle ButtonStyle; internal static GUIStyle PrimaryButton; internal static GUIStyle SuccessButton; internal static GUIStyle DangerButton; internal static GUIStyle SmallButton; internal static GUIStyle CloseButton; internal static GUIStyle Chip; internal static GUIStyle PillSuccess; internal static GUIStyle PillDanger; internal static GUIStyle SliderTrack; internal static GUIStyle SliderThumb; private static GUIStyle _shadowStyle; private static Texture2D _dim; private static bool _ready; private const float ScreenMargin = 12f; private const float TopFraction = 0.08f; internal static void Window(int id, WindowState state, float width, WindowFunction draw) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Invalid comparison between Unknown and I4 //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) EnsureStyles(); bool num = state.Height > 0f; if (num && state.Scale <= 0f) { float num2 = Mathf.Max(1f, (float)Screen.height / 1080f); float num3 = (float)Screen.height * 0.92f / (state.Height + 12f); state.Scale = Mathf.Min(num2, num3); } float num4 = ((state.Scale > 0f) ? state.Scale : Mathf.Max(1f, (float)Screen.height / 1080f)); GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num4, num4, 1f)); float num5 = (float)Screen.width / num4; float num6 = (float)Screen.height / num4; GUI.DrawTexture(new Rect(0f, 0f, num5, num6), (Texture)(object)_dim); float num7 = Mathf.Round(Mathf.Max(12f, num6 * 0.08f)); float num8 = Mathf.Round((num5 - width) / 2f); Color color = GUI.color; if (!num) { GUI.color = Color.clear; } else { GUI.Box(new Rect(num8 - 14f, num7 - 10f, width + 28f, state.Height + 32f), GUIContent.none, _shadowStyle); } GUILayout.BeginArea(new Rect(num8, num7, width, Mathf.Max(100f, num6 - num7 - 12f))); GUILayout.BeginVertical(PanelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(width) }); draw.Invoke(id); GUILayout.EndVertical(); if ((int)Event.current.type == 7) { Rect lastRect = GUILayoutUtility.GetLastRect(); float height = ((Rect)(ref lastRect)).height; if (height > 0f) { state.Height = height; } } GUILayout.EndArea(); GUI.color = color; GUI.matrix = Matrix4x4.identity; } internal static bool Header(string title, string subtitle = null, GUIStyle pill = null, string pillText = null) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.BeginVertical(Array.Empty()); GUILayout.Label(title, Title, Array.Empty()); if (subtitle != null) { GUILayout.Label(subtitle, LabelMuted, Array.Empty()); } GUILayout.EndVertical(); GUILayout.FlexibleSpace(); if (pill != null) { GUILayout.Label(pillText, pill, Array.Empty()); GUILayout.Space(6f); } bool result = GUILayout.Button("X", CloseButton, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.Space(10f); return result; } internal static void BeginCard(string header) { GUILayout.BeginVertical(CardStyle, Array.Empty()); if (header != null) { GUILayout.Label(header.ToUpperInvariant(), SectionHeader, Array.Empty()); GUILayout.Space(4f); } } internal static void EndCard() { GUILayout.EndVertical(); GUILayout.Space(10f); } internal static float Slider(float value, float min, float max) { return GUILayout.HorizontalSlider(value, min, max, SliderTrack, SliderThumb, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); } private static void EnsureStyles() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0097: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_00e5: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown //IL_0141: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_0188: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Expected O, but got Unknown //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Expected O, but got Unknown //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Expected O, but got Unknown //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Expected O, but got Unknown //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Expected O, but got Unknown //IL_04d6: Expected O, but got Unknown //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Expected O, but got Unknown if (!_ready || !((Object)(object)PanelStyle.normal.background != (Object)null)) { _ready = true; _dim = Solid(new Color(0f, 0f, 0f, 0.35f)); GUIStyle val = new GUIStyle(); val.normal.background = Rounded(new Color(0f, 0f, 0f, 0.55f), 24, 0, Color.clear, soft: true); val.border = new RectOffset(24, 24, 24, 24); _shadowStyle = val; GUIStyle val2 = new GUIStyle(); val2.normal.background = Rounded(Panel, 12, 2, PanelBorder); val2.border = new RectOffset(14, 14, 14, 14); val2.padding = new RectOffset(20, 20, 18, 16); PanelStyle = val2; GUIStyle val3 = new GUIStyle(); val3.normal.background = Rounded(Card, 8, 1, CardBorder); val3.border = new RectOffset(10, 10, 10, 10); val3.padding = new RectOffset(14, 14, 12, 14); val3.margin = new RectOffset(0, 0, 0, 0); CardStyle = val3; GUIStyle val4 = new GUIStyle(); val4.normal.background = Rounded(Panel, 6, 1, CardBorder); val4.border = new RectOffset(8, 8, 8, 8); val4.padding = new RectOffset(10, 10, 6, 6); RowStyle = val4; Title = TextStyle(20, Accent, (FontStyle)1); SectionHeader = TextStyle(11, TextMuted, (FontStyle)1); Label = TextStyle(14, Text, (FontStyle)0); LabelMuted = TextStyle(12, TextMuted, (FontStyle)0); Hint = TextStyle(12, TextMuted, (FontStyle)0); Hint.wordWrap = true; BigValue = TextStyle(22, Text, (FontStyle)1); RowTitle = TextStyle(15, Text, (FontStyle)1); RowTitle.margin = new RectOffset(0, 8, 0, 0); ButtonStyle = MakeButton(Button, ButtonHover, ButtonPressed, Text, 14, 36f); PrimaryButton = MakeButton(Accent, AccentHover, AccentPressed, TextOnAccent, 14, 36f); PrimaryButton.fontStyle = (FontStyle)1; SuccessButton = MakeButton(Success, SuccessHover, Success, Color.white, 14, 36f); SuccessButton.fontStyle = (FontStyle)1; DangerButton = MakeButton(Danger, DangerHover, Danger, Color.white, 14, 36f); DangerButton.fontStyle = (FontStyle)1; SmallButton = MakeButton(Button, ButtonHover, ButtonPressed, Text, 12, 26f); SmallButton.padding = new RectOffset(10, 10, 4, 4); CloseButton = MakeButton(Card, Danger, Danger, TextMuted, 14, 28f); CloseButton.fixedWidth = 28f; CloseButton.hover.textColor = Color.white; CloseButton.padding = new RectOffset(0, 0, 0, 0); Chip = MakeButton(Card, ButtonHover, ButtonPressed, TextMuted, 13, 32f, Rounded(Card, 16, 1, PanelBorder)); Chip.border = new RectOffset(16, 16, 16, 16); Chip.onNormal.background = Rounded(Accent, 16, 0, Accent); Chip.onHover.background = Rounded(AccentHover, 16, 0, AccentHover); Chip.onActive.background = Rounded(AccentPressed, 16, 0, AccentPressed); GUIStyleState onNormal = Chip.onNormal; GUIStyleState onHover = Chip.onHover; Color val5 = (Chip.onActive.textColor = TextOnAccent); Color textColor = (onHover.textColor = val5); onNormal.textColor = textColor; Chip.hover.textColor = Text; PillSuccess = Pill(Success); PillDanger = Pill(Danger); GUIStyle val7 = new GUIStyle(); val7.normal.background = SliderTrackTexture(); val7.border = new RectOffset(4, 4, 0, 0); val7.fixedHeight = 20f; val7.margin = new RectOffset(8, 8, 8, 8); SliderTrack = val7; GUIStyle val8 = new GUIStyle(); val8.normal.background = Circle(Accent); val8.hover.background = Circle(AccentHover); val8.active.background = Circle(AccentPressed); val8.fixedWidth = 20f; val8.fixedHeight = 20f; SliderThumb = val8; } } private static GUIStyle TextStyle(int size, Color color, FontStyle style = (FontStyle)0) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003d: Expected O, but got Unknown GUIStyle val = new GUIStyle { fontSize = size, fontStyle = style }; val.normal.textColor = color; val.alignment = (TextAnchor)3; val.richText = true; val.padding = new RectOffset(0, 0, 2, 2); return val; } private static GUIStyle MakeButton(Color normal, Color hover, Color pressed, Color text, int fontSize, float height, Texture2D normalTexture = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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) //IL_0068: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008e: 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_009d: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) GUIStyle val = new GUIStyle(); val.normal.background = normalTexture ?? Rounded(normal, 6, 0, normal); val.normal.textColor = text; val.hover.background = Rounded(hover, 6, 0, hover); val.hover.textColor = text; val.active.background = Rounded(pressed, 6, 0, pressed); val.active.textColor = text; val.border = new RectOffset(8, 8, 8, 8); val.padding = new RectOffset(14, 14, 6, 6); val.margin = new RectOffset(0, 0, 3, 3); val.alignment = (TextAnchor)4; val.fontSize = fontSize; val.fixedHeight = height; val.richText = true; return val; } private static GUIStyle Pill(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown GUIStyle val = new GUIStyle(); val.normal.background = Rounded(color, 11, 0, color); val.normal.textColor = Color.white; val.border = new RectOffset(12, 12, 12, 12); val.padding = new RectOffset(10, 10, 3, 3); val.alignment = (TextAnchor)4; val.fontSize = 12; val.fontStyle = (FontStyle)1; val.fixedHeight = 22f; return val; } private static Texture2D Solid(Color color) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Texture2D obj = NewTexture(1, 1); obj.SetPixel(0, 0, color); obj.Apply(); return obj; } private static Texture2D Rounded(Color fill, int radius, int borderWidth, Color border, bool soft = false) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) int num = radius * 2 + 2; Texture2D val = NewTexture(num, num); float num2 = (float)num / 2f; float num3 = num2 - (float)radius; Color val2 = default(Color); for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num4 = Mathf.Max(Mathf.Abs((float)j + 0.5f - num2) - num3, 0f); float num5 = Mathf.Max(Mathf.Abs((float)i + 0.5f - num2) - num3, 0f); float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5) - (float)radius; if (soft) { float num7 = Mathf.Clamp01((0f - num6) / (float)radius); ((Color)(ref val2))..ctor(fill.r, fill.g, fill.b, fill.a * num7 * num7); } else { float num8 = Mathf.Clamp01(0.5f - num6); val2 = ((borderWidth > 0 && num6 > (float)(-borderWidth) - 0.5f) ? Color.Lerp(border, fill, Mathf.Clamp01(0f - num6 - (float)borderWidth + 0.5f)) : fill); val2.a *= num8; } val.SetPixel(j, i, val2); } } val.Apply(); return val; } private static Texture2D Circle(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return Rounded(color, 10, 2, Color.Lerp(color, Color.black, 0.35f)); } private static Texture2D SliderTrackTexture() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) Texture2D val = NewTexture(12, 20); for (int i = 0; i < 20; i++) { for (int j = 0; j < 12; j++) { bool num = i >= 7 && i < 13; float num2 = Mathf.Min((float)j + 0.5f, (float)(12 - j) - 0.5f); float a = (num ? Mathf.Clamp01(num2) : 0f); Color buttonHover = ButtonHover; buttonHover.a = a; val.SetPixel(j, i, buttonHover); } } val.Apply(); return val; } private static Texture2D NewTexture(int width, int height) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown return new Texture2D(width, height, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; } private static Color Hex(int rgb) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) return new Color((float)((rgb >> 16) & 0xFF) / 255f, (float)((rgb >> 8) & 0xFF) / 255f, (float)(rgb & 0xFF) / 255f, 1f); } } public class WoodcutterAI : MonoBehaviour { private enum State { Idle, MovingToTarget, Chopping, MovingToItem, ScanningAfterFell, ReturningToZone, ReturningHome, Depositing, WaitingForStorage } private enum PickupResult { Collected, NotReadyYet, InventoryFull } private const float SearchRadius = 20f; private const float SearchInterval = 1f; private const float StopDistance = 2f; private const float LogStopDistance = 1.3f; private const float ItemPickupDistance = 1.5f; private const float AfterFellScanRadius = 25f; private const float ScanTimeout = 12f; private const float StuckProgressEpsilon = 0.3f; private const float StuckAbandonTime = 6f; private const float BlockedMoveEpsilon = 0.5f; private const float BlockedTime = 4f; private const float TouchRadius = 1.1f; private const float TreeBlockedReach = 3.5f; private const float EquipRetryInterval = 1f; private const float DurabilitySaveInterval = 5f; private const float AvoidTargetDuration = 45f; private const float ZoneSearchInterval = 5f; private const float ZoneArriveDistance = 5f; private const float ZoneArriveMargin = 10f; private const float WaterDepthLimit = 0.3f; private const float RecallArriveDistance = 1.5f; private const float HomeArriveDistance = 1.5f; private const float DepositReach = 3f; private const float DepositBlockedReach = 6f; private const float DepositRetryInterval = 5f; private const float RecallStuckTeleportTime = 8f; private const float RepairRetryInterval = 5f; private const float SkillSaveInterval = 10f; private const float RecallDetourTimeout = 30f; private const string ClaimZdoKey = "WoodcutterNPC_Claim"; private static readonly List Loaded = new List(); private static readonly FieldInfo ItemDropNetViewField = AccessTools.Field(typeof(ItemDrop), "m_nview"); private static readonly string[] SwingTriggerCandidates = new string[2] { "attack_mace", "attack" }; private Character _character; private Humanoid _humanoid; private ZSyncAnimation _zanim; private ZNetView _nview; private Container _container; private WoodcutterInteraction _interaction; private ItemData _axe; private string _equippedAxeKey; private string _swingTrigger; private float _nextEquipRetry; private float _nextDurabilitySave; private bool _wearUnsaved; private int _skill; private float _skillProgress; private bool _skillUnsaved; private float _nextSkillSave; private bool _lowWarningArmed; private bool _brokenWarningArmed; private float _nextRepairTry; private string _repairNotice; private float _nextRegenTime; private ZDOID _claimedId = ZDOID.None; private bool _claimWritten; private Vector3 _lastTargetPosition; private float _nextDepositTry; private bool _storageFullNotified; private bool _recalling; private float _recallBestDistance; private float _recallStuckSince; private State _state; private MonoBehaviour _target; private IDestructible _targetDestructible; private Collider[] _targetColliders = (Collider[])(object)new Collider[0]; private Vector3 _chainAnchor; private ItemDrop _pickupTarget; private float _itemChaseDeadline; private readonly Dictionary _avoidUntil = new Dictionary(); private float _nextSearchTime; private float _nextZoneSearchTime; private float _nextChopTime; private float _scanUntil; private readonly WoodcutterPathMover _mover = new WoodcutterPathMover(); private Vector3 _moveAnchor; private float _moveAnchorTime; private bool HasUsableAxe { get { if (_axe != null) { return !WoodcutterAxeSlot.IsBroken(_axe); } return false; } } private float TargetStopDistance { get { if (_targetColliders.Length == 0) { return 2f; } return 1.3f; } } private void Awake() { _character = ((Component)this).GetComponent(); ref Humanoid humanoid = ref _humanoid; Character character = _character; humanoid = (Humanoid)(object)((character is Humanoid) ? character : null); _zanim = ((Component)this).GetComponent(); _nview = ((Component)this).GetComponent(); _container = ((Component)this).GetComponent(); _interaction = ((Component)this).GetComponent(); } private void OnEnable() { Loaded.Add(this); } private void OnDisable() { Loaded.Remove(this); } private void Start() { RefreshAxe(); } private void RefreshAxe() { Inventory inventory = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null); WoodcutterAxeSlot.Register(inventory); _axe = WoodcutterAxeSlot.GetAxe(inventory); string text = AxeKey(_axe); if (text == _equippedAxeKey) { if (Time.time < _nextEquipRetry) { return; } _nextEquipRetry = Time.time + 1f; if (!IsHandEmpty()) { return; } } _equippedAxeKey = text; _repairNotice = null; _swingTrigger = ResolveSwingTrigger(_axe); float num = DurabilityFraction(_axe); _lowWarningArmed = num > 0.05f; _brokenWarningArmed = num > 0f; EquipAxe(_axe); } private static string AxeKey(ItemData axe) { if (axe == null) { return null; } return axe.m_shared.m_name + "|" + axe.m_quality + "|" + axe.m_variant + "|" + axe.m_worldLevel; } private bool IsHandEmpty() { if (_axe != null && (Object)(object)_humanoid != (Object)null) { return _humanoid.GetInventory().GetEquippedItems().Count == 0; } return false; } private void EquipAxe(ItemData axe) { if (!((Object)(object)_humanoid == (Object)null)) { _humanoid.UnequipAllItems(); _humanoid.GetInventory().RemoveAll(); if (axe != null) { ItemData val = axe.Clone(); val.m_stack = 1; _humanoid.GetInventory().AddItem(val); _humanoid.EquipItem(val, true); } } } private string ResolveSwingTrigger(ItemData axe) { if ((Object)(object)_zanim == (Object)null) { return null; } string text = axe?.m_shared?.m_attack?.m_attackAnimation; if (!string.IsNullOrEmpty(text) && _zanim.HasParameter(text, (AnimatorControllerParameterType)9)) { return text; } string[] swingTriggerCandidates = SwingTriggerCandidates; foreach (string text2 in swingTriggerCandidates) { if (_zanim.HasParameter(text2, (AnimatorControllerParameterType)9)) { return text2; } } return null; } private void WearDownAxe() { if (Plugin.UseDurability && _axe != null && _axe.m_shared.m_useDurability) { _axe.m_durability = Mathf.Max(0f, _axe.m_durability - _axe.m_shared.m_useDurabilityDrain); _wearUnsaved = true; NotifyAxeWear(); if (!(_axe.m_durability > 0f) || !(Time.time < _nextDurabilitySave)) { FlushWear(); } } } private void FlushWear() { if (_wearUnsaved) { _wearUnsaved = false; _nextDurabilitySave = Time.time + 5f; if ((Object)(object)_container != (Object)null) { WoodcutterAxeSlot.NotifyChanged(_container.GetInventory()); } } } private static float DurabilityFraction(ItemData axe) { if (axe == null || !axe.m_shared.m_useDurability) { return 1f; } float maxDurability = axe.GetMaxDurability(); if (!(maxDurability > 0f)) { return 0f; } return axe.m_durability / maxDurability; } private void TryAutoRepair() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (_axe == null || !WoodcutterAxeSlot.IsBroken(_axe) || (Object)(object)_interaction == (Object)null || (Object)(object)_container == (Object)null || Time.time < _nextRepairTry) { return; } WoodcutterHirePost postInstance = _interaction.PostInstance; if ((Object)(object)postInstance == (Object)null) { return; } Vector3 val = ((Component)postInstance).transform.position - ((Component)this).transform.position; val.y = 0f; if (!(((Vector3)(ref val)).magnitude > 6f)) { _nextRepairTry = Time.time + 5f; FlushWear(); List cost; WoodcutterHirePost.RepairResult repairResult = postInstance.TryRepair(_axe, out cost); string name = _interaction.Name; switch (repairResult) { case WoodcutterHirePost.RepairResult.Repaired: WoodcutterAxeSlot.NotifyChanged(_container.GetInventory()); _lowWarningArmed = true; _brokenWarningArmed = true; _repairNotice = null; _nextSearchTime = 0f; WoodcutterNotifications.Send("notify_axe_repaired", name, WoodcutterRepair.Describe(cost)); break; case WoodcutterHirePost.RepairResult.MissingMaterials: AnnounceRepairProblem("notify_repair_missing", name, WoodcutterRepair.Describe(cost)); break; case WoodcutterHirePost.RepairResult.NotRepairable: AnnounceRepairProblem("notify_repair_impossible", name); break; case WoodcutterHirePost.RepairResult.Disabled: break; } } } private void AnnounceRepairProblem(string key, params string[] args) { string text = key + "|" + string.Join("|", args); if (!(text == _repairNotice)) { _repairNotice = text; WoodcutterNotifications.Send(key, args); } } private void NotifyAxeWear() { float value = DurabilityFraction(_axe); string text = (((Object)(object)_interaction != (Object)null) ? _interaction.Name : ""); if (WoodcutterLogic.Warn(ref _brokenWarningArmed, value, 0f, 0.15f)) { _lowWarningArmed = false; WoodcutterNotifications.Send("notify_axe_broken", text); } else if (WoodcutterLogic.Warn(ref _lowWarningArmed, value, 0.05f, 0.15f)) { int num = WoodcutterLogic.DurabilityPercent(_axe.m_durability, _axe.GetMaxDurability()); WoodcutterNotifications.Send("notify_axe_low", text, num.ToString()); } } private void TickHealth() { if (!(Time.time < _nextRegenTime)) { _nextRegenTime = Time.time + Plugin.RegenInterval; FlushWear(); SyncMaxHealth(); if (Plugin.RegenAmount > 0f && !_character.IsDead() && _character.GetHealth() < _character.GetMaxHealth()) { _character.Heal(Plugin.RegenAmount, true); } } } private void SyncMaxHealth() { _character.m_health = Plugin.MaxHealth; float num = _character.GetMaxHealthBase() * (float)_character.GetLevel(); if (!Mathf.Approximately(_character.GetMaxHealth(), num)) { _character.SetMaxHealth(num); } } private static int MinToolTierOf(MonoBehaviour target) { return ((TreeBase)(((target is TreeBase) ? target : null)?)).m_minToolTier ?? ((TreeLog)(((target is TreeLog) ? target : null)?)).m_minToolTier ?? 0; } private void FixedUpdate() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner()) { return; } RefreshAxe(); TickHealth(); if ((Object)(object)_interaction != (Object)null) { _interaction.EnsurePost(); } if ((Object)(object)_interaction == (Object)null || !_interaction.WorkEnabled) { if ((Object)(object)_interaction != (Object)null && _interaction.IsRecalled) { TickRecall(); } else { _recalling = false; _character.SetMoveDir(Vector3.zero); } UpdateClaim(null); } else { _recalling = false; TickState(); MonoBehaviour current = (MonoBehaviour)((_state == State.MovingToItem) ? ((object)_pickupTarget) : ((object)_target)); UpdateClaim(current); } } private void TickState() { switch (_state) { case State.Idle: TickIdle(); break; case State.MovingToTarget: TickMovingToTarget(); break; case State.Chopping: TickChopping(); break; case State.MovingToItem: TickMovingToItem(); break; case State.ScanningAfterFell: TickScanningAfterFell(); break; case State.ReturningToZone: TickReturningToZone(); break; case State.ReturningHome: TickReturningHome(); break; case State.Depositing: TickDepositing(); break; case State.WaitingForStorage: TickWaitingForStorage(); break; } } private void TickIdle() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) _character.SetMoveDir(Vector3.zero); if (Time.time < _nextSearchTime) { return; } _nextSearchTime = Time.time + 1f; TryAutoRepair(); bool hasUsableAxe = HasUsableAxe; int tier = (hasUsableAxe ? _axe.m_shared.m_toolTier : (-1)); if (ShouldGoDeposit()) { StartWalking(); _state = State.Depositing; return; } if ((Object)(object)_interaction != (Object)null && !_interaction.IsInZone(((Component)this).transform.position)) { StartReturningToZone(); return; } TreeLog log; float logDistSqr; ItemDrop drop; float itemDistSqr; TreeBase tree; float treeDistSqr; bool flag = FindWork(((Component)this).transform.position, 20f, hasUsableAxe, tier, includeItems: true, out log, out logDistSqr, out drop, out itemDistSqr, out tree, out treeDistSqr); bool zoneSearched = false; if (!flag && (Object)(object)_interaction != (Object)null && Time.time >= _nextZoneSearchTime) { _nextZoneSearchTime = Time.time + 5f; zoneSearched = true; if (hasUsableAxe) { flag = FindWork(_interaction.ZoneCenter, _interaction.ZoneRadius, hasUsableAxe, tier, includeItems: false, out log, out logDistSqr, out drop, out itemDistSqr, out tree, out treeDistSqr); } } if ((Object)(object)_interaction != (Object)null) { Vector3 val = _interaction.HomeSpot - ((Component)this).transform.position; val.y = 0f; if (WoodcutterLogic.ShouldGoHome(zoneSearched, flag, ((Vector3)(ref val)).magnitude, 1.5f)) { StartWalking(); _state = State.ReturningHome; return; } } bool num = (Object)(object)log != (Object)null; bool flag2 = (Object)(object)drop != (Object)null; bool flag3 = (Object)(object)tree != (Object)null; if (num && (!flag2 || logDistSqr <= itemDistSqr) && (!flag3 || logDistSqr <= treeDistSqr)) { SetTarget((MonoBehaviour)(object)log, (IDestructible)(object)log); _chainAnchor = ((Component)log).transform.position; _state = State.MovingToTarget; } else if (flag2 && (!flag3 || itemDistSqr <= treeDistSqr)) { _pickupTarget = drop; _itemChaseDeadline = float.MaxValue; StartWalking(); _state = State.MovingToItem; } else if (flag3) { SetTarget((MonoBehaviour)(object)tree, (IDestructible)(object)tree); _chainAnchor = ((Component)tree).transform.position; _state = State.MovingToTarget; } } private void TickMovingToTarget() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!IsTargetAlive() || !IsSpeciesAllowed(_target)) { AbandonTarget(blacklist: false); return; } _lastTargetPosition = ((Component)_target).transform.position; Vector3 val = TargetAimPoint() - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).magnitude <= TargetStopDistance) { _character.SetMoveDir(Vector3.zero); _nextChopTime = 0f; _state = State.Chopping; } else if (IsBlocked()) { if (IsTouchingTarget()) { _character.SetMoveDir(Vector3.zero); _nextChopTime = 0f; _state = State.Chopping; } else { AbandonTarget(blacklist: true); } } else { WalkTowards(TargetAimPoint()); } } private void WalkTowards(Vector3 goal) { //IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) _character.SetRun(false); Vector3 val = _mover.DirectionTo(((Component)this).transform.position, goal); _character.SetMoveDir(val); if (val != Vector3.zero) { _character.SetLookDir(val, 0f); } } private void TickChopping() { //IL_000e: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) if (!HasUsableAxe) { _character.SetMoveDir(Vector3.zero); AbandonTarget(blacklist: false); return; } if (!IsTargetAlive()) { _character.SetMoveDir(Vector3.zero); ClearTarget(); _chainAnchor = _lastTargetPosition; _scanUntil = Time.time + 12f; _state = State.ScanningAfterFell; return; } _lastTargetPosition = ((Component)_target).transform.position; if (MinToolTierOf(_target) > _axe.m_shared.m_toolTier || !IsSpeciesAllowed(_target)) { AbandonTarget(blacklist: false); return; } Vector3 val = TargetAimPoint(); Vector3 val2 = val - ((Component)this).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).magnitude > TargetStopDistance + 0.5f && !IsTouchingTarget()) { StartWalking(); _state = State.MovingToTarget; return; } _character.SetMoveDir(Vector3.zero); if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { _character.SetLookDir(val2, 0f); } if (!(Time.time < _nextChopTime)) { _nextChopTime = Time.time + Plugin.ChopInterval; if ((Object)(object)_zanim != (Object)null && _swingTrigger != null) { _zanim.SetTrigger(_swingTrigger); } HitData val3 = new HitData(); val3.m_damage = _axe.GetDamage(); ((DamageTypes)(ref val3.m_damage)).Modify(WoodcutterLogic.SkillDamageFactor(CurrentSkill(), Random.value)); val3.m_damage.m_chop *= Plugin.ChopDamageMultiplier; val3.m_toolTier = (short)_axe.m_shared.m_toolTier; val3.m_point = ((_targetColliders.Length != 0) ? val : (val + Vector3.up * 0.5f)); val3.m_dir = ((((Vector3)(ref val2)).sqrMagnitude > 0.0001f) ? (-((Vector3)(ref val2)).normalized) : Vector3.forward); val3.SetAttacker(_character); _targetDestructible.Damage(val3); WearDownAxe(); RaiseSkill(); } } internal bool TryGetUnsavedSkill(out int level, out float progress) { level = _skill; progress = _skillProgress; return _skillUnsaved; } private int CurrentSkill() { if (!_skillUnsaved) { ZDO zDO = _nview.GetZDO(); _skill = WoodcutterInteraction.SkillOf(zDO); _skillProgress = zDO.GetFloat("WoodcutterNPC_SkillProgress", 0f); } return _skill; } private void RaiseSkill() { CurrentSkill(); bool num = WoodcutterLogic.RaiseSkill(ref _skill, ref _skillProgress, Plugin.SkillGainRate * Game.m_skillGainRate); if (num || _skillProgress > 0f) { _skillUnsaved = true; } if (num || Time.time >= _nextSkillSave) { SaveSkill(); } } private void SaveSkill() { if (_skillUnsaved) { _skillUnsaved = false; _nextSkillSave = Time.time + 10f; FlushWear(); ZDO zDO = _nview.GetZDO(); zDO.Set("WoodcutterNPC_Skill", _skill); zDO.Set("WoodcutterNPC_SkillProgress", _skillProgress); } } private void TickMovingToItem() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pickupTarget == (Object)null || _pickupTarget.m_itemData == null) { _pickupTarget = null; _state = State.Idle; return; } Vector3 val = ((Component)_pickupTarget).transform.position - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).magnitude <= 1.5f) { _character.SetMoveDir(Vector3.zero); if (_itemChaseDeadline == float.MaxValue) { _itemChaseDeadline = Time.time + 6f; } PickupResult pickupResult = TryCollectItem(_pickupTarget); if (pickupResult != PickupResult.NotReadyYet || !(Time.time < _itemChaseDeadline)) { if (pickupResult != PickupResult.Collected) { Avoid((MonoBehaviour)(object)_pickupTarget); } _pickupTarget = null; _state = State.Idle; _nextSearchTime = 0f; } } else if (IsBlocked()) { Avoid((MonoBehaviour)(object)_pickupTarget); _pickupTarget = null; _state = State.Idle; } else { WalkTowards(((Component)_pickupTarget).transform.position); } } private void TickScanningAfterFell() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_container == (Object)null) { _state = State.Idle; return; } Collider[] array = Physics.OverlapSphere(_chainAnchor, 25f); TreeLog val = null; float num = float.MaxValue; bool flag = false; bool flag2 = false; Collider[] array2 = array; foreach (Collider val2 in array2) { TreeLog componentInParent = ((Component)val2).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { if (HasUsableAxe && componentInParent.m_minToolTier <= _axe.m_shared.m_toolTier && IsSpeciesAllowed((MonoBehaviour)(object)componentInParent) && !IsClaimedByOther((MonoBehaviour)(object)componentInParent)) { Vector3 val3 = ((Component)componentInParent).transform.position - ((Component)this).transform.position; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; val = componentInParent; } } continue; } ItemDrop componentInParent2 = ((Component)val2).GetComponentInParent(); if (!((Object)(object)componentInParent2 == (Object)null) && componentInParent2.m_itemData != null) { switch (TryCollectItem(componentInParent2)) { case PickupResult.NotReadyYet: flag = true; break; case PickupResult.InventoryFull: flag2 = true; flag = true; break; } } } if ((Object)(object)val != (Object)null) { SetTarget((MonoBehaviour)(object)val, (IDestructible)(object)val); _state = State.MovingToTarget; } else if (!flag || flag2 || Time.time > _scanUntil) { _state = State.Idle; _nextSearchTime = 0f; } } private PickupResult TryCollectItem(ItemDrop drop) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!drop.CanPickup(true)) { drop.RequestOwn(); return PickupResult.NotReadyYet; } if (WoodcutterAxeSlot.AddItem(_container.GetInventory(), drop.m_itemData.Clone())) { ZNetView val = (ZNetView)ItemDropNetViewField.GetValue(drop); if ((int)val != 0) { val.Destroy(); } return PickupResult.Collected; } return PickupResult.InventoryFull; } private void TickRecall() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0140: 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) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (!_recalling) { _recalling = true; _recallBestDistance = float.MaxValue; _recallStuckSince = Time.time; StartWalking(); ClearTarget(); _pickupTarget = null; _state = State.Idle; } Vector3 recallTarget = _interaction.RecallTarget; Vector3 val = recallTarget - ((Component)this).transform.position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= 1.5f) { Arrive(); return; } if (magnitude < _recallBestDistance - 0.3f) { _recallBestDistance = magnitude; _recallStuckSince = Time.time; } IsBlocked(); float noProgressLimit = (_mover.FollowingPath ? 30f : 8f); if (WoodcutterLogic.ShouldTeleportRecall(Time.time - _moveAnchorTime, 8f, Time.time - _recallStuckSince, noProgressLimit)) { float y = default(float); if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.FindFloor(recallTarget + Vector3.up * 2f, ref y)) { recallTarget.y = y; } Vector3 position = recallTarget + Vector3.up * 0.2f; ((Component)this).transform.position = position; Rigidbody component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { component.position = position; component.linearVelocity = Vector3.zero; } Arrive(); } else { WalkTowards(_interaction.RecallTarget); } void Arrive() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _character.SetMoveDir(Vector3.zero); _interaction.ClearRecall(); _recalling = false; } } private void TickReturningHome() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_interaction == (Object)null) { _state = State.Idle; return; } Vector3 val = _interaction.HomeSpot - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).magnitude <= 1.5f || IsBlocked()) { _character.SetMoveDir(Vector3.zero); _state = State.Idle; } else { WalkTowards(_interaction.HomeSpot); } } private void CountLoad(out int used, out int total) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null); total = 17; used = 0; if (val == null) { return; } foreach (ItemData allItem in val.GetAllItems()) { if (allItem.m_gridPos != WoodcutterAxeSlot.Position) { used++; } } } private bool IsLoadFull() { CountLoad(out var used, out var total); return WoodcutterLogic.ShouldDeposit(used, total); } private bool ShouldGoDeposit() { if ((Object)(object)_interaction != (Object)null && _interaction.HasPost && Time.time >= _nextDepositTry) { return IsLoadFull(); } return false; } private void TickDepositing() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_interaction == (Object)null || !_interaction.HasPost) { _state = State.Idle; return; } Vector3 val = _interaction.ZoneCenter - ((Component)this).transform.position; val.y = 0f; Vector3 val2 = _interaction.HomeSpot - ((Component)this).transform.position; val2.y = 0f; if (((Vector3)(ref val)).magnitude <= 3f || ((Vector3)(ref val2)).magnitude <= 1.5f) { Unload(); } else if (IsBlocked()) { if (((Vector3)(ref val)).magnitude <= 6f) { Unload(); return; } _character.SetMoveDir(Vector3.zero); _nextDepositTry = Time.time + 5f; _state = State.Idle; } else { WalkTowards(_interaction.HomeSpot); } } private void Unload() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) _character.SetMoveDir(Vector3.zero); WoodcutterHirePost postInstance = _interaction.PostInstance; Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null); if ((Object)(object)postInstance == (Object)null || val == null) { _nextDepositTry = Time.time + 5f; _state = State.Idle; return; } FlushWear(); WoodcutterHirePost.DepositResult num = postInstance.DepositFrom(val, WoodcutterAxeSlot.Position); _nextDepositTry = Time.time + 5f; if (num == WoodcutterHirePost.DepositResult.Busy) { _state = State.WaitingForStorage; } else if (IsLoadFull()) { _interaction.SetStorageFull(full: true); if (!_storageFullNotified) { _storageFullNotified = true; WoodcutterNotifications.Send("notify_storage_full", _interaction.Name); } _state = State.WaitingForStorage; } else { _interaction.SetStorageFull(full: false); _storageFullNotified = false; _nextDepositTry = 0f; _state = State.Idle; _nextSearchTime = 0f; } } private void TickWaitingForStorage() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _character.SetMoveDir(Vector3.zero); if ((Object)(object)_interaction == (Object)null || !_interaction.HasPost || !IsLoadFull()) { _interaction?.SetStorageFull(full: false); _storageFullNotified = false; _nextDepositTry = 0f; _state = State.Idle; } else if (Time.time >= _nextDepositTry) { Unload(); } } private void StartReturningToZone() { StartWalking(); _state = State.ReturningToZone; } private void TickReturningToZone() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_interaction == (Object)null) { _state = State.Idle; return; } Vector3 val = _interaction.ZoneCenter - ((Component)this).transform.position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; float num = Mathf.Max(5f, _interaction.ZoneRadius - 10f); if (magnitude <= num) { _character.SetMoveDir(Vector3.zero); _state = State.Idle; _nextSearchTime = 0f; } else if (IsBlocked()) { _character.SetMoveDir(Vector3.zero); _state = State.Idle; _nextSearchTime = Time.time + 5f; } else { WalkTowards(_interaction.ZoneCenter); } } private bool FindWork(Vector3 origin, float radius, bool canChop, int tier, bool includeItems, out TreeLog log, out float logDistSqr, out ItemDrop drop, out float itemDistSqr, out TreeBase tree, out float treeDistSqr) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) PruneAvoidList(); log = null; drop = null; tree = null; logDistSqr = (itemDistSqr = (treeDistSqr = float.MaxValue)); Collider[] array = Physics.OverlapSphere(origin, radius); foreach (Collider val in array) { if (canChop) { TreeLog componentInParent = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { if (componentInParent.m_minToolTier <= tier && IsSpeciesAllowed((MonoBehaviour)(object)componentInParent)) { Consider(componentInParent, ref log, ref logDistSqr); } continue; } TreeBase componentInParent2 = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null) { if (componentInParent2.m_minToolTier <= tier && IsSpeciesAllowed((MonoBehaviour)(object)componentInParent2)) { Consider(componentInParent2, ref tree, ref treeDistSqr); } continue; } } if (includeItems) { ItemDrop componentInParent3 = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null && componentInParent3.m_itemData != null) { Consider(componentInParent3, ref drop, ref itemDistSqr); } } } if (!((Object)(object)log != (Object)null) && !((Object)(object)drop != (Object)null)) { return (Object)(object)tree != (Object)null; } return true; } private void Consider(T candidate, ref T nearest, ref float nearestDistanceSqr) where T : MonoBehaviour { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (((Component)(object)candidate).gameObject.activeInHierarchy && !IsAvoided((MonoBehaviour)(object)candidate) && !IsClaimedByOther((MonoBehaviour)(object)candidate) && (!((Object)(object)_interaction != (Object)null) || _interaction.IsInZone(((Component)(object)candidate).transform.position)) && !IsInWater(((Component)(object)candidate).transform.position)) { Vector3 val = ((Component)(object)candidate).transform.position - ((Component)this).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < nearestDistanceSqr) { nearestDistanceSqr = sqrMagnitude; nearest = candidate; } } } private bool IsSpeciesAllowed(MonoBehaviour treeOrLog) { if (!((Object)(object)_interaction == (Object)null)) { return _interaction.IsSpeciesAllowed(treeOrLog); } return true; } private static bool IsInWater(Vector3 position) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance != (Object)null) { return instance.GetGroundHeight(position) < instance.m_waterLevel - 0.3f; } return false; } private bool IsAvoided(MonoBehaviour candidate) { if (_avoidUntil.TryGetValue(candidate, out var value)) { return Time.time < value; } return false; } private void Avoid(MonoBehaviour candidate) { if ((Object)(object)candidate != (Object)null) { _avoidUntil[candidate] = Time.time + 45f; } } private void PruneAvoidList() { if (_avoidUntil.Count == 0) { return; } List list = null; foreach (KeyValuePair item in _avoidUntil) { if ((Object)(object)item.Key == (Object)null || Time.time >= item.Value) { (list ?? (list = new List())).Add(item.Key); } } if (list == null) { return; } foreach (MonoBehaviour item2 in list) { _avoidUntil.Remove(item2); } } private void UpdateClaim(MonoBehaviour current) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) ZDOID val = ClaimIdOf(current); if (!_claimWritten || !(val == _claimedId)) { _claimWritten = true; _claimedId = val; FlushWear(); _nview.GetZDO().Set("WoodcutterNPC_Claim", val); } } private static ZDOID ClaimIdOf(MonoBehaviour target) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return ZDOID.None; } ZNetView componentInParent = ((Component)target).GetComponentInParent(); return (((Object)(object)componentInParent != (Object)null) ? componentInParent.GetZDO() : null)?.m_uid ?? ZDOID.None; } private bool IsClaimedByOther(MonoBehaviour candidate) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if (Loaded.Count < 2) { return false; } ZDOID val = ClaimIdOf(candidate); if (val == ZDOID.None) { return false; } foreach (WoodcutterAI item in Loaded) { if (!((Object)(object)item == (Object)(object)this) && !((Object)(object)item == (Object)null) && !((Object)(object)item._nview == (Object)null) && item._nview.IsValid() && item._nview.GetZDO().GetZDOID("WoodcutterNPC_Claim") == val) { return true; } } return false; } private void StartWalking() { ResetBlocked(); _mover.Reset(); } private void ResetBlocked() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) _moveAnchor = ((Component)this).transform.position; _moveAnchorTime = Time.time; } private bool IsBlocked() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //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_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)this).transform.position - _moveAnchor; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.25f) { ResetBlocked(); return false; } return Time.time - _moveAnchorTime > 4f; } private bool IsTouchingTarget() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0029: Unknown result type (might be due to invalid IL or missing references) MonoBehaviour target = _target; TreeLog val = (TreeLog)(object)((target is TreeLog) ? target : null); if (val != null) { Collider[] array = Physics.OverlapSphere(((Component)this).transform.position + Vector3.up * 0.8f, 1.1f); for (int i = 0; i < array.Length; i++) { if ((Object)(object)((Component)array[i]).GetComponentInParent() == (Object)(object)val) { return true; } } return false; } Vector3 val2 = ((Component)_target).transform.position - ((Component)this).transform.position; val2.y = 0f; return ((Vector3)(ref val2)).magnitude <= 3.5f; } private Vector3 TargetAimPoint() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)this).transform.position; Vector3 result = ((Component)_target).transform.position; float num = float.MaxValue; Collider[] targetColliders = _targetColliders; foreach (Collider val in targetColliders) { if (!((Object)(object)val == (Object)null) && val.enabled) { Vector3 val2 = val.ClosestPoint(position); Vector3 val3 = val2 - position; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < num) { num = ((Vector3)(ref val3)).sqrMagnitude; result = val2; } } } return result; } private static Collider[] SolidCollidersOf(MonoBehaviour target) { Collider[] componentsInChildren = ((Component)target).GetComponentsInChildren(); List list = new List(componentsInChildren.Length); Collider[] array = componentsInChildren; foreach (Collider val in array) { if (!val.isTrigger) { MeshCollider val2 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if (val2 == null || val2.convex) { list.Add(val); } } } return list.ToArray(); } private void SetTarget(MonoBehaviour target, IDestructible destructible) { _target = target; _targetDestructible = destructible; _targetColliders = (Collider[])((target is TreeLog) ? ((Array)SolidCollidersOf(target)) : ((Array)new Collider[0])); StartWalking(); } private void ClearTarget() { _target = null; _targetDestructible = null; _targetColliders = (Collider[])(object)new Collider[0]; } private void AbandonTarget(bool blacklist) { if (blacklist) { Avoid(_target); } ClearTarget(); _state = State.Idle; } private bool IsTargetAlive() { return (Object)(object)_target != (Object)null; } } internal static class WoodcutterAxeSlot { internal enum Layout { Woodcutter, Post } internal static readonly Vector2i Position = new Vector2i(0, 0); private const string GhostIconItem = "AxeStone"; private static readonly MethodInfo ChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); private static readonly Dictionary Managed = new Dictionary(); private static Sprite _ghostIcon; internal static Sprite GhostIcon { get { if ((Object)(object)_ghostIcon != (Object)null) { return _ghostIcon; } GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("AxeStone") : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)val2 != (Object)null && val2.m_itemData != null) { _ghostIcon = val2.m_itemData.GetIcon(); } return _ghostIcon; } } internal static void NotifyChanged(Inventory inventory) { if (inventory != null && !(ChangedMethod == null)) { ChangedMethod.Invoke(inventory, new object[2] { false, false }); } } internal static void Register(Inventory inventory, Layout layout = Layout.Woodcutter) { if (inventory != null) { Managed[inventory] = layout; } } internal static void Unregister(Inventory inventory) { if (inventory != null) { Managed.Remove(inventory); } } internal static bool IsManaged(Inventory inventory) { if (inventory != null) { return Managed.ContainsKey(inventory); } return false; } internal static bool IsPost(Inventory inventory) { if (inventory != null && Managed.TryGetValue(inventory, out var value)) { return value == Layout.Post; } return false; } internal static bool IsAxeCell(Inventory inventory, int x, int y) { if (inventory == null || !Managed.TryGetValue(inventory, out var value)) { return false; } if (value != Layout.Post) { if (x == Position.x) { return y == Position.y; } return false; } return y == 0; } internal static bool IsAxe(ItemData item) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return false; } ItemType itemType = item.m_shared.m_itemType; if ((int)itemType <= 14) { if ((int)itemType != 3 && (int)itemType != 14) { goto IL_0033; } } else if ((int)itemType != 19 && (int)itemType != 22) { goto IL_0033; } return item.GetDamage().m_chop > 0f; IL_0033: return false; } internal static ItemData GetAxe(Inventory inventory) { if (inventory == null) { return null; } ItemData itemAt = inventory.GetItemAt(Position.x, Position.y); if (!IsAxe(itemAt)) { return null; } return itemAt; } internal static bool IsBroken(ItemData axe) { if (axe != null && axe.m_shared.m_useDurability) { return axe.m_durability <= 0f; } return false; } internal static bool AddItem(Inventory inventory, ItemData item) { //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || item == null || item.m_shared == null) { return false; } int num = Mathf.Max(1, item.m_shared.m_maxStackSize); int num2 = CountFreeSlots(inventory, axeCells: false) * num; if (num > 1) { foreach (ItemData allItem in inventory.GetAllItems()) { if (CanStackOnto(inventory, allItem, item)) { num2 += num - allItem.m_stack; } } } if (num2 < item.m_stack) { return false; } if (num > 1) { foreach (ItemData allItem2 in inventory.GetAllItems()) { if (CanStackOnto(inventory, allItem2, item)) { int num3 = Mathf.Min(num - allItem2.m_stack, item.m_stack); allItem2.m_stack += num3; item.m_stack -= num3; if (item.m_stack <= 0) { NotifyChanged(inventory); return true; } } } } Vector2i val = FindFreeSlot(inventory, axeCells: false); if (val.x < 0) { NotifyChanged(inventory); return false; } return inventory.AddItem(item, val); } internal static bool Rearrange(Inventory inventory, ItemData item) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || item == null || !inventory.ContainsItem(item)) { return false; } bool num = IsAxeCell(inventory, item.m_gridPos.x, item.m_gridPos.y); bool flag = IsAxe(item); if (num == flag) { return false; } Vector2i val = FindFreeSlot(inventory, flag); if (val.x < 0) { return false; } item.m_gridPos = val; NotifyChanged(inventory); return true; } internal static void EnforceLayout(Inventory inventory) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_005c: Unknown result type (might be due to invalid IL or missing references) if (!IsManaged(inventory)) { return; } bool flag = false; foreach (ItemData allItem in inventory.GetAllItems()) { if (!IsAxe(allItem) && IsAxeCell(inventory, allItem.m_gridPos.x, allItem.m_gridPos.y)) { Vector2i val = FindFreeSlot(inventory, axeCells: false); if (val.x < 0) { break; } allItem.m_gridPos = val; flag = true; } } if (flag) { NotifyChanged(inventory); } } internal static int Deposit(Inventory inventory, ItemData item) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || item == null || item.m_shared == null || item.m_stack <= 0) { return 0; } if (IsAxe(item)) { Vector2i val = FindFreeSlot(inventory, axeCells: true); if (val.x >= 0) { ItemData val2 = item.Clone(); if (!inventory.AddItem(val2, val)) { return 0; } return item.m_stack; } } int i = 0; int num = Mathf.Max(1, item.m_shared.m_maxStackSize); if (num > 1) { foreach (ItemData allItem in inventory.GetAllItems()) { if (i >= item.m_stack) { break; } if (CanStackOnto(inventory, allItem, item)) { int num2 = Mathf.Min(num - allItem.m_stack, item.m_stack - i); allItem.m_stack += num2; i += num2; } } } ItemData val4; for (; i < item.m_stack; i += val4.m_stack) { Vector2i val3 = FindFreeSlot(inventory, axeCells: false); if (val3.x < 0) { break; } val4 = item.Clone(); val4.m_stack = Mathf.Min(num, item.m_stack - i); if (!inventory.AddItem(val4, val3)) { break; } } NotifyChanged(inventory); return i; } private static bool CanStackOnto(Inventory inventory, ItemData existing, ItemData item) { if (!IsAxeCell(inventory, existing.m_gridPos.x, existing.m_gridPos.y) && existing.m_stack < existing.m_shared.m_maxStackSize && existing.m_shared.m_name == item.m_shared.m_name && existing.m_quality == item.m_quality && existing.m_variant == item.m_variant) { return existing.m_worldLevel == item.m_worldLevel; } return false; } internal static int CountFreeSlots(Inventory inventory, bool axeCells) { int num = 0; for (int i = 0; i < inventory.GetHeight(); i++) { for (int j = 0; j < inventory.GetWidth(); j++) { if (IsAxeCell(inventory, j, i) == axeCells && inventory.GetItemAt(j, i) == null) { num++; } } } return num; } private static Vector2i FindFreeSlot(Inventory inventory, bool axeCells) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < inventory.GetHeight(); i++) { for (int j = 0; j < inventory.GetWidth(); j++) { if (IsAxeCell(inventory, j, i) == axeCells && inventory.GetItemAt(j, i) == null) { return new Vector2i(j, i); } } } return new Vector2i(-1, -1); } } public class WoodcutterHirePost : MonoBehaviour { internal enum DepositResult { Done, Busy } internal enum RepairResult { Repaired, Disabled, NotRepairable, MissingMaterials, Busy } internal const int StorageWidth = 5; internal const int StorageHeight = 5; private const float LayoutCheckInterval = 2f; private const string RadiusZdoKey = "WoodcutterNPC_PostRadius"; private const string SetRadiusRpc = "WoodcutterNPC_SetPostRadius"; private const string AutoRepairZdoKey = "WoodcutterNPC_AutoRepair"; private const string SetAutoRepairRpc = "WoodcutterNPC_SetAutoRepair"; private const string CoinsItemName = "$item_coins"; private const float SpawnDistance = 1.8f; private static readonly List Loaded = new List(); private ZNetView _nview; private Inventory _registered; private float _nextLayoutCheck; internal static string DisplayName => WoodcutterTexts.T("post_name"); internal Container Storage { get; private set; } internal ZDOID Id { get { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_nview != (Object)null) || !_nview.IsValid()) { return ZDOID.None; } return _nview.GetZDO().m_uid; } } internal float Radius { get { if (!((Object)(object)_nview != (Object)null) || !_nview.IsValid()) { return Plugin.DefaultZoneRadius; } return RadiusOf(_nview.GetZDO()); } } internal bool AutoRepair { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO().GetBool("WoodcutterNPC_AutoRepair", false); } return false; } } internal bool IsStorageOpen { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1; } return false; } } internal static float RadiusOf(ZDO postZdo) { return postZdo.GetFloat("WoodcutterNPC_PostRadius", Plugin.DefaultZoneRadius); } internal void SetRadius(float radius) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.InvokeRPC("WoodcutterNPC_SetPostRadius", new object[1] { WoodcutterLogic.SnapRadius(radius) }); } } internal void SetAutoRepair(bool on) { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid()) { _nview.InvokeRPC("WoodcutterNPC_SetAutoRepair", new object[1] { on }); } } private void Awake() { _nview = ((Component)this).GetComponent(); Storage = ((Component)this).GetComponent(); if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { _nview.Register("WoodcutterNPC_SetPostRadius", (Action)RPC_SetRadius); _nview.Register("WoodcutterNPC_SetAutoRepair", (Action)RPC_SetAutoRepair); } } private void RPC_SetAutoRepair(long sender, bool on) { if (_nview.IsOwner()) { _nview.GetZDO().Set("WoodcutterNPC_AutoRepair", on); } } private void RPC_SetRadius(long sender, float radius) { if (_nview.IsOwner()) { _nview.GetZDO().Set("WoodcutterNPC_PostRadius", WoodcutterLogic.SnapRadius(radius)); } } private void OnEnable() { Loaded.Add(this); } private void OnDisable() { Loaded.Remove(this); } private void OnDestroy() { WoodcutterAxeSlot.Unregister(_registered); } private void Update() { Inventory val = (((Object)(object)Storage != (Object)null) ? Storage.GetInventory() : null); if (val != null && val != _registered) { WoodcutterAxeSlot.Unregister(_registered); WoodcutterAxeSlot.Register(val, WoodcutterAxeSlot.Layout.Post); _registered = val; } if (val != null && !(Time.time < _nextLayoutCheck)) { _nextLayoutCheck = Time.time + 2f; if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner()) { WoodcutterAxeSlot.EnforceLayout(val); } } } internal DepositResult DepositFrom(Inventory from, Vector2i? keep) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Inventory val = (((Object)(object)Storage != (Object)null) ? Storage.GetInventory() : null); if (val == null || from == null) { return DepositResult.Done; } if (!_nview.IsOwner()) { if (IsStorageOpen) { return DepositResult.Busy; } _nview.ClaimOwnership(); } bool flag = false; foreach (ItemData item in new List(from.GetAllItems())) { if (keep.HasValue && item.m_gridPos == keep.Value) { continue; } int num = WoodcutterAxeSlot.Deposit(val, item); if (num > 0) { flag = true; if (num >= item.m_stack) { from.RemoveItem(item); } else { item.m_stack -= num; } } } if (flag) { WoodcutterAxeSlot.NotifyChanged(from); } return DepositResult.Done; } internal RepairResult TryRepair(ItemData axe, out List cost) { cost = null; if (!AutoRepair) { return RepairResult.Disabled; } cost = WoodcutterRepair.CostOf(axe); if (cost == null) { return RepairResult.NotRepairable; } Inventory storage = (((Object)(object)Storage != (Object)null) ? Storage.GetInventory() : null); if (!WoodcutterRepair.CanPay(storage, cost)) { return RepairResult.MissingMaterials; } if (!_nview.IsOwner()) { if (IsStorageOpen) { return RepairResult.Busy; } _nview.ClaimOwnership(); } WoodcutterRepair.Pay(storage, cost); axe.m_durability = axe.GetMaxDurability(); return RepairResult.Repaired; } internal void CountStorage(out int used, out int total, out int axesUsed, out int axeCells) { axeCells = 5; total = 20; Inventory val = (((Object)(object)Storage != (Object)null) ? Storage.GetInventory() : null); if (val == null) { used = 0; axesUsed = 0; } else { axesUsed = axeCells - WoodcutterAxeSlot.CountFreeSlots(val, axeCells: true); used = total - WoodcutterAxeSlot.CountFreeSlots(val, axeCells: false); } } internal static WoodcutterHirePost Nearest(Vector3 position, float maxDistance) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) WoodcutterHirePost result = null; float num = maxDistance * maxDistance; foreach (WoodcutterHirePost item in Loaded) { if (!((Object)(object)item == (Object)null)) { Vector3 val = ((Component)item).transform.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= num) { num = sqrMagnitude; result = item; } } } return result; } internal string BuildHoverText() { string text = WoodcutterTexts.T("post_hover_title", DisplayName, WoodcutterProgress.Level) + "\n[$KEY_Use] " + WoodcutterTexts.T("post_hover_storage") + "\n[$KEY_AltPlace + $KEY_Use] " + WoodcutterTexts.T("post_hover_manage"); return Localization.instance.Localize(text); } internal static int CoinsOf(Player player) { if (!((Object)(object)player != (Object)null)) { return 0; } return ((Humanoid)player).GetInventory().CountItems("$item_coins", -1, true); } internal string Hire(Player player) { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) int count = WoodcutterInteraction.FindAll().Count; int level = WoodcutterProgress.Level; int num = WoodcutterProgress.HirePrice(count); if (num < 0) { if (level >= 3) { return WoodcutterTexts.T("hire_max", count, WoodcutterLogic.WoodcuttersWord(count)); } return WoodcutterTexts.T("hire_limit", level, count, WoodcutterLogic.WoodcuttersWord(count)); } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory.CountItems("$item_coins", -1, true) < num) { return WoodcutterTexts.T("hire_no_coins", num); } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("WoodcutterNPC") : null); if ((Object)(object)val == (Object)null) { return WoodcutterTexts.T("hire_no_prefab", "WoodcutterNPC"); } if (num > 0) { inventory.RemoveItem("$item_coins", num, -1, true); } Vector3 val2 = SpawnPositionFor(player); Quaternion val3 = Quaternion.LookRotation(Flat(((Component)player).transform.position - val2)); WoodcutterInteraction.InitializeHired(Object.Instantiate(val, val2, val3), Id); if (count == 2) { WoodcutterProgress.MarkThirdHired(); } return WoodcutterTexts.T("hire_done"); } private Vector3 SpawnPositionFor(Player player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Flat(((Component)player).transform.position - ((Component)this).transform.position); Vector3 val2 = Vector3.Cross(Vector3.up, val); Vector3 position = ((Component)this).transform.position; Vector3 val3 = val + val2; Vector3 val4 = position + ((Vector3)(ref val3)).normalized * 1.8f; float y = default(float); if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.FindFloor(val4 + Vector3.up * 2f, ref y)) { val4.y = y; } return val4 + Vector3.up * 0.2f; } private static Vector3 Flat(Vector3 v) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) v.y = 0f; if (!(((Vector3)(ref v)).sqrMagnitude > 0.0001f)) { return Vector3.forward; } return ((Vector3)(ref v)).normalized; } } public class WoodcutterInteraction : MonoBehaviour { internal const string WorkEnabledZdoKey = "WoodcutterNPC_WorkEnabled"; private const string SetWorkEnabledRpc = "WoodcutterNPC_SetWorkEnabled"; private const string HasZoneZdoKey = "WoodcutterNPC_HasZone"; internal const string ZoneCenterZdoKey = "WoodcutterNPC_ZoneCenter"; internal const string ZoneRadiusZdoKey = "WoodcutterNPC_ZoneRadius"; private const string SetPostRpc = "WoodcutterNPC_SetPost"; private const string TreeMaskZdoKey = "WoodcutterNPC_TreeMask"; private const string SetTreeMaskRpc = "WoodcutterNPC_SetTreeMask"; internal const string RecallZdoKey = "WoodcutterNPC_Recall"; private const string RecallTargetZdoKey = "WoodcutterNPC_RecallTarget"; private const string RecallRpc = "WoodcutterNPC_Recall"; internal const string PostZdoKey = "WoodcutterNPC_Post"; internal const string StorageFullZdoKey = "WoodcutterNPC_StorageFull"; internal const string SkillZdoKey = "WoodcutterNPC_Skill"; internal const string SkillProgressZdoKey = "WoodcutterNPC_SkillProgress"; private const string DismissRpc = "WoodcutterNPC_Dismiss"; private const float RecallSpread = 2.5f; private const float DismissPostSearchRadius = 200f; private const float AutoBindPostRadius = 300f; private const float PostCheckInterval = 5f; internal const float MinZoneRadius = 10f; internal const float MaxZoneRadius = 300f; public Container Inventory; private ZNetView _nview; private float _nextPostCheck; public Vector3 ZoneCenter { get { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!IsValid) { return ((Component)this).transform.position; } ZoneOf(_nview.GetZDO(), out var center, out var _); return center; } } public float ZoneRadius { get { if (!IsValid) { return Plugin.DefaultZoneRadius; } ZoneOf(_nview.GetZDO(), out var _, out var radius); return radius; } } internal bool HasPost { get { if (IsValid) { return PostZdoOf(_nview.GetZDO()) != null; } return false; } } internal WoodcutterHirePost PostInstance { get { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!IsValid || (Object)(object)ZNetScene.instance == (Object)null) { return null; } ZDOID zDOID = _nview.GetZDO().GetZDOID("WoodcutterNPC_Post"); GameObject val = ((zDOID != ZDOID.None) ? ZNetScene.instance.FindInstance(zDOID) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent(); } } internal Vector3 HomeSpot { get { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZDO val = (IsValid ? PostZdoOf(_nview.GetZDO()) : null); if (val == null) { return ZoneCenter; } return HomeSpotFor(_nview.GetZDO().m_uid, val.GetPosition()); } } private bool IsValid { get { if ((Object)(object)_nview != (Object)null) { return _nview.IsValid(); } return false; } } internal string Name { get { if (!IsValid) { return WoodcutterTexts.T("npc_name"); } return NameOf(_nview.GetZDO()); } } public int TreeMask { get { if (!IsValid) { return -1; } return _nview.GetZDO().GetInt("WoodcutterNPC_TreeMask", -1); } set { if (IsValid) { _nview.InvokeRPC("WoodcutterNPC_SetTreeMask", new object[1] { value }); } } } public bool WorkEnabled { get { if (!((Object)(object)_nview == (Object)null) && _nview.IsValid()) { return _nview.GetZDO().GetBool("WoodcutterNPC_WorkEnabled", true); } return true; } set { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { _nview.InvokeRPC("WoodcutterNPC_SetWorkEnabled", new object[1] { value }); } } } internal bool IsRecalled { get { if (IsValid) { return _nview.GetZDO().GetBool("WoodcutterNPC_Recall", false); } return false; } } internal Vector3 RecallTarget { get { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!IsValid) { return ((Component)this).transform.position; } return _nview.GetZDO().GetVec3("WoodcutterNPC_RecallTarget", ((Component)this).transform.position); } } internal void SetStorageFull(bool full) { if (IsValid && _nview.IsOwner() && _nview.GetZDO().GetBool("WoodcutterNPC_StorageFull", false) != full) { _nview.GetZDO().Set("WoodcutterNPC_StorageFull", full); } } internal static void ZoneOf(ZDO npc, out Vector3 center, out float radius) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_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) ZDO val = PostZdoOf(npc); if (val != null) { center = val.GetPosition(); radius = WoodcutterHirePost.RadiusOf(val); } else { center = npc.GetVec3("WoodcutterNPC_ZoneCenter", npc.GetPosition()); radius = npc.GetFloat("WoodcutterNPC_ZoneRadius", Plugin.DefaultZoneRadius); } } internal static int SkillOf(ZDO npc) { return npc.GetInt("WoodcutterNPC_Skill", Plugin.SkillStartLevel); } internal static ZDO PostZdoOf(ZDO npc) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID = npc.GetZDOID("WoodcutterNPC_Post"); if (zDOID == ZDOID.None || ZDOMan.instance == null) { return null; } ZDO zDO = ZDOMan.instance.GetZDO(zDOID); if (zDO == null || !zDO.IsValid()) { return null; } return zDO; } internal static string NameOf(ZDO zdo) { return WoodcutterLogic.NameFor(((ZDOID)(ref zdo.m_uid)).UserID, ((ZDOID)(ref zdo.m_uid)).ID); } public bool IsSpeciesAllowed(MonoBehaviour treeOrLog) { return TreeSpecies.IsAllowed(treeOrLog, TreeMask); } public bool IsInZone(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = position - ZoneCenter; val.y = 0f; float zoneRadius = ZoneRadius; return ((Vector3)(ref val)).sqrMagnitude <= zoneRadius * zoneRadius; } internal void EnsurePost() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!IsValid || !_nview.IsOwner() || Time.time < _nextPostCheck) { return; } _nextPostCheck = Time.time + 5f; ZDO zDO = _nview.GetZDO(); if (PostZdoOf(zDO) == null) { WoodcutterHirePost woodcutterHirePost = WoodcutterHirePost.Nearest(((Component)this).transform.position, 300f); if ((Object)(object)woodcutterHirePost != (Object)null && woodcutterHirePost.Id != ZDOID.None) { zDO.Set("WoodcutterNPC_Post", woodcutterHirePost.Id); } else if (!zDO.GetBool("WoodcutterNPC_HasZone", false)) { WriteZone(zDO, ((Component)this).transform.position, Plugin.DefaultZoneRadius); } } } internal static int BindAllTo(ZDOID post) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return ForEachWoodcutter(delegate(ZDO zdo, bool owned) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (owned) { zdo.Set("WoodcutterNPC_Post", post); } else { ZRoutedRpc.instance.InvokeRoutedRPC(zdo.GetOwner(), zdo.m_uid, "WoodcutterNPC_SetPost", new object[1] { post }); } }); } internal static int RecallAllTo(Vector3 postPosition) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return ForEachWoodcutter(delegate(ZDO zdo, bool owned) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_0083: Unknown result type (might be due to invalid IL or missing references) Vector3 val = HomeSpotFor(zdo.m_uid, postPosition); if (!owned) { ZRoutedRpc.instance.InvokeRoutedRPC(zdo.GetOwner(), zdo.m_uid, "WoodcutterNPC_Recall", new object[1] { val }); } else { zdo.Set("WoodcutterNPC_WorkEnabled", false); if ((Object)(object)ZNetScene.instance != (Object)null && (Object)(object)ZNetScene.instance.FindInstance(zdo.m_uid) != (Object)null) { zdo.Set("WoodcutterNPC_Recall", true); zdo.Set("WoodcutterNPC_RecallTarget", val); } else { zdo.Set("WoodcutterNPC_Recall", false); zdo.SetPosition(val); } } }); } internal static int StartAll() { return ForEachWoodcutter(delegate(ZDO zdo, bool owned) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (owned) { zdo.Set("WoodcutterNPC_WorkEnabled", true); zdo.Set("WoodcutterNPC_Recall", false); } else { ZRoutedRpc.instance.InvokeRoutedRPC(zdo.GetOwner(), zdo.m_uid, "WoodcutterNPC_SetWorkEnabled", new object[1] { true }); } }); } internal static void SetWorkEnabled(ZDO zdo, bool enabled) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || !zdo.IsValid()) { return; } if (!zdo.IsOwner() && !zdo.HasOwner()) { zdo.SetOwner(ZDOMan.GetSessionID()); } if (zdo.IsOwner()) { zdo.Set("WoodcutterNPC_WorkEnabled", enabled); if (enabled) { zdo.Set("WoodcutterNPC_Recall", false); } } else { ZRoutedRpc.instance.InvokeRoutedRPC(zdo.GetOwner(), zdo.m_uid, "WoodcutterNPC_SetWorkEnabled", new object[1] { enabled }); } } internal static List FindAll() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (ZDOMan.instance == null) { return list; } List list2 = new List(); int num = 0; while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("WoodcutterNPC", list2, ref num)) { } HashSet hashSet = new HashSet(); foreach (ZDO item in list2) { if (item.IsValid() && hashSet.Add(item.m_uid)) { list.Add(item); } } return list; } private static int ForEachWoodcutter(Action apply) { List list = FindAll(); foreach (ZDO item in list) { if (!item.IsOwner() && !item.HasOwner()) { item.SetOwner(ZDOMan.GetSessionID()); } apply(item, item.IsOwner()); } return list.Count; } internal static Vector3 HomeSpotFor(ZDOID id, Vector3 postPosition) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) float num = WoodcutterLogic.HomeAngleDegrees(((ZDOID)(ref id)).ID) * ((float)Math.PI / 180f); return postPosition + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 2.5f; } internal static void InitializeHired(GameObject npc, ZDOID post) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) ZNetView component = npc.GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { ZDO zDO = component.GetZDO(); zDO.Set("WoodcutterNPC_WorkEnabled", false); zDO.Set("WoodcutterNPC_Post", post); } } private static void WriteZone(ZDO zdo, Vector3 center, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) zdo.Set("WoodcutterNPC_ZoneCenter", center); zdo.Set("WoodcutterNPC_ZoneRadius", radius); zdo.Set("WoodcutterNPC_HasZone", true); } private void RPC_SetPost(long sender, ZDOID post) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (_nview.IsOwner()) { _nview.GetZDO().Set("WoodcutterNPC_Post", post); } } internal void ClearRecall() { if (IsValid && _nview.IsOwner()) { _nview.GetZDO().Set("WoodcutterNPC_Recall", false); } } internal void Dismiss() { if (IsValid) { _nview.InvokeRPC("WoodcutterNPC_Dismiss", Array.Empty()); } } private void Awake() { _nview = ((Component)this).GetComponent(); if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { _nview.Register("WoodcutterNPC_SetWorkEnabled", (Action)RPC_SetWorkEnabled); _nview.Register("WoodcutterNPC_SetPost", (Action)RPC_SetPost); _nview.Register("WoodcutterNPC_SetTreeMask", (Action)RPC_SetTreeMask); _nview.Register("WoodcutterNPC_Recall", (Action)RPC_Recall); _nview.Register("WoodcutterNPC_Dismiss", (Action)RPC_Dismiss); } EnsureRegistered(); } private void RPC_SetTreeMask(long sender, int mask) { if (_nview.IsOwner()) { _nview.GetZDO().Set("WoodcutterNPC_TreeMask", mask); } } private void RPC_SetWorkEnabled(long sender, bool enabled) { if (_nview.IsOwner()) { _nview.GetZDO().Set("WoodcutterNPC_WorkEnabled", enabled); if (enabled) { _nview.GetZDO().Set("WoodcutterNPC_Recall", false); } } } private void RPC_Recall(long sender, Vector3 target) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (_nview.IsOwner()) { ZDO zDO = _nview.GetZDO(); zDO.Set("WoodcutterNPC_WorkEnabled", false); zDO.Set("WoodcutterNPC_Recall", true); zDO.Set("WoodcutterNPC_RecallTarget", target); } } private void RPC_Dismiss(long sender) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (!_nview.IsOwner()) { return; } WoodcutterHirePost woodcutterHirePost = FindPostForDismiss(); Inventory val = (((Object)(object)Inventory != (Object)null) ? Inventory.GetInventory() : null); Vector3 val2 = (((Object)(object)woodcutterHirePost != (Object)null) ? ((Component)woodcutterHirePost).transform.position : ((Component)this).transform.position); if (val != null) { if ((Object)(object)woodcutterHirePost != (Object)null) { woodcutterHirePost.DepositFrom(val, null); } foreach (ItemData item in new List(val.GetAllItems())) { Vector3 val3 = val2 + Vector3.up + Random.insideUnitSphere * 0.5f; ItemDrop.DropItem(item.Clone(), 0, val3, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); } val.RemoveAll(); } _nview.Destroy(); } private WoodcutterHirePost FindPostForDismiss() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0017: 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) //IL_0035: Unknown result type (might be due to invalid IL or missing references) ZDOID zDOID = _nview.GetZDO().GetZDOID("WoodcutterNPC_Post"); if (zDOID != ZDOID.None && (Object)(object)ZNetScene.instance != (Object)null) { GameObject val = ZNetScene.instance.FindInstance(zDOID); WoodcutterHirePost woodcutterHirePost = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)woodcutterHirePost != (Object)null) { return woodcutterHirePost; } } return WoodcutterHirePost.Nearest(((Component)this).transform.position, 200f); } private void Start() { EnsureRegistered(); } private void EnsureRegistered() { if ((Object)(object)Inventory != (Object)null) { WoodcutterAxeSlot.Register(Inventory.GetInventory()); } } private void OnDestroy() { if ((Object)(object)Inventory != (Object)null) { WoodcutterAxeSlot.Unregister(Inventory.GetInventory()); } } public string BuildHoverText() { string text = WoodcutterTexts.T(WorkEnabled ? "state_working" : "state_stopped"); string text2 = WoodcutterTexts.T("npc_hover_title", Name, text) + "\n" + BuildAxeLine(withQuality: false) + "\n" + BuildSkillLine() + "\n" + (HasPost ? (WoodcutterTexts.T("npc_zone_post", Mathf.RoundToInt(ZoneRadius)) + "\n") : (WoodcutterTexts.T("npc_zone_nopost", Mathf.RoundToInt(ZoneRadius)) + "\n")) + "[$KEY_Use] " + WoodcutterTexts.T("npc_hover_inventory") + "\n[$KEY_AltPlace + $KEY_Use] " + WoodcutterTexts.T("npc_hover_settings"); return Localization.instance.Localize(text2); } internal string BuildRepairLine() { ItemData axe = WoodcutterAxeSlot.GetAxe(((Object)(object)Inventory != (Object)null) ? Inventory.GetInventory() : null); if (axe == null || !axe.m_shared.m_useDurability) { return " "; } List list = WoodcutterRepair.CostOf(axe); if (list != null) { return WoodcutterTexts.T("repair_cost", WoodcutterRepair.Describe(list)); } return WoodcutterTexts.T("repair_none"); } internal string BuildSkillLine() { WoodcutterAI component = ((Component)this).GetComponent(); if ((Object)(object)component == (Object)null || !component.TryGetUnsavedSkill(out var level, out var progress)) { if (!IsValid) { return ""; } ZDO zDO = _nview.GetZDO(); level = SkillOf(zDO); progress = zDO.GetFloat("WoodcutterNPC_SkillProgress", 0f); } if (level < 100) { return WoodcutterTexts.T("npc_skill", level, WoodcutterLogic.SkillProgressPercent(level, progress), level + 1); } return WoodcutterTexts.T("npc_skill_max", level); } internal string BuildAxeLine(bool withQuality = true) { ItemData axe = WoodcutterAxeSlot.GetAxe(((Object)(object)Inventory != (Object)null) ? Inventory.GetInventory() : null); if (axe == null) { return WoodcutterTexts.T("axe_none"); } string text = axe.m_shared.m_name; if (withQuality && axe.m_quality > 1) { text += $" ({axe.m_quality})"; } if (WoodcutterAxeSlot.IsBroken(axe)) { return WoodcutterTexts.T("axe_broken", text); } if (!axe.m_shared.m_useDurability) { return WoodcutterTexts.T("axe_plain", text); } return WoodcutterTexts.T("axe_percent", text, Mathf.RoundToInt(axe.GetDurabilityPercentage() * 100f)); } } internal static class WoodcutterLogic { internal enum State { Working, Stopped, Returning, NoAxe, AxeBroken, StorageFull, InventoryFull } internal static readonly string[][] SpeciesKeywords = new string[9][] { new string[1] { "beech" }, new string[1] { "birch" }, new string[1] { "oak" }, new string[1] { "firtree" }, new string[1] { "pinetree" }, new string[1] { "swamptree" }, new string[2] { "yggashoot", "yggdrasil" }, new string[2] { "ashland", "ashwood" }, new string[0] }; internal const int NameCount = 16; internal const float LowDurabilityThreshold = 0.05f; internal const float WarningRearmMargin = 0.15f; internal const int DepositPercent = 90; internal const float MinZoneRadius = 10f; internal const float MaxZoneRadius = 300f; internal const float ZoneRadiusStep = 5f; internal const int MaxPostLevel = 3; internal const float MinRepathInterval = 0.5f; internal const float RetryPathInterval = 1f; internal const float RepathInterval = 2f; internal const float RepathGoalMove = 1.5f; internal const float WaypointReach = 0.7f; internal const int MaxSkill = 100; private static readonly string[] HandleWoods = new string[6] { "Wood", "FineWood", "RoundLog", "ElderBark", "YggdrasilWood", "Blackwood" }; internal static int SpeciesCount => SpeciesKeywords.Length; internal static int OtherSpeciesIndex => SpeciesCount - 1; internal static int ClassifySpecies(string prefabName) { string text = (prefabName ?? string.Empty).ToLowerInvariant(); for (int i = 0; i < OtherSpeciesIndex; i++) { string[] array = SpeciesKeywords[i]; foreach (string value in array) { if (text.Contains(value)) { return i; } } } return OtherSpeciesIndex; } internal static bool IsSpeciesAllowed(int mask, int speciesIndex) { return (mask & (1 << speciesIndex)) != 0; } internal static int NameIndex(long userId, uint id) { long num = userId * 31 + id; long num2 = (num ^ (num >>> 17)) * -7046029254386353131L; return (int)((ulong)(num2 ^ (num2 >>> 29)) % 16uL); } internal static string NameFor(long userId, uint id) { return WoodcutterTexts.WoodcutterName(NameIndex(userId, id)); } internal static bool CrossedDownTo(float before, float after, float threshold) { if (before > threshold) { return after <= threshold; } return false; } internal static bool Warn(ref bool armed, float value, float threshold, float rearmMargin) { if (armed) { if (value <= threshold) { armed = false; return true; } } else if (value > threshold + rearmMargin) { armed = true; } return false; } internal static State ResolveState(bool workEnabled, bool recalled, bool hasAxe, bool axeBroken, bool storageFull, bool inventoryFull) { if (!workEnabled) { if (!recalled) { return State.Stopped; } return State.Returning; } if (!hasAxe) { return State.NoAxe; } if (axeBroken) { return State.AxeBroken; } if (storageFull) { return State.StorageFull; } if (!inventoryFull) { return State.Working; } return State.InventoryFull; } internal static bool ShouldDeposit(int usedSlots, int totalSlots) { if (totalSlots > 0) { return usedSlots * 100 >= totalSlots * 90; } return false; } internal static string StateKey(State state) { return state switch { State.Working => "state_working", State.Stopped => "state_stopped", State.Returning => "state_returning", State.NoAxe => "state_noaxe", State.AxeBroken => "state_axebroken", State.StorageFull => "state_storagefull", State.InventoryFull => "state_inventoryfull", _ => state.ToString(), }; } internal static string StateLabel(State state) { return WoodcutterTexts.T(StateKey(state)); } internal static bool IsProblem(State state) { if (state != State.NoAxe && state != State.AxeBroken && state != State.StorageFull) { return state == State.InventoryFull; } return true; } internal static int Percent(int used, int total) { if (total <= 0) { return 0; } used = Math.Max(0, Math.Min(used, total)); return used * 100 / total; } internal static int DurabilityPercent(float current, float max) { if (max <= 0f) { return 100; } if (current <= 0f) { return 0; } int val = (int)Math.Round(current / max * 100f); return Math.Max(1, Math.Min(100, val)); } internal static int PageCount(int items, int perPage) { if (items > 0) { return (items + perPage - 1) / perPage; } return 1; } internal static int ClampPage(int page, int items, int perPage) { return Math.Max(0, Math.Min(page, PageCount(items, perPage) - 1)); } internal static int RingPointCount(float radius) { int val = (int)Math.Ceiling(Math.PI * 2.0 * (double)Math.Max(0f, radius) / 2.0); return Math.Max(48, Math.Min(720, val)); } internal static float SnapRadius(float value) { float val = (float)Math.Round(value / 5f) * 5f; return Math.Max(10f, Math.Min(300f, val)); } internal static float HomeAngleDegrees(uint id) { return id % 360; } internal static bool ShouldGoHome(bool zoneSearched, bool foundWork, float distanceToHome, float arriveDistance) { if (zoneSearched && !foundWork) { return distanceToHome > arriveDistance; } return false; } internal static int PostLevel(bool hasLevel2, bool hasLevel3) { if (!hasLevel3) { if (!hasLevel2) { return 1; } return 2; } return 3; } internal static int MaxWoodcutters(int level) { return Math.Max(1, Math.Min(3, level)); } internal static bool CanHire(int existing, int level) { return existing < MaxWoodcutters(level); } internal static int UpgradeCost(int level, int toLevel2, int toLevel3) { return level switch { 1 => toLevel2, 2 => toLevel3, _ => 0, }; } internal static int HirePrice(int existing, bool thirdHiredBefore, int price1, int price2, int price3, int rehireDiscountPercent) { switch (existing) { case 0: return price1; case 1: return price2; case 2: { if (!thirdHiredBefore) { return price3; } int num = Math.Max(0, Math.Min(100, rehireDiscountPercent)); return price3 * (100 - num) / 100; } default: return -1; } } internal static bool ShouldRepath(bool havePath, float sinceLastQuery, float goalMoved) { if (sinceLastQuery < 0.5f) { return false; } if (!havePath) { return sinceLastQuery >= 1f; } if (!(goalMoved > 1.5f)) { return sinceLastQuery >= 2f; } return true; } internal static int AdvanceWaypoint(int index, int count, float flatDistanceToCurrent) { if (index >= count) { return count; } if (!(flatDistanceToCurrent <= 0.7f)) { return index; } return index + 1; } internal static bool ShouldTeleportRecall(float stillFor, float stillLimit, float noProgressFor, float noProgressLimit) { if (!(stillFor >= stillLimit)) { return noProgressFor >= noProgressLimit; } return true; } internal static float SkillDamageFactor(int level, float random01) { float num = Clamp01((float)level / 100f); float num2 = 0.4f + 0.6f * num; float num3 = Clamp01(num2 - 0.15f); float num4 = Clamp01(num2 + 0.15f); return num3 + (num4 - num3) * Clamp01(random01); } internal static float SkillLevelRequirement(int level) { return (float)Math.Pow(level + 1, 1.5) * 0.5f + 0.5f; } internal static bool RaiseSkill(ref int level, ref float accumulator, float amount) { if (level >= 100 || amount <= 0f) { return false; } accumulator += amount; if (accumulator < SkillLevelRequirement(level)) { return false; } level = Math.Min(100, level + 1); accumulator = 0f; return true; } internal static int SkillProgressPercent(int level, float accumulator) { if (level >= 100) { return 100; } int val = (int)(Clamp01(accumulator / SkillLevelRequirement(level)) * 100f); return Math.Min(99, val); } private static float Clamp01(float v) { if (!(v < 0f)) { if (!(v > 1f)) { return v; } return 1f; } return 0f; } internal static bool IsHandleWood(string prefabName) { if (prefabName != null) { return Array.IndexOf(HandleWoods, prefabName) >= 0; } return false; } internal static int MainRepairMaterial(string[] prefabNames, int[] amounts) { int num = -1; bool flag = true; for (int i = 0; i < prefabNames.Length; i++) { if (amounts[i] > 0) { bool flag2 = IsHandleWood(prefabNames[i]); if (num < 0 || (flag && !flag2) || (flag2 == flag && amounts[i] > amounts[num])) { num = i; flag = flag2; } } } return num; } internal static int RepairAmount(int amount, int amountPerLevel, int quality, int percent) { int num = amount + amountPerLevel * Math.Max(0, quality - 1); if (num <= 0) { return 0; } int val = (int)Math.Round((double)(num * Math.Max(0, Math.Min(100, percent))) / 100.0, MidpointRounding.AwayFromZero); return Math.Max(1, val); } internal static string CoinsWord(int n) { return WoodcutterTexts.Plural("coins", n); } internal static string CoresWord(int n) { return WoodcutterTexts.Plural("cores", n); } internal static string WoodcuttersWord(int n) { return WoodcutterTexts.Plural("woodcutters", n); } } public class WoodcutterMapPins : MonoBehaviour { private const string IconItemName = "AxeStone"; private const PinType PinType = (PinType)3; private const float RescanInterval = 10f; private const float PositionInterval = 0.5f; private static readonly FieldRef> PinsRef = AccessTools.FieldRefAccess>("m_pins"); private readonly Dictionary _pins = new Dictionary(); private readonly List _scanResults = new List(); private readonly HashSet _found = new HashSet(); private Minimap _minimap; private Sprite _icon; private int _scanIndex; private bool _scanning; private float _nextScanTime; private float _nextPositionTime; private void Update() { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || ZDOMan.instance == null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } if ((Object)(object)instance != (Object)(object)_minimap) { _minimap = instance; _pins.Clear(); _scanning = false; _nextScanTime = 0f; } if (!Plugin.ShowMapPins) { RemoveAllPins(); return; } if (Time.time >= _nextPositionTime) { _nextPositionTime = Time.time + 0.5f; MoveKnownPins(); } ContinueScan(); } private void ContinueScan() { if (!_scanning) { if (Time.time < _nextScanTime) { return; } _scanning = true; _scanIndex = 0; _scanResults.Clear(); } if (ZDOMan.instance.GetAllZDOsWithPrefabIterative("WoodcutterNPC", _scanResults, ref _scanIndex)) { _scanning = false; _nextScanTime = Time.time + 10f; ApplyScan(); } } private void ApplyScan() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) _found.Clear(); foreach (ZDO scanResult in _scanResults) { _found.Add(scanResult.m_uid); if (!_pins.ContainsKey(scanResult.m_uid)) { _pins[scanResult.m_uid] = CreatePin(scanResult.GetPosition()); } } List list = null; foreach (ZDOID key in _pins.Keys) { if (!_found.Contains(key)) { (list ?? (list = new List())).Add(key); } } if (list == null) { return; } foreach (ZDOID item in list) { RemovePin(item); } } private void MoveKnownPins() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) if (_pins.Count == 0) { return; } List list = PinsRef.Invoke(_minimap); List list2 = null; List> list3 = null; foreach (KeyValuePair pin in _pins) { ZDO zDO = ZDOMan.instance.GetZDO(pin.Key); if (zDO == null || !zDO.IsValid()) { (list2 ?? (list2 = new List())).Add(pin.Key); } else if (!list.Contains(pin.Value)) { (list3 ?? (list3 = new List>())).Add(pin); } else { pin.Value.m_pos = zDO.GetPosition(); } } if (list2 != null) { foreach (ZDOID item in list2) { RemovePin(item); } } if (list3 == null) { return; } foreach (KeyValuePair item2 in list3) { ZDO zDO2 = ZDOMan.instance.GetZDO(item2.Key); _pins[item2.Key] = CreatePin(zDO2.GetPosition()); } } private PinData CreatePin(Vector3 position) { //IL_0006: 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_0023: Unknown result type (might be due to invalid IL or missing references) PinData val = _minimap.AddPin(position, (PinType)3, WoodcutterTexts.T("npc_name"), false, false, 0L, default(PlatformUserID)); Sprite icon = GetIcon(); if ((Object)(object)icon != (Object)null) { val.m_icon = icon; } return val; } private Sprite GetIcon() { if ((Object)(object)_icon == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("AxeStone"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); _icon = (((Object)(object)val != (Object)null) ? val.m_itemData.GetIcon() : null); } return _icon; } private void RemovePin(ZDOID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (_pins.TryGetValue(id, out var value)) { _minimap.RemovePin(value); _pins.Remove(id); } } private void RemoveAllPins() { if (_pins.Count == 0) { return; } foreach (PinData value in _pins.Values) { _minimap.RemovePin(value); } _pins.Clear(); _scanning = false; _nextScanTime = 0f; } } internal static class WoodcutterNotifications { private const string NotifyRpc = "WoodcutterNPC_Notify"; private const string IconItemName = "AxeStone"; private static ZRoutedRpc _registeredOn; private static Sprite _icon; private const char Separator = '\u001f'; internal static void Send(string key, params string[] args) { string text = ((args == null || args.Length == 0) ? key : (key + "\u001f" + string.Join('\u001f'.ToString(), args))); if (!EnsureRegistered()) { Show(text); return; } ZRoutedRpc.instance.InvokeRoutedRPC(0L, "WoodcutterNPC_Notify", new object[1] { text }); } internal static bool EnsureRegistered() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return false; } if (instance != _registeredOn) { instance.Register("WoodcutterNPC_Notify", (Action)delegate(long sender, string text) { Show(text); }); _registeredOn = instance; } return true; } private static void Show(string payload) { Player localPlayer = Player.m_localPlayer; if (Plugin.Notifications && !((Object)(object)localPlayer == (Object)null) && !string.IsNullOrEmpty(payload)) { string[] array = payload.Split(new char[1] { '\u001f' }); object[] array2 = new object[array.Length - 1]; for (int i = 1; i < array.Length; i++) { array2[i - 1] = array[i]; } string text = Localization.instance.Localize(WoodcutterTexts.T(array[0], array2)); ((Character)localPlayer).Message((MessageType)1, text, 0, GetIcon(), false); } } private static Sprite GetIcon() { if ((Object)(object)_icon == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("AxeStone"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); _icon = (((Object)(object)val != (Object)null) ? val.m_itemData.GetIcon() : null); } return _icon; } } public class WoodcutterNotificationListener : MonoBehaviour { private float _nextLanguageCheck; private void Update() { WoodcutterNotifications.EnsureRegistered(); if (Time.time >= _nextLanguageCheck) { _nextLanguageCheck = Time.time + 1f; Plugin.ApplyLanguage(); } } } internal sealed class WoodcutterPathMover { private const AgentType Agent = (AgentType)6; private readonly List _path = new List(); private int _next; private bool _havePath; private Vector3 _pathGoal; private float _lastQuery = float.NegativeInfinity; internal bool FollowingPath { get { if (_havePath) { return _next < _path.Count; } return false; } } internal void Reset() { _path.Clear(); _next = 0; _havePath = false; _lastQuery = float.NegativeInfinity; } internal Vector3 DirectionTo(Vector3 self, Vector3 goal) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0056: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) Vector3 result = Flat(goal - self); if (((Vector3)(ref result)).sqrMagnitude < 0.0001f) { return Vector3.zero; } ((Vector3)(ref result)).Normalize(); if (!Plugin.UsePathfinding || (Object)(object)Pathfinding.instance == (Object)null) { _havePath = false; return result; } float num; Vector3 val; if (!_havePath) { num = 0f; } else { val = Flat(goal - _pathGoal); num = ((Vector3)(ref val)).magnitude; } float goalMoved = num; if (WoodcutterLogic.ShouldRepath(_havePath, Time.time - _lastQuery, goalMoved)) { Query(self, goal); } if (!_havePath) { return result; } while (_next < _path.Count) { int next = _next; int count = _path.Count; val = Flat(_path[_next] - self); int num2 = WoodcutterLogic.AdvanceWaypoint(next, count, ((Vector3)(ref val)).magnitude); if (num2 == _next) { break; } _next = num2; } if (_next >= _path.Count) { return result; } val = Flat(_path[_next] - self); return ((Vector3)(ref val)).normalized; } private void Query(Vector3 self, Vector3 goal) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) _lastQuery = Time.time; _pathGoal = goal; _next = 0; _havePath = Pathfinding.instance.GetPath(self, goal, _path, (AgentType)6, false, true, false) && _path.Count > 0; } private static Vector3 Flat(Vector3 v) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) v.y = 0f; return v; } } public class WoodcutterPostWindow : MonoBehaviour { private enum Tab { Workers, Upgrade } private const int WindowId = 5718864; private const float Width = 900f; private const float LeftColumnWidth = 390f; private const float ColumnGap = 16f; private const float MaxUseDistance = 15f; private const float ListRefreshInterval = 2f; private const int RowsPerPage = 5; private static WoodcutterPostWindow _instance; private readonly UiTheme.WindowState _window = new UiTheme.WindowState(); private WoodcutterHirePost _post; private string _status; private List _list = new List(); private float _nextListRefresh; private int _page; private Tab _tab; private Tab? _pendingTab; private float _pendingRadius; internal static bool IsOpen { get { if ((Object)(object)_instance != (Object)null) { return (Object)(object)_instance._post != (Object)null; } return false; } } internal static void Open(WoodcutterHirePost post) { if (!((Object)(object)_instance == (Object)null) && !((Object)(object)post == (Object)null)) { _instance._post = post; _instance._status = null; _instance._page = 0; _instance._tab = Tab.Workers; _instance._pendingTab = null; _instance._pendingRadius = post.Radius; _instance._nextListRefresh = 0f; _instance._window.Reset(); if ((Object)(object)Player.m_localPlayer != (Object)null) { _instance.RefreshList(Player.m_localPlayer); } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } } private void Awake() { _instance = this; } private void OnDestroy() { Close(); if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void Close() { if (_post != null) { _post = null; _list.Clear(); ZCursor.Hide(); ZCursor.LockState = (CursorLockMode)1; ModUi.NotifyClosed(); } } private void Update() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_post == (Object)null) { Close(); return; } Player localPlayer = Player.m_localPlayer; if (Input.GetKeyDown((KeyCode)27) || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)_post).transform.position) > 15f) { Close(); return; } if (Time.time >= _nextListRefresh) { RefreshList(localPlayer); } WoodcutterZoneRings.Request(((Component)_post).transform.position, _pendingRadius); } private void RefreshList(Player player) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) _nextListRefresh = Time.time + 2f; Vector3 from = (((Object)(object)_post != (Object)null) ? ((Component)_post).transform.position : ((Component)player).transform.position); _list = (from zdo in WoodcutterInteraction.FindAll() select WoodcutterStatus.Read(zdo, @from) into s orderby s.Distance select s).ToList(); _page = WoodcutterLogic.ClampPage(_page, _list.Count, 5); } private void OnGUI() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!((Object)(object)_post == (Object)null)) { UiTheme.Window(5718864, _window, 900f, new WindowFunction(DrawWindow)); } } private void DrawWindow(int id) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 Player localPlayer = Player.m_localPlayer; if ((Object)(object)_post == (Object)null || (Object)(object)localPlayer == (Object)null) { return; } if ((int)Event.current.type == 8 && _pendingTab.HasValue) { _tab = _pendingTab.Value; _pendingTab = null; } if (UiTheme.Header(WoodcutterHirePost.DisplayName, WoodcutterTexts.T("post_level_of", WoodcutterProgress.Level, 3))) { Close(); return; } DrawTabs(); if (_tab == Tab.Workers) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(390f) }); DrawHire(localPlayer); DrawStorage(); DrawZone(); DrawAll(localPlayer); GUILayout.EndVertical(); GUILayout.Space(16f); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); DrawList(localPlayer); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } else { DrawUpgradeTab(localPlayer); } GUILayout.Label(string.IsNullOrEmpty(_status) ? " " : _status, UiTheme.Label, Array.Empty()); GUILayout.Space(4f); GUILayout.Label(WoodcutterTexts.T("esc_close"), UiTheme.Hint, Array.Empty()); } private void DrawTabs() { GUILayout.BeginHorizontal(Array.Empty()); DrawTab(Tab.Workers, WoodcutterTexts.T("tab_workers")); GUILayout.Space(8f); DrawTab(Tab.Upgrade, WoodcutterTexts.T("tab_upgrade")); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(10f); } private void DrawTab(Tab tab, string title) { bool flag = _tab == tab; if (GUILayout.Toggle(flag, title, UiTheme.Chip, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }) && !flag) { _pendingTab = tab; } } private void DrawHire(Player player) { UiTheme.BeginCard(WoodcutterTexts.T("card_hire")); int count = _list.Count; int level = WoodcutterProgress.Level; int num = WoodcutterLogic.MaxWoodcutters(level); int num2 = WoodcutterProgress.HirePrice(count); int num3 = WoodcutterHirePost.CoinsOf(player); GUILayout.Label(WoodcutterTexts.T("hire_count", count, num, level), UiTheme.Label, Array.Empty()); if (num2 >= 0) { GUI.enabled = num3 >= num2; if (GUILayout.Button(WoodcutterTexts.T("btn_hire", num2, WoodcutterLogic.CoinsWord(num2)), UiTheme.PrimaryButton, Array.Empty())) { _status = _post.Hire(player); _nextListRefresh = 0f; } GUI.enabled = true; } else { GUI.enabled = false; GUILayout.Button(WoodcutterTexts.T((level < 3) ? "btn_level_limit" : "btn_max_woodcutters"), UiTheme.ButtonStyle, Array.Empty()); GUI.enabled = true; } GUILayout.Label(WoodcutterTexts.T("you_have", num3, WoodcutterLogic.CoinsWord(num3)), UiTheme.LabelMuted, Array.Empty()); GUILayout.Label((num2 < 0 && level < 3) ? WoodcutterTexts.T("hire_more_hint") : WoodcutterTexts.T("hire_hint"), UiTheme.LabelMuted, Array.Empty()); UiTheme.EndCard(); } private void DrawUpgradeTab(Player player) { int level = WoodcutterProgress.Level; int num = WoodcutterProgress.CoresOf(player); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(390f) }); UiTheme.BeginCard(WoodcutterTexts.T("card_level")); GUILayout.Label(WoodcutterTexts.T("post_level_of", level, 3), UiTheme.BigValue, Array.Empty()); int num2 = WoodcutterLogic.MaxWoodcutters(level); GUILayout.Label(WoodcutterTexts.T("level_allows", num2, WoodcutterLogic.WoodcuttersWord(num2)), UiTheme.LabelMuted, Array.Empty()); GUILayout.Space(6f); if (level < 3) { int nextUpgradeCost = WoodcutterProgress.NextUpgradeCost; GUI.enabled = num >= nextUpgradeCost; if (GUILayout.Button(WoodcutterTexts.T("btn_upgrade", level + 1, nextUpgradeCost, WoodcutterLogic.CoresWord(nextUpgradeCost)), UiTheme.PrimaryButton, Array.Empty())) { _status = WoodcutterProgress.Upgrade(player); } GUI.enabled = true; } else { GUI.enabled = false; GUILayout.Button(WoodcutterTexts.T("btn_max_level"), UiTheme.ButtonStyle, Array.Empty()); GUI.enabled = true; } GUILayout.Label(WoodcutterTexts.T("you_have", num, WoodcutterLogic.CoresWord(num)), UiTheme.LabelMuted, Array.Empty()); GUILayout.Space(4f); GUILayout.Label(WoodcutterTexts.T("upgrade_hint"), UiTheme.Hint, Array.Empty()); UiTheme.EndCard(); GUILayout.EndVertical(); GUILayout.Space(16f); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); UiTheme.BeginCard(WoodcutterTexts.T("card_levels")); DrawLevelRow(1, level, "1 " + WoodcutterLogic.WoodcuttersWord(1), WoodcutterTexts.T("level_free"), WoodcutterTexts.T("level_hire1", Plugin.HirePrice1, WoodcutterLogic.CoinsWord(Plugin.HirePrice1))); DrawLevelRow(2, level, "2 " + WoodcutterLogic.WoodcuttersWord(2), $"{Plugin.Level2Cores} {WoodcutterLogic.CoresWord(Plugin.Level2Cores)}", WoodcutterTexts.T("level_hire2", Plugin.HirePrice2, WoodcutterLogic.CoinsWord(Plugin.HirePrice2))); int num3 = WoodcutterLogic.HirePrice(2, thirdHiredBefore: true, Plugin.HirePrice1, Plugin.HirePrice2, Plugin.HirePrice3, Plugin.RehireDiscountPercent); DrawLevelRow(3, level, "3 " + WoodcutterLogic.WoodcuttersWord(3), $"{Plugin.Level3Cores} {WoodcutterLogic.CoresWord(Plugin.Level3Cores)}", WoodcutterTexts.T("level_hire3", Plugin.HirePrice3, num3, WoodcutterLogic.CoinsWord(num3))); UiTheme.EndCard(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } private static void DrawLevelRow(int rowLevel, int currentLevel, string gives, string costs, string hire) { GUILayout.BeginVertical(UiTheme.RowStyle, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label((rowLevel == currentLevel) ? ("" + WoodcutterTexts.T("level_row", rowLevel) + "") : ((rowLevel < currentLevel) ? WoodcutterTexts.T("level_row", rowLevel) : ("" + WoodcutterTexts.T("level_row", rowLevel) + "")), UiTheme.RowTitle, Array.Empty()); GUILayout.FlexibleSpace(); GUILayout.Label((rowLevel == currentLevel) ? WoodcutterTexts.T("level_current") : ((rowLevel < currentLevel) ? WoodcutterTexts.T("level_unlocked") : costs), UiTheme.LabelMuted, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.Label(gives + " · " + hire, UiTheme.LabelMuted, Array.Empty()); GUILayout.EndVertical(); GUILayout.Space(4f); } private void DrawStorage() { UiTheme.BeginCard(WoodcutterTexts.T("card_storage")); _post.CountStorage(out var used, out var total, out var axesUsed, out var axeCells); string text = ((used >= total) ? $"{used}/{total}" : $"{used}/{total}"); GUILayout.Label(WoodcutterTexts.T("storage_line", text, axesUsed, axeCells), UiTheme.Label, Array.Empty()); GUILayout.Label(WoodcutterTexts.T("storage_hint"), UiTheme.Hint, Array.Empty()); GUILayout.Space(6f); bool autoRepair = _post.AutoRepair; if (GUILayout.Toggle(autoRepair, WoodcutterTexts.T("auto_repair"), UiTheme.Chip, Array.Empty()) != autoRepair) { _post.SetAutoRepair(!autoRepair); } GUILayout.Label(WoodcutterTexts.T("auto_repair_hint", Plugin.RepairCostPercent), UiTheme.Hint, Array.Empty()); UiTheme.EndCard(); } private void DrawZone() { UiTheme.BeginCard(WoodcutterTexts.T("card_post_zone")); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(WoodcutterTexts.T("radius"), UiTheme.Label, Array.Empty()); GUILayout.FlexibleSpace(); GUILayout.Label(WoodcutterTexts.T("meters", Mathf.RoundToInt(_pendingRadius)), UiTheme.BigValue, Array.Empty()); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("−", UiTheme.SmallButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) })) { _pendingRadius -= 5f; } float num = UiTheme.Slider(_pendingRadius, 10f, 300f); if (!Mathf.Approximately(num, _pendingRadius)) { _pendingRadius = num; } if (GUILayout.Button("+", UiTheme.SmallButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) })) { _pendingRadius += 5f; } GUILayout.EndHorizontal(); _pendingRadius = WoodcutterLogic.SnapRadius(_pendingRadius); bool flag = (GUI.enabled = !Mathf.Approximately(_pendingRadius, _post.Radius)); if (GUILayout.Button(WoodcutterTexts.T(flag ? "btn_save_radius" : "radius_saved"), flag ? UiTheme.PrimaryButton : UiTheme.ButtonStyle, Array.Empty())) { _post.SetRadius(_pendingRadius); _status = WoodcutterTexts.T("status_radius", Mathf.RoundToInt(_pendingRadius)); } GUI.enabled = true; GUILayout.Label(WoodcutterTexts.T("zone_hint"), UiTheme.Hint, Array.Empty()); UiTheme.EndCard(); } private void DrawList(Player player) { UiTheme.BeginCard(WoodcutterTexts.T("card_list", _list.Count)); int num = _page * 5; for (int i = num; i < num + 5; i++) { if (i < _list.Count) { DrawRow(_list[i]); } else if (i == 0) { DrawRowShell(WoodcutterTexts.T("list_empty_title"), " ", WoodcutterTexts.T("list_empty_hint"), " ", visible: true); } else { DrawRowShell(" ", " ", " ", " ", visible: false); } } int num2 = WoodcutterLogic.PageCount(_list.Count, 5); GUILayout.BeginHorizontal(Array.Empty()); GUI.enabled = _page > 0; if (GUILayout.Button("<", UiTheme.SmallButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) })) { _page--; } GUI.enabled = true; GUILayout.FlexibleSpace(); GUILayout.Label($"{_page + 1} / {num2}", UiTheme.LabelMuted, Array.Empty()); GUILayout.FlexibleSpace(); GUI.enabled = _page < num2 - 1; if (GUILayout.Button(">", UiTheme.SmallButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) })) { _page++; } GUI.enabled = true; GUILayout.EndHorizontal(); UiTheme.EndCard(); } private void DrawRow(WoodcutterStatus status) { GUILayout.BeginVertical(UiTheme.RowStyle, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(status.Name, UiTheme.RowTitle, Array.Empty()); string text = WoodcutterLogic.StateLabel(status.State); string text2 = (WoodcutterLogic.IsProblem(status.State) ? "#E07A5F" : ((status.State == WoodcutterLogic.State.Working) ? "#7FC47A" : "#C9BFAF")); GUILayout.Label("" + text + "", UiTheme.Label, Array.Empty()); GUILayout.Label(" · " + WoodcutterTexts.T("row_skill", status.Skill), UiTheme.LabelMuted, Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button(WoodcutterTexts.T(status.WorkEnabled ? "btn_stop" : "btn_start"), UiTheme.SmallButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) })) { WoodcutterInteraction.SetWorkEnabled(status.Zdo, !status.WorkEnabled); _nextListRefresh = Time.time + 0.3f; } GUILayout.EndHorizontal(); string text3 = ((status.AxeName == null) ? WoodcutterTexts.T("row_no_axe") : ((status.AxePercent >= 0) ? (status.AxeName + " " + PercentText(status.AxePercent, 5)) : status.AxeName)); string text4 = WoodcutterTexts.T("row_inventory", PercentText(status.InventoryPercent, -1, 100), status.UsedSlots, status.TotalSlots); string obj = (status.Loaded ? WoodcutterTexts.T("row_distance", Mathf.RoundToInt(status.Distance)) : WoodcutterTexts.T("row_distance_unloaded", Mathf.RoundToInt(status.Distance))); GUILayout.Label(text3 + " · " + text4, UiTheme.LabelMuted, Array.Empty()); GUILayout.Label(obj, UiTheme.LabelMuted, Array.Empty()); GUILayout.EndVertical(); GUILayout.Space(4f); } private static void DrawRowShell(string title, string state, string detail, string detail2, bool visible) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; if (!visible) { GUI.color = Color.clear; } GUILayout.BeginVertical(UiTheme.RowStyle, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(title, UiTheme.RowTitle, Array.Empty()); GUILayout.Label(state, UiTheme.Label, Array.Empty()); GUILayout.FlexibleSpace(); bool enabled = GUI.enabled; GUI.enabled = false; GUILayout.Button(" ", UiTheme.SmallButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(96f) }); GUI.enabled = enabled; GUILayout.EndHorizontal(); GUILayout.Label(detail, UiTheme.LabelMuted, Array.Empty()); GUILayout.Label(detail2, UiTheme.LabelMuted, Array.Empty()); GUILayout.EndVertical(); GUILayout.Space(4f); GUI.color = color; } private static string PercentText(int percent, int warnBelow = -1, int warnAbove = 101) { if (percent > warnBelow && percent < warnAbove) { return $"{percent}%"; } return $"{percent}%"; } private void DrawAll(Player player) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) UiTheme.BeginCard(WoodcutterTexts.T("card_all")); if (GUILayout.Button(WoodcutterTexts.T("btn_recall_all"), UiTheme.DangerButton, Array.Empty())) { int num = WoodcutterInteraction.RecallAllTo(((Component)_post).transform.position); _status = ((num > 0) ? WoodcutterTexts.T("status_recalled", num) : WoodcutterTexts.T("status_none_in_world")); _nextListRefresh = Time.time + 0.3f; } GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button(WoodcutterTexts.T("btn_start_all"), UiTheme.SuccessButton, Array.Empty())) { int num2 = WoodcutterInteraction.StartAll(); _status = ((num2 > 0) ? WoodcutterTexts.T("status_started", num2) : WoodcutterTexts.T("status_none_in_world")); _nextListRefresh = Time.time + 0.3f; } GUILayout.Space(6f); if (GUILayout.Button(WoodcutterTexts.T("btn_bind_all"), UiTheme.ButtonStyle, Array.Empty())) { int num3 = WoodcutterInteraction.BindAllTo(_post.Id); _status = ((num3 > 0) ? WoodcutterTexts.T("status_bound", num3) : WoodcutterTexts.T("status_none_in_world")); _nextListRefresh = Time.time + 0.3f; } GUILayout.EndHorizontal(); GUILayout.Label(WoodcutterTexts.T("all_hint"), UiTheme.Hint, Array.Empty()); UiTheme.EndCard(); } } internal static class WoodcutterProgress { private const string Level2Key = "woodcutternpc_postlevel2"; private const string Level3Key = "woodcutternpc_postlevel3"; private const string ThirdHiredKey = "woodcutternpc_thirdhired"; private const string SurtlingCoreItem = "$item_surtlingcore"; private static int _paidLevel; private static ZoneSystem _paidIn; internal static int Level { get { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return 1; } int num = WoodcutterLogic.PostLevel(instance.GetGlobalKey("woodcutternpc_postlevel2"), instance.GetGlobalKey("woodcutternpc_postlevel3")); if (instance != _paidIn) { return num; } return Math.Max(num, _paidLevel); } } internal static bool ThirdHiredBefore { get { if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetGlobalKey("woodcutternpc_thirdhired"); } return false; } } internal static int NextUpgradeCost => WoodcutterLogic.UpgradeCost(Level, Plugin.Level2Cores, Plugin.Level3Cores); internal static int CoresOf(Player player) { if (!((Object)(object)player != (Object)null)) { return 0; } return ((Humanoid)player).GetInventory().CountItems("$item_surtlingcore", -1, true); } internal static int HirePrice(int existing) { if (!WoodcutterLogic.CanHire(existing, Level)) { return -1; } return WoodcutterLogic.HirePrice(existing, ThirdHiredBefore, Plugin.HirePrice1, Plugin.HirePrice2, Plugin.HirePrice3, Plugin.RehireDiscountPercent); } internal static void MarkThirdHired() { ZoneSystem instance = ZoneSystem.instance; if (instance != null) { instance.SetGlobalKey("woodcutternpc_thirdhired"); } } internal static string Upgrade(Player player) { int level = Level; if (level >= 3 || (Object)(object)ZoneSystem.instance == (Object)null) { return WoodcutterTexts.T("up_max"); } int nextUpgradeCost = NextUpgradeCost; if (CoresOf(player) < nextUpgradeCost) { return WoodcutterTexts.T("up_need", nextUpgradeCost, WoodcutterLogic.CoresWord(nextUpgradeCost)); } if (nextUpgradeCost > 0) { ((Humanoid)player).GetInventory().RemoveItem("$item_surtlingcore", nextUpgradeCost, -1, true); } ZoneSystem.instance.SetGlobalKey((level == 1) ? "woodcutternpc_postlevel2" : "woodcutternpc_postlevel3"); int num = (_paidLevel = level + 1); _paidIn = ZoneSystem.instance; return WoodcutterTexts.T("up_done", num, WoodcutterLogic.WoodcuttersWord(num)); } } internal static class WoodcutterRepair { internal struct Material { internal string Name; internal int Amount; } internal static List CostOf(ItemData axe) { Recipe val = ((axe != null && (Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetRecipe(axe) : null); if ((Object)(object)val == (Object)null || val.m_resources == null) { return null; } List list = new List(); Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && (Object)(object)val2.m_resItem != (Object)null) { list.Add(val2); } } string[] array = new string[list.Count]; int[] array2 = new int[list.Count]; for (int j = 0; j < list.Count; j++) { array[j] = ((Object)((Component)list[j].m_resItem).gameObject).name; array2[j] = list[j].m_amount; } int num = WoodcutterLogic.MainRepairMaterial(array, array2); if (num < 0) { return null; } Requirement val3 = list[num]; int amount = WoodcutterLogic.RepairAmount(val3.m_amount, val3.m_amountPerLevel, axe.m_quality, Plugin.RepairCostPercent); return new List { new Material { Name = val3.m_resItem.m_itemData.m_shared.m_name, Amount = amount } }; } internal static bool CanPay(Inventory storage, List cost) { if (storage == null || cost == null) { return false; } foreach (Material item in cost) { if (storage.CountItems(item.Name, -1, true) < item.Amount) { return false; } } return true; } internal static void Pay(Inventory storage, List cost) { foreach (Material item in cost) { storage.RemoveItem(item.Name, item.Amount, -1, true); } } internal static string Describe(List cost) { if (cost == null) { return ""; } StringBuilder stringBuilder = new StringBuilder(); foreach (Material item in cost) { if (stringBuilder.Length > 0) { stringBuilder.Append(", "); } stringBuilder.Append(item.Amount).Append(' ').Append(item.Name); } return stringBuilder.ToString(); } } public class WoodcutterSettingsWindow : MonoBehaviour { private const float MaxUseDistance = 15f; private const int WindowId = 5718867; private const float Width = 420f; private const float ChipWidth = 172f; private static WoodcutterSettingsWindow _instance; private WoodcutterInteraction _target; private bool _confirmDismiss; private bool? _pendingConfirmDismiss; private readonly UiTheme.WindowState _window = new UiTheme.WindowState(); internal static bool IsOpen { get { if ((Object)(object)_instance != (Object)null) { return (Object)(object)_instance._target != (Object)null; } return false; } } internal static void Open(WoodcutterInteraction woodcutter) { if (!((Object)(object)_instance == (Object)null) && !((Object)(object)woodcutter == (Object)null)) { _instance._target = woodcutter; _instance._window.Reset(); _instance._confirmDismiss = false; _instance._pendingConfirmDismiss = null; ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } } private void Awake() { _instance = this; } private void OnDestroy() { Close(); if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void Close() { if (_target != null) { _target = null; ZCursor.Hide(); ZCursor.LockState = (CursorLockMode)1; ModUi.NotifyClosed(); } } private void Update() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_target == (Object)null) { Close(); return; } Player localPlayer = Player.m_localPlayer; if (Input.GetKeyDown((KeyCode)27) || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)_target).transform.position) > 15f) { Close(); } else { WoodcutterZoneRings.Request(_target.ZoneCenter, _target.ZoneRadius); } } private void OnGUI() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!((Object)(object)_target == (Object)null)) { UiTheme.Window(5718867, _window, 420f, new WindowFunction(DrawWindow)); } } private void DrawWindow(int id) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if (!((Object)(object)_target == (Object)null)) { if ((int)Event.current.type == 8 && _pendingConfirmDismiss.HasValue) { _confirmDismiss = _pendingConfirmDismiss.Value; _pendingConfirmDismiss = null; } bool workEnabled = _target.WorkEnabled; if (UiTheme.Header(WoodcutterTexts.T("set_title", _target.Name), WoodcutterTexts.T("set_subtitle"), workEnabled ? UiTheme.PillSuccess : UiTheme.PillDanger, WoodcutterTexts.T(workEnabled ? "pill_working" : "pill_stopped"))) { Close(); return; } DrawWork(workEnabled); DrawSpecies(); DrawZone(); DrawDismiss(); GUILayout.Label(WoodcutterTexts.T("esc_close"), UiTheme.Hint, Array.Empty()); } } private void DrawWork(bool working) { UiTheme.BeginCard(WoodcutterTexts.T("card_work")); GUILayout.Label(Localization.instance.Localize(_target.BuildAxeLine()), UiTheme.Label, Array.Empty()); GUILayout.Label(_target.BuildSkillLine(), UiTheme.LabelMuted, Array.Empty()); GUILayout.Label(Localization.instance.Localize(_target.BuildRepairLine()), UiTheme.LabelMuted, Array.Empty()); GUILayout.Space(6f); if (GUILayout.Button(WoodcutterTexts.T(working ? "btn_stop" : "btn_start"), working ? UiTheme.DangerButton : UiTheme.SuccessButton, Array.Empty())) { _target.WorkEnabled = !working; } UiTheme.EndCard(); } private void DrawSpecies() { UiTheme.BeginCard(WoodcutterTexts.T("card_species")); int treeMask = _target.TreeMask; int num = treeMask; int count = TreeSpecies.Count; for (int i = 0; i < count; i += 2) { GUILayout.BeginHorizontal(Array.Empty()); for (int j = i; j < i + 2 && j < count; j++) { int num2 = 1 << j; bool flag = (treeMask & num2) != 0; string text = WoodcutterTexts.SpeciesName(j); if (GUILayout.Toggle(flag, text, UiTheme.Chip, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(172f) }) != flag) { num = (flag ? (num & ~num2) : (num | num2)); } if (j == i) { GUILayout.Space(8f); } } GUILayout.EndHorizontal(); } GUILayout.Space(4f); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label((treeMask == 0) ? WoodcutterTexts.T("species_none") : " ", UiTheme.LabelMuted, Array.Empty()); GUILayout.FlexibleSpace(); if (GUILayout.Button(WoodcutterTexts.T("btn_all"), UiTheme.SmallButton, Array.Empty())) { num = -1; } GUILayout.Space(6f); if (GUILayout.Button(WoodcutterTexts.T("btn_none"), UiTheme.SmallButton, Array.Empty())) { num = 0; } GUILayout.EndHorizontal(); if (num != treeMask) { _target.TreeMask = num; } UiTheme.EndCard(); } private void DrawDismiss() { UiTheme.BeginCard(WoodcutterTexts.T("card_dismiss")); if (!_confirmDismiss) { GUILayout.Label(WoodcutterTexts.T("dismiss_hint"), UiTheme.LabelMuted, Array.Empty()); if (GUILayout.Button(WoodcutterTexts.T("btn_dismiss"), UiTheme.ButtonStyle, Array.Empty())) { _pendingConfirmDismiss = true; } } else { GUILayout.Label(WoodcutterTexts.T("dismiss_confirm"), UiTheme.LabelMuted, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button(WoodcutterTexts.T("btn_dismiss_yes"), UiTheme.DangerButton, Array.Empty())) { _target.Dismiss(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, WoodcutterTexts.T("dismiss_done"), 0, (Sprite)null, false); } Close(); GUILayout.EndHorizontal(); UiTheme.EndCard(); return; } GUILayout.Space(6f); if (GUILayout.Button(WoodcutterTexts.T("btn_cancel"), UiTheme.ButtonStyle, Array.Empty())) { _pendingConfirmDismiss = false; } GUILayout.EndHorizontal(); } UiTheme.EndCard(); } private void DrawZone() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) UiTheme.BeginCard(WoodcutterTexts.T("card_zone")); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(WoodcutterTexts.T(_target.HasPost ? "zone_around_post" : "zone_no_post"), UiTheme.Label, Array.Empty()); GUILayout.FlexibleSpace(); GUILayout.Label(WoodcutterTexts.T("meters", Mathf.RoundToInt(_target.ZoneRadius)), UiTheme.BigValue, Array.Empty()); GUILayout.EndHorizontal(); Player localPlayer = Player.m_localPlayer; float num = 0f; if ((Object)(object)localPlayer != (Object)null) { Vector3 val = _target.ZoneCenter - ((Component)localPlayer).transform.position; val.y = 0f; num = ((Vector3)(ref val)).magnitude; } GUILayout.Label(WoodcutterTexts.T("zone_center_dist", Mathf.RoundToInt(num)), UiTheme.LabelMuted, Array.Empty()); GUILayout.Label(WoodcutterTexts.T("zone_radius_hint"), UiTheme.Hint, Array.Empty()); UiTheme.EndCard(); } } internal sealed class WoodcutterStatus { internal ZDO Zdo; internal string Name; internal WoodcutterLogic.State State; internal bool WorkEnabled; internal bool Loaded; internal int UsedSlots; internal int TotalSlots; internal string AxeName; internal int AxePercent; internal float Distance; internal Vector3 ZoneCenter; internal float ZoneRadius; internal int Skill; internal int InventoryPercent => WoodcutterLogic.Percent(UsedSlots, TotalSlots); internal static WoodcutterStatus Read(ZDO zdo, Vector3 from) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) bool loaded; Inventory val = LiveInventory(zdo, out loaded) ?? SavedInventory(zdo); ItemData axe = WoodcutterAxeSlot.GetAxe(val); int num = 17; int num2 = 0; if (val != null) { foreach (ItemData allItem in val.GetAllItems()) { if (allItem.m_gridPos != WoodcutterAxeSlot.Position) { num2++; } } } bool workEnabled = zdo.GetBool("WoodcutterNPC_WorkEnabled", true); bool recalled = zdo.GetBool("WoodcutterNPC_Recall", false); bool axeBroken = WoodcutterAxeSlot.IsBroken(axe); bool storageFull = zdo.GetBool("WoodcutterNPC_StorageFull", false); Vector3 val2 = zdo.GetPosition() - from; val2.y = 0f; WoodcutterInteraction.ZoneOf(zdo, out var center, out var radius); return new WoodcutterStatus { Zdo = zdo, Name = WoodcutterInteraction.NameOf(zdo), State = WoodcutterLogic.ResolveState(workEnabled, recalled, axe != null, axeBroken, storageFull, num2 >= num), WorkEnabled = workEnabled, Loaded = loaded, UsedSlots = num2, TotalSlots = num, AxeName = ((axe != null) ? Localization.instance.Localize(axe.m_shared.m_name) : null), AxePercent = ((axe != null && axe.m_shared.m_useDurability) ? WoodcutterLogic.DurabilityPercent(axe.m_durability, axe.GetMaxDurability()) : (-1)), Distance = ((Vector3)(ref val2)).magnitude, ZoneCenter = center, ZoneRadius = radius, Skill = WoodcutterInteraction.SkillOf(zdo) }; } private static Inventory LiveInventory(ZDO zdo, out bool loaded) { ZNetView val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(zdo) : null); loaded = (Object)(object)val != (Object)null; Container val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.GetInventory(); } private static Inventory SavedInventory(ZDO zdo) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Inventory val = new Inventory("", (Sprite)null, 6, 3); byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray != null) { val.Load(new ZPackage(byteArray)); } return val; } } internal static class WoodcutterTexts { internal enum Lang { English, Ukrainian, Russian } internal static Lang Current = Lang.English; internal const string AutoLanguage = "Auto"; internal static readonly string[][] Species = new string[3][] { new string[9] { "Beech", "Birch", "Oak", "Fir", "Pine", "Ancient tree", "Yggdrasil shoot", "Ashwood", "Other" }, new string[9] { "Бук", "Береза", "Дуб", "Ялина", "Сосна", "Древнє дерево", "Паросток Іґґдрасиля", "Попелясте дерево", "Інші" }, new string[9] { "Бук", "Берёза", "Дуб", "Ель", "Сосна", "Древнее дерево", "Побег Иггдрасиля", "Пепельное дерево", "Другие" } }; internal static readonly string[][] Names = new string[3][] { new string[16] { "Ostap", "Taras", "Bohdan", "Myron", "Danylo", "Stepan", "Hnat", "Panas", "Orest", "Yakym", "Savka", "Luka", "Nazar", "Yurko", "Trokhym", "Omelko" }, new string[16] { "Остап", "Тарас", "Богдан", "Мирон", "Данило", "Степан", "Гнат", "Панас", "Орест", "Яким", "Савка", "Лука", "Назар", "Юрко", "Трохим", "Омелько" }, new string[16] { "Остап", "Тарас", "Богдан", "Мирон", "Данила", "Степан", "Игнат", "Панас", "Орест", "Яким", "Савка", "Лука", "Назар", "Юрка", "Трофим", "Емельян" } }; internal static readonly Dictionary Plurals = new Dictionary { ["coins"] = new string[3] { "coin|coins|coins", "монета|монети|монет", "монета|монеты|монет" }, ["cores"] = new string[3] { "surtling core|surtling cores|surtling cores", "ядро суртлінга|ядра суртлінга|ядер суртлінга", "ядро суртлинга|ядра суртлинга|ядер суртлинга" }, ["woodcutters"] = new string[3] { "woodcutter|woodcutters|woodcutters", "лісоруб|лісоруби|лісорубів", "лесоруб|лесоруба|лесорубов" } }; internal static readonly Dictionary Table = new Dictionary { ["npc_name"] = new string[3] { "Woodcutter", "Лісоруб", "Лесоруб" }, ["post_name"] = new string[3] { "Woodcutter's Post", "Колода лісоруба", "Колода лесоруба" }, ["post_desc"] = new string[3] { "Hire woodcutters here.", "Тут можна найняти лісоруба.", "Здесь можно нанять лесоруба." }, ["esc_close"] = new string[3] { "Esc - close", "Esc - закрити", "Esc - закрыть" }, ["meters"] = new string[3] { "{0} m", "{0} м", "{0} м" }, ["btn_stop"] = new string[3] { "Stop", "Зупинити", "Остановить" }, ["btn_start"] = new string[3] { "Start", "Запустити", "Запустить" }, ["state_working"] = new string[3] { "Working", "Працює", "Работает" }, ["state_stopped"] = new string[3] { "Stopped", "Зупинено", "Остановлен" }, ["state_returning"] = new string[3] { "Returning to post", "Іде до колоди", "Идёт к колоде" }, ["state_noaxe"] = new string[3] { "No axe", "Без сокири", "Без топора" }, ["state_axebroken"] = new string[3] { "Axe broken", "Сокира зламана", "Топор сломан" }, ["state_storagefull"] = new string[3] { "Storage full", "Сховище повне", "Хранилище полное" }, ["state_inventoryfull"] = new string[3] { "Inventory full", "Інвентар повний", "Инвентарь полон" }, ["drop_post_axerow"] = new string[3] { "Only axes go in the top row", "У верхній ряд кладуться лише сокири", "В верхний ряд кладутся только топоры" }, ["drop_axeslot"] = new string[3] { "Only an axe goes in this slot", "У цю комірку кладеться лише сокира", "В эту ячейку кладётся только топор" }, ["notify_axe_broken"] = new string[3] { "Woodcutter {0}: axe is broken", "Лісоруб {0}: сокира зламалась", "Лесоруб {0}: топор сломался" }, ["notify_axe_low"] = new string[3] { "Woodcutter {0}: axe almost broken ({1}%)", "Лісоруб {0}: сокира майже зламана ({1}%)", "Лесоруб {0}: топор почти сломан ({1}%)" }, ["notify_storage_full"] = new string[3] { "Woodcutter {0}: post storage is full", "Лісоруб {0}: сховище колоди повне", "Лесоруб {0}: хранилище колоды заполнено" }, ["post_hover_title"] = new string[3] { "{0} (level {1})", "{0} (рівень {1})", "{0} (уровень {1})" }, ["post_hover_storage"] = new string[3] { "Storage", "Сховище", "Хранилище" }, ["post_hover_manage"] = new string[3] { "Manage woodcutters", "Керування лісорубами", "Управление лесорубами" }, ["hire_limit"] = new string[3] { "Level {0} limit: {1} {2}. Upgrade the post.", "Ліміт рівня {0}: {1} {2}. Поліпште колоду.", "Лимит уровня {0}: {1} {2}. Улучшите колоду." }, ["hire_max"] = new string[3] { "Maximum reached: {0} {1}", "Досягнуто максимуму: {0} {1}", "Достигнут максимум: {0} {1}" }, ["hire_no_coins"] = new string[3] { "Not enough coins: {0} needed", "Не вистачає монет: потрібно {0}", "Не хватает монет: нужно {0}" }, ["hire_no_prefab"] = new string[3] { "Prefab '{0}' not found", "Префаб '{0}' не знайдено", "Префаб '{0}' не найден" }, ["hire_done"] = new string[3] { "Woodcutter hired. Put an axe in its first slot and start it in its settings", "Лісоруба найнято. Дайте йому сокиру в перший слот і запустіть у налаштуваннях", "Лесоруб нанят. Дайте ему топор в первый слот и запустите в настройках" }, ["npc_hover_title"] = new string[3] { "Woodcutter {0} ({1})", "Лісоруб {0} ({1})", "Лесоруб {0} ({1})" }, ["npc_zone_post"] = new string[3] { "Work zone: {0} m around the post", "Робоча зона: {0} м навколо колоди", "Рабочая зона: {0} м вокруг колоды" }, ["npc_zone_nopost"] = new string[3] { "Work zone: {0} m (no post)", "Робоча зона: {0} м (без колоди)", "Рабочая зона: {0} м (без колоды)" }, ["npc_skill"] = new string[3] { "Woodcutting: {0} ({1}% to {2})", "Рубка дерев: {0} ({1}% до {2})", "Рубка деревьев: {0} ({1}% до {2})" }, ["npc_skill_max"] = new string[3] { "Woodcutting: {0} (max)", "Рубка дерев: {0} (макс.)", "Рубка деревьев: {0} (макс.)" }, ["npc_hover_inventory"] = new string[3] { "Open inventory", "Відкрити інвентар", "Открыть инвентарь" }, ["npc_hover_settings"] = new string[3] { "Settings", "Налаштування", "Настройки" }, ["axe_none"] = new string[3] { "No axe - put an axe in the first slot", "Без сокири - покладіть сокиру в перший слот", "Без топора - положите топор в первый слот" }, ["axe_broken"] = new string[3] { "Axe broken: {0}", "Сокира зламана: {0}", "Топор сломан: {0}" }, ["axe_plain"] = new string[3] { "Axe: {0}", "Сокира: {0}", "Топор: {0}" }, ["axe_percent"] = new string[3] { "Axe: {0} - {1}%", "Сокира: {0} - {1}%", "Топор: {0} - {1}%" }, ["up_max"] = new string[3] { "The post is already at max level", "Колода вже на максимальному рівні", "Колода уже на максимальном уровне" }, ["up_need"] = new string[3] { "{0} {1} needed", "Потрібно {0} {1}", "Нужно {0} {1}" }, ["up_done"] = new string[3] { "Post upgraded to level {0}: you can now have {0} {1}", "Колоду поліпшено до рівня {0}: тепер можна мати {0} {1}", "Колода улучшена до уровня {0}: теперь можно иметь {0} {1}" }, ["set_title"] = new string[3] { "Woodcutter {0}", "Лісоруб {0}", "Лесоруб {0}" }, ["set_subtitle"] = new string[3] { "Hired hand settings", "Налаштування найманця", "Настройки наёмника" }, ["pill_working"] = new string[3] { "WORKING", "ПРАЦЮЄ", "РАБОТАЕТ" }, ["pill_stopped"] = new string[3] { "STOPPED", "ЗУПИНЕНО", "ОСТАНОВЛЕН" }, ["card_work"] = new string[3] { "Work", "Робота", "Работа" }, ["card_species"] = new string[3] { "Tree species", "Породи дерев", "Породы деревьев" }, ["species_none"] = new string[3] { "Nothing selected - it won't chop", "Нічого не вибрано - лісоруб не рубатиме", "Ничего не выбрано - лесоруб не будет рубить" }, ["btn_all"] = new string[3] { "All", "Усі", "Все" }, ["btn_none"] = new string[3] { "None", "Жодного", "Ничего" }, ["card_dismiss"] = new string[3] { "Dismiss", "Звільнення", "Увольнение" }, ["dismiss_hint"] = new string[3] { "The axe and items go to the post's storage.", "Сокира й речі перейдуть у сховище колоди.", "Топор и вещи перейдут в хранилище колоды." }, ["btn_dismiss"] = new string[3] { "Dismiss woodcutter", "Звільнити лісоруба", "Уволить лесоруба" }, ["dismiss_confirm"] = new string[3] { "Really dismiss? It will be gone for good.", "Точно звільнити? Лісоруб зникне назавжди.", "Точно уволить? Лесоруб исчезнет навсегда." }, ["btn_dismiss_yes"] = new string[3] { "Yes, dismiss", "Так, звільнити", "Да, уволить" }, ["btn_cancel"] = new string[3] { "Cancel", "Скасувати", "Отмена" }, ["dismiss_done"] = new string[3] { "Woodcutter dismissed. Its belongings are in the post's storage", "Лісоруба звільнено. Його речі - у сховищі колоди", "Лесоруб уволен. Его вещи - в хранилище колоды" }, ["card_zone"] = new string[3] { "Work zone", "Робоча зона", "Рабочая зона" }, ["zone_around_post"] = new string[3] { "Around the post", "Навколо колоди", "Вокруг колоды" }, ["zone_no_post"] = new string[3] { "No post", "Без колоди", "Без колоды" }, ["zone_center_dist"] = new string[3] { "Zone center is {0} m from you", "Центр зони за {0} м від вас", "Центр зоны в {0} м от вас" }, ["zone_radius_hint"] = new string[3] { "The radius is set in the Woodcutter's Post window - one for all its woodcutters.", "Радіус зони змінюється у вікні Колоди лісоруба - один на всіх її лісорубів.", "Радиус зоны меняется в окне Колоды лесоруба - один на всех её лесорубов." }, ["post_level_of"] = new string[3] { "Level {0} of {1}", "Рівень {0} з {1}", "Уровень {0} из {1}" }, ["tab_workers"] = new string[3] { "Woodcutters", "Лісоруби", "Лесорубы" }, ["tab_upgrade"] = new string[3] { "Upgrade", "Поліпшення", "Улучшение" }, ["card_hire"] = new string[3] { "Hiring", "Найм", "Наём" }, ["hire_count"] = new string[3] { "Woodcutters: {0} of {1} (level {2})", "Лісорубів: {0} з {1} (рівень {2})", "Лесорубов: {0} из {1} (уровень {2})" }, ["btn_hire"] = new string[3] { "Hire a woodcutter - {0} {1}", "Найняти лісоруба - {0} {1}", "Нанять лесоруба - {0} {1}" }, ["btn_level_limit"] = new string[3] { "Level limit", "Ліміт рівня", "Лимит уровня" }, ["btn_max_woodcutters"] = new string[3] { "Max woodcutters", "Максимум лісорубів", "Максимум лесорубов" }, ["you_have"] = new string[3] { "You have {0} {1}", "У вас {0} {1}", "У вас {0} {1}" }, ["hire_more_hint"] = new string[3] { "More woodcutters - see the Upgrade tab", "Більше лісорубів - у вкладці «Поліпшення»", "Больше лесорубов - во вкладке «Улучшение»" }, ["hire_hint"] = new string[3] { "A new one starts stopped - give it an axe", "Лісоруб з'являється зупиненим - дайте йому сокиру", "Лесоруб появляется остановленным - дайте ему топор" }, ["card_level"] = new string[3] { "Post level", "Рівень колоди", "Уровень колоды" }, ["level_allows"] = new string[3] { "Allows {0} {1}", "Можна мати {0} {1}", "Можно иметь {0} {1}" }, ["btn_upgrade"] = new string[3] { "Upgrade to level {0} - {1} {2}", "Поліпшити до рівня {0} - {1} {2}", "Улучшить до уровня {0} - {1} {2}" }, ["btn_max_level"] = new string[3] { "Max level", "Максимальний рівень", "Максимальный уровень" }, ["upgrade_hint"] = new string[3] { "Bought once for the whole world: even if the post is torn down and rebuilt, the level stays.", "Поліпшення купується один раз на весь світ: навіть якщо колоду знести й поставити знову, рівень лишиться.", "Улучшение покупается один раз на весь мир: даже если колоду снести и поставить снова, уровень останется." }, ["card_levels"] = new string[3] { "Levels", "Рівні", "Уровни" }, ["level_row"] = new string[3] { "Level {0}", "Рівень {0}", "Уровень {0}" }, ["level_current"] = new string[3] { "current", "поточний", "текущий" }, ["level_unlocked"] = new string[3] { "unlocked", "відкрито", "открыт" }, ["level_free"] = new string[3] { "no upgrade", "без поліпшення", "без улучшения" }, ["level_hire1"] = new string[3] { "hire - {0} {1}", "найм - {0} {1}", "наём - {0} {1}" }, ["level_hire2"] = new string[3] { "hire 2nd - {0} {1}", "найм 2-го - {0} {1}", "наём 2-го - {0} {1}" }, ["level_hire3"] = new string[3] { "hire 3rd - {0} (again - {1}) {2}", "найм 3-го - {0} (повторно - {1}) {2}", "наём 3-го - {0} (повторно - {1}) {2}" }, ["auto_repair"] = new string[3] { "Repair broken axes automatically", "Автоматично ремонтувати сокири", "Автоматически чинить топоры" }, ["auto_repair_hint"] = new string[3] { "A broken axe is repaired here for {0}% of its main material (bronze for a bronze axe...) - put it in this storage.", "Зламану сокиру ремонтують тут за {0}% її основного матеріалу (бронза для бронзової...) - покладіть його в це сховище.", "Сломанный топор чинят здесь за {0}% его основного материала (бронза для бронзового...) - положите его в это хранилище." }, ["repair_cost"] = new string[3] { "Repair: {0}", "Ремонт: {0}", "Ремонт: {0}" }, ["repair_none"] = new string[3] { "Repair: not possible for this axe", "Ремонт: для цієї сокири неможливий", "Ремонт: для этого топора невозможен" }, ["notify_axe_repaired"] = new string[3] { "Woodcutter {0}: axe repaired ({1})", "Лісоруб {0}: сокиру відремонтовано ({1})", "Лесоруб {0}: топор починен ({1})" }, ["notify_repair_missing"] = new string[3] { "Woodcutter {0}: can't repair the axe - the post needs {1}", "Лісоруб {0}: не вистачає на ремонт сокири - у колоді потрібно {1}", "Лесоруб {0}: не хватает на ремонт топора - в колоде нужно {1}" }, ["notify_repair_impossible"] = new string[3] { "Woodcutter {0}: this axe can't be repaired automatically", "Лісоруб {0}: цю сокиру не можна відремонтувати автоматично", "Лесоруб {0}: этот топор нельзя починить автоматически" }, ["card_storage"] = new string[3] { "Post storage", "Сховище колоди", "Хранилище колоды" }, ["storage_line"] = new string[3] { "Slots: {0} · axes: {1}/{2}", "Місць: {0} · сокир: {1}/{2}", "Мест: {0} · топоров: {1}/{2}" }, ["storage_hint"] = new string[3] { "E on the post - open. Woodcutters unload wood here when their inventory is 90% full; the top row is for axes.", "E на колоді - відкрити. Лісоруби складають сюди дерево, коли їхній інвентар заповнено на 90%; верхній ряд - під сокири.", "E на колоде - открыть. Лесорубы складывают сюда дерево, когда их инвентарь заполнен на 90%; верхний ряд - для топоров." }, ["card_post_zone"] = new string[3] { "Post work zone", "Робоча зона колоди", "Рабочая зона колоды" }, ["radius"] = new string[3] { "Radius", "Радіус", "Радиус" }, ["btn_save_radius"] = new string[3] { "Save radius", "Зберегти радіус", "Сохранить радиус" }, ["radius_saved"] = new string[3] { "Radius saved", "Радіус збережено", "Радиус сохранён" }, ["status_radius"] = new string[3] { "Zone radius: {0} m", "Радіус зони: {0} м", "Радиус зоны: {0} м" }, ["zone_hint"] = new string[3] { "When the zone runs out of trees, woodcutters come back here and wait until something grows.", "Коли в зоні скінчаться дерева, лісоруби повертаються сюди й чекають, поки щось виросте.", "Когда в зоне кончатся деревья, лесорубы возвращаются сюда и ждут, пока что-нибудь вырастет." }, ["card_list"] = new string[3] { "Woodcutters ({0})", "Лісоруби ({0})", "Лесорубы ({0})" }, ["list_empty_title"] = new string[3] { "Nobody yet", "Поки що жодного", "Пока никого" }, ["list_empty_hint"] = new string[3] { "Hire your first woodcutter on the left.", "Найміть першого лісоруба ліворуч.", "Наймите первого лесоруба слева." }, ["row_no_axe"] = new string[3] { "no axe", "без сокири", "без топора" }, ["row_inventory"] = new string[3] { "inventory {0} ({1}/{2})", "інвентар {0} ({1}/{2})", "инвентарь {0} ({1}/{2})" }, ["row_skill"] = new string[3] { "woodcutting {0}", "рубка дерев {0}", "рубка деревьев {0}" }, ["row_distance"] = new string[3] { "{0} m from the post", "{0} м від колоди", "{0} м от колоды" }, ["row_distance_unloaded"] = new string[3] { "{0} m from the post, not loaded - not working", "{0} м від колоди, не завантажений - не працює", "{0} м от колоды, не загружен - не работает" }, ["card_all"] = new string[3] { "All woodcutters", "Усі лісоруби", "Все лесорубы" }, ["btn_recall_all"] = new string[3] { "Stop all and call here", "Зупинити всіх і покликати сюди", "Остановить всех и позвать сюда" }, ["status_recalled"] = new string[3] { "Stopped and called to the post: {0}", "Зупинено й покликано до колоди: {0}", "Остановлено и позвано к колоде: {0}" }, ["status_none_in_world"] = new string[3] { "There are no woodcutters in the world", "У світі немає жодного лісоруба", "В мире нет ни одного лесоруба" }, ["btn_start_all"] = new string[3] { "Start all", "Запустити всіх", "Запустить всех" }, ["status_started"] = new string[3] { "Started: {0}", "Запущено: {0}", "Запущено: {0}" }, ["btn_bind_all"] = new string[3] { "Bind all here", "Закріпити всіх тут", "Закрепить всех здесь" }, ["status_bound"] = new string[3] { "Bound to this post: {0}", "Закріплено за цією колодою: {0}", "Закреплено за этой колодой: {0}" }, ["all_hint"] = new string[3] { "Bound woodcutters work in this post's zone. Far-away ones the game hasn't loaded don't work; called ones appear by the post right away.", "Закріплені лісоруби працюють у зоні цієї колоди. Далекі, яких гра зараз не завантажила, не працюють; покликані - одразу опиняються біля колоди.", "Закреплённые лесорубы работают в зоне этой колоды. Дальние, которых игра сейчас не загрузила, не работают; позванные - сразу оказываются у колоды." } }; internal static Lang Resolve(string configValue, string gameLanguage) { if (TryParse(configValue, out var lang)) { return lang; } if (!TryParse(gameLanguage, out var lang2)) { return Lang.English; } return lang2; } private static bool TryParse(string value, out Lang lang) { switch ((value ?? string.Empty).Trim().ToLowerInvariant()) { case "english": lang = Lang.English; return true; case "ukrainian": lang = Lang.Ukrainian; return true; case "russian": lang = Lang.Russian; return true; default: lang = Lang.English; return false; } } internal static string T(string key, params object[] args) { return Get(Current, key, args); } internal static string Get(Lang lang, string key, params object[] args) { if (!Table.TryGetValue(key, out var value)) { return key; } string text = value[(int)lang]; if (args != null && args.Length != 0) { return string.Format(CultureInfo.InvariantCulture, text, args); } return text; } internal static string Plural(string key, int n) { return Plural(Current, key, n); } internal static string Plural(Lang lang, string key, int n) { if (!Plurals.TryGetValue(key, out var value)) { return key; } return value[(int)lang].Split(new char[1] { '|' })[FormIndex(lang, n)]; } internal static int FormIndex(Lang lang, int n) { n = Math.Abs(n); if (lang == Lang.English) { if (n != 1) { return 2; } return 0; } int num = n % 100; int num2 = n % 10; if (num >= 11 && num <= 14) { return 2; } switch (num2) { case 1: return 0; default: return 2; case 2: case 3: case 4: return 1; } } internal static string SpeciesName(int index) { return Species[(int)Current][index]; } internal static string WoodcutterName(int index) { return Names[(int)Current][index]; } internal static IEnumerable AllLanguages(string key) { if (!Table.TryGetValue(key, out var value)) { return new string[0]; } return value; } } public class WoodcutterZoneRings : MonoBehaviour { private sealed class Ring { public LineRenderer Line; public Vector3 Center; public float Radius; public float BuiltAt; } private const float LineWidth = 0.3f; private const float HeightOffset = 0.35f; private const float RebuildInterval = 2f; private static readonly Color RingColor = new Color(0.95f, 0.68f, 0.25f, 0.9f); private static readonly string[] ShaderCandidates = new string[3] { "Sprites/Default", "Legacy Shaders/Particles/Alpha Blended", "Unlit/Color" }; private static WoodcutterZoneRings _instance; private readonly List<(Vector3 center, float radius)> _requests = new List<(Vector3, float)>(); private readonly List _rings = new List(); private Material _material; private bool _materialFailed; internal static void Request(Vector3 center, float radius) { //IL_0030: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) if ((Object)(object)_instance == (Object)null || radius <= 0f) { return; } foreach (var request in _instance._requests) { Vector3 item = request.center; float item2 = request.radius; Vector3 val = item - center; if (((Vector3)(ref val)).sqrMagnitude < 0.01f && Mathf.Abs(item2 - radius) < 0.01f) { return; } } _instance._requests.Add((center, radius)); } private void Awake() { _instance = this; } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } private void LateUpdate() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) int num = 0; if ((Object)(object)Player.m_localPlayer != (Object)null && EnsureMaterial()) { foreach (var request in _requests) { Vector3 item = request.center; float item2 = request.radius; Ring ring = ((num < _rings.Count) ? _rings[num] : CreateRing()); num++; Show(ring, item, item2); } } _requests.Clear(); for (int i = num; i < _rings.Count; i++) { if ((Object)(object)_rings[i].Line != (Object)null && ((Renderer)_rings[i].Line).enabled) { ((Renderer)_rings[i].Line).enabled = false; } } } private void Show(Ring ring, Vector3 center, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ring.Center - center; if (((Vector3)(ref val)).sqrMagnitude > 0.01f || !Mathf.Approximately(ring.Radius, radius) || !((Renderer)ring.Line).enabled || Time.time - ring.BuiltAt > 2f) { Build(ring, center, radius); } ((Renderer)ring.Line).enabled = true; } private static void Build(Ring ring, Vector3 center, float radius) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) int num = WoodcutterLogic.RingPointCount(radius); ring.Line.positionCount = num; for (int i = 0; i < num; i++) { float num2 = (float)i * (float)Math.PI * 2f / (float)num; Vector3 val = center + new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * radius; val.y = GroundHeight(val, center.y) + 0.35f; ring.Line.SetPosition(i, val); } ring.Center = center; ring.Radius = radius; ring.BuiltAt = Time.time; } private static float GroundHeight(Vector3 point, float fallback) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) float result = default(float); if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(point, ref result)) { return result; } return fallback; } private Ring CreateRing() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("WoodcutterZoneRing"); val.transform.SetParent(((Component)this).transform, false); LineRenderer val2 = val.AddComponent(); val2.useWorldSpace = true; val2.loop = true; val2.widthMultiplier = 0.3f; ((Renderer)val2).material = _material; val2.startColor = RingColor; val2.endColor = RingColor; val2.numCornerVertices = 2; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val2).receiveShadows = false; ((Renderer)val2).enabled = false; Ring ring = new Ring { Line = val2 }; _rings.Add(ring); return ring; } private bool EnsureMaterial() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if ((Object)(object)_material != (Object)null) { return true; } if (_materialFailed) { return false; } string[] shaderCandidates = ShaderCandidates; for (int i = 0; i < shaderCandidates.Length; i++) { Shader val = Shader.Find(shaderCandidates[i]); if ((Object)(object)val != (Object)null) { _material = new Material(val) { color = RingColor }; return true; } } _materialFailed = true; Logger.LogWarning((object)"WoodcutterNPC: no usable shader found, work zone rings are disabled."); return false; } } }