Decompiled source of GK2 Zombie PlusPlus v0.1.0
GK2ZombiePlusPlus.dll
Decompiled 21 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GK2.Framework; using HarmonyLib; using LazyBearTechnology; using Microsoft.CodeAnalysis; using Pathfinding; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [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 GK2ZombiePlusPlus { internal static class Chores { private static readonly HashSet<string> HiveIds = new HashSet<string> { "honey_home", "honey_wild" }; private static readonly HashSet<string> HarvestItems = new HashSet<string> { "honey", "beeswax", "apple", "berry", "berry_blue", "flower_rhod", "fireflight", "fertilizer:peat" }; internal const string Leaf = "leaf"; private static readonly FieldRef<WorldZoneData, List<OrderBase>> ZoneOrders = AccessTools.FieldRefAccess<WorldZoneData, List<OrderBase>>("orders"); private static List<Item> _capture; private static readonly FieldInfo CurScene = AccessTools.Field(AccessTools.TypeByName("PlayerController"), "currentGameScene"); private static readonly PropertyInfo PlayerCtl = AccessTools.Property(typeof(MainGame), "PlayerController"); private static int _readyTicks; private static ZombieWgoData _collector; private static readonly FieldRef<ZombieWgoData, SGuid> GardenerTarget = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("gardenerCurrentTargetUniqueId"); private static readonly MethodInfo GardenerArrived = AccessTools.Method(typeof(ZombieWgoData), "GardenerOnPathSuccess", (Type[])null, (Type[])null); private static readonly FieldRef<ZombieWgoData, SGuid> GardenerMoveTarget = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("gardenerCurrentMovementTargetUniqueId"); private static readonly FieldRef<ZombieWgoData, SGuid> GardenerStationId = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("gardenerStation"); private static readonly FieldRef<ZombieWgoData, ZombieGardenerState> GardenerPrevState = AccessTools.FieldRefAccess<ZombieWgoData, ZombieGardenerState>("gardenerPreviousState"); private static readonly FieldRef<ZombieWgoData, float> GardenerRetryTimer = AccessTools.FieldRefAccess<ZombieWgoData, float>("gardenerTimeForCheckFailedPathAgain"); private static readonly HashSet<Guid> OffRoad = new HashSet<Guid>(); private static readonly Dictionary<Guid, int> WalkFails = new Dictionary<Guid, int>(); private const int MaxWalkFails = 3; private static bool _hpTickWarned; private static readonly HashSet<string> Told = new HashSet<string>(); private static readonly FieldRef<ZombieWgoData, Inventory> PorterInv = AccessTools.FieldRefAccess<ZombieWgoData, Inventory>("porterInventory"); public static void TickPost() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 if (!Plugin.Enabled.Value) { return; } try { if (!IsHostOrSolo() || !SceneReady()) { return; } ZombieSystemData zombieSystemData = MainGame.ZombieSystemData; if (zombieSystemData == null || MainGame.WorldData == null) { return; } Dictionary<WorldZoneData, List<ZombieWgoData>> dictionary = new Dictionary<WorldZoneData, List<ZombieWgoData>>(); Dictionary<WorldZoneData, List<ZombieWgoData>> dictionary2 = new Dictionary<WorldZoneData, List<ZombieWgoData>>(); List<ZombieWgoData> list = new List<ZombieWgoData>(); foreach (SGuid item in new List<SGuid>(zombieSystemData.zombieOnSceneWgoIds)) { ZombieWgoData zombie = zombieSystemData.GetZombie(item); WorldZoneData val = ((zombie != null) ? ((WgoData)zombie).WorldZoneData : null); if (val == null) { continue; } list.Add(zombie); Dictionary<WorldZoneData, List<ZombieWgoData>> dictionary3 = (((int)zombie.ZombieType == 2) ? dictionary : (((int)zombie.ZombieType == 6 && HasShovel(zombie)) ? dictionary2 : null)); if (dictionary3 != null) { if (!dictionary3.TryGetValue(val, out var value)) { value = (dictionary3[val] = new List<ZombieWgoData>()); } value.Add(zombie); } } Errands.Watch(list); Errands.DescribeGardeners(list); bool value2 = Plugin.GardenerCompost.Value; bool value3 = Plugin.HelperCollects.Value; foreach (KeyValuePair<WorldZoneData, List<ZombieWgoData>> item2 in dictionary) { bool flag = value2 && !dictionary2.ContainsKey(item2.Key); if (value3 || flag) { Errands.Helpers(item2.Key, item2.Value, value3, flag); } } foreach (KeyValuePair<WorldZoneData, List<ZombieWgoData>> item3 in dictionary2) { if (value2) { Errands.Compost(item3.Key, item3.Value); } PlaceHarvestOrders(item3.Key, item3.Value); } Notify.Tick(list); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Tick failed: " + ex)); } } private static bool SceneReady() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 bool flag = false; try { MainGame instance = MainGame.Instance; object obj = ((!((Object)(object)instance != (Object)null) || (int)instance.gameState != 1) ? null : PlayerCtl?.GetValue(null)); flag = obj != null && (CurScene == null || CurScene.GetValue(obj) != null); } catch { } if (!flag) { _readyTicks = 0; return false; } return ++_readyTicks >= 2; } private static bool IsHostOrSolo() { try { return !LazyNetwork.IsInitialized || !LazyNetwork.NetworkManager.IsCoopGame || LazyNetwork.NetworkManager.IsHost; } catch { return true; } } private static bool HasShovel(ZombieWgoData z) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 Item hand = z.Hand; if (hand != null && !hand.IsEmpty && ((ObjectLinkedToDefinition<ItemDef>)(object)hand).Definition != null) { return (int)((ObjectLinkedToDefinition<ItemDef>)(object)hand).Definition.type == 2; } return false; } internal static IEnumerable<WgoData> ZoneObjects(WorldZoneData zone) { foreach (SGuid item in new List<SGuid>(zone.wgoDataList)) { WgoData wgoData = MainGame.WorldData.GetWgoData(item); if (wgoData != null && ((ObjectLinkedToDefinition<WGODef>)(object)wgoData).Definition != null) { yield return wgoData; } } } internal static bool IsCompost(WgoData w) { if (((ObjectLinkedToDefinition<WGODef>)(object)w).id != null) { return ((ObjectLinkedToDefinition<WGODef>)(object)w).id.StartsWith("compost_pile"); } return false; } internal static List<Item> FinishCraft(WgoData w, ZombieWgoData by) { List<Item> result = (_capture = new List<Item>()); _collector = by; try { w.ProcessReadyToFinishCraft(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("finishing " + ((ObjectLinkedToDefinition<WGODef>)(object)w).id + " threw, keeping what came out: " + ex.Message)); } finally { _capture = null; _collector = null; } return result; } public static bool DropTechPre(WgoData __instance) { ZombieWgoData collector = _collector; if (collector == null || _capture == null) { return true; } try { int gameResInt = __instance.GetGameResInt("game_res_tech_red"); int gameResInt2 = __instance.GetGameResInt("game_res_tech_green"); int gameResInt3 = __instance.GetGameResInt("game_res_tech_blue"); __instance.SetGameRes("game_res_tech_red", 0); __instance.SetGameRes("game_res_tech_green", 0); __instance.SetGameRes("game_res_tech_blue", 0); if (gameResInt + gameResInt2 + gameResInt3 > 0) { collector.DoTechPointsReward(__instance, gameResInt, gameResInt2, gameResInt3); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("tech points from " + ((ObjectLinkedToDefinition<WGODef>)(object)__instance).id + " to the zombie: " + gameResInt + "/" + gameResInt2 + "/" + gameResInt3)); } } return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("tech points: " + ex.Message)); return true; } } public static bool MakeDropPre(Item item) { if (_capture == null || item == null || item.IsEmpty) { return true; } _capture.Add(item); return false; } internal static void Store(List<Inventory> inventories, Item item) { int num = 0; while (item.Count > 0 && num < 64) { Inventory val = null; foreach (Inventory inventory in inventories) { if (((inventory != null) ? inventory.Data : null) != null && inventory.Data.CanAddItemCountToInventory(item, true, (Item)null, false) > 0) { if (inventory.Data.HasItemByItemId(((ObjectLinkedToDefinition<ItemDef>)(object)item).id, 1)) { val = inventory; break; } if (val == null) { val = inventory; } } } if (val == null) { break; } if (((ObjectLinkedToDefinition<ItemDef>)(object)item).Definition.stackCount == 1 || val.Data.CanAddItemCountToInventory(item, true, (Item)null, false) >= item.Count) { int count = item.Count; val.AddItemToInventory(item, (Item)null, false); if (count - item.Count <= 0) { break; } } else { int num2 = Math.Min(val.Data.CanAddItemCountToInventory(item, true, (Item)null, false), item.Count); if (num2 <= 0) { break; } Item val2 = item.Split(num2, false); val.AddItemToInventory(val2, (Item)null, false); int num3 = num2 - val2.Count; if (val2.Count > 0) { item.Count += val2.Count; } if (num3 <= 0) { break; } } num++; } } internal static string ZoneName(WgoData w) { try { return ((BalanceBaseObject)(((ObjectLinkedToDefinition<WorldZoneDef>)(object)w.WorldZoneData)?.Definition?)).id ?? "?"; } catch { return "?"; } } internal static CraftDefBase CompostCanStart(WgoData w, MultiInventory chests) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 CraftComponent craftComponent = w.CraftComponent; if (craftComponent == null || craftComponent.IsStarted || craftComponent.HasCraftsInQueue || craftComponent.IsDestroyingCraftActive || (int)craftComponent.Status == 7) { return null; } CraftDefBase val = null; List<CraftDefBase> availableCrafts = craftComponent.AvailableCrafts; if (availableCrafts != null) { foreach (CraftDefBase item in availableCrafts) { if (item != null && item.isAuto) { val = item; break; } } } if (val == null || chests == null || chests.inventoryList.Count == 0) { return null; } int num = 0; foreach (NeedItemData needItem in val.needItems) { if (needItem.id == "leaf") { num += needItem.GetCount(w); } } if (num > 0 && chests.GetTotalCount("leaf") - Plugin.CompostKeepLeaves.Value < num) { return null; } return val; } private static bool IsHarvestTarget(WgoData w) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 WGODef definition = ((ObjectLinkedToDefinition<WGODef>)(object)w).Definition; if (definition == null || (int)definition.interactionType != 1) { return false; } if (HiveIds.Contains(((ObjectLinkedToDefinition<WGODef>)(object)w).id)) { return Plugin.GardenerHives.Value; } if (((ObjectLinkedToDefinition<WGODef>)(object)w).id.StartsWith("tree_apple_")) { return Plugin.GardenerTreesBushes.Value; } if (definition.wgoGroup == "collectable_bushes") { return Plugin.GardenerTreesBushes.Value; } return false; } private static void PlaceHarvestOrders(WorldZoneData zone, List<ZombieWgoData> gardeners) { //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown foreach (WgoData item in ZoneObjects(zone)) { if (Plugin.Verbose.Value && ((ObjectLinkedToDefinition<WGODef>)(object)item).id != null && ((ObjectLinkedToDefinition<WGODef>)(object)item).id.EndsWith("_ready") && (((ObjectLinkedToDefinition<WGODef>)(object)item).id.StartsWith("garden_") || ((ObjectLinkedToDefinition<WGODef>)(object)item).id.StartsWith("vineyard_")) && zone.FindOrdersByTarget(item.UniqueId, typeof(GatherOrder)).Count == 0) { Why(item, "ripe bed with no crop sign on it: the game gives gardeners no order for it (put the crop's sign on the bed)"); } if (!IsHarvestTarget(item)) { continue; } if (item.HpComponent == null || item.HpComponent.Hp <= 0) { if (Plugin.Verbose.Value) { Why(item, "nothing to take yet (hp " + ((item.HpComponent == null) ? "none" : item.HpComponent.Hp.ToString()) + ")"); } } else if (!AnyCanHarvest(gardeners, item)) { if (!Plugin.Verbose.Value) { continue; } int val = 0; foreach (ZombieWgoData gardener in gardeners) { val = Math.Max(val, gardener.GetMasteryLevelForTalentBranch("talent_green", (CraftDefBase)null)); } Why(item, "ready, but no gardener here has the green talent for it (best " + val + ")"); } else if (zone.FindOrdersByTarget(item.UniqueId, typeof(GatherOrder)).Count <= 0) { zone.PlaceNewOrder((OrderBase)new GatherOrder(item.UniqueId, Item.Empty)); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("gather order for " + ((ObjectLinkedToDefinition<WGODef>)(object)item).id + " in " + ZoneName(item))); } } } } public static bool GardenerMovePre(ZombieWgoData __instance) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Invalid comparison between Unknown and I4 //IL_025a: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Enabled.Value || GardenerArrived == null) { return true; } try { Guid guid = ((WgoData)__instance).UniqueId.Guid; SGuid val = GardenerTarget.Invoke(__instance); WgoData val2 = ((val == (SGuid)null) ? null : MainGame.WorldData.GetWgoData(val)); if (val2 == null) { return true; } bool flag = IsHarvestTarget(val2) || Errands.IsGardenerErrand(__instance, val2); if (!flag && !OffRoad.Contains(guid)) { return true; } if ((int)__instance.GardenerState == 8) { if (GardenerRetryTimer.Invoke(__instance) > 0f) { return false; } GardenerRetryTimer.Invoke(__instance) = 0f; __instance.GardenerState = GardenerPrevState.Invoke(__instance); WalkFails.TryGetValue(guid, out var value); value = (WalkFails[guid] = value + 1); if (value == 2 && flag) { if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("gardener finds no path to " + ((ObjectLinkedToDefinition<WGODef>)(object)val2).id + ", walks straight")); } if (((WgoData)__instance).MovementComponent.IsMoving) { ((WgoData)__instance).MovementComponent.ForceStop(); } if (StartWalk(__instance, val2, val, (Graph)(-1))) { return false; } } if (value >= 3) { Plugin.Log.LogWarning((object)("gardener can't walk to " + ((ObjectLinkedToDefinition<WGODef>)(object)val2).id + " in " + ZoneName(val2) + ", working it from where it stands")); OffRoad.Remove(guid); WalkFails.Remove(guid); if (!flag) { return true; } if (((WgoData)__instance).MovementComponent.IsMoving) { ((WgoData)__instance).MovementComponent.ForceStop(); } GardenerArrived.Invoke(__instance, null); return false; } } else { SGuid obj = GardenerMoveTarget.Invoke(__instance); if (((obj != null) ? new Guid?(obj.Guid) : ((Guid?)null)) == val.Guid) { return false; } } if (((WgoData)__instance).MovementComponent.IsMoving) { ((WgoData)__instance).MovementComponent.ForceStop(); } StartWalk(__instance, val2, val, WalkGraph(((WgoData)__instance).WorldZoneData)); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Gardener move: " + ex.Message)); return true; } } private unsafe static bool StartWalk(ZombieWgoData z, WgoData target, SGuid targetId, Graph graph) { //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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Invalid comparison between Unknown and I4 //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Invalid comparison between Unknown and I4 SGuid obj = GardenerStationId.Invoke(z); bool toStation = ((obj != null) ? new Guid?(obj.Guid) : ((Guid?)null)) == targetId.Guid; Vector3 val = WalkEnd(z, target, toStation); StartPathResult val2 = (((int)graph != -1) ? ((WgoData)z).MovementComponent.StartPath(val, graph, ((WgoData)z).WorldId, 1.5f, "", (Action)null, (DestinationType)0) : ((WgoData)z).MovementComponent.StartPath(val, ((WgoData)z).WorldId, ((WgoData)z).WorldId, (MovementType)1, 1.5f, "", (Action)null, (Seeker)null, (DestinationType)0)); if ((int)val2 != 0) { if ((int)val2 == 1) { GardenerArrived.Invoke(z, null); return true; } GardenerRetryTimer.Invoke(z) = 1f; z.GardenerState = (ZombieGardenerState)8; return false; } GardenerMoveTarget.Invoke(z) = targetId; OffRoad.Add(((WgoData)z).UniqueId.Guid); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("gardener walks (" + (((int)graph != -1) ? ("mesh " + ((object)(*(Graph*)(&graph))/*cast due to .constrained prefix*/).ToString()) : "straight") + ") to " + ((ObjectLinkedToDefinition<WGODef>)(object)target).id)); } return true; } public static bool HpTickPre(Wgo __instance) { if ((Object)(object)__instance != (Object)null) { return (Object)(object)__instance.MainWgoPart != (Object)null; } return false; } public static Exception HpTickFin(Exception __exception, Wgo __instance) { if (__exception == null) { return null; } if (!_hpTickWarned) { _hpTickWarned = true; Plugin.Log.LogWarning((object)("the hit animation of " + (((__instance == null) ? null : ((ObjectLinkedToDefinition<WGODef>)(object)__instance.Data)?.id) ?? "?") + " failed (" + __exception.GetType().Name + "); skipped so the work goes on")); } return null; } public static bool GardenerArrivedPre(ZombieWgoData __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 try { Guid guid = ((WgoData)__instance).UniqueId.Guid; WalkFails.Remove(guid); if ((int)__instance.GardenerState == 1) { OffRoad.Remove(guid); } return Errands.GardenerArrived(__instance); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Gardener arrival: " + ex.Message)); return true; } } private static Graph WalkGraph(WorldZoneData zone) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000d: 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_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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0046: 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_0066: Unknown result type (might be due to invalid IL or missing references) if (zone != null) { if ((int)zone.navigationGraph != -1) { return zone.navigationGraph; } if (ZoneNav.TryGet(zone, out var graph)) { return graph; } List<Graph> movementGraphs = zone.MovementGraphs; if (movementGraphs != null) { foreach (Graph item in movementGraphs) { if ((int)item != -1 && (int)item != 2 && (int)item != 3) { return item; } } } } return (Graph)(-1); } private static Vector3 WalkEnd(ZombieWgoData z, WgoData target, bool toStation) { //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_0038: 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_001a: 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_004d: 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_0045: 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) Vector3 position = ((WgoData)z).Position; Vector3 result = default(Vector3); Direction val = default(Direction); if (toStation) { GDPointData gDPointData = target.GetGDPointData("zombie_garden_crafter_gd_point"); if (gDPointData != null) { return gDPointData.Position; } } else if (GardenBedNavigation.IsGardenPlot(target) && GardenBedNavigation.TryGetOpenApproach(target, position, ref result, ref val)) { return result; } if (target.GetNearestDockPointData(position, (Availability)0) != null) { return target.GetNearestDockPointDataWorldPositionOrMyPosition(position, (Availability)0, (Func<DockPointData, Vector3, bool>)null); } return StepShort(position, target); } internal static Vector3 StepShort(Vector3 from, WgoData target) { //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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_013d: 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_0028: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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) Vector3 val = target.Position; float num = 1.2f; try { Rect val2 = ((target.MainWgoPartData != null) ? target.MainWgoPartData.GetCollisionBoundsRect(target.Position) : Rect.zero); if (((Rect)(ref val2)).width > 0.01f && ((Rect)(ref val2)).height > 0.01f) { val = new Vector3(((Rect)(ref val2)).center.x, target.Position.y, ((Rect)(ref val2)).center.y); Vector3 val3 = from - val; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { val3 = Vector3.back; } ((Vector3)(ref val3)).Normalize(); float num2 = ((Mathf.Abs(val3.x) > 0.001f) ? (((Rect)(ref val2)).width * 0.5f / Mathf.Abs(val3.x)) : float.MaxValue); float num3 = ((Mathf.Abs(val3.z) > 0.001f) ? (((Rect)(ref val2)).height * 0.5f / Mathf.Abs(val3.z)) : float.MaxValue); num = Mathf.Clamp(Mathf.Min(num2, num3) + 0.4f, 0.5f, 2.5f); } } catch { } Vector3 val4 = from - val; val4.y = 0f; if (((Vector3)(ref val4)).sqrMagnitude < 0.01f) { val4 = Vector3.back; } return val + ((Vector3)(ref val4)).normalized * num; } private static bool CanHarvest(ZombieWgoData z, WgoData hive) { string talent = ((ObjectLinkedToDefinition<WGODef>)(object)hive).Definition.talent; if (string.IsNullOrEmpty(talent) || ((ObjectLinkedToDefinition<WGODef>)(object)hive).Definition.noMasteryLock) { return true; } return z.GetMasteryLevelForTalentBranch(talent, (CraftDefBase)null) >= ((ObjectLinkedToDefinition<WGODef>)(object)hive).Definition.MasteryLock; } private static void Why(WgoData w, string reason) { if (Told.Add(w.UniqueId.Guid.ToString() + reason)) { Plugin.Log.LogInfo((object)(((ObjectLinkedToDefinition<WGODef>)(object)w).id + " in " + ZoneName(w) + ": " + reason)); } } private static bool AnyCanHarvest(List<ZombieWgoData> gardeners, WgoData hive) { foreach (ZombieWgoData gardener in gardeners) { if (CanHarvest(gardener, hive)) { return true; } } return false; } public static void GardenerOrderPre(WorldZoneData __instance, ZombieWgoData orderTaker, ref List<OrderBase> __state) { __state = null; if (!Plugin.Enabled.Value || orderTaker == null) { return; } try { List<OrderBase> list = ZoneOrders.Invoke(__instance); if (list == null) { return; } foreach (OrderBase item in list) { if (item is GatherOrder && item.ExecutorUniqueId.IsEmpty) { WgoData wgoData = MainGame.WorldData.GetWgoData(item.TargetWgoUniqueId); if (wgoData != null && IsHarvestTarget(wgoData) && !CanHarvest(orderTaker, wgoData)) { item.ExecutorUniqueId = ((WgoData)orderTaker).UniqueId; (__state ?? (__state = new List<OrderBase>())).Add(item); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Hive order filter: " + ex.Message)); } } public static Exception GardenerOrderFin(Exception __exception, List<OrderBase> __state) { if (__state != null) { foreach (OrderBase item in __state) { item.ExecutorUniqueId = SGuid.Empty; } } return __exception; } public static void GardenerDepositPost(ZombieWgoData __instance) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Enabled.Value) { return; } try { Inventory workerInventory = __instance.WorkerInventory; object obj; if (workerInventory == null) { obj = null; } else { Item data = workerInventory.Data; obj = ((data != null) ? data.Inventory : null); } if (obj == null) { return; } List<string> list = null; foreach (Item item in workerInventory.Data.Inventory) { if (item != null && !item.IsEmpty && (Plugin.GardenerUnloadAll.Value ? IsCargo(__instance, item) : HarvestItems.Contains(((ObjectLinkedToDefinition<ItemDef>)(object)item).id)) && (list == null || !list.Contains(((ObjectLinkedToDefinition<ItemDef>)(object)item).id))) { (list ?? (list = new List<string>())).Add(((ObjectLinkedToDefinition<ItemDef>)(object)item).id); } } if (list == null) { return; } List<Inventory> inventoryList = new MultiInventory(((WgoData)__instance).WorldZoneData, (WgoData)null, false).inventoryList; foreach (string item2 in list) { foreach (Item item3 in workerInventory.RemoveItemById(item2, -1, (Item)null, (Item)null, false)) { Store(inventoryList, item3); if (item3.Count > 0) { workerInventory.AddItemToInventory(item3, (Item)null, false); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Gardener unload: " + ex.Message)); } } internal static bool IsCargo(ZombieWgoData z, Item it) { ItemDef definition = ((ObjectLinkedToDefinition<ItemDef>)(object)it).Definition; if (definition == null || ((ObjectLinkedToDefinition<ItemDef>)(object)it).id == "fake_porter_slot_filler") { return false; } if (definition.isMainOrgan || definition.isOrganMistake || definition.isTool || definition.isWeapon || definition.isBag) { return false; } if (definition.redSkulls != 0 || definition.whiteSkulls != 0) { return false; } List<string> itemGroupIds = definition.itemGroupIds; if (itemGroupIds != null && (itemGroupIds.Contains("bodypart") || itemGroupIds.Contains("burial_reward"))) { return false; } SGuid uniqueId = it.UniqueId; if (uniqueId != (SGuid)null && (uniqueId == z.equippedHand || uniqueId == z.equippedArmor || uniqueId == z.equippedCollar)) { return false; } return true; } public static void PorterCheckPre(ZombieWgoData __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 if (!Plugin.Enabled.Value || (int)__instance.ZombieType != 5) { return; } try { Inventory val = PorterInv.Invoke(__instance); int value = Plugin.PorterSlots.Value; if (((val != null) ? val.Data : null) != null && val.Data.InventorySize != value && val.Data.InventoryFillSize <= 0 && ((WgoData)__instance).GetGameResInt("is_staying_at_porter_station") == 1) { PorterInv.Invoke(__instance) = Inventory.Create(value, false, (WhiteListItemFilter)null, (BlackListItemFilter)null, ""); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("porter backpack: " + val.Data.InventorySize + " -> " + value + " slots")); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Porter backpack: " + ex.Message)); } } public static void PorterUnloadPost(ZombieWgoData __instance) { try { Notify.PorterUnloaded(__instance, PorterInv.Invoke(__instance)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Porter check: " + ex.Message)); } } } internal static class Cosmetics { internal sealed class Item { public string Id; public string Folder; public readonly Dictionary<string, string> Names = new Dictionary<string, string>(); public Sprite[] Frames = (Sprite[])(object)new Sprite[0]; public Sprite[] Left; public Sprite[] Up; public float Sink = 10f; public float X; public float Y; public float Fps = 12f; public bool HideUp; public int Beard; public Sprite RefDown; public Sprite RefLeft; public string Name { get { if (Beard > 0) { return T.S("WardrobeBeard") + " " + (Beard - 9000); } string text = "en"; try { text = (LLBase.CurrentLang ?? "en").ToLowerInvariant(); } catch { } if (Names.TryGetValue(text, out var value) || (text.Length >= 2 && Names.TryGetValue(text.Substring(0, 2), out value))) { return value; } if (!Names.TryGetValue("en", out value)) { return Path.GetFileName(Folder); } return value; } } } private static List<Item> _items; internal const string LayerName = "zpp_accessory"; private static Material _plain; private static readonly Dictionary<Shader, Material> BeardMats = new Dictionary<Shader, Material>(); private static Texture2D _beardPalette; private static float _beardPaletteAt = -100f; private static readonly Dictionary<string, Sprite> StillFrames = new Dictionary<string, Sprite>(); internal static List<Item> All { get { if (_items == null) { Load(); } return _items; } } internal static Item Find(string id) { if (string.IsNullOrEmpty(id)) { return null; } foreach (Item item in All) { if (item.Id == id) { return item; } } return null; } internal static void Reload() { _items = null; } private static void Load() { _items = new List<Item>(); List<string> list = new List<string>(); try { string[] directories = Directory.GetDirectories(Paths.PluginPath, "zombie_cosmetics", SearchOption.AllDirectories); foreach (string item in directories) { list.Add(item); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("cosmetics: " + ex.Message)); } foreach (string item3 in list) { string fileName = Path.GetFileName(Path.GetDirectoryName(item3)); string[] directories = Directory.GetDirectories(item3); foreach (string text in directories) { try { Item item2 = LoadItem(fileName, text); if (item2 != null && item2.Frames.Length != 0) { _items.Add(item2); } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("cosmetic " + text + ": " + ex2.Message)); } } } _items.Sort((Item a, Item b) => string.CompareOrdinal(a.Id, b.Id)); try { _items.InsertRange(0, GameBeards()); } catch (Exception ex3) { Plugin.Log.LogWarning((object)("cosmetics: the game's beards: " + ex3.Message)); } Plugin.Log.LogInfo((object)("cosmetics: " + _items.Count + " items from " + list.Count + " pack folder(s)")); } private static Item LoadItem(string pack, string dir) { Item item = new Item { Id = pack + "/" + Path.GetFileName(dir), Folder = dir }; string path = Path.Combine(dir, "item.txt"); if (File.Exists(path)) { string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); int num = text.IndexOf('#'); if (num >= 0) { text = text.Substring(0, num).Trim(); } int num2 = text.IndexOf('='); if (num2 <= 0) { continue; } string text2 = text.Substring(0, num2).Trim().ToLowerInvariant(); string text3 = text.Substring(num2 + 1).Trim(); if (text2 == "name") { item.Names["en"] = text3; continue; } if (text2.StartsWith("name.")) { item.Names[text2.Substring(5)] = text3; continue; } switch (text2) { case "sink": item.Sink = F(text3, item.Sink); break; case "x": item.X = F(text3, 0f); break; case "y": item.Y = F(text3, 0f); break; case "fps": item.Fps = F(text3, item.Fps); break; case "hide.up": item.HideUp = text3.Equals("true", StringComparison.OrdinalIgnoreCase) || text3 == "1"; break; } } } item.Frames = Frames(dir, ""); Sprite[] array2 = Frames(dir, "left_"); Sprite[] array3 = Frames(dir, "up_"); if (array2.Length != 0) { item.Left = array2; } if (array3.Length != 0) { item.Up = array3; } return item; } private static List<Item> GameBeards() { List<Item> list = new List<Item>(); EasySpritesCollection coll = LazySingletonSO<EasySpritesCollection>.Instance; Sprite val = Get("9001_hed_static_down"); Sprite val2 = Get("9001_hed_static_left"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return list; } for (int i = 9001; i <= 9099; i++) { Sprite val3 = Get(i + "_brd_static_down"); if (!((Object)(object)val3 == (Object)null)) { Sprite val4 = Get(i + "_brd_static_left"); list.Add(new Item { Id = "game/beard_" + i, Folder = "", Beard = i, HideUp = true, Sink = 0f, Frames = (Sprite[])(object)new Sprite[1] { val3 }, Left = (Sprite[])(object)((!((Object)(object)val4 != (Object)null)) ? null : new Sprite[1] { val4 }), RefDown = val, RefLeft = val2 }); } } return list; Sprite Get(string n) { if (!coll.HasSprite(n)) { return null; } return coll.GetSprite(n, (string)null); } } private static float F(string s, float def) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return def; } return result; } private static Sprite[] Frames(string dir, string prefix) { //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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0070: 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) List<Sprite> list = new List<Sprite>(); int num = 0; while (true) { string path = Path.Combine(dir, prefix + num + ".png"); if (!File.Exists(path)) { break; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path))) { break; } ((Texture)val).filterMode = (FilterMode)0; list.Add(Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0f), 50f)); num++; } return list.ToArray(); } internal static void Draw(Component view, Item item) { //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0375: 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_0338: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)view == (Object)null) { return; } SpriteRenderer val = null; SpriteRenderer[] componentsInChildren = view.GetComponentsInChildren<SpriteRenderer>(false); foreach (SpriteRenderer val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sprite != (Object)null && ((Object)val2).name != "zpp_accessory" && ((Object)val2).name != "zpp_hat" && ((Object)val2.sprite).name.Contains("_hed_")) { val = val2; break; } } if ((Object)(object)val == (Object)null) { return; } Transform val3 = ((Component)val).transform.Find("zpp_accessory"); if (item == null) { if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } return; } string name = ((Object)val.sprite).name; bool flag = name.Contains("_up"); bool flag2 = name.Contains("_left") || name.Contains("_right"); if (flag && item.HideUp) { if ((Object)(object)val3 != (Object)null) { ((Component)val3).gameObject.SetActive(false); } return; } Sprite[] array = ((flag && item.Up != null) ? item.Up : ((flag2 && item.Left != null) ? item.Left : item.Frames)); if (array.Length == 0) { return; } SpriteRenderer val5; if ((Object)(object)val3 == (Object)null) { GameObject val4 = new GameObject("zpp_accessory"); val4.transform.SetParent(((Component)val).transform, false); val4.layer = ((Component)val).gameObject.layer; val5 = val4.AddComponent<SpriteRenderer>(); if ((Object)(object)_plain == (Object)null) { _plain = ((Renderer)val5).sharedMaterial; } val3 = val4.transform; } else { val5 = ((Component)val3).GetComponent<SpriteRenderer>(); } ((Component)val3).gameObject.SetActive(true); Material val6 = ((item.Beard > 0) ? BeardMaterial(val) : null); Material val7 = (((Object)(object)val6 != (Object)null) ? val6 : _plain); if ((Object)(object)val7 != (Object)null && (Object)(object)((Renderer)val5).sharedMaterial != (Object)(object)val7) { ((Renderer)val5).sharedMaterial = val7; } ((Renderer)val5).sortingLayerID = ((Renderer)val).sortingLayerID; int sortingOrder = ((Renderer)val).sortingOrder; componentsInChildren = view.GetComponentsInChildren<SpriteRenderer>(false); foreach (SpriteRenderer val8 in componentsInChildren) { if ((Object)(object)val8 != (Object)null && (Object)(object)val8 != (Object)(object)val5 && ((Renderer)val8).sortingLayerID == ((Renderer)val).sortingLayerID && ((Renderer)val8).sortingOrder > sortingOrder) { sortingOrder = ((Renderer)val8).sortingOrder; } } ((Renderer)val5).sortingOrder = sortingOrder + 1; val5.flipX = val.flipX; val5.sprite = ((array.Length == 1) ? array[0] : array[(int)(Time.time * Mathf.Max(0.1f, item.Fps)) % array.Length]); if (item.Beard > 0) { Sprite s = (flag2 ? item.RefLeft : item.RefDown); float mid; Vector2 val9 = Drawn(Still(val.sprite), out mid); float mid2; Vector2 val10 = Drawn(s, out mid2); float num = mid - mid2; float num2 = val9.y - val10.y; val3.localPosition = new Vector3(val.flipX ? (0f - num) : num, num2 + item.Y / 50f, 0f); return; } Sprite val11 = Still(val.sprite); float num3 = ((val11.pixelsPerUnit > 0f) ? val11.pixelsPerUnit : 50f); Vector2 val12; Rect val13; try { val12 = val11.textureRectOffset; val13 = val11.textureRect; } catch { val12 = Vector2.zero; val13 = val11.rect; } float num4 = (val12.y + ((Rect)(ref val13)).height - val11.pivot.y) / num3; float num5 = (val12.x + ((Rect)(ref val13)).width * 0.5f - val11.pivot.x) / num3 + (flag2 ? ((0f - item.X) / num3) : 0f); val3.localPosition = new Vector3(val.flipX ? (0f - num5) : num5, num4 - item.Sink / num3 + item.Y / num3, 0f); } private static Material BeardMaterial(SpriteRenderer head) { //IL_00b1: 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_00c2: Expected O, but got Unknown //IL_00c8: 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_0139: Unknown result type (might be due to invalid IL or missing references) Material sharedMaterial = ((Renderer)head).sharedMaterial; if ((Object)(object)sharedMaterial == (Object)null || (Object)(object)sharedMaterial.shader == (Object)null || !sharedMaterial.HasProperty(SkinChangerGK2.shaderPaletteId)) { return null; } if (Time.unscaledTime - _beardPaletteAt > 5f || (Object)(object)_beardPalette == (Object)null) { _beardPaletteAt = Time.unscaledTime; try { _beardPalette = PlayerSkinHelper.GetColorReplacementPalette(MainGame.PlayerData.customization)?.palette; } catch { _beardPalette = null; } } if ((Object)(object)_beardPalette == (Object)null) { return null; } if (!BeardMats.TryGetValue(sharedMaterial.shader, out var value) || (Object)(object)value == (Object)null) { value = new Material(sharedMaterial) { name = "zpp_beard" }; value.SetColor(SkinChangerGK2.shaderColorId, Color.white); value.SetFloat(SkinChangerGK2.shaderHueShiftId, 0f); value.SetFloat(SkinChangerGK2.shaderSaturationId, 1f); value.SetFloat(SkinChangerGK2.shaderValueId, 1f); value.SetFloat(SkinChangerGK2.shaderBrightnessId, 0f); value.SetFloat(SkinChangerGK2.shaderContrastId, 0f); value.DisableKeyword(((object)(ColorReplaceType)0/*cast due to .constrained prefix*/).ToString()); value.EnableKeyword(((object)(ColorReplaceType)1/*cast due to .constrained prefix*/).ToString()); BeardMats[sharedMaterial.shader] = value; } if ((Object)(object)value.GetTexture(SkinChangerGK2.shaderPaletteId) != (Object)(object)_beardPalette) { value.SetTexture(SkinChangerGK2.shaderPaletteId, (Texture)(object)_beardPalette); } return value; } internal static Sprite Still(Sprite s) { string text = Outfits.Clean(((Object)s).name); int num = text.LastIndexOf('_'); if (num < 0 || text.Length - num != 3 || !char.IsDigit(text[num + 1]) || !char.IsDigit(text[num + 2]) || text.IndexOf("_static_", StringComparison.Ordinal) < 0) { return s; } if (!StillFrames.TryGetValue(text, out var value)) { EasySpritesCollection instance = LazySingletonSO<EasySpritesCollection>.Instance; string text2 = text.Substring(0, num); value = (instance.HasSprite(text2) ? instance.GetSprite(text2, (string)null) : null); StillFrames[text] = value; } if (!((Object)(object)value != (Object)null)) { return s; } return value; } internal static Vector2 Drawn(Sprite s, out float mid) { //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_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_003c: 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_005f: 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_0073: 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_0087: 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_0021: 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_0028: Unknown result type (might be due to invalid IL or missing references) float num = ((s.pixelsPerUnit > 0f) ? s.pixelsPerUnit : 50f); Vector2 val; Rect val2; try { val = s.textureRectOffset; val2 = s.textureRect; } catch { val = Vector2.zero; val2 = s.rect; } mid = (val.x + ((Rect)(ref val2)).width * 0.5f - s.pivot.x) / num; return new Vector2((val.x - s.pivot.x) / num, (val.y - s.pivot.y) / num); } } internal static class Errands { private class Errand { public SGuid Target; public float Since; public int Fails; } private static readonly Dictionary<Guid, Errand> ByZombie = new Dictionary<Guid, Errand>(); private static readonly HashSet<Guid> Leftovers = new HashSet<Guid>(); private static readonly HashSet<Guid> Stranded = new HashSet<Guid>(); private const float Timeout = 180f; private const int MaxWalkFails = 3; private const ZombieCaretakerState HelperGoing = (ZombieCaretakerState)5; private const ZombieGardenerState GardenerGoing = (ZombieGardenerState)5; private static readonly FieldRef<ZombieWgoData, SGuid> HelperTarget = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("caretakerCurrentTargetUniqueId"); private static readonly FieldRef<ZombieWgoData, SGuid> HelperMoveTarget = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("caretakerCurrentMovementTargetUniqueId"); private static readonly FieldRef<ZombieWgoData, SGuid> HelperOrder = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("caretakerExecutingOrder"); private static readonly FieldRef<ZombieWgoData, ZombieCaretakerState> HelperPrevState = AccessTools.FieldRefAccess<ZombieWgoData, ZombieCaretakerState>("caretakerPreviousState"); private static readonly FieldRef<ZombieWgoData, float> HelperRetryTimer = AccessTools.FieldRefAccess<ZombieWgoData, float>("caretakerTimeForCheckFailedPathAgain"); private static readonly MethodInfo HelperToChest = AccessTools.Method(typeof(ZombieWgoData), "CaretakerTryMoveToNearestInventoryToPutPickedUpOrderItem", (Type[])null, (Type[])null); private static readonly MethodInfo HelperNextOrHome = AccessTools.Method(typeof(ZombieWgoData), "CaretakerTryGetNewOrderOrMoveToStation", (Type[])null, (Type[])null); private static readonly FieldRef<ZombieWgoData, SGuid> GardenerTarget = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("gardenerCurrentTargetUniqueId"); private static readonly FieldRef<ZombieWgoData, SGuid> GardenerOrder = AccessTools.FieldRefAccess<ZombieWgoData, SGuid>("gardenerExecutingOrder"); private static readonly MethodInfo GardenerMove = AccessTools.Method(typeof(ZombieWgoData), "GardenerTryMoveToCurrentTarget", (Type[])null, (Type[])null); private static readonly MethodInfo GardenerHome = AccessTools.Method(typeof(ZombieWgoData), "GardenerTryMoveToStation", (Type[])null, (Type[])null); private static readonly Dictionary<Guid, string> Said = new Dictionary<Guid, string>(); private static readonly Dictionary<Guid, float> PileCheckAt = new Dictionary<Guid, float>(); private static float _describeAt; public static bool Ready { get { if (HelperToChest != null && HelperNextOrHome != null && GardenerMove != null) { return GardenerHome != null; } return false; } } public static void Reset() { ByZombie.Clear(); Leftovers.Clear(); Stranded.Clear(); } private static bool Busy(WgoData w) { foreach (Errand value in ByZombie.Values) { if (value.Target.Guid == w.UniqueId.Guid) { return true; } } return false; } private static Errand Of(ZombieWgoData z, SGuid target) { if (!(target != (SGuid)null) || !ByZombie.TryGetValue(((WgoData)z).UniqueId.Guid, out var value) || !(value.Target.Guid == target.Guid)) { return null; } return value; } private static void Call(MethodInfo m, ZombieWgoData z) { try { m.Invoke(z, null); } catch (Exception ex) { Plugin.Log.LogWarning((object)(m.Name + ": " + (ex.InnerException ?? ex).Message)); } } public static void Watch(List<ZombieWgoData> zombies) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Invalid comparison between Unknown and I4 //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 HashSet<Guid> hashSet = new HashSet<Guid>(); foreach (ZombieWgoData zombie in zombies) { Guid guid = ((WgoData)zombie).UniqueId.Guid; hashSet.Add(guid); bool flag = (int)zombie.ZombieType == 2; bool flag2 = (int)zombie.ZombieType == 6; if (!flag && !flag2) { continue; } if (ByZombie.TryGetValue(guid, out var value)) { bool flag3 = ((!flag) ? ((int)zombie.GardenerState == 5 || (int)zombie.GardenerState == 8) : ((int)zombie.CaretakerState == 5 || (int)zombie.CaretakerState == 10)); WgoData wgoData = MainGame.WorldData.GetWgoData(value.Target); if (!flag3 || wgoData == null || !(Time.time - value.Since < 180f)) { ByZombie.Remove(guid); if (flag3) { Plugin.Log.LogWarning((object)((flag ? "helper" : "gardener") + " gave up on " + (((ObjectLinkedToDefinition<WGODef>)(object)wgoData)?.id ?? "a removed object"))); Home(zombie); } } continue; } bool isEmpty; if (!flag) { if ((int)zombie.GardenerState == 5) { isEmpty = GardenerOrder.Invoke(zombie).IsEmpty; goto IL_0160; } } else if ((int)zombie.CaretakerState == 5) { isEmpty = HelperOrder.Invoke(zombie).IsEmpty; goto IL_0160; } goto IL_016f; IL_016f: Stranded.Remove(guid); continue; IL_0160: if (isEmpty && !((WgoData)zombie).MovementComponent.IsMoving) { if (!Stranded.Add(guid)) { Stranded.Remove(guid); Home(zombie); } continue; } goto IL_016f; } List<Guid> list = new List<Guid>(); foreach (Guid key in ByZombie.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (Guid item in list) { ByZombie.Remove(item); } } private static void Home(ZombieWgoData z) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)z.ZombieType == 2) { Call(HelperNextOrHome, z); } else { Call(GardenerHome, z); } } private static bool HelperIdle(ZombieWgoData z) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)z.CaretakerState == 0 && HelperOrder.Invoke(z).IsEmpty && (z.CaretakerPortableItem == null || z.CaretakerPortableItem.IsEmpty)) { return !ByZombie.ContainsKey(((WgoData)z).UniqueId.Guid); } return false; } private static bool HasOutput(WgoData w) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 CraftComponent craftComponent = w.CraftComponent; if (craftComponent == null || craftComponent.IsDestroyingCraftActive) { return false; } if ((int)craftComponent.Status == 7) { return true; } if (!Leftovers.Contains(w.UniqueId.Guid)) { return false; } Inventory craftableObjectCraftInventory = w.CraftableObjectCraftInventory; object obj; if (craftableObjectCraftInventory == null) { obj = null; } else { Item data = craftableObjectCraftInventory.Data; obj = ((data != null) ? data.Inventory : null); } if (obj != null) { foreach (Item item in craftableObjectCraftInventory.Data.Inventory) { if (item != null && !item.IsEmpty) { return true; } } } Leftovers.Remove(w.UniqueId.Guid); return false; } public static void Helpers(WorldZoneData zone, List<ZombieWgoData> helpers, bool furnaces, bool compost) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_0075: 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_00bb: Unknown result type (might be due to invalid IL or missing references) List<Inventory> list = null; foreach (WgoData item in Chores.ZoneObjects(zone)) { WGODef definition = ((ObjectLinkedToDefinition<WGODef>)(object)item).Definition; if (!definition.isAutoCrafter || (int)definition.interactionType != 2 || !(Chores.IsCompost(item) ? compost : furnaces) || item.Worker is ZombieWgoData || Busy(item) || !HasOutput(item)) { continue; } if (list == null) { list = new MultiInventory(zone, (WgoData)null, false).inventoryList; } if (list.Count == 0) { break; } ZombieWgoData val = null; float num = float.MaxValue; foreach (ZombieWgoData helper in helpers) { if (HelperIdle(helper)) { float num2 = Vector3.Distance(((WgoData)helper).Position, item.Position); if (num2 < num) { num = num2; val = helper; } } } if (val == null) { break; } ByZombie[((WgoData)val).UniqueId.Guid] = new Errand { Target = item.UniqueId, Since = Time.time }; HelperTarget.Invoke(val) = item.UniqueId; val.CaretakerState = (ZombieCaretakerState)5; HelperWalk(val, item); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("helper goes to " + ((ObjectLinkedToDefinition<WGODef>)(object)item).id + " in " + Chores.ZoneName(item))); } } } private static void HelperWalk(ZombieWgoData z, WgoData w) { //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_002a: 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_0035: 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_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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_009d: 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) //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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Invalid comparison between Unknown and I4 Errand errand = Of(z, w.UniqueId); MovementComponent movementComponent = ((WgoData)z).MovementComponent; if (movementComponent.IsMoving) { movementComponent.ForceStop(); } Vector3 position = ((WgoData)z).Position; DockPointData nearestDockPointData = w.GetNearestDockPointData(position, (Availability)0); Vector3 val = ((nearestDockPointData != null) ? w.GetNearestDockPointDataWorldPositionOrMyPosition(position, (Availability)0, (Func<DockPointData, Vector3, bool>)((DockPointData d, Vector3 p) => d.BakedData == null || !d.BakedData.DisableTargetingForCaretaker)) : Chores.StepShort(position, w)); WorldZoneData worldZoneData = ((WgoData)z).WorldZoneData; GraphMask val2 = NavigationGraphMaskUtils.ToGraphMask((IEnumerable<Graph>)((worldZoneData != null) ? worldZoneData.MovementGraphs : null), (Graph)((worldZoneData == null) ? (-1) : ((int)worldZoneData.navigationGraph))); if (ZoneNav.TryGet(worldZoneData, out var graph)) { val2 |= NavigationGraphMaskUtils.ToGraphMask(graph); } StartPathResult val3 = ((((nearestDockPointData != null) ? nearestDockPointData.BakedData : null) != null) ? movementComponent.StartPath(val, nearestDockPointData.BakedData, val2, ((WgoData)z).WorldId, 1.5f, "", (Action)null) : movementComponent.StartPath(val, val2, ((WgoData)z).WorldId, 1.5f, "", (Action)null, (DestinationType)0)); if ((int)val3 != 0) { if ((int)val3 == 1) { HelperArrived(z, w); } else if (errand != null && ++errand.Fails >= 3) { Plugin.Log.LogWarning((object)("helper can't walk to " + ((ObjectLinkedToDefinition<WGODef>)(object)w).id + " in " + Chores.ZoneName(w) + ", taking the work from where it stands")); HelperArrived(z, w); } else { HelperRetryTimer.Invoke(z) = 1f; z.CaretakerState = (ZombieCaretakerState)10; } } else { HelperMoveTarget.Invoke(z) = w.UniqueId; } } public static bool HelperMovePre(ZombieWgoData __instance) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 try { Errand errand = Of(__instance, HelperTarget.Invoke(__instance)); if (errand == null) { return true; } WgoData wgoData = MainGame.WorldData.GetWgoData(errand.Target); if (wgoData == null) { return true; } if ((int)__instance.CaretakerState == 10) { if (HelperRetryTimer.Invoke(__instance) > 0f) { return false; } HelperRetryTimer.Invoke(__instance) = 0f; __instance.CaretakerState = HelperPrevState.Invoke(__instance); if (++errand.Fails >= 3) { Plugin.Log.LogWarning((object)("helper can't walk to " + ((ObjectLinkedToDefinition<WGODef>)(object)wgoData).id + " in " + Chores.ZoneName(wgoData) + ", taking the work from where it stands")); HelperArrived(__instance, wgoData); return false; } } else { SGuid obj = HelperMoveTarget.Invoke(__instance); if (((obj != null) ? new Guid?(obj.Guid) : ((Guid?)null)) == wgoData.UniqueId.Guid) { return false; } } HelperWalk(__instance, wgoData); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Helper move: " + ex.Message)); return true; } } public static bool HelperArrivedPre(ZombieWgoData __instance) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 try { if ((int)__instance.CaretakerState != 5) { return true; } Errand errand = Of(__instance, HelperTarget.Invoke(__instance)); if (errand == null) { return true; } WgoData wgoData = MainGame.WorldData.GetWgoData(errand.Target); if (wgoData == null) { return true; } HelperArrived(__instance, wgoData); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Helper arrival: " + ex.Message)); return true; } } private static void HelperArrived(ZombieWgoData z, WgoData w) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 ByZombie.Remove(((WgoData)z).UniqueId.Guid); MovementComponent movementComponent = ((WgoData)z).MovementComponent; if (movementComponent.IsMoving) { movementComponent.ForceStop(); } List<Item> list = new List<Item>(); if (!(w.Worker is ZombieWgoData) && HasOutput(w)) { if ((int)w.CraftComponent.Status == 7) { list = Chores.FinishCraft(w, z); } else { list.AddRange(w.CraftableObjectCraftInventory.Data.RemoveAllItems()); } } list.RemoveAll((Item i) => i == null || i.IsEmpty); if (list.Count == 0) { Call(HelperNextOrHome, z); return; } Item val = list[0]; bool flag = false; Inventory craftableObjectCraftInventory = w.CraftableObjectCraftInventory; for (int num = 1; num < list.Count; num++) { Item val2 = list[num]; if (((craftableObjectCraftInventory != null) ? craftableObjectCraftInventory.Data : null) != null && craftableObjectCraftInventory.CanAddItemToInventory(val2)) { craftableObjectCraftInventory.AddItemToInventory(val2, (Item)null, false); flag = true; } if (val2.Count > 0) { w.MakeDrop(val2); } } if (flag) { Leftovers.Add(w.UniqueId.Guid); } else { Leftovers.Remove(w.UniqueId.Guid); } z.CaretakerPortableItem = val; z.CaretakerState = (ZombieCaretakerState)6; Call(HelperToChest, z); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("helper took " + ((ObjectLinkedToDefinition<ItemDef>)(object)val).id + " x" + val.Count + " from " + ((ObjectLinkedToDefinition<WGODef>)(object)w).id + " in " + Chores.ZoneName(w))); } } private static bool GardenerIdle(ZombieWgoData z) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)z.GardenerState == 0 && GardenerOrder.Invoke(z).IsEmpty) { return !ByZombie.ContainsKey(((WgoData)z).UniqueId.Guid); } return false; } private static bool PileWantsVisit(WgoData w, MultiInventory chests) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 CraftComponent craftComponent = w.CraftComponent; if (craftComponent == null || craftComponent.IsDestroyingCraftActive) { return false; } if ((int)craftComponent.Status == 7 || HasPeat(w)) { return true; } return Chores.CompostCanStart(w, chests) != null; } private static bool HasPeat(WgoData w) { Inventory craftableObjectCraftInventory = w.CraftableObjectCraftInventory; object obj; if (craftableObjectCraftInventory == null) { obj = null; } else { Item data = craftableObjectCraftInventory.Data; obj = ((data != null) ? data.Inventory : null); } if (obj == null) { return false; } foreach (Item item in craftableObjectCraftInventory.Data.Inventory) { if (item != null && !item.IsEmpty && ((ObjectLinkedToDefinition<ItemDef>)(object)item).id != "leaf") { return true; } } return false; } private static void SayWhyNot(WgoData w, MultiInventory chests) { if (Plugin.Verbose.Value) { CraftComponent craftComponent = w.CraftComponent; string text; if (craftComponent == null) { text = "no craft component"; } else if (craftComponent.IsDestroyingCraftActive) { text = "being destroyed"; } else if (craftComponent.IsStarted || craftComponent.HasCraftsInQueue) { text = "composting, the peat isn't ready yet"; } else { int totalCount = chests.GetTotalCount("leaf"); int value = Plugin.CompostKeepLeaves.Value; text = "waiting for leaves: " + totalCount + " in the chests, " + value + " kept (CompostKeepLeaves), a batch needs more"; } if (!Said.TryGetValue(w.UniqueId.Guid, out var value2) || !(value2 == text)) { Said[w.UniqueId.Guid] = text; Plugin.Log.LogInfo((object)(((ObjectLinkedToDefinition<WGODef>)(object)w).id + " in " + Chores.ZoneName(w) + ": no gardener sent, " + text)); } } } public static void Compost(WorldZoneData zone, List<ZombieWgoData> gardeners) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //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) MultiInventory val = null; foreach (WgoData item in Chores.ZoneObjects(zone)) { if (!Chores.IsCompost(item) || item.Worker is ZombieWgoData || Busy(item)) { continue; } if (val == null) { val = new MultiInventory(zone, (WgoData)null, false); } if (val.inventoryList.Count == 0) { break; } if (!PileWantsVisit(item, val)) { SayWhyNot(item, val); continue; } ZombieWgoData val2 = null; float num = float.MaxValue; foreach (ZombieWgoData gardener in gardeners) { if (GardenerIdle(gardener)) { float num2 = Vector3.Distance(((WgoData)gardener).Position, item.Position); if (num2 < num) { num = num2; val2 = gardener; } } } if (val2 == null) { SayBusy(item); break; } SendToPile(val2, item); } } private static void SayBusy(WgoData w) { if (Plugin.Verbose.Value && (!Said.TryGetValue(w.UniqueId.Guid, out var value) || !(value == "every gardener is busy; the first to come back to its station goes"))) { Said[w.UniqueId.Guid] = "every gardener is busy; the first to come back to its station goes"; Plugin.Log.LogInfo((object)(((ObjectLinkedToDefinition<WGODef>)(object)w).id + " in " + Chores.ZoneName(w) + ": every gardener is busy; the first to come back to its station goes")); } } private static void SendToPile(ZombieWgoData z, WgoData w) { Said.Remove(w.UniqueId.Guid); ByZombie[((WgoData)z).UniqueId.Guid] = new Errand { Target = w.UniqueId, Since = Time.time }; GardenerTarget.Invoke(z) = w.UniqueId; z.GardenerState = (ZombieGardenerState)5; Call(GardenerMove, z); if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("gardener goes to " + ((ObjectLinkedToDefinition<WGODef>)(object)w).id + " in " + Chores.ZoneName(w))); } } public static bool GardenerNewOrderPre(ZombieWgoData __instance) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_002c: 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_00cc: Invalid comparison between Unknown and I4 //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown try { if (!Plugin.Enabled.Value || !Plugin.GardenerCompost.Value || (int)__instance.ZombieType != 6) { return true; } if ((int)__instance.GardenerState != 0 || !GardenerOrder.Invoke(__instance).IsEmpty || ByZombie.ContainsKey(((WgoData)__instance).UniqueId.Guid)) { return true; } Guid guid = ((WgoData)__instance).UniqueId.Guid; if (PileCheckAt.TryGetValue(guid, out var value) && Time.time < value) { return true; } PileCheckAt[guid] = Time.time + 2f; Item hand = __instance.Hand; if (hand == null || hand.IsEmpty || ((ObjectLinkedToDefinition<ItemDef>)(object)hand).Definition == null || (int)((ObjectLinkedToDefinition<ItemDef>)(object)hand).Definition.type != 2) { return true; } WorldZoneData worldZoneData = ((WgoData)__instance).WorldZoneData; if (worldZoneData == null) { return true; } MultiInventory val = null; foreach (WgoData item in Chores.ZoneObjects(worldZoneData)) { if (Chores.IsCompost(item) && !(item.Worker is ZombieWgoData) && !Busy(item)) { if (val == null) { val = new MultiInventory(worldZoneData, (WgoData)null, false); } if (val.inventoryList.Count == 0) { return true; } if (PileWantsVisit(item, val)) { SendToPile(__instance, item); return false; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Gardener compost check: " + ex.Message)); } return true; } public static void DescribeGardeners(List<ZombieWgoData> all) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 //IL_0168: 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) if (!Plugin.Verbose.Value || Time.unscaledTime < _describeAt) { return; } _describeAt = Time.unscaledTime + 15f; foreach (ZombieWgoData item in all) { if (item == null || (int)item.ZombieType != 6) { continue; } try { WorldZoneData worldZoneData = ((WgoData)item).WorldZoneData; int num = 0; int num2 = 0; int num3 = 0; List<OrderBase> list = ((worldZoneData != null) ? Traverse.Create((object)worldZoneData).Field("orders").GetValue<List<OrderBase>>() : null); if (list != null) { foreach (OrderBase item2 in list) { if (item2 is GatherOrder || item2 is PlantOrder) { if (!item2.ExecutorUniqueId.IsEmpty) { num3++; } else if (item2 is GatherOrder) { num++; } else { num2++; } } } } SGuid val = GardenerOrder.Invoke(item); OrderBase val2 = ((!val.IsEmpty && worldZoneData != null) ? worldZoneData.FindOrder(val) : null); WgoData wgoData = MainGame.WorldData.GetWgoData(GardenerTarget.Invoke(item)); Item hand = item.Hand; Plugin.Log.LogInfo((object)("gardener in " + (((ObjectLinkedToDefinition<WorldZoneDef>)(object)worldZoneData)?.id ?? "no zone") + ": " + ((object)item.GardenerState/*cast due to .constrained prefix*/).ToString() + ", order " + (val.IsEmpty ? "none" : ((val2 == null) ? ("GONE " + (object)val) : ((object)val2).GetType().Name)) + ", target " + (((ObjectLinkedToDefinition<WGODef>)(object)wgoData)?.id ?? "none") + ", hand " + ((hand == null || hand.IsEmpty) ? "empty" : ((ObjectLinkedToDefinition<ItemDef>)(object)hand).id) + ", station " + (((ObjectLinkedToDefinition<WGODef>)(object)item.AttachedWgoData)?.id ?? "none") + ", our errand " + ByZombie.ContainsKey(((WgoData)item).UniqueId.Guid) + "; zone orders free: gather " + num + ", plant " + num2 + "; taken " + num3)); } catch (Exception ex) { Plugin.Log.LogInfo((object)("gardener describe: " + ex.Message)); } } } public static bool IsGardenerErrand(ZombieWgoData z, WgoData target) { if (target != null) { return Of(z, target.UniqueId) != null; } return false; } public static bool GardenerArrived(ZombieWgoData z) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between Unknown and I4 //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Expected O, but got Unknown if ((int)z.GardenerState != 5) { return true; } Errand errand = Of(z, GardenerTarget.Invoke(z)); if (errand == null) { return true; } WgoData wgoData = MainGame.WorldData.GetWgoData(errand.Target); if (wgoData == null) { return true; } ByZombie.Remove(((WgoData)z).UniqueId.Guid); List<Item> list = new List<Item>(); CraftComponent craftComponent = wgoData.CraftComponent; if (craftComponent != null && (int)craftComponent.Status == 7 && !craftComponent.IsDestroyingCraftActive) { list = Chores.FinishCraft(wgoData, z); } Inventory craftableObjectCraftInventory = wgoData.CraftableObjectCraftInventory; object obj; if (craftableObjectCraftInventory == null) { obj = null; } else { Item data = craftableObjectCraftInventory.Data; obj = ((data != null) ? data.Inventory : null); } if (obj != null) { foreach (Item item in new List<Item>(craftableObjectCraftInventory.Data.Inventory)) { if (item != null && !item.IsEmpty && ((ObjectLinkedToDefinition<ItemDef>)(object)item).id != "leaf") { list.AddRange(craftableObjectCraftInventory.RemoveItemById(((ObjectLinkedToDefinition<ItemDef>)(object)item).id, item.Count, (Item)null, (Item)null, false)); } } } Inventory workerInventory = z.WorkerInventory; int num = 0; foreach (Item item2 in list) { if (item2 == null || item2.IsEmpty) { continue; } int count = item2.Count; if (((workerInventory != null) ? workerInventory.Data : null) != null && workerInventory.CanAddItemToInventory(item2)) { workerInventory.AddItemToInventory(item2, (Item)null, false); } num += count - item2.Count; if (item2.Count > 0) { Notify.Overflow(wgoData, ((ObjectLinkedToDefinition<ItemDef>)(object)item2).id); if (((craftableObjectCraftInventory != null) ? craftableObjectCraftInventory.Data : null) != null && craftableObjectCraftInventory.CanAddItemToInventory(item2)) { craftableObjectCraftInventory.AddItemToInventory(item2, (Item)null, false); } if (item2.Count > 0) { wgoData.MakeDrop(item2); } } } string text = null; CraftDefBase val = Chores.CompostCanStart(wgoData, new MultiInventory(((WgoData)z).WorldZoneData, (WgoData)null, false)); if (val != null) { CraftElement val2 = new CraftElement(((BalanceBaseObject)val).id, 1, new List<NeedItemData>(val.needItems), new CraftParamsData(((BalanceBaseObject)val).id, wgoData, (CraftParamsType)0, -1)); if (wgoData.CraftComponent.TryStartCraft((CraftElementBase)(object)val2)) { text = ((BalanceBaseObject)val).id; } } if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)("gardener at " + ((ObjectLinkedToDefinition<WGODef>)(object)wgoData).id + " in " + Chores.ZoneName(wgoData) + ": took " + num + ((text != null) ? (", started " + text) : ""))); } Call(GardenerHome, z); return false; } } internal static class Fishing { private enum Phase { Start, Cast, Wait, Pull, Catch, Release, Rest, Idle } private class Fisher { public SGuid Id; public Phase Phase = Phase.Rest; public float Left = 1f; public FishingDef Fish; public bool Hooked; public string Blocked; public bool Empty; public Direction Dir = (Direction)3; } private static readonly Dictionary<Guid, Fisher> Fishers = new Dictionary<Guid, Fisher>(); private static float _scanAt; private static readonly Dictionary<string, float> Said = new Dictionary<string, float>(); private static readonly Regex BodyFrame = new Regex("_bdy_fishing_(start|cast|idle|pull|catch)_(left|right|up|down)_(\\d+)$"); private static readonly Dictionary<string, int> BodyFrames = new Dictionary<string, int> { { "start", 7 }, { "cast", 12 }, { "idle", 4 }, { "pull", 7 }, { "catch", 10 } }; private static readonly Dictionary<string, int> RodFrames = new Dictionary<string, int> { { "start", 5 }, { "cast", 15 }, { "idle", 8 }, { "pull", 7 }, { "catch", 10 } }; private const string ArmName = "zpp_fish_arm"; private const string RodName = "zpp_fish_rod"; private static bool _layersWarned; private static bool _rodLogged; private static Vector3? _playerRodOffset; private static bool _playerRodLooked; private const string BasketKey = "zpp_basket:"; private static List<string> _fishIds; internal static List<string> FishIds { get { if (_fishIds == null) { _fishIds = new List<string>(); foreach (FishingDef fishingDef in GameBalance.Me.fishingDefs) { if (fishingDef != null && !string.IsNullOrEmpty(fishingDef.fishId) && !_fishIds.Contains(fishingDef.fishId)) { _fishIds.Add(fishingDef.fishId); } } } return _fishIds; } } public static bool ReservoirPre(object __instance, ref bool __result) { //IL_00fe: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: 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_01c7: Expected I4, but got Unknown try { if (!Plugin.Enabled.Value || !Plugin.ZombieFishing.Value || !Yard.CarriedZombie(out var item)) { return true; } Wgo value = Traverse.Create(__instance).Field("assignedWgo").GetValue<Wgo>(); if ((Object)(object)value == (Object)null || value.Data == null) { return true; } __result = true; foreach (Fisher value2 in Fishers.Values) { ZombieWgoData zombie = MainGame.ZombieSystemData.GetZombie(value2.Id); if (zombie != null && ((WgoData)zombie).GameResStr.Get("zpp_fish", "") == value.Data.UniqueId.Guid.ToString()) { Yard.Say(T.S("FishTaken")); return false; } } DockPoint val = value.TryGetDockPointForWorker(false, default(Vector3)); if ((Object)(object)val == (Object)null) { val = value.TryGetDockPointForWorker(true, MainGame.PlayerData.position.Value); } if ((Object)(object)val == (Object)null) { Yard.Say(T.S("FishNoSpot")); return false; } PlayerData playerData = MainGame.PlayerData; ZombieWgoData val2 = MainGame.ZombieSystemData.PutZombieFromStoreToGameSceneAsCommon(playerData, item, playerData.currentGameSceneId, ((Component)val).transform.position, val.Direction); if (val2 == null) { return false; } ((WgoData)val2).GameResStr.Set("zpp_fish", value.Data.UniqueId.Guid.ToString()); ((WgoData)val2).GameResStr.Set("zpp_fish_dir", ((int)val.Direction).ToString()); Plugin.Log.LogInfo((object)("zombie " + ((ObjectLinkedToDefinition<WGODef>)(object)val2).id + " fishes at " + ((ObjectLinkedToDefinition<WGODef>)(object)value.Data).id + " (" + playerData.currentGameSceneId + ")")); Yard.Say(T.F("FishStart", Notify.ZombieName(val2))); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Fishing: " + ex)); return true; } } internal static void Released(ZombieWgoData z) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (Fishers.TryGetValue(((WgoData)z).UniqueId.Guid, out var value)) { Show(z, (AnimationState)0, value.Dir, rope: false); Fishers.Remove(((WgoData)z).UniqueId.Guid); } } public static void Tick() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 if (!Plugin.Enabled.Value || !Plugin.ZombieFishing.Value) { return; } try { if ((Object)(object)MainGame.Instance == (Object)null || (int)MainGame.Instance.gameState != 1 || MainGame.WorldData == null) { return; } if (Time.unscaledTime >= _scanAt) { _scanAt = Time.unscaledTime + 1f; Scan(); } float deltaTime = Time.deltaTime; foreach (Fisher item in new List<Fisher>(Fishers.Values)) { ZombieWgoData zombie = MainGame.ZombieSystemData.GetZombie(item.Id); if (zombie == null) { Fishers.Remove(item.Id.Guid); } else { Step(zombie, item, deltaTime); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Fishing: " + ex.Message)); } } private static void Scan() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) ZombieSystemData zombieSystemData = MainGame.ZombieSystemData; if (zombieSystemData == null) { return; } foreach (SGuid zombieOnSceneWgoId in zombieSystemData.zombieOnSceneWgoIds) { if (Fishers.ContainsKey(zombieOnSceneWgoId.Guid)) { continue; } ZombieWgoData zombie = zombieSystemData.GetZombie(zombieOnSceneWgoId); if (zombie != null && ((WgoData)zombie).GameResStr.Has("zpp_fish") && Yard.IsLoose(zombie)) { Fisher fisher = new Fisher { Id = zombieOnSceneWgoId }; if (int.TryParse(((WgoData)zombie).GameResStr.Get("zpp_fish_dir", ""), out var result)) { fisher.Dir = (Direction)result; } Fishers[zombieOnSceneWgoId.Guid] = fisher; } } } private static WgoData Spot(ZombieWgoData z) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!Guid.TryParse(((WgoData)z).GameResStr.Get("zpp_fish", ""), out var result)) { return null; } return MainGame.WorldData.GetWgoData(new SGuid(result)); } private static void Step(ZombieWgoData z, Fisher f, float dt) { //IL_0015: 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_009d: Unknown result type (might be due to invalid IL or missing references) f.Left -= dt; Show(z, StateOf(f.Phase), f.Dir, f.Phase >= Phase.Cast && f.Phase <= Phase.Catch); if (f.Left > 0f) { return; } WgoData val = Spot(z); if (val == null) { Plugin.Log.LogWarning((object)("fishing spot of " + ((ObjectLinkedToDefinition<WGODef>)(object)z).id + " is gone")); ((WgoData)z).GameResStr.Remove("zpp_fish"); Fishers.Remove(f.Id.Guid); Show(z, (AnimationState)0, f.Dir, rope: false); return; } switch (f.Phase) { case Phase.Rest: case Phase.Idle: if (!Ready(z, val, f)) { f.Phase = Phase.Idle; f.Left = 5f; } else if (!Choose(z, val, f)) { f.Phase = Phase.Idle; f.Left = 5f; } else { f.Phase = Phase.Start; f.Left = 0.7f; } break; case Phase.Start: f.Phase = Phase.Cast; f.Left = 1.2f; break; case Phase.Cast: f.Phase = Phase.Wait; f.Left = Random.Range(Mathf.Max(1.5f, f.Fish.WaitTimeLeft), Mathf.Max(3f, f.Fish.WaitTimeRight)); break; case Phase.Wait: f.Phase = Phase.Pull; f.Left = 2.5f; break; case Phase.Pull: f.Hooked = Random.value < HookChance(z, f.Fish); if (f.Hooked) { Land(z, val, f.Fish); f.Phase = Phase.Catch; f.Left = 1.5f; break; } f.Phase = Phase.Release; f.Left = 1.2f; if (Plugin.Verbose.Value) { Plugin.Log.LogInfo((object)(((ObjectLinkedToDefinition<WGODef>)(object)z).id + " lost a " + f.Fish.fishId)); } break; default: f.Phase = Phase.Rest; f.Left = 1.5f; break; } } private static AnimationState StateOf(Phase p) { return (AnimationState)(p switch { Phase.Start => 201, Phase.Cast => 202, Phase.Wait => 203, Phase.Pull => 204, Phase.Catch => 206, Phase.Release => 205, Phase.Rest => 203, _ => 0, }); } private static Vector3 PlayerRodOffset() { //IL_0033: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026e: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if (_playerRodLooked) { return (Vector3)(((??)_playerRodOffset) ?? Vector3.zero); } PlayerController playerController = MainGame.PlayerController; if ((Object)(object)playerController == (Object)null) { return Vector3.zero; } _playerRodLooked = true; try { Transform val = null; Transform val2 = null; Transform[] componentsInChildren = ((Component)playerController).GetComponentsInChildren<Transform>(true); foreach (Transform val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)null && (Object)(object)val2 == (Object)null && ((Object)val3).name.StartsWith("bdy", StringComparison.OrdinalIgnoreCase) && (Object)(object)((Component)val3).GetComponent<SpriteRenderer>() != (Object)null) { val2 = val3; } } FishingContainer componentInChildren = ((Component)playerController).GetComponentInChildren<FishingContainer>(true); List<string> list = new List<string>(); if ((Object)(object)componentInChildren != (Object)null) { SpriteRenderer[] componentsInChildren2 = ((Component)componentInChildren).GetComponentsInChildren<SpriteRenderer>(true); foreach (SpriteRenderer val4 in componentsInChildren2) { if (!((Object)(object)val4 == (Object)null)) { string name = ((Object)val4).name; string obj = (((Object)(object)val4.sprite != (Object)null) ? ("=" + ((Object)val4.sprite).name) : ""); object obj2; if (!((Object)(object)val2 != (Object)null)) { obj2 = "?"; } else { Vector3 val5 = val2.InverseTransformPoint(((Component)val4).transform.position); obj2 = ((Vector3)(ref val5)).ToString("F3"); } list.Add(name + obj + "@" + (string?)obj2); if ((Object)(object)val == (Object)null && (((Object)val4).name.IndexOf("rod", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)(object)val4.sprite != (Object)null && ((Object)val4.sprite).name.Contains("_rod_")))) { val = ((Component)val4).transform; } } } } if ((Object)(object)val == (Object)null && (Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.AnimationComponent != (Object)null && (Object)(object)((AnimationComponentBase)componentInChildren.AnimationComponent).Animator != (Object)null) { val = ((Component)((AnimationComponentBase)componentInChildren.AnimationComponent).Animator).transform; } Plugin.Log.LogInfo((object)("fishing rod: player's FishingContainer " + (((Object)(object)componentInChildren != (Object)null) ? "found" : "missing") + ", renderers: " + string.Join(", ", list.ToArray()))); if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { Vector3 value = val2.InverseTransformPoint(val.position); value.z = 0f; _playerRodOffset = value; Plugin.Log.LogInfo((object)("fishing rod offset from the player's prefab: " + ((Vector3)(ref value)).ToString("F3") + " (rod '" + ((Object)val).name + "' under '" + (((Object)(object)val.parent != (Object)null) ? ((Object)val.parent).name : "-") + "', body '" + ((Object)val2).name + "' under '" + (((Object)(object)val2.parent != (Object)null) ? ((Object)val2.parent).name : "-") + "')")); } else { Plugin.Log.LogInfo((object)("fishing rod offset: the player has no rod/bdy renderers (" + ((Object)(object)val != (Object)null) + "/" + ((Object)(object)val2 != (Object)null) + ")")); } } catch (Exception ex) { Plugin.Log.LogInfo((object)("fishing rod offset: " + ex.Message)); } return (Vector3)(((??)_playerRodOffset) ?? Vector3.zero); } private static SpriteRenderer FindBody(Wgo view) { SpriteRenderer[] componentsInChildren = ((Component)view).GetComponentsInChildren<SpriteRenderer>(false); foreach (SpriteRenderer val in componentsInChildren) { if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null && ((Object)val.sprite).name.Contains("_bdy_") && ((Object)val).name != "zpp_fish_arm" && ((Object)val).name != "zpp_fish_rod") { return val; } } return null; } private static SpriteRenderer Layer(SpriteRenderer body, string name, int above, bool bodyMaterial) { //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_002e: 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) Transform val = ((Component)body).transform.Find(name); SpriteRenderer val3; if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject(name); val2.transform.SetParent(((Component)body).transform, false); val2.layer = ((Component)body).gameObject.layer; val3 = val2.AddComponent<SpriteRenderer>(); if (bodyMaterial) { ((Renderer)val3).sharedMaterial = ((Renderer)body).sharedMaterial; } } else { val3 = ((Component)val).GetComponent<SpriteRenderer>(); } ((Renderer)val3).sortingLayerID = ((Renderer)body).sortingLayerID; ((Renderer)val3).sortingOrder = ((Renderer)body).sortingOrder + above; val3.flipX = body.flipX; if (bodyMaterial) { val3.color = body.color; } val3.flipY = body.flipY; return val3; } private static Sprite Frame(string name) { try { return LazySingletonSO<EasySpritesCollection>.Instance.GetSprite(name, (string)null); } catch { return null; } } private static void Layers(ZombieWgoData z, bool fishing) { //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: 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_0458: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_047e: 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) Wgo wgoViewGlobal = GameScene.GetWgoViewGlobal(((WgoData)z).UniqueId); if ((Object)(object)wgoViewGlobal == (Object)null) { return; } SpriteRenderer val = FindBody(wgoViewGlobal); if ((Object)(object)val == (Object)null) { return; } Match match = ((fishing && (Object)(object)val.sprite != (Object)null) ? BodyFrame.Match(((Object)val.sprite).name.Replace("(Clone)", "")) : null); if (match == null || !match.Success) { string[] array = new string[2] { "zpp_fish_arm", "zpp_fish_rod" }; foreach (string text in array) { Transform val2 = ((Component)val).transform.Find(text); if ((Object)(object)val2 != (Object)null) { ((Renderer)((Component)val2).GetComponent<SpriteRenderer>()).enabled = false; } } return; } string value = match.Groups