using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using LazyBearTechnology;
using Microsoft.CodeAnalysis;
using Pathfinding;
using Timbn.GraveyardKeeperTwo.Core.Framework;
using Timbn.GraveyardKeeperTwo.VanillaTweaks.Tweaks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Timbn.GraveyardKeeperTwo.VanillaTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.3.0")]
[assembly: AssemblyInformationalVersion("1.3.3+42577719540a953590d1b1b778a9af1bc1cbf13e")]
[assembly: AssemblyProduct("Timbn Vanilla Tweaks")]
[assembly: AssemblyTitle("Timbn.GraveyardKeeperTwo.VanillaTweaks")]
[assembly: AssemblyVersion("1.3.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 Timbn.GraveyardKeeperTwo.VanillaTweaks
{
[BepInPlugin("Timbn.GraveyardKeeperTwo.VanillaTweaks", "Timbn Vanilla Tweaks", "1.3.3")]
[BepInDependency("Timbn.GraveyardKeeperTwo.Core", "1.2.0")]
public class Plugin : TimbnFrameworkPlugin<Plugin>
{
private SpecialStorageFilters? _storageFilters;
private GreenThumbTalentBonus? _greenThumb;
private TechPointCap? _techPointCap;
private StrayTechPoints? _strayTechPoints;
private StuckCarriers? _stuckCarriers;
private OvenIngredientSlots? _ovenSlots;
private BuiltEarlyQuests? _builtEarly;
private UnreachableDismantle? _unreachableDismantle;
private CollisionFixes? _collisionFixes;
protected override void BindConfig(ConfigFile config)
{
PluginConfig.Bind(config);
}
protected override void OnAwake()
{
//IL_0277: Unknown result type (might be due to invalid IL or missing references)
if (PluginConfig.SpecialStorageFilters.Value)
{
_storageFilters = new SpecialStorageFilters();
((TimbnFrameworkPlugin)this).Events.GameStarted((Action)_storageFilters.Apply);
if (TimbnGame.IsInGame)
{
_storageFilters.Apply();
}
}
if (PluginConfig.GreenThumbTalentBonus.Value)
{
_greenThumb = new GreenThumbTalentBonus();
((TimbnFrameworkPlugin)this).Events.GameStarted((Action)_greenThumb.Apply);
if (TimbnGame.IsInGame)
{
_greenThumb.Apply();
}
}
if (PluginConfig.TechPointCap.Value > 999)
{
_techPointCap = new TechPointCap(PluginConfig.TechPointCap.Value);
((TimbnFrameworkPlugin)this).Events.GameStarted((Action)_techPointCap.Apply);
if (TimbnGame.IsInGame)
{
_techPointCap.Apply();
}
}
if (PluginConfig.StudyTableNoStuckCrafts.Value)
{
((TimbnFrameworkPlugin)this).Events.GameStarted((Action)StudyTableStuckCraft.ClearStuckCrafts);
if (TimbnGame.IsInGame)
{
StudyTableStuckCraft.ClearStuckCrafts();
}
}
if (PluginConfig.OvenNoLostIngredients.Value)
{
_ovenSlots = new OvenIngredientSlots();
((TimbnFrameworkPlugin)this).Events.GameStarted((Action)_ovenSlots.Apply);
if (TimbnGame.IsInGame)
{
_ovenSlots.Apply();
}
}
if (PluginConfig.CollectStrayTechPoints.Value)
{
_strayTechPoints = new StrayTechPoints();
}
if (PluginConfig.SoftLockedBoards.Value)
{
SoftLockedBoards.Register((TimbnFrameworkPlugin)(object)this);
}
if (PluginConfig.BuiltEarlyQuests.Value)
{
_builtEarly = new BuiltEarlyQuests();
((TimbnFrameworkPlugin)this).Events.GameStarted((Action)_builtEarly.Queue);
((TimbnFrameworkPlugin)this).Events.QuestStarted((Action<QuestData>)_builtEarly.OnQuestStarted);
_builtEarly.Queue();
}
if (PluginConfig.StuckCarriers.Value)
{
_stuckCarriers = new StuckCarriers();
((TimbnFrameworkPlugin)this).Events.GoToMainMenu((Action)_stuckCarriers.Reset);
}
_unreachableDismantle = new UnreachableDismantle();
_unreachableDismantle.Apply();
if (PluginConfig.CollisionFixes.Value)
{
_collisionFixes = new CollisionFixes();
_collisionFixes.Subscribe(((TimbnFrameworkPlugin)this).Events);
_collisionFixes.ApplyToLoadedScenes();
}
TimbnFrameworkPlugin<Plugin>.Logger.LogMessage((object)$"Vanilla Tweaks started. Unstuck on {PluginConfig.UnstuckKey.Value}.");
}
protected override void OnUpdate()
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
if (TimbnGame.IsInGame)
{
_strayTechPoints?.Tick();
_stuckCarriers?.Tick();
_builtEarly?.Tick();
}
if (TimbnInput.IsDownWithControl(PluginConfig.UnstuckKey.Value))
{
Unstuck.Run(PluginConfig.UnstuckRange.Value);
}
}
protected override void OnDestroyed()
{
_storageFilters?.Revert();
_greenThumb?.Revert();
_techPointCap?.Revert();
_ovenSlots?.Revert();
_unreachableDismantle?.Revert();
_collisionFixes?.Revert();
}
}
internal static class PluginConfig
{
private const string _bugFixes = "Bug Fixes";
private const string _softLocks = "Soft Locks";
private const string _tweaks = "Tweaks";
public static ConfigEntry<bool> SpecialStorageFilters { get; private set; }
public static ConfigEntry<bool> StudyTableNoStuckCrafts { get; private set; }
public static ConfigEntry<bool> GreenThumbTalentBonus { get; private set; }
public static ConfigEntry<bool> CollectStrayTechPoints { get; private set; }
public static ConfigEntry<bool> OvenNoLostIngredients { get; private set; }
public static ConfigEntry<bool> SermonFaithRounding { get; private set; }
public static ConfigEntry<bool> StuckCarriers { get; private set; }
public static ConfigEntry<bool> RemoveInWholeArea { get; private set; }
public static ConfigEntry<bool> CollisionFixes { get; private set; }
public static ConfigEntry<bool> BuiltEarlyQuests { get; private set; }
public static ConfigEntry<bool> DismantleUnreachable { get; private set; }
public static ConfigEntry<bool> SoftLockedBoards { get; private set; }
public static ConfigEntry<KeyboardShortcut> UnstuckKey { get; private set; }
public static ConfigEntry<float> UnstuckRange { get; private set; }
public static ConfigEntry<bool> BedSaveWhenRested { get; private set; }
public static ConfigEntry<int> TechPointCap { get; private set; }
public static void Bind(ConfigFile config)
{
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Expected O, but got Unknown
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Expected O, but got Unknown
SpecialStorageFilters = config.Bind<bool>("Bug Fixes", "SpecialStorageFilters", true, "Stops zombies from putting the wrong item in storage meant for one thing, which they do when the rest of the storage nearby is full. Flax in the garden well stops it giving water, and anything but science in a study table built before version 1.005 makes every science afterwards lost. Covers the garden wells and any storage built before the game limited what it takes. Anything already in the wrong place is dropped beside it when a save loads.");
StudyTableNoStuckCrafts = config.Bind<bool>("Bug Fixes", "StudyTableNoStuckCrafts", true, "Frees a study table the game left stuck partway through a decompose or study, showing Work with nothing to work on. Checked when a save loads. The item and science were already spent, so nothing is lost.");
GreenThumbTalentBonus = config.Bind<bool>("Bug Fixes", "GreenThumbTalentBonus", true, "Makes the Green Thumb perk grant its +2 green talent when planting. The game puts the value in a field that planting crafts throw away, so the perk does nothing at all. Does nothing once the game fixes it.");
CollectStrayTechPoints = config.Bind<bool>("Bug Fixes", "CollectStrayTechPoints", true, "Pulls a tech point orb to you when it settles off the walkable ground, say through a wall, where the game's magnet can never reach it. The game only does this when you sleep.");
OvenNoLostIngredients = config.Bind<bool>("Bug Fixes", "OvenNoLostIngredients", true, "Gives the oven room for every ingredient its recipes need. It has one ingredient slot, so a zombie cook's second ingredient (the oil for onion rings, say) has nowhere to go and is destroyed on delivery, over and over. Also refuses any delivery a station has no room for, instead of destroying it.");
SermonFaithRounding = config.Bind<bool>("Bug Fixes", "SermonFaithRounding", true, "Rounds ceremony faith the way the numbers say. Priest makes Basic Prayer pay 0.35 faith per parishioner, but 0.35 is stored as 0.3499999, so at 10, 30, 50 parishioners and so on 3.5 comes out as 3.4999999 and rounds down, and Priest adds nothing.");
StuckCarriers = config.Bind<bool>("Bug Fixes", "StuckCarriers", true, "When a carrier zombie has nothing in its room to put its item into, it shows the no storage icon the game already uses for gardeners and walks back to its supplier station instead of freezing where it stands. It goes on with its work as soon as a slot frees up, as it would anyway.");
RemoveInWholeArea = config.Bind<bool>("Bug Fixes", "RemoveInWholeArea", true, "Allows you to remove buildings you should be allowed to but the game blocks its. Chests built in the resurrection lab from the morgue build desk are an example.");
CollisionFixes = config.Bind<bool>("Bug Fixes", "CollisionFixes", true, "Fixes spots where you can get stuck, such as the stairs from the dock up to the stone pier on the far right of the Port Area. Each fix does nothing once the game fixes that spot.");
BuiltEarlyQuests = config.Bind<bool>("Soft Locks", "BuiltEarlyQuests", true, "Finishes Agatha's choir step and the woodcarver's organ step when you built the choir or organ before being asked. The game only checks the moment you build it, and it can be built once, so building it early locks the quest line for good. Checked when a save loads and when the step starts.");
DismantleUnreachable = config.Bind<bool>("Soft Locks", "DismantleUnreachable", true, "A station up against a fence or wall might be blocked from dismantling. This will allow you to still work on it.");
SoftLockedBoards = config.Bind<bool>("Soft Locks", "SoftLockedBoards", true, "If you are soft locked and run out of boards without a sawhorse or circular saw, Larry will help you out.");
UnstuckKey = config.Bind<KeyboardShortcut>("Tweaks", "UnstuckKey", new KeyboardShortcut((KeyCode)117, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Moves you to the nearest open ground when you are boxed in, say between chests or inside a collider. Only works while you can move, so not with a window open or during dialog or a cutscene. Clear it to turn the key off.");
UnstuckRange = config.Bind<float>("Tweaks", "UnstuckRange", 30f, new ConfigDescription("How far Unstuck may move you, in world units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
BedSaveWhenRested = config.Bind<bool>("Tweaks", "BedSaveWhenRested", false, "Saves the game when you use the bed with full energy and the Keeper refuses to sleep. The game only saves when you actually sleep.");
TechPointCap = config.Bind<int>("Tweaks", "TechPointCap", 999, new ConfigDescription("The most red, green, or blue tech points you can hold. The game caps each at 999 and throws away anything past it. Set to 999 to keep the game's cap.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(999, 999999), Array.Empty<object>()));
CarryOver(config, ((ConfigEntryBase)(object)SpecialStorageFilters, "Bug Fixes", "StudyTableScienceOnly"), ((ConfigEntryBase)(object)SpecialStorageFilters, "StudyTable", "ScienceOnly"), ((ConfigEntryBase)(object)StudyTableNoStuckCrafts, "StudyTable", "NoStuckCrafts"), ((ConfigEntryBase)(object)GreenThumbTalentBonus, "GreenThumb", "TalentBonus"), ((ConfigEntryBase)(object)CollectStrayTechPoints, "TechPoints", "CollectStray"), ((ConfigEntryBase)(object)OvenNoLostIngredients, "Oven", "NoLostIngredients"), ((ConfigEntryBase)(object)SermonFaithRounding, "Sermons", "FaithRounding"), ((ConfigEntryBase)(object)StuckCarriers, "Carriers", "ShowWhenStuck"), ((ConfigEntryBase)(object)RemoveInWholeArea, "Building", "RemoveInWholeArea"), ((ConfigEntryBase)(object)BuiltEarlyQuests, "Quests", "BuiltEarly"), ((ConfigEntryBase)(object)DismantleUnreachable, "Building", "DismantleUnreachable"), ((ConfigEntryBase)(object)SoftLockedBoards, "Boards", "SoftLockedBoards"), ((ConfigEntryBase)(object)UnstuckKey, "Unstuck", "Key"), ((ConfigEntryBase)(object)UnstuckRange, "Unstuck", "Range"), ((ConfigEntryBase)(object)BedSaveWhenRested, "Bed", "SaveWhenRested"), ((ConfigEntryBase)(object)TechPointCap, "TechPoints", "Cap"));
}
private static void CarryOver(ConfigFile config, params (ConfigEntryBase Entry, string Section, string Key)[] moves)
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
if (!(AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(config) is Dictionary<ConfigDefinition, string> dictionary))
{
return;
}
int num = 0;
for (int i = 0; i < moves.Length; i++)
{
(ConfigEntryBase Entry, string Section, string Key) tuple = moves[i];
ConfigEntryBase item = tuple.Entry;
string item2 = tuple.Section;
string item3 = tuple.Key;
ConfigDefinition key = new ConfigDefinition(item2, item3);
if (dictionary.TryGetValue(key, out var value))
{
item.SetSerializedValue(value);
dictionary.Remove(key);
num++;
}
}
if (num > 0)
{
config.Save();
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "Timbn.GraveyardKeeperTwo.VanillaTweaks";
public const string PLUGIN_NAME = "Timbn Vanilla Tweaks";
public const string PLUGIN_VERSION = "1.3.3";
}
}
namespace Timbn.GraveyardKeeperTwo.VanillaTweaks.Tweaks
{
internal sealed class BuiltEarlyQuests
{
private static readonly (string Quest, string Building, string Wgo)[] _quests = new(string, string, string)[2]
{
("74_crossroad_chore_build", "zmb_choir_unlock_s", "zmb_choir_unlock"),
("96_crossroad_organ_build", "zmb_organ_unlock_s", "zmb_organ_unlock")
};
private bool _pending;
public void Queue()
{
_pending = true;
}
public void OnQuestStarted(QuestData quest)
{
(string, string, string)[] quests = _quests;
for (int i = 0; i < quests.Length; i++)
{
if (quests[i].Item1 == ((ObjectLinkedToDefinition<QuestDef>)(object)quest).id)
{
_pending = true;
}
}
}
public void Tick()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Invalid comparison between Unknown and I4
if (!_pending)
{
return;
}
_pending = false;
List<string> lockedBuildings = MainGame.Instance.GameSave.knowledgeSystem.lockedBuildings;
(string, string, string)[] quests = _quests;
for (int i = 0; i < quests.Length; i++)
{
(string, string, string) tuple = quests[i];
if ((int)TimbnQuests.StatusOf(tuple.Item1).GetValueOrDefault() == 2 && lockedBuildings.Contains(tuple.Item2))
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)(tuple.Item2 + " was built before " + tuple.Item1 + " started, finishing the quest."));
GlobalEventsSystem.FireTrigger((Type)9, tuple.Item3);
}
}
}
}
internal sealed class CollisionFixes
{
private sealed class CollisionFix(string scene, string path, Vector3 shipped, Vector3 offset, string where)
{
public string Scene { get; } = scene;
public string Path { get; } = path;
public Vector3 Shipped { get; } = shipped;
public Vector3 Offset { get; } = offset;
public string Where { get; } = where;
}
private static readonly CollisionFix[] _fixes = new CollisionFix[1]
{
new CollisionFix("RuinedTemple", "World/StaticContent/TownZone/PortArea/StonePier/port_area_stone_pier/SmallLadderCollider", new Vector3(6.67f, -1.787f, 1.8f), new Vector3(0.14f, 0.055f, 0f), "the pier stairs at the very right in the Port Area")
};
private readonly List<(Transform Target, Vector3 Offset)> _applied = new List<(Transform, Vector3)>();
public void Subscribe(TimbnPluginEvents events)
{
events.StaticEvent<Scene, LoadSceneMode>((Action<Scene, LoadSceneMode>)OnSceneLoaded, (Action<Action<Scene, LoadSceneMode>>)delegate(Action<Scene, LoadSceneMode> h)
{
SceneManager.sceneLoaded += AsUnityAction(h);
}, (Action<Action<Scene, LoadSceneMode>>)delegate(Action<Scene, LoadSceneMode> h)
{
SceneManager.sceneLoaded -= AsUnityAction(h);
});
}
public void ApplyToLoadedScenes()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Apply(SceneManager.GetSceneAt(i));
}
}
public void Revert()
{
//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_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_0033: Unknown result type (might be due to invalid IL or missing references)
foreach (var (val, val2) in _applied)
{
if ((Object)(object)val != (Object)null)
{
val.localPosition -= val2;
}
}
_applied.Clear();
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
Apply(scene);
}
private void Apply(Scene scene)
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00b3: Unknown result type (might be due to invalid IL or missing references)
if (!((Scene)(ref scene)).isLoaded)
{
return;
}
_applied.RemoveAll(((Transform Target, Vector3 Offset) applied) => (Object)(object)applied.Target == (Object)null);
CollisionFix[] fixes = _fixes;
foreach (CollisionFix collisionFix in fixes)
{
if (collisionFix.Scene != ((Scene)(ref scene)).name)
{
continue;
}
Transform val = Find(scene, collisionFix.Path);
if (!((Object)(object)val == (Object)null))
{
Vector3 val2 = val.localPosition - collisionFix.Shipped;
if (!(((Vector3)(ref val2)).sqrMagnitude > 1E-06f))
{
val.localPosition += collisionFix.Offset;
_applied.Add((val, collisionFix.Offset));
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)("Fixed the ground at " + collisionFix.Where + " so you can walk there."));
}
}
}
}
private static Transform? Find(Scene scene, string path)
{
int num = path.IndexOf('/');
string text = ((num < 0) ? path : path.Substring(0, num));
GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
foreach (GameObject val in rootGameObjects)
{
if (!(((Object)val).name != text))
{
Transform val2 = ((num < 0) ? val.transform : val.transform.Find(path.Substring(num + 1)));
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
}
}
return null;
}
private static UnityAction<Scene, LoadSceneMode> AsUnityAction(Action<Scene, LoadSceneMode> handler)
{
return (UnityAction<Scene, LoadSceneMode>)(object)Delegate.CreateDelegate(typeof(UnityAction<Scene, LoadSceneMode>), handler.Target, handler.Method);
}
}
internal sealed class GreenThumbTalentBonus
{
private const string _perkId = "perk_green_thumb";
private PerkDef? _patched;
private int _craftStartTicks;
public void Apply()
{
if (_patched == null)
{
PerkDef dataOrNull = ((GameBalanceBase)GameBalance.Me).GetDataOrNull<PerkDef>("perk_green_thumb");
if (dataOrNull == null)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogWarning((object)"The balance has no perk_green_thumb, leaving Green Thumb alone.");
}
else if (dataOrNull.craftMasteryBonus != 0)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Green Thumb already grants +{dataOrNull.craftMasteryBonus} green talent, leaving it alone.");
}
else if (dataOrNull.craftStartTicks != 0)
{
_craftStartTicks = dataOrNull.craftStartTicks;
dataOrNull.craftMasteryBonus = dataOrNull.craftStartTicks;
dataOrNull.craftStartTicks = 0;
_patched = dataOrNull;
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Green Thumb now grants +{dataOrNull.craftMasteryBonus} green talent when planting.");
}
}
}
public void Revert()
{
if (_patched != null)
{
_patched.craftStartTicks = _craftStartTicks;
_patched.craftMasteryBonus = 0;
_patched = null;
}
}
}
internal static class NestedZoneRemoval
{
public static bool IsInsideBuildArea(IBuildRemovable removable)
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
Wgo val = (Wgo)(object)((removable is Wgo) ? removable : null);
WorldZone worldZone = LazySingleton<BuildManager>.Instance.WorldZone;
WorldZoneData val2 = ((worldZone != null) ? worldZone.Data : null);
if ((Object)(object)val == (Object)null || val.Data == null || val2 == null || val.Data.WorldId != val2.gameSceneId)
{
return false;
}
return ((Rect)(ref val2.wholeZoneRect)).Contains(new Vector2(val.Data.Position.x, val.Data.Position.z));
}
}
internal sealed class OvenIngredientSlots
{
private static readonly string[] _ovenIds = new string[2] { "kitchen_oven", "kitchen_oven_t2" };
private readonly Dictionary<WGODef, int> _originalSizes = new Dictionary<WGODef, int>();
public void Apply()
{
string[] ovenIds = _ovenIds;
foreach (string text in ovenIds)
{
WGODef dataOrNull = ((GameBalanceBase)GameBalance.Me).GetDataOrNull<WGODef>(text);
if (dataOrNull == null)
{
continue;
}
int num = MostIngredients(text);
if (dataOrNull.craftInventorySize < num)
{
if (!_originalSizes.ContainsKey(dataOrNull))
{
_originalSizes[dataOrNull] = dataOrNull.craftInventorySize;
}
dataOrNull.craftInventorySize = num;
}
int num2 = 0;
foreach (WgoData wgoData in MainGame.Instance.GameSave.WorldData.GetWgoDataList(text))
{
Inventory craftableObjectCraftInventory = wgoData.CraftableObjectCraftInventory;
Item val = ((craftableObjectCraftInventory != null) ? craftableObjectCraftInventory.Data : null);
if (val != null && val.InventorySize < num)
{
val.InventorySize = num;
num2++;
}
}
if (num2 > 0)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Gave {num2} {text} room for {num} ingredients.");
}
}
}
public void Revert()
{
foreach (KeyValuePair<WGODef, int> originalSize in _originalSizes)
{
originalSize.Key.craftInventorySize = originalSize.Value;
}
_originalSizes.Clear();
}
private static int MostIngredients(string stationId)
{
return (from craft in GameBalance.Me.craftDefs
where ((CraftDefBase)craft).craftsIn.Contains(stationId)
select (from need in ((CraftDefBase)craft).needItems.Where(delegate(NeedItemData need)
{
ItemDef dataOrNull = ((GameBalanceBase)GameBalance.Me).GetDataOrNull<ItemDef>(need.id);
return dataOrNull == null || !dataOrNull.isFuel;
})
select need.id).Distinct().Count()).DefaultIfEmpty(0).Max();
}
}
internal static class SoftLockedBoards
{
private const string _npcId = "npc_larry";
private const string _talkId = "timbn_larry_boards_talk";
private const string _boardId = "flitch";
private const string _sawhorseTechId = "wood_basic";
private const int _sawhorseBoards = 2;
private const int _boardsGiven = 2;
private static readonly string[] _boardMakerIds = new string[4] { "sawhorse", "sawhorse_place", "circular_saw", "circular_saw_place" };
private static readonly Dictionary<string, string> _texts = new Dictionary<string, string>
{
["timbn_larry_boards_offer_1"] = "I may have run out of boards with no way to get more.",
["timbn_larry_boards_offer_2"] = "No sawhorse, no boards. No boards, no sawhorse... Even I can see the problem, and I don't have a brain.",
["timbn_larry_boards_accept"] = "Got any boards lying around?",
["timbn_larry_boards_decline"] = "I'll figure something out.",
["timbn_larry_boards_given"] = "Lucky for you, the Inquisitors left a couple behind my box. Here... Try not to lose these too. He he.",
["timbn_larry_boards_declined"] = "Suit yourself... I'll be right here on my box. As always.",
["timbn_larry_boards_accepted"] = "Thank you, I will be more careful next time."
};
public static void Register(TimbnFrameworkPlugin plugin)
{
plugin.Text.Add((IReadOnlyDictionary<string, string>)_texts);
plugin.Dialog.AddTalk("npc_larry", "timbn_larry_boards_talk", (Func<bool>)IsStuck, (Action<TimbnConversation>)delegate(TimbnConversation talk)
{
talk.PlayerSay("timbn_larry_boards_offer_1").Say("timbn_larry_boards_offer_2").Ask(new string[2] { "timbn_larry_boards_accept", "timbn_larry_boards_decline" })
.If("timbn_larry_boards_accept", (Action<TimbnConversation>)delegate(TimbnConversation then)
{
then.Do((Action)delegate
{
GiveBoards(talk.Npc);
}).Say("timbn_larry_boards_given").PlayerSay("timbn_larry_boards_accepted");
})
.If("timbn_larry_boards_decline", (Action<TimbnConversation>)delegate(TimbnConversation then)
{
then.Say("timbn_larry_boards_declined");
});
});
}
private static bool IsStuck()
{
if (!MainGame.Instance.GameSave.knowledgeSystem.IsTechUnlocked("wood_basic"))
{
return false;
}
WorldData world = MainGame.WorldData;
if (_boardMakerIds.Any((string id) => world.GetWgoDataList(id).Count > 0))
{
return false;
}
return !HasBoards();
}
private static bool HasBoards()
{
int num = MainGame.PlayerData.inventory.Data.GetTotalCountInInventory("flitch", (Item)null, false);
foreach (GameSceneData gameSceneData in MainGame.WorldData.gameSceneDataList)
{
foreach (WgoData wgoData in gameSceneData.wgoDataList)
{
WGODef definition = ((ObjectLinkedToDefinition<WGODef>)(object)wgoData).Definition;
if (definition == null || !definition.hasRefToOtherWgoInventory)
{
int num2 = num;
Inventory inventory = wgoData.Inventory;
int? obj;
if (inventory == null)
{
obj = null;
}
else
{
Item data = inventory.Data;
obj = ((data != null) ? new int?(data.GetTotalCountInInventory("flitch", (Item)null, false)) : ((int?)null));
}
int? num3 = obj;
num = num2 + num3.GetValueOrDefault();
int num4 = num;
Inventory craftInventory = wgoData.CraftInventory;
int? obj2;
if (craftInventory == null)
{
obj2 = null;
}
else
{
Item data2 = craftInventory.Data;
obj2 = ((data2 != null) ? new int?(data2.GetTotalCountInInventory("flitch", (Item)null, false)) : ((int?)null));
}
num3 = obj2;
num = num4 + num3.GetValueOrDefault();
}
}
num += gameSceneData.droppedItems.Where((DropData drop) => drop.Id == "flitch").Sum((DropData drop) => drop.Count);
if (num >= 2)
{
return true;
}
}
return false;
}
private static void GiveBoards(WgoData larry)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
Item val = new Item("flitch", 2);
int num = new MultiInventory(MainGame.PlayerData, true).AddItem(val);
if (num < val.Count)
{
Item val2 = Item.Copy(val);
val2.Count = val.Count - num;
MainGame.Instance.dropSystem.DropItemAsDropView(val2, larry.WorldId, larry.Position);
}
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Larry gave you {2} boards, {num} into your inventory.");
}
}
internal sealed class SpecialStorageFilters
{
private static readonly Dictionary<string, string[]> _missingWhiteLists = new Dictionary<string, string[]>
{
["well_garden_1"] = new string[1] { "water" },
["well_garden_2"] = new string[1] { "water" }
};
private readonly Dictionary<WGODef, WhiteListItemFilter> _originalWhiteLists = new Dictionary<WGODef, WhiteListItemFilter>();
private readonly List<Item> _addedWhiteLists = new List<Item>();
private readonly List<Item> _addedBlackLists = new List<Item>();
public void Apply()
{
AddMissingWhiteLists();
int num = 0;
foreach (WGODef wgoDef in GameBalance.Me.wgoDefs)
{
if (wgoDef == null || !wgoDef.OpenInMultiInventory || wgoDef.inventorySize <= 0 || (IsEmpty((ItemFilter?)(object)wgoDef.inventoryWhiteList) && IsEmpty((ItemFilter?)(object)wgoDef.inventoryBlackList)))
{
continue;
}
foreach (WgoData wgoData in MainGame.Instance.GameSave.WorldData.GetWgoDataList(((BalanceBaseObject)wgoDef).id))
{
Inventory inventory = wgoData.Inventory;
if (((inventory != null) ? inventory.Data : null) != null)
{
if (FilterInventory(wgoDef, inventory.Data))
{
num++;
}
DropStrays(wgoData, inventory);
}
}
}
if (num > 0)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Added the missing item filter to {num} storage object(s).");
}
}
public void Revert()
{
foreach (Item addedWhiteList in _addedWhiteLists)
{
addedWhiteList.RemoveProperty<WhiteListFilterSerializedItemProperty>();
}
_addedWhiteLists.Clear();
foreach (Item addedBlackList in _addedBlackLists)
{
addedBlackList.RemoveProperty<BlackListFilterSerializedItemProperty>();
}
_addedBlackLists.Clear();
foreach (KeyValuePair<WGODef, WhiteListItemFilter> originalWhiteList in _originalWhiteLists)
{
originalWhiteList.Deconstruct(out var key, out var value);
WGODef obj = key;
WhiteListItemFilter inventoryWhiteList = value;
obj.inventoryWhiteList = inventoryWhiteList;
}
_originalWhiteLists.Clear();
}
private void AddMissingWhiteLists()
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
foreach (KeyValuePair<string, string[]> missingWhiteList in _missingWhiteLists)
{
missingWhiteList.Deconstruct(out var key, out var value);
string text = key;
string[] array = value;
WGODef data = ((GameBalanceBase)GameBalance.Me).GetData<WGODef>(text);
if (data != null && !_originalWhiteLists.ContainsKey(data) && IsEmpty((ItemFilter?)(object)data.inventoryWhiteList))
{
WhiteListItemFilter val = new WhiteListItemFilter();
value = array;
foreach (string text2 in value)
{
((ItemFilter)val).AddElement(text2, (ItemFilterElementType)0);
}
_originalWhiteLists[data] = data.inventoryWhiteList;
data.inventoryWhiteList = val;
}
}
}
private bool FilterInventory(WGODef definition, Item data)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
bool result = false;
if (!IsEmpty((ItemFilter?)(object)definition.inventoryWhiteList) && !data.HasProperty<WhiteListFilterSerializedItemProperty>())
{
data.AddProperty<WhiteListFilterSerializedItemProperty>(new WhiteListFilterSerializedItemProperty(Copy<WhiteListItemFilter>(new WhiteListItemFilter(), (ItemFilter)(object)definition.inventoryWhiteList)));
_addedWhiteLists.Add(data);
result = true;
}
if (!IsEmpty((ItemFilter?)(object)definition.inventoryBlackList) && !data.HasProperty<BlackListFilterSerializedItemProperty>())
{
data.AddProperty<BlackListFilterSerializedItemProperty>(new BlackListFilterSerializedItemProperty(Copy<BlackListItemFilter>(new BlackListItemFilter(), (ItemFilter)(object)definition.inventoryBlackList)));
_addedBlackLists.Add(data);
result = true;
}
return result;
}
private static void DropStrays(WgoData storage, Inventory inventory)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
foreach (Item item in inventory.Data.Inventory.Where((Item i) => i != null && !i.IsEmpty && ((ObjectLinkedToDefinition<ItemDef>)(object)i).Definition != null && !Allows(inventory.Data, ((ObjectLinkedToDefinition<ItemDef>)(object)i).Definition)).ToList())
{
if (inventory.RemoveItemFromInventoryByUID(item, -1))
{
MainGame.Instance.dropSystem.DropItem(item, storage.WorldId, storage.GetDropPos(item), (List<Item>)null);
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Dropped {item.Count} {((ObjectLinkedToDefinition<ItemDef>)(object)item).id} out of {((ObjectLinkedToDefinition<WGODef>)(object)storage).id} beside it.");
}
}
}
private static bool Allows(Item data, ItemDef definition)
{
WhiteListFilterSerializedItemProperty val = default(WhiteListFilterSerializedItemProperty);
if (data.TryGetProperty<WhiteListFilterSerializedItemProperty>(ref val) && !((ItemFilter)val.WhiteList).Contains(definition))
{
return false;
}
BlackListFilterSerializedItemProperty val2 = default(BlackListFilterSerializedItemProperty);
if (data.TryGetProperty<BlackListFilterSerializedItemProperty>(ref val2))
{
return !((ItemFilter)val2.BlackList).Contains(definition);
}
return true;
}
private static T Copy<T>(T target, ItemFilter source) where T : ItemFilter
{
((ItemFilter)target).itemsIds.AddRange(source.itemsIds);
((ItemFilter)target).groupsIds.AddRange(source.groupsIds);
return target;
}
private static bool IsEmpty(ItemFilter? filter)
{
if (filter != null)
{
return filter.IsEmpty;
}
return true;
}
}
internal sealed class StrayTechPoints
{
private const float _interval = 1f;
private const float _collectDuration = 1f;
private static readonly FieldRef<List<TechPointDrop>> _activeDrops = AccessTools.StaticFieldRefAccess<List<TechPointDrop>>(AccessTools.Field(typeof(TechPointDrop), "activeDrops"));
private static readonly FieldRef<TechPointDrop, bool> _isTimedCollecting = AccessTools.FieldRefAccess<TechPointDrop, bool>("isTimedCollecting");
private static readonly FieldRef<TechPointDrop, float> _curTime = AccessTools.FieldRefAccess<TechPointDrop, float>("curTime");
private static readonly FieldRef<TechPointDrop, float> _collectDelay = AccessTools.FieldRefAccess<TechPointDrop, float>("collectDelay");
private static readonly FieldRef<TechPointDrop, float> _magnetRadius = AccessTools.FieldRefAccess<TechPointDrop, float>("magnetRadius");
private readonly HashSet<TechPointDrop> _offMeshLastCheck = new HashSet<TechPointDrop>();
private float _nextCheck;
public void Tick()
{
//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_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
if (Time.time < _nextCheck)
{
return;
}
_nextCheck = Time.time + 1f;
PlayerController playerController = MainGame.PlayerController;
RecastGraph val = (((Object)(object)playerController != (Object)null) ? playerController.SceneRecastGraph : null);
if (val == null)
{
_offMeshLastCheck.Clear();
return;
}
Vector3 position = ((Component)playerController).transform.position;
List<TechPointDrop> list = new List<TechPointDrop>();
foreach (TechPointDrop item in _activeDrops.Invoke())
{
if (!((Object)(object)item == (Object)null) && !_isTimedCollecting.Invoke(item) && !(_curTime.Invoke(item) < _collectDelay.Invoke(item)))
{
Vector3 position2 = ((Component)item).transform.position;
Vector3 val2 = VectorExtensions.XZ(position - position2);
if (!(((Vector3)(ref val2)).sqrMagnitude <= _magnetRadius.Invoke(item)) && !((NavGraph)val).IsPointOnNavmesh(VectorExtensions.XZ(position2)))
{
list.Add(item);
}
}
}
foreach (TechPointDrop item2 in list)
{
if (_offMeshLastCheck.Contains(item2))
{
item2.MoveToCollectorTimed(((Component)playerController).transform, 1f);
}
}
_offMeshLastCheck.Clear();
_offMeshLastCheck.UnionWith(list);
}
}
internal sealed class StuckCarriers
{
private const float _interval = 0.5f;
private HashSet<ZombieWgoData> _stuck = new HashSet<ZombieWgoData>();
private float _nextCheck;
public static bool IsStuck(ZombieWgoData zombie)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Invalid comparison between Unknown and I4
if ((int)zombie.ZombieType == 2)
{
return (int)zombie.CaretakerState == 11;
}
return false;
}
public void Tick()
{
if (Time.time < _nextCheck)
{
return;
}
_nextCheck = Time.time + 0.5f;
HashSet<ZombieWgoData> stuck = new HashSet<ZombieWgoData>();
foreach (SGuid zombieOnSceneWgoId in MainGame.ZombieSystemData.zombieOnSceneWgoIds)
{
WgoData wgoData = MainGame.WorldData.GetWgoData(zombieOnSceneWgoId);
ZombieWgoData val = (ZombieWgoData)(object)((wgoData is ZombieWgoData) ? wgoData : null);
if (val != null && IsStuck(val))
{
stuck.Add(val);
}
}
foreach (ZombieWgoData item in stuck.Where((ZombieWgoData z) => !_stuck.Contains(z)))
{
Redraw(item);
WalkToStation(item);
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)($"Carrier {item.Name} has nowhere to put {item.CaretakerPortableItem.Count} " + ((ObjectLinkedToDefinition<ItemDef>)(object)item.CaretakerPortableItem).id + " in " + ((ObjectLinkedToDefinition<WorldZoneDef>)(object)((WgoData)item).WorldZoneData)?.id + "."));
}
foreach (ZombieWgoData item2 in _stuck.Where((ZombieWgoData z) => !stuck.Contains(z)))
{
Redraw(item2);
}
_stuck = stuck;
}
public void Reset()
{
_stuck.Clear();
}
private static void Redraw(ZombieWgoData zombie)
{
Wgo wgoViewGlobal = GameScene.GetWgoViewGlobal(((WgoData)zombie).UniqueId);
if (wgoViewGlobal != null)
{
wgoViewGlobal.DrawWidgets();
}
}
private static void WalkToStation(ZombieWgoData zombie)
{
//IL_0029: 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_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00b3: 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_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
WorldZoneData worldZoneData = ((WgoData)zombie).WorldZoneData;
WgoData attachedWgoData = zombie.AttachedWgoData;
MovementComponent movementComponent = ((WgoData)zombie).MovementComponent;
if (worldZoneData != null && attachedWgoData != null && movementComponent != null && !movementComponent.IsMoving)
{
DockPointData nearestDockPointData = attachedWgoData.GetNearestDockPointData(((WgoData)zombie).Position, (Availability)0);
Vector3 nearestDockPointDataWorldPositionOrMyPosition = attachedWgoData.GetNearestDockPointDataWorldPositionOrMyPosition(((WgoData)zombie).Position, (Availability)1, (Func<DockPointData, Vector3, bool>)((DockPointData point, Vector3 _) => !point.BakedData.DisableTargetingForCaretaker));
GraphMask val = NavigationGraphMaskUtils.ToGraphMask((IEnumerable<Graph>)worldZoneData.MovementGraphs, worldZoneData.navigationGraph);
if (nearestDockPointData != null)
{
movementComponent.StartPath(nearestDockPointDataWorldPositionOrMyPosition, nearestDockPointData.BakedData, val, ((WgoData)zombie).WorldId, 1.5f, "", (Action)null);
}
else
{
movementComponent.StartPath(nearestDockPointDataWorldPositionOrMyPosition, val, ((WgoData)zombie).WorldId, 1.5f, "", (Action)null, (DestinationType)0);
}
}
}
}
internal static class StudyTableStuckCraft
{
private const string _tableId = "survey_wgo";
public static void ClearStuckCrafts()
{
int num = 0;
foreach (WgoData wgoData in MainGame.Instance.GameSave.WorldData.GetWgoDataList("survey_wgo"))
{
CraftComponent craftComponent = wgoData.CraftComponent;
if (craftComponent != null && craftComponent.IsStarted)
{
CraftElementBase currentCraftElement = craftComponent.CurrentCraftElement;
if (currentCraftElement == null || !currentCraftElement.IsStarted)
{
craftComponent.Clear();
num++;
}
}
}
if (num > 0)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Freed {num} study table(s) stuck on a craft that had already finished.");
}
}
}
internal sealed class TechPointCap
{
private static readonly string[] _resourceIds = new string[3] { "tech_red", "tech_green", "tech_blue" };
private readonly int _cap;
private readonly Dictionary<GameResSystemDef, LazyExpression> _originals = new Dictionary<GameResSystemDef, LazyExpression>();
public TechPointCap(int cap)
{
_cap = cap;
}
public void Apply()
{
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
string[] resourceIds = _resourceIds;
foreach (string text in resourceIds)
{
GameResSystemDef dataOrNull = ((GameBalanceBase)GameBalance.Me).GetDataOrNull<GameResSystemDef>(text);
if (dataOrNull != null && !_originals.ContainsKey(dataOrNull))
{
float num = dataOrNull.max.EvaluateFloat();
if (num >= (float)_cap)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"{text} already caps at {num}, leaving it alone.");
continue;
}
_originals[dataOrNull] = dataOrNull.max;
dataOrNull.max = new LazyExpression(_cap.ToString(CultureInfo.InvariantCulture));
}
}
if (_originals.Count > 0)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)$"Tech points now cap at {_cap}.");
}
}
public void Revert()
{
foreach (KeyValuePair<GameResSystemDef, LazyExpression> original in _originals)
{
original.Key.max = original.Value;
}
_originals.Clear();
}
}
internal sealed class UnreachableDismantle
{
private DockPoint? _standIn;
private WgoData? _station;
public static UnreachableDismantle? Active { get; private set; }
public void Apply()
{
Active = this;
}
public void Revert()
{
Active = null;
if ((Object)(object)_standIn != (Object)null)
{
Object.Destroy((Object)(object)((Component)_standIn).gameObject);
}
_standIn = null;
_station = null;
}
public DockPoint? StandInFor(PlayerWorkComponent work, Wgo station, Transform player, Vector2 facing)
{
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)station == (Object)null || (Object)(object)station.MainWgoPart == (Object)null || !IsMarkedForDismantle(station.Data) || !work.CanWorkOn(station.Data))
{
return null;
}
if (_station != station.Data)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)("Working " + ((ObjectLinkedToDefinition<WGODef>)(object)station.Data).id + " from where you stand, since none of its work spots can be reached."));
}
_station = station.Data;
DockPoint standIn = GetStandIn();
standIn.Init(station.MainWgoPart);
standIn.direction = DirectionExtensions.ConvertFromVector2(facing);
((Component)standIn).transform.position = player.position;
return standIn;
}
public bool TryGetDropPosition(WgoData data, out Vector3 position)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
position = MainGame.PlayerData.position.Value;
if (data == _station)
{
return IsMarkedForDismantle(data);
}
return false;
}
private static bool IsMarkedForDismantle(WgoData? data)
{
if (data == null)
{
return false;
}
CraftComponent craftComponent = data.CraftComponent;
return ((craftComponent != null) ? new bool?(craftComponent.IsDestroyingCraftActive) : ((bool?)null)) == true;
}
private DockPoint GetStandIn()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Expected O, but got Unknown
if ((Object)(object)_standIn != (Object)null)
{
return _standIn;
}
GameObject val = new GameObject("VanillaTweaks stand in dock point")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)(object)val);
_standIn = val.AddComponent<DockPoint>();
return _standIn;
}
}
internal static class Unstuck
{
private const float _step = 0.5f;
private const float _clearance = 0.3f;
private const int _blockingLayers = 257;
private const float _fallbackDistance = 1f;
private const int _worldZoneLayers = 131072;
private static readonly RaycastHit[] _zoneHits = (RaycastHit[])(object)new RaycastHit[15];
public static bool Run(float range)
{
//IL_0058: 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_005f: 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_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
if (!TimbnGame.IsInGame || !TryGetRecastGraph(MainGame.PlayerData.currentGameSceneId, out NavGraph graph))
{
TimbnFrameworkPlugin<Plugin>.Logger.LogWarning((object)"No recast graph in this scene.");
return false;
}
Dictionary<uint, int> areaSizes = new Dictionary<uint, int>();
int value3;
graph.GetNodes((Action<GraphNode>)delegate(GraphNode val3)
{
if (val3.Walkable)
{
areaSizes[val3.Area] = ((!areaSizes.TryGetValue(val3.Area, out value3)) ? 1 : (value3 + 1));
}
});
Vector3 value = MainGame.PlayerData.position.Value;
GraphNode node = graph.GetNearest(value).node;
int value2;
int hereSize = ((node != null && areaSizes.TryGetValue(node.Area, out value2)) ? value2 : 0);
bool overlapping = IsBlocked(value);
HashSet<string> zones = WorldZonesAt(value);
Vector3? val = FindOpenGround(graph, value, 0f, range, zones, (GraphNode val3) => overlapping || (areaSizes.TryGetValue(val3.Area, out value3) ? value3 : 0) > hereSize);
Vector3? val2 = val;
if (!val2.HasValue)
{
val = FindOpenGround(graph, value, 1f, range, zones, (GraphNode _) => true);
}
if (!val.HasValue)
{
TimbnFrameworkPlugin<Plugin>.Logger.LogWarning((object)$"No open ground within {range:0} m.");
return false;
}
MainGame.PlayerController.SetPosition(val.Value, true, true);
TimbnFrameworkPlugin<Plugin>.Logger.LogMessage((object)$"Unstuck, moved {Vector3.Distance(value, val.Value):0.0} m.");
return true;
}
private static Vector3? FindOpenGround(NavGraph graph, Vector3 from, float minDistance, float range, HashSet<string> zones, Func<GraphNode, bool> accept)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: 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_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
for (float num = Mathf.Max(0.5f, minDistance); num <= range; num += 0.5f)
{
int num2 = Mathf.Max(8, Mathf.CeilToInt(MathF.PI * 2f * num / 0.5f));
for (int i = 0; i < num2; i++)
{
float num3 = MathF.PI * 2f * (float)i / (float)num2;
Vector3 val = from + new Vector3(Mathf.Cos(num3), 0f, Mathf.Sin(num3)) * num;
NNInfo nearest = graph.GetNearest(val);
if (nearest.node != null && nearest.node.Walkable && !(Vector3.Distance(val, nearest.position) > 0.3f) && accept(nearest.node) && !IsBlocked(nearest.position) && SharesZone(zones, nearest.position))
{
return nearest.position;
}
}
}
return null;
}
private static bool SharesZone(HashSet<string> zones, Vector3 position)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
if (zones.Count != 0)
{
return zones.Overlaps(WorldZonesAt(position));
}
return true;
}
private static HashSet<string> WorldZonesAt(Vector3 position)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
int num = Physics.RaycastNonAlloc(new Ray(position + Vector3.up * 50f, Vector3.down), _zoneHits, 100f, 131072, (QueryTriggerInteraction)2);
HashSet<string> hashSet = new HashSet<string>();
for (int i = 0; i < num; i++)
{
Collider collider = ((RaycastHit)(ref _zoneHits[i])).collider;
WorldZone component = ((Component)collider).GetComponent<WorldZone>();
if ((Object)(object)component == (Object)null && (Object)(object)((Component)collider).transform.parent != (Object)null)
{
component = ((Component)((Component)collider).transform.parent).GetComponent<WorldZone>();
}
if ((Object)(object)component != (Object)null)
{
hashSet.Add(component.Id);
}
}
return hashSet;
}
private static bool IsBlocked(Vector3 position)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)MainGame.PlayerController).transform;
Collider[] array = Physics.OverlapSphere(position, 0.3f, 257);
foreach (Collider val in array)
{
if (!val.isTrigger && !((Component)val).transform.IsChildOf(transform))
{
return true;
}
}
return false;
}
private static bool TryGetRecastGraph(string worldId, out NavGraph graph)
{
graph = null;
GraphHelper instance = GraphHelper.Instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
SceneGraphsData sceneGraphsData = instance.SceneGraphsData;
obj = ((sceneGraphsData != null) ? sceneGraphsData.GetRecastGraphIndexByWorldId(worldId) : null);
}
List<int> list = (List<int>)obj;
NavGraph[] array = AstarPath.active?.data?.graphs;
if (list == null || list.Count == 0 || array == null || list[0] < 0 || list[0] >= array.Length)
{
return false;
}
graph = array[list[0]];
return graph != null;
}
}
}
namespace Timbn.GraveyardKeeperTwo.VanillaTweaks.Patches
{
[HarmonyPatch(typeof(DeliveryOrder), "CanOrderBeExecuted")]
internal static class DeliveryOrderPatch
{
[HarmonyPostfix]
private static void RefuseWithoutRoom(DeliveryOrder __instance, ref bool __result, ref string reasonIfNot)
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
if (__result && PluginConfig.OvenNoLostIngredients.Value)
{
ZombieWgoData zombieWgoData = ((OrderBase)__instance).ZombieWgoData;
Inventory val = ((zombieWgoData != null) ? ((WgoData)zombieWgoData).CraftableObjectCraftInventory : null);
if (val != null && !val.CanAddItemToInventory(new Item(((ObjectLinkedToDefinition<ItemDef>)(object)((OrderBase)__instance).Item).id, ((OrderBase)__instance).Item.Count)))
{
__result = false;
reasonIfNot = "inventory_is_full";
}
}
}
}
[HarmonyPatch(typeof(EnergySystem), "StartSleeping")]
internal static class EnergySystemPatch
{
[HarmonyPrefix]
private static void SaveWhenNotSleepy(ref Action onSleepDidNotStartedCallback, bool sleepWithoutSavingGame)
{
if (!sleepWithoutSavingGame && PluginConfig.BedSaveWhenRested.Value)
{
Action notSleepy = onSleepDidNotStartedCallback;
onSleepDidNotStartedCallback = delegate
{
SaveSystem.Save(MainGame.Instance.SaveSlotData, MainGame.Instance.GameSave, (Action)null, (Action)null, true, (Action<SaveSlotData, GameSave>)null);
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)"Saved from the bed without sleeping.");
notSleepy?.Invoke();
};
}
}
}
[HarmonyPatch(typeof(PlayerWorkComponent))]
internal static class PlayerWorkComponentPatch
{
[HarmonyPatch("FindNearestDockPoint")]
[HarmonyPostfix]
private static void FindNearestDockPointPostFix(PlayerWorkComponent __instance, PlayerController ___playerController, Vector2 direction, List<Wgo>? onlyWgoInList, ref DockPoint? __result)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__result == (Object)null && PluginConfig.DismantleUnreachable.Value && onlyWgoInList != null && onlyWgoInList.Count == 1)
{
Wgo station = onlyWgoInList[0];
__result = UnreachableDismantle.Active?.StandInFor(__instance, station, ((Component)___playerController).transform, direction);
}
}
}
[HarmonyPatch(typeof(RemovePointer), "IsFromCurrentWorldZone")]
internal static class RemovePointerPatch
{
[HarmonyPostfix]
private static void AllowWholeBuildArea(IBuildRemovable removable, ref bool __result)
{
if (!__result && PluginConfig.RemoveInWholeArea.Value && NestedZoneRemoval.IsInsideBuildArea(removable))
{
__result = true;
}
}
}
[HarmonyPatch]
internal static class SermonResultDataPatch
{
private const int _snapDecimals = 4;
private static readonly MethodInfo _gameRound = AccessTools.Method(typeof(Math), "Round", new Type[2]
{
typeof(double),
typeof(MidpointRounding)
}, (Type[])null);
private static readonly MethodInfo _faithRound = AccessTools.Method(typeof(SermonResultDataPatch), "RoundFaith", (Type[])null, (Type[])null);
private static IEnumerable<MethodBase> TargetMethods()
{
yield return AccessTools.Constructor(typeof(SermonResultData), new Type[6]
{
typeof(string),
typeof(string),
typeof(int),
typeof(bool),
typeof(int),
typeof(int)
}, false);
yield return AccessTools.PropertyGetter(typeof(SermonResultData), "FaithOnlyParishioners");
yield return AccessTools.PropertyGetter(typeof(SermonResultData), "FaithOnlyBonus");
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, _gameRound))
{
instruction.operand = _faithRound;
}
yield return instruction;
}
}
private static double RoundFaith(double value, MidpointRounding mode)
{
return Math.Round(PluginConfig.SermonFaithRounding.Value ? Math.Round(value, 4) : value, mode);
}
}
[HarmonyPatch(typeof(UIInfoWidget), "UpdateDescription")]
internal static class UIInfoWidgetPatch
{
private static readonly Action<UIInfoWidget> _unsubscribe = AccessTools.MethodDelegate<Action<UIInfoWidget>>(AccessTools.Method(typeof(UIInfoWidget), "UnsubscribeFromWgoEvents", (Type[])null, (Type[])null), (object)null, true);
[HarmonyPrefix]
private static bool SkipDestroyed(UIInfoWidget __instance)
{
if (Object.op_Implicit((Object)(object)__instance))
{
return true;
}
_unsubscribe(__instance);
TimbnFrameworkPlugin<Plugin>.Logger.LogInfo((object)"Dropped a destroyed info widget that was still listening to a workstation's inventory.");
return false;
}
}
[HarmonyPatch(typeof(WgoData))]
internal static class WgoDataPatch
{
[HarmonyPatch("GetDropPos")]
[HarmonyPostfix]
private static void GetDropPosPostFix(WgoData __instance, ref Vector3 __result)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
UnreachableDismantle active = UnreachableDismantle.Active;
if (active != null && active.TryGetDropPosition(__instance, out var position))
{
__result = position;
}
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
internal static class ZombieWgoDataPatch
{
[HarmonyPostfix]
private static void ShowForStuckCarriers(ZombieWgoData __instance, ref bool __result)
{
if (!__result && PluginConfig.StuckCarriers.Value && StuckCarriers.IsStuck(__instance))
{
__result = true;
}
}
}
}