Decompiled source of GK2 Thoughtful Week v0.4.0

GK2ThoughtfulWeek.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GK2.Framework;
using HarmonyLib;
using LazyBearTechnology;
using Rewired;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace GK2DayPlanner
{
	internal static class Clock
	{
		public const float DayStart = 0.25f;

		public const float NightStart = 0.75f;

		private static readonly FieldInfo EngineCache = AccessTools.Field(typeof(EnvironmentData), "envEngineCache");

		private static float _lastT = -1f;

		private static float _lastReal;

		private static float _rate = -1f;

		private static float _sinceMove;

		private static Sprite _sun;

		private static Sprite _moon;

		private static readonly string[] SunPixels = new string[9] { "....#....", ".#.....#.", "...###...", "..#####..", "#.#####.#", "..#####..", "...###...", ".#.....#.", "....#...." };

		private static readonly string[] MoonPixels = new string[9] { "...###...", "..###....", ".###.....", ".###.....", ".###.....", ".###.....", ".####....", "..#####..", "...###..." };

		public static bool TryRead(out float t, out float realDayMinutes)
		{
			t = 0f;
			realDayMinutes = 0f;
			try
			{
				EnvironmentData val = ((!((Object)(object)MainGame.Instance != (Object)null)) ? null : MainGame.Instance.GameSave)?.environmentData;
				if (val == null)
				{
					return false;
				}
				t = Mathf.Repeat(val.TimeOfDay, 1f);
				EnvironmentEngine val2 = (EnvironmentEngine)((!(EngineCache != null)) ? null : /*isinst with value type is only supported in some contexts*/);
				if ((Object)(object)val2 != (Object)null)
				{
					realDayMinutes = Traverse.Create((object)val2).Field("gameplayDayInMinutes").GetValue<float>();
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static void Sample()
		{
			if (!TryRead(out var t, out var _))
			{
				_lastT = -1f;
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (_lastT < 0f)
			{
				_lastT = t;
				_lastReal = unscaledTime;
				return;
			}
			float num = unscaledTime - _lastReal;
			if (num < 2f)
			{
				return;
			}
			float num2 = t - _lastT;
			if (num2 < -0.5f)
			{
				num2 += 1f;
			}
			if (num2 < 0f || num2 > 0.2f)
			{
				_lastT = t;
				_lastReal = unscaledTime;
				_rate = -1f;
				return;
			}
			float num3 = num2 / num;
			if (num3 <= 0f)
			{
				_sinceMove += num;
			}
			else
			{
				_sinceMove = 0f;
				_rate = ((!(_rate < 0f)) ? Mathf.Lerp(_rate, num3, 0.5f) : num3);
			}
			_lastT = t;
			_lastReal = unscaledTime;
		}

		private static float RealSecondsPerDay(float dayMin)
		{
			if (_sinceMove > 0f)
			{
				return -1f;
			}
			if (_rate > 0f)
			{
				return 1f / _rate;
			}
			if (dayMin > 0.01f)
			{
				return dayMin * 60f / Mathf.Max(Time.timeScale, 0.01f);
			}
			return -1f;
		}

		public static bool IsDay(float t)
		{
			return t >= 0.25f && t < 0.75f;
		}

		public static string Hhmm(float fraction)
		{
			int num = Mathf.FloorToInt(Mathf.Repeat(fraction, 1f) * 1440f);
			return (num / 60).ToString("00") + ":" + (num % 60).ToString("00");
		}

		public static bool Read(out string time, out bool day, out string left)
		{
			time = "";
			left = "";
			day = true;
			if (!TryRead(out var t, out var realDayMinutes))
			{
				return false;
			}
			day = IsDay(t);
			float num = Mathf.Repeat(((!day) ? 0.25f : 0.75f) - t, 1f);
			time = Hhmm(t);
			left = Hhmm(num);
			float num2 = RealSecondsPerDay(realDayMinutes);
			if (num2 > 0f)
			{
				float num3 = num * num2 / 60f;
				left = left + " · " + ((!(num3 < 1f)) ? L10n.F("RealMin", Mathf.RoundToInt(num3)) : L10n.T("RealLessMin"));
			}
			return true;
		}

		public static Sprite NextIcon(bool day)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (day)
			{
				return _moon ?? (_moon = Draw(MoonPixels, new Color32((byte)216, (byte)224, (byte)244, byte.MaxValue)));
			}
			return _sun ?? (_sun = Draw(SunPixels, new Color32((byte)245, (byte)197, (byte)66, byte.MaxValue)));
		}

		private static Sprite Draw(string[] rows, Color32 ink)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = rows.Length;
				int length = rows[0].Length;
				Texture2D val = new Texture2D(length, num, (TextureFormat)4, false);
				((Texture)val).filterMode = (FilterMode)0;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				Texture2D val2 = val;
				Color32 val3 = default(Color32);
				((Color32)(ref val3))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
				for (int i = 0; i < num; i++)
				{
					for (int j = 0; j < length; j++)
					{
						val2.SetPixel(j, num - 1 - i, (rows[i][j] != '#') ? Color32.op_Implicit(val3) : Color32.op_Implicit(ink));
					}
				}
				val2.Apply();
				return Sprite.Create(val2, new Rect(0f, 0f, (float)length, (float)num), new Vector2(0.5f, 0.5f), 100f);
			}
			catch
			{
				return null;
			}
		}
	}
	internal static class Cm
	{
		public static ConfigDescription D(string description, string name, int order, bool advanced = false, AcceptableValueBase range = null, bool browsable = true)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes();
			configurationManagerAttributes.DispName = name;
			configurationManagerAttributes.Order = order;
			ConfigurationManagerAttributes configurationManagerAttributes2 = configurationManagerAttributes;
			if (advanced)
			{
				configurationManagerAttributes2.IsAdvanced = true;
			}
			if (!browsable)
			{
				configurationManagerAttributes2.Browsable = false;
			}
			return new ConfigDescription(description, range, new object[1] { configurationManagerAttributes2 });
		}
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
namespace GK2DayPlanner
{
	internal static class Framework
	{
		private sealed class Entry : Gk2ModBase
		{
			private readonly Gk2ModMetadata _meta = new Gk2ModMetadata("gk2.thoughtfulweek", "GK2 Thoughtful Week", "SaintArchI", "0.4.0", FwText.L("A morning thought on what the day of the week is good for, plus your town orders at a glance. Inspired by p1xel8ted's Thoughtful Reminders for Graveyard Keeper."), false, false);

			private readonly IReadOnlyList<Gk2ModDependency> _deps = (IReadOnlyList<Gk2ModDependency>)(object)new Gk2ModDependency[1]
			{
				new Gk2ModDependency("ru.superman4eg.gk2.framework", "0.1.0", "0.2.0", false)
			};

			public override Gk2ModMetadata Metadata => _meta;

			public override IReadOnlyList<Gk2ModDependency> Dependencies => _deps;

			public override void OnRegister(Gk2ModContext context)
			{
				//IL_001c: 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)
				Gk2Settings settings = context.Settings;
				settings.AddKeybind("Hotkeys", "ToggleWindow", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), FwText.L("Open the week"), FwText.L("Opens and closes the week panel."), 0);
				settings.AddKeybind("Hotkeys", "ThoughtKey", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), FwText.L("Think about today"), FwText.L("Shows today's thought bubble right now, whatever the time."), 0);
				settings.AddToggle("Morning", "Enabled", true, FwText.L("Morning reminder"), FwText.L("A thought bubble over your head when a new day starts, saying what the day is good for."), 1);
				settings.AddToggle("Morning", "OnLoad", true, FwText.L("After loading a save"), FwText.L("Also show the reminder a few seconds after you load a save, so you know where you are in the week."), 1);
				settings.AddToggle("Morning", "OpenPanel", false, FwText.L("Open the panel instead"), FwText.L("Open the full week panel in the morning instead of the bubble."), 2);
				settings.AddToggle("Morning", "ShowEvents", true, FwText.L("Say what the day allows"), FwText.L("Off leaves just the name of the day."), 3);
				settings.AddToggle("Morning", "ShowOrders", true, FwText.L("Mention the orders"), FwText.L("Add a word about the town orders you are carrying."), 4);
				settings.AddFloatSlider("Morning", "TimeOfDay", 0.05f, 0f, 0.5f, FwText.L("When in the morning"), FwText.L("How far into the day the reminder waits, as a fraction of the day."), 0.01f, 5);
				settings.AddToggle("Morning", "OnlyWhenSomethingToDo", false, FwText.L("Only when there is something"), FwText.L("Skip the reminder on a day that allows nothing and has no open orders."), 6);
				settings.AddText("Gamepad", "WindowKey", "LeftTrigger+LeftStick", FwText.L("Open the week"), FwText.L("Gamepad action that opens and closes the panel, by the game's own name for it (RightStick, Fold, RightTrigger+RightStick for a chord...). Turn Log pad input on to see which actions each button of your pad sends."), 20);
				settings.AddText("Gamepad", "ThoughtKey", "None", FwText.L("Think about today"), FwText.L("Gamepad action that shows today's thought bubble, by the game's own name for it."), 20);
				settings.AddToggle("Gamepad", "ExclusivePlain", true, FwText.L("Leave chords alone"), FwText.L("A binding without a chord stays quiet while a trigger or R1 is held, so another mod can use that same button as a chord."), 21);
				settings.AddToggle("Gamepad", "LogInput", false, FwText.L("Log pad input"), FwText.L("Writes every gamepad action to BepInEx/LogOutput.log, so a free button can be found."), 22);
			}
		}

		public const string FrameworkGuid = "ru.superman4eg.gk2.framework";

		public static void TryRegister(BaseUnityPlugin plugin)
		{
			try
			{
				if (AppDomain.CurrentDomain.GetAssemblies().Any((Assembly a) => a.GetName().Name == "GK2.Framework"))
				{
					Register(plugin);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogInfo((object)("Mod Framework not used: " + ex.Message));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void Register(BaseUnityPlugin plugin)
		{
			FrameworkApi.RegisterMod((IGk2Mod)(object)new Entry(), plugin.Config);
			Plugin.Log.LogInfo((object)"Registered in GK2 Mod Framework");
		}
	}
	internal static class FwText
	{
		private static readonly string[] Langs = new string[10] { "ru", "de", "fr", "es", "pt", "pl", "tr", "ja", "zh", "ko" };

		private static int _idx = -2;

		private static readonly Dictionary<string, string[]> Table = new Dictionary<string, string[]>
		{
			{
				"Log pad input",
				new string[10] { "Писать кнопки геймпада в лог", "Gamepad-Eingaben protokollieren", "Journaliser la manette", "Registrar el mando", "Registrar o controle", "Zapisuj pad do logu", "Gamepad girdilerini kaydet", "パッド入力をログに記録", "记录手柄输入", "패드 입력 기록" }
			},
			{
				"Writes every gamepad action to BepInEx/LogOutput.log, so a free button can be found.",
				new string[10] { "Пишет каждое действие геймпада в BepInEx/LogOutput.log, чтобы найти свободную кнопку.", "Schreibt jede Gamepad-Aktion in BepInEx/LogOutput.log, damit sich eine freie Taste finden lässt.", "Écrit chaque action de la manette dans BepInEx/LogOutput.log, pour trouver un bouton libre.", "Escribe cada acción del mando en BepInEx/LogOutput.log para encontrar un botón libre.", "Grava cada ação do controle em BepInEx/LogOutput.log, para achar um botão livre.", "Zapisuje każdą akcję pada w BepInEx/LogOutput.log, żeby znaleźć wolny przycisk.", "Boş bir tuş bulmak için her gamepad eylemini BepInEx/LogOutput.log dosyasına yazar.", "空いているボタンを探せるよう、パッドの操作をすべて BepInEx/LogOutput.log に書き出します。", "将手柄的每个动作写入 BepInEx/LogOutput.log,便于找到空闲按键。", "빈 버튼을 찾을 수 있도록 패드의 모든 동작을 BepInEx/LogOutput.log에 기록합니다." }
			},
			{
				"Leave chords alone",
				new string[10] { "Не мешать сочетаниям", "Kombinationen freilassen", "Laisser les combinaisons", "Respetar combinaciones", "Respeitar combinações", "Nie przeszkadzaj kombinacjom", "Kombinasyonlara dokunma", "組み合わせを優先", "不干扰组合键", "조합키 비켜주기" }
			},
			{
				"A binding without a chord stays quiet while a trigger or R1 is held, so another mod can use that same button as a chord.",
				new string[10] { "Кнопка без сочетания молчит, пока зажат курок или R1, — тогда другой мод может использовать её в сочетании.", "Eine Belegung ohne Kombination schweigt, solange ein Trigger oder R1 gehalten wird, damit ein anderer Mod dieselbe Taste als Kombination nutzen kann.", "Une touche sans combinaison ne réagit pas tant qu'une gâchette ou R1 est enfoncée, pour qu'un autre mod l'utilise en combinaison.", "Un botón sin combinación no reacciona mientras se mantiene un gatillo o R1, así otro mod puede usarlo en combinación.", "Um botão sem combinação não reage enquanto um gatilho ou R1 estiver pressionado, para outro mod usá-lo em combinação.", "Przycisk bez kombinacji milczy, gdy wciśnięty jest spust lub R1, więc inny mod może go użyć w kombinacji.", "Kombinasyonsuz bir atama, tetik veya R1 basılıyken çalışmaz; böylece başka bir mod aynı tuşu kombinasyonda kullanabilir.", "トリガーやR1を押している間は単独割り当てが反応しないので、他のMODが同じボタンを組み合わせで使えます。", "按住扳机或 R1 时,单键绑定不响应,这样其他模组可以把同一按键用作组合键。", "트리거나 R1을 누르고 있는 동안 단독 할당은 반응하지 않아, 다른 모드가 같은 버튼을 조합키로 쓸 수 있습니다." }
			},
			{
				"Open the week",
				new string[10] { "Открыть неделю", "Woche öffnen", "Ouvrir la semaine", "Abrir la semana", "Abrir a semana", "Otwórz tydzień", "Haftayı aç", "週を開く", "打开本周", "주간 열기" }
			},
			{
				"Gamepad action that opens and closes the panel, by the game's own name for it (RightStick, Fold, RightTrigger+RightStick for a chord...). Turn Log pad input on to see which actions each button of your pad sends.",
				new string[10] { "Действие геймпада, которое открывает и закрывает окно, по названию из самой игры (RightStick, Fold, RightTrigger+RightStick для сочетания…). Включите «Писать кнопки геймпада в лог», чтобы увидеть, какие действия шлёт каждая кнопка.", "Gamepad-Aktion, die das Fenster öffnet und schließt, mit dem spieleigenen Namen (RightStick, Fold, RightTrigger+RightStick für eine Kombination …). Schalte „Gamepad-Eingaben protokollieren“ ein, um zu sehen, welche Aktionen jede Taste sendet.", "Action de la manette qui ouvre et ferme le panneau, sous le nom que lui donne le jeu (RightStick, Fold, RightTrigger+RightStick pour une combinaison…). Activez « Journaliser la manette » pour voir ce qu'envoie chaque bouton.", "Acción del mando que abre y cierra el panel, con el nombre que le da el juego (RightStick, Fold, RightTrigger+RightStick para una combinación…). Activa «Registrar el mando» para ver qué envía cada botón.", "Ação do controle que abre e fecha o painel, pelo nome que o jogo lhe dá (RightStick, Fold, RightTrigger+RightStick para uma combinação…). Ative «Registrar o controle» para ver o que cada botão envia.", "Akcja pada, która otwiera i zamyka panel, pod nazwą z gry (RightStick, Fold, RightTrigger+RightStick dla kombinacji…). Włącz „Zapisuj pad do logu”, by zobaczyć, co wysyła każdy przycisk.", "Paneli açıp kapatan gamepad eylemi, oyunun verdiği adla (RightStick, Fold, kombinasyon için RightTrigger+RightStick…). Her tuşun ne gönderdiğini görmek için «Gamepad girdilerini kaydet»i açın.", "パネルを開閉するパッドの操作(ゲーム内の名前で指定:RightStick、Fold、組み合わせは RightTrigger+RightStick など)。各ボタンが何を送るかは「パッド入力をログに記録」をオンにすると分かります。", "打开和关闭面板的手柄动作,使用游戏自己的名称(RightStick、Fold,组合键如 RightTrigger+RightStick…)。打开“记录手柄输入”可查看每个按键发送的动作。", "패널을 열고 닫는 패드 동작으로, 게임에서 쓰는 이름으로 지정합니다(RightStick, Fold, 조합키는 RightTrigger+RightStick 등). 각 버튼이 보내는 동작은 「패드 입력 기록」을 켜면 볼 수 있습니다." }
			},
			{
				"Only when there is something",
				new string[10] { "Только если есть дела", "Nur wenn etwas ansteht", "Seulement s'il y a quelque chose", "Solo si hay algo", "Só se houver algo", "Tylko gdy jest coś do zrobienia", "Yalnızca yapılacak bir şey varsa", "用事がある日だけ", "仅在有事时", "할 일이 있을 때만" }
			},
			{
				"Skip the reminder on a day that allows nothing and has no open orders.",
				new string[10] { "Не напоминать в день, когда ничего не открыто и нет незакрытых заказов.", "Keine Erinnerung an einem Tag, der nichts erlaubt und keine offenen Aufträge hat.", "Pas de rappel un jour qui n'offre rien et sans commande en cours.", "Sin recordatorio en un día que no ofrece nada y sin pedidos abiertos.", "Sem lembrete num dia que não oferece nada e sem pedidos abertos.", "Bez przypomnienia w dniu, który nic nie oferuje i nie ma otwartych zleceń.", "Hiçbir şeye izin vermeyen ve açık siparişi olmayan günlerde hatırlatma yapma.", "何もできず、未完了の注文もない日はお知らせしません。", "在什么都做不了、也没有未完成订单的日子不提醒。", "할 수 있는 것도, 진행 중인 주문도 없는 날에는 알리지 않습니다." }
			},
			{
				"When in the morning",
				new string[10] { "Когда утром", "Wann am Morgen", "À quel moment du matin", "Cuándo por la mañana", "Quando de manhã", "Kiedy rano", "Sabah ne zaman", "朝のいつ", "早上何时", "아침 언제" }
			},
			{
				"How far into the day the reminder waits, as a fraction of the day.",
				new string[10] { "Сколько ждать напоминания после начала дня, в долях дня.", "Wie weit in den Tag hinein die Erinnerung wartet, als Anteil des Tages.", "Combien de temps le rappel attend après le début du jour, en fraction de journée.", "Cuánto espera el recordatorio tras empezar el día, como fracción del día.", "Quanto o lembrete espera depois do início do dia, como fração do dia.", "Ile przypomnienie czeka po początku dnia, jako ułamek dnia.", "Hatırlatmanın gün başladıktan sonra ne kadar beklediği, günün kesri olarak.", "一日の始まりからお知らせまでの待ち時間(一日に対する割合)。", "提醒在一天开始后等待多久,以一天的比例表示。", "하루가 시작된 뒤 알림까지 기다리는 시간(하루에 대한 비율)입니다." }
			},
			{
				"Mention the orders",
				new string[10] { "Упоминать заказы", "Aufträge erwähnen", "Parler des commandes", "Mencionar los pedidos", "Mencionar os pedidos", "Wspominaj zlecenia", "Siparişlerden bahset", "注文にも触れる", "提及订单", "주문 언급" }
			},
			{
				"Add a word about the town orders you are carrying.",
				new string[10] { "Добавлять пару слов о взятых городских заказах.", "Ein Wort zu den angenommenen Stadtaufträgen hinzufügen.", "Ajouter un mot sur les commandes de la ville en cours.", "Añadir una palabra sobre los pedidos del pueblo que llevas.", "Acrescentar uma palavra sobre os pedidos da cidade que você pegou.", "Dodaj słowo o przyjętych zleceniach miasta.", "Aldığın kasaba siparişleri hakkında bir söz ekle.", "受けている町の注文についてひとこと添えます。", "附上一句关于你接下的城镇订单的话。", "받아 둔 마을 주문에 대해 한마디 덧붙입니다." }
			},
			{
				"Say what the day allows",
				new string[10] { "Говорить, что можно сделать", "Sagen, was der Tag erlaubt", "Dire ce que permet le jour", "Decir qué permite el día", "Dizer o que o dia permite", "Mów, na co pozwala dzień", "Günün neye izin verdiğini söyle", "その日にできることを言う", "说明今天能做什么", "그날 할 수 있는 것 알려주기" }
			},
			{
				"Off leaves just the name of the day.",
				new string[10] { "Если выключено, остаётся только название дня.", "Aus lässt nur den Namen des Tages.", "Désactivé, seul le nom du jour reste.", "Desactivado, solo queda el nombre del día.", "Desligado, fica só o nome do dia.", "Wyłączone zostawia tylko nazwę dnia.", "Kapalıyken yalnızca günün adı kalır.", "オフにすると曜日名だけになります。", "关闭后只显示当天的名称。", "끄면 요일 이름만 남습니다." }
			},
			{
				"Open the panel instead",
				new string[10] { "Открывать окно вместо мысли", "Stattdessen das Fenster öffnen", "Ouvrir le panneau à la place", "Abrir el panel en su lugar", "Abrir o painel em vez disso", "Zamiast tego otwórz panel", "Bunun yerine paneli aç", "代わりにパネルを開く", "改为打开面板", "대신 패널 열기" }
			},
			{
				"Open the full week panel in the morning instead of the bubble.",
				new string[10] { "Утром открывать окно недели вместо мысли над головой.", "Morgens das ganze Wochenfenster öffnen statt der Gedankenblase.", "Le matin, ouvrir le panneau de la semaine au lieu de la bulle.", "Por la mañana, abrir el panel de la semana en vez de la burbuja.", "De manhã, abrir o painel da semana em vez do balão.", "Rano otwieraj panel tygodnia zamiast dymka.", "Sabah balon yerine tüm hafta panelini aç.", "朝、吹き出しの代わりに週のパネルを開きます。", "早上打开整周面板,而不是气泡。", "아침에 말풍선 대신 주간 패널을 엽니다." }
			},
			{
				"After loading a save",
				new string[10] { "После загрузки сохранения", "Nach dem Laden eines Spielstands", "Après le chargement d'une partie", "Tras cargar una partida", "Depois de carregar um jogo", "Po wczytaniu zapisu", "Kayıt yüklendikten sonra", "セーブを読み込んだ後", "读取存档后", "저장 불러온 후" }
			},
			{
				"Also show the reminder a few seconds after you load a save, so you know where you are in the week.",
				new string[10] { "Показывать напоминание и через пару секунд после загрузки сохранения, чтобы сразу понять, какой сейчас день недели.", "Die Erinnerung auch ein paar Sekunden nach dem Laden eines Spielstands zeigen, damit du weißt, wo du in der Woche stehst.", "Afficher aussi le rappel quelques secondes après le chargement d'une partie, pour savoir où vous en êtes dans la semaine.", "Mostrar también el recordatorio unos segundos después de cargar una partida, para saber en qué día de la semana estás.", "Mostrar o lembrete também alguns segundos depois de carregar um jogo, para saber em que dia da semana você está.", "Pokazuj przypomnienie także kilka sekund po wczytaniu zapisu, by wiedzieć, jaki to dzień tygodnia.", "Kayıt yüklendikten birkaç saniye sonra da hatırlatmayı göster, böylece haftanın hangi gününde olduğunu bilirsin.", "セーブを読み込んだ数秒後にもお知らせを出し、今が週のどの日かわかるようにします。", "读取存档几秒后也显示提醒,让你知道现在是一周中的哪一天。", "저장을 불러온 몇 초 뒤에도 알림을 띄워, 지금이 주중 어느 날인지 알 수 있게 합니다." }
			},
			{
				"Think about today",
				new string[10] { "Подумать о сегодняшнем дне", "Über heute nachdenken", "Penser à aujourd'hui", "Pensar en el día de hoy", "Pensar no dia de hoje", "Pomyśl o dzisiejszym dniu", "Bugünü düşün", "今日のことを考える", "想想今天", "오늘 생각하기" }
			},
			{
				"Shows today's thought bubble right now, whatever the time.",
				new string[10] { "Показывает облачко с мыслью о сегодняшнем дне прямо сейчас, в любое время.", "Zeigt die Gedankenblase zum heutigen Tag sofort, egal zu welcher Uhrzeit.", "Affiche tout de suite la bulle de pensée du jour, quelle que soit l'heure.", "Muestra ahora mismo la burbuja de pensamiento del día, sea la hora que sea.", "Mostra agora mesmo o balão de pensamento do dia, a qualquer hora.", "Pokazuje dymek z myślą o dzisiejszym dniu od razu, o dowolnej porze.", "Bugünün düşünce balonunu saat kaç olursa olsun hemen gösterir.", "時間に関係なく、今日の考えの吹き出しをすぐに表示します。", "无论何时,立即显示今天的思考气泡。", "시간과 상관없이 오늘의 생각 말풍선을 바로 보여 줍니다." }
			},
			{
				"Gamepad action that shows today's thought bubble, by the game's own name for it.",
				new string[10] { "Действие геймпада, которое показывает облачко с мыслью о сегодняшнем дне (по названию в игре).", "Gamepad-Aktion, die die Gedankenblase zum heutigen Tag zeigt, mit dem spieleigenen Namen.", "Action de la manette qui affiche la bulle de pensée du jour, sous le nom que lui donne le jeu.", "Acción del mando que muestra la burbuja de pensamiento del día, con el nombre que le da el juego.", "Ação do controle que mostra o balão de pensamento do dia, pelo nome que o jogo lhe dá.", "Akcja pada pokazująca dymek z myślą o dzisiejszym dniu, pod nazwą używaną w grze.", "Bugünün düşünce balonunu gösteren oyun kolu eylemi, oyundaki adıyla.", "今日の考えの吹き出しを表示するゲームパッドのアクション(ゲーム内の名前で指定)。", "显示今天思考气泡的手柄动作,使用游戏内的名称。", "오늘의 생각 말풍선을 보여 주는 게임패드 동작(게임 내 이름으로 지정)." }
			},
			{
				"Morning reminder",
				new string[10] { "Утреннее напоминание", "Morgendliche Erinnerung", "Rappel du matin", "Recordatorio matutino", "Lembrete da manhã", "Poranne przypomnienie", "Sabah hatırlatması", "朝のお知らせ", "早晨提醒", "아침 알림" }
			},
			{
				"A thought bubble over your head when a new day starts, saying what the day is good for.",
				new string[10] { "Мысль над головой в начале нового дня: для чего этот день подходит.", "Eine Gedankenblase über deinem Kopf zu Beginn eines neuen Tages, die sagt, wofür der Tag gut ist.", "Une bulle de pensée au-dessus de votre tête au début d'un nouveau jour, qui dit à quoi il est bon.", "Una burbuja de pensamiento sobre tu cabeza al empezar un día, que dice para qué sirve.", "Um balão de pensamento sobre sua cabeça no início de um novo dia, dizendo para que ele serve.", "Dymek myśli nad głową na początku nowego dnia, mówiący, do czego ten dzień się nadaje.", "Yeni bir gün başladığında başının üstünde, günün neye uygun olduğunu söyleyen bir düşünce balonu.", "新しい日の始まりに、その日に向いていることを頭上の吹き出しで知らせます。", "新的一天开始时,头顶出现想法气泡,说明今天适合做什么。", "새 날이 시작되면 머리 위 생각 말풍선으로 그날 하기 좋은 일을 알려줍니다." }
			},
			{
				"Opens and closes the week panel.",
				new string[10] { "Открывает и закрывает окно недели.", "Öffnet und schließt das Wochenfenster.", "Ouvre et ferme le panneau de la semaine.", "Abre y cierra el panel de la semana.", "Abre e fecha o painel da semana.", "Otwiera i zamyka panel tygodnia.", "Hafta panelini açar ve kapatır.", "週のパネルを開閉します。", "打开和关闭本周面板。", "주간 패널을 열고 닫습니다." }
			},
			{
				"A morning thought on what the day of the week is good for, plus your town orders at a glance. Inspired by p1xel8ted's Thoughtful Reminders for Graveyard Keeper.",
				new string[10] { "Утренняя мысль о том, для чего подходит этот день недели, и ваши городские заказы одним взглядом. По мотивам Thoughtful Reminders от p1xel8ted для Graveyard Keeper.", "Ein morgendlicher Gedanke dazu, wofür der Wochentag gut ist, und deine Stadtaufträge auf einen Blick. Inspiriert von p1xel8teds Thoughtful Reminders für Graveyard Keeper.", "Une pensée du matin sur ce à quoi sert le jour de la semaine, et vos commandes de la ville d'un coup d'œil. Inspiré de Thoughtful Reminders de p1xel8ted pour Graveyard Keeper.", "Un pensamiento matutino sobre para qué sirve el día de la semana, y tus pedidos del pueblo de un vistazo. Inspirado en Thoughtful Reminders de p1xel8ted para Graveyard Keeper.", "Um pensamento matinal sobre para que serve o dia da semana, e seus pedidos da cidade num relance. Inspirado em Thoughtful Reminders, de p1xel8ted, para Graveyard Keeper.", "Poranna myśl o tym, do czego nadaje się dzień tygodnia, i zlecenia miasta w skrócie. Na podstawie Thoughtful Reminders autorstwa p1xel8ted dla Graveyard Keeper.", "Haftanın gününün neye uygun olduğuna dair bir sabah düşüncesi ve kasaba siparişlerine hızlı bakış. p1xel8ted'in Graveyard Keeper için yaptığı Thoughtful Reminders'tan esinlenmiştir.", "その曜日に向いていることを朝の吹き出しで知らせ、町の注文もひと目で確認できます。p1xel8ted 作の Graveyard Keeper 用 MOD「Thoughtful Reminders」に着想を得ています。", "早晨提示这一天适合做什么,并一眼看到你的城镇订单。灵感来自 p1xel8ted 为 Graveyard Keeper 制作的 Thoughtful Reminders。", "아침마다 그 요일에 하기 좋은 일을 알려주고, 마을 주문을 한눈에 보여줍니다. p1xel8ted의 Graveyard Keeper용 모드 Thoughtful Reminders에서 영감을 받았습니다." }
			}
		};

		private static int Index
		{
			get
			{
				if (_idx != -2)
				{
					return _idx;
				}
				string text = null;
				try
				{
					text = FrameworkLanguage();
				}
				catch
				{
				}
				text = (text ?? "en").ToLowerInvariant();
				_idx = -1;
				for (int i = 0; i < Langs.Length; i++)
				{
					if (text.StartsWith(Langs[i]))
					{
						_idx = i;
						break;
					}
				}
				return _idx;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string FrameworkLanguage()
		{
			return FrameworkLocalization.CurrentLanguage;
		}

		public static string L(string en)
		{
			int index = Index;
			if (index < 0 || en == null || !Table.TryGetValue(en, out var value) || index >= value.Length || string.IsNullOrEmpty(value[index]))
			{
				return en;
			}
			return value[index];
		}
	}
	internal static class GameApi
	{
		public static bool InGame()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			try
			{
				MainGame instance = MainGame.Instance;
				return (Object)(object)instance != (Object)null && (int)instance.gameState == 1 && MainGame.PlayerData != null;
			}
			catch
			{
				return false;
			}
		}

		public static string SlotKey()
		{
			try
			{
				string text = ((!((Object)(object)MainGame.Instance != (Object)null)) ? null : MainGame.Instance.SaveSlotData)?.slotName;
				if (string.IsNullOrEmpty(text))
				{
					return null;
				}
				return Regex.Replace(text, "_backup_\\d+$", "");
			}
			catch
			{
				return null;
			}
		}

		public static string Lang()
		{
			try
			{
				return LLBase.CurrentLang ?? "";
			}
			catch
			{
				return "";
			}
		}

		public static string L(string key)
		{
			try
			{
				return (!LLBase.HasL(key)) ? null : LLBase.L(key);
			}
			catch
			{
				return null;
			}
		}

		public static ItemDef ItemDef(string id)
		{
			try
			{
				return ((GameBalanceBase)GameBalance.Me).GetDataOrNull<ItemDef>(id);
			}
			catch
			{
				return null;
			}
		}

		public static string ItemName(string id, bool isGroup)
		{
			ItemDef val = ItemDef(id);
			if (val != null)
			{
				try
				{
					string header = val.GetHeader();
					if (!string.IsNullOrEmpty(header))
					{
						return header;
					}
				}
				catch
				{
				}
			}
			return L(id) ?? id;
		}

		public static string ItemIcon(string id, bool isGroup)
		{
			return ItemDef(id)?.iconId;
		}

		public static Sprite Sprite(string iconId)
		{
			if (string.IsNullOrEmpty(iconId))
			{
				return null;
			}
			try
			{
				return LazySingletonSO<EasySpritesCollection>.Instance.GetSprite(iconId, (string)null);
			}
			catch
			{
				return null;
			}
		}

		public static List<ItemDef> GroupDefs(string groupNeedId)
		{
			return new List<ItemDef>();
		}

		public static string IconTag(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return "";
			}
			try
			{
				return UIExtensions.FontIcon(id) ?? "";
			}
			catch
			{
				return "";
			}
		}
	}
	internal static class L10n
	{
		private static readonly string[] Langs = new string[11]
		{
			"en", "ru", "de", "fr", "es", "pt", "pl", "tr", "ja", "zh",
			"ko"
		};

		private static readonly Dictionary<string, string[]> Table = new Dictionary<string, string[]>
		{
			{
				"Title",
				new string[11]
				{
					"The week", "Неделя", "Die Woche", "La semaine", "La semana", "A semana", "Tydzień", "Hafta", "一週間", "一周",
					"한 주"
				}
			},
			{
				"SecToday",
				new string[11]
				{
					"Today", "Сегодня", "Heute", "Aujourd'hui", "Hoy", "Hoje", "Dziś", "Bugün", "今日", "今天",
					"오늘"
				}
			},
			{
				"SecAhead",
				new string[11]
				{
					"Ahead", "Дальше", "Danach", "Ensuite", "Después", "Depois", "Dalej", "Sonrası", "この先", "接下来",
					"이후"
				}
			},
			{
				"SecOrders",
				new string[11]
				{
					"Orders", "Заказы", "Aufträge", "Commandes", "Pedidos", "Pedidos", "Zlecenia", "Siparişler", "注文", "订单",
					"주문"
				}
			},
			{
				"NothingToday",
				new string[11]
				{
					"Nothing is tied to this day.", "К этому дню ничего не привязано.", "An diesen Tag ist nichts gebunden.", "Rien n'est lié à ce jour.", "Nada está ligado a este día.", "Nada está ligado a este dia.", "Nic nie jest przypisane do tego dnia.", "Bu güne bağlı bir şey yok.", "この日に結びついたことはありません。", "这一天没有绑定任何事。",
					"이 날에 묶인 일은 없습니다."
				}
			},
			{
				"Tomorrow",
				new string[11]
				{
					"tomorrow", "завтра", "morgen", "demain", "mañana", "amanhã", "jutro", "yarın", "明日", "明天",
					"내일"
				}
			},
			{
				"InDays",
				new string[11]
				{
					"in {0} d.", "через {0} дн.", "in {0} T.", "dans {0} j.", "en {0} d.", "em {0} d.", "za {0} dn.", "{0} gün sonra", "{0}日後", "{0} 天后",
					"{0}일 후"
				}
			},
			{
				"NoOrders",
				new string[11]
				{
					"No orders taken.", "Заказов нет.", "Keine Aufträge.", "Aucune commande.", "No hay pedidos.", "Nenhum pedido.", "Brak zleceń.", "Sipariş yok.", "注文はありません。", "没有订单。",
					"주문이 없습니다."
				}
			},
			{
				"OrdersHint",
				new string[11]
				{
					"Goods go on the town pallets in the Warehouse", "Товар кладётся на паллеты городского склада", "Waren auf die Stadtpaletten im Lager legen", "Les marchandises vont sur les palettes de l'entrepôt", "La mercancía va en los palés del almacén", "A mercadoria vai nos paletes do armazém", "Towar kładzie się na paletach w magazynie", "Mallar deponun paletlerine konur", "品物は倉庫のパレットに置きます", "货物放在仓库的托盘上",
					"물건은 창고 팔레트에 둡니다"
				}
			},
			{
				"OrderUrgent",
				new string[11]
				{
					"urgent: all at once", "срочный: всё сразу", "eilig: alles auf einmal", "urgent : tout d'un coup", "urgente: todo de una vez", "urgente: tudo de uma vez", "pilne: wszystko naraz", "acil: hepsi bir seferde", "緊急: 一度に全部", "紧急:一次凑齐",
					"긴급: 한 번에 전부"
				}
			},
			{
				"OrderReady",
				new string[11]
				{
					"ready — collect", "готов — забрать", "fertig – abholen", "prête — à récupérer", "listo — recoger", "pronto — recolher", "gotowe — odbierz", "hazır — teslim al", "完了 — 受け取る", "已完成 — 领取",
					"완료 — 수령"
				}
			},
			{
				"OrderOnPallets",
				new string[11]
				{
					"all there, counted on {0}", "всё на месте, зачтут в {0}", "alles da, gezählt am {0}", "tout y est, compté le {0}", "todo listo, se cuenta el {0}", "tudo pronto, contado no {0}", "wszystko jest, liczone w {0}", "hepsi hazır, {0} günü sayılır", "揃った: {0}に集計", "已备齐,{0}结算",
					"준비 완료, {0}에 집계"
				}
			},
			{
				"BubbleOrdersCountTomorrow",
				new string[11]
				{
					"Pallets are counted tomorrow morning: {0} order still short", "Завтра утром пересчёт паллет. Недобор по заказам: {0}", "Morgen früh werden die Paletten gezählt: {0} Auftrag unvollständig", "Palettes comptées demain matin : {0} commande incomplète", "Mañana temprano se cuentan los palés: {0} pedido incompleto", "Amanhã cedo contam os paletes: {0} pedido incompleto", "Jutro rano liczenie palet: {0} zlecenie niepełne", "Paletler yarın sabah sayılıyor: {0} sipariş eksik", "明朝パレット集計: 未達の注文{0}件", "明早清点托盘:{0} 个订单还差货",
					"내일 아침 팔레트 집계: 부족한 주문 {0}건"
				}
			},
			{
				"EveryDay",
				new string[11]
				{
					"every day", "каждый день", "jeden Tag", "chaque jour", "cada día", "todo dia", "codziennie", "her gün", "毎日", "每天",
					"매일"
				}
			},
			{
				"OrderCounted",
				new string[11]
				{
					"{0} counted in", "зачтено {0}", "{0} angerechnet", "{0} comptés", "{0} contados", "{0} contados", "zaliczono {0}", "{0} sayıldı", "{0}個 計上済み", "已计入 {0}",
					"{0} 반영됨"
				}
			},
			{
				"PadClose",
				new string[11]
				{
					"close", "закрыть", "schließen", "fermer", "cerrar", "fechar", "zamknij", "kapat", "閉じる", "关闭",
					"닫기"
				}
			},
			{
				"BubbleOrdersReady",
				new string[11]
				{
					"An order is ready to hand in", "Заказ готов к сдаче", "Ein Auftrag ist fertig", "Une commande est prête", "Un pedido está listo", "Um pedido está pronto", "Zlecenie gotowe do oddania", "Bir sipariş teslime hazır", "注文を渡せます", "有订单可以交付",
					"넘길 주문이 있습니다"
				}
			},
			{
				"BubbleOrdersUrgent",
				new string[11]
				{
					"{0} urgent order still short", "Срочный заказ ещё не собран: {0}", "{0} eiliger Auftrag noch offen", "{0} commande urgente incomplète", "{0} pedido urgente incompleto", "{0} pedido urgente incompleto", "{0} pilne zlecenie niegotowe", "{0} acil sipariş eksik", "緊急の注文が{0}件 未達", "{0} 个紧急订单还差货",
					"긴급 주문 {0}건 미완"
				}
			},
			{
				"BubbleOrdersOpen",
				new string[11]
				{
					"{0} order still open", "Открытых заказов: {0}", "{0} Auftrag noch offen", "{0} commande en cours", "{0} pedido pendiente", "{0} pedido em aberto", "{0} zlecenie w toku", "{0} sipariş açık", "注文が{0}件 進行中", "{0} 个订单进行中",
					"진행 중인 주문 {0}건"
				}
			},
			{
				"SinPride",
				new string[11]
				{
					"Pride", "Гордыня", "Stolz", "Orgueil", "Orgullo", "Orgulho", "Pycha", "Kibir", "傲慢", "傲慢",
					"자만"
				}
			},
			{
				"SinLust",
				new string[11]
				{
					"Lust", "Похоть", "Lust", "Luxure", "Lujuria", "Luxúria", "Nieczystość", "Şehvet", "色欲", "色欲",
					"색욕"
				}
			},
			{
				"SinGluttony",
				new string[11]
				{
					"Gluttony", "Чревоугодие", "Völlerei", "Gourmandise", "Gula", "Gula", "Łakomstwo", "Oburluk", "暴食", "暴食",
					"식욕"
				}
			},
			{
				"SinEnvy",
				new string[11]
				{
					"Envy", "Зависть", "Neid", "Jalousie", "Envidia", "Inveja", "Zawiść", "Kıskançlık", "嫉妬", "嫉妒",
					"질투"
				}
			},
			{
				"SinWrath",
				new string[11]
				{
					"Wrath", "Гнев", "Zorn", "Colère", "Ira", "Ira", "Gniew", "Öfke", "憤怒", "愤怒",
					"분노"
				}
			},
			{
				"SinSloth",
				new string[11]
				{
					"Sloth", "Уныние", "Trägheit", "Paresse", "Pereza", "Preguiça", "Lenistwo", "Tembellik", "怠惰", "懒惰",
					"나태"
				}
			},
			{
				"ActOrders",
				new string[11]
				{
					"Town orders", "Городские заказы", "Stadtaufträge", "Commandes de la ville", "Pedidos de la ciudad", "Pedidos da cidade", "Zlecenia miasta", "Kasaba siparişleri", "町の注文", "镇上的订单",
					"마을 주문"
				}
			},
			{
				"ActOrdersD",
				new string[11]
				{
					"New orders can be taken, and every vendor's weekly happiness limit resets.", "Можно взять новые заказы, и у каждого торговца сбрасывается недельный лимит счастья.", "Neue Aufträge sind zu haben, und das Wochenlimit an Zufriedenheit jedes Händlers wird zurückgesetzt.", "De nouvelles commandes sont disponibles, et la limite hebdomadaire de satisfaction de chaque marchand est remise à zéro.", "Se pueden tomar nuevos pedidos y se reinicia el límite semanal de felicidad de cada vendedor.", "Dá para pegar novos pedidos, e o limite semanal de felicidade de cada vendedor é zerado.", "Można wziąć nowe zlecenia, a tygodniowy limit zadowolenia każdego kupca się zeruje.", "Yeni siparişler alınabilir ve her satıcının haftalık mutluluk sınırı sıfırlanır.", "新しい注文を受けられ、各商人の週の幸福度上限がリセットされます。", "可以接新订单,每个商人的每周幸福上限也会重置。",
					"새 주문을 받을 수 있고, 각 상인의 주간 행복 한도가 초기화됩니다."
				}
			},
			{
				"ActSermon",
				new string[11]
				{
					"Sermon at the church", "Проповедь в церкви", "Predigt in der Kirche", "Sermon à l'église", "Sermón en la iglesia", "Sermão na igreja", "Kazanie w kościele", "Kilisede vaaz", "教会での説教", "在教堂布道",
					"교회 설교"
				}
			},
			{
				"ActResurrection",
				new string[11]
				{
					"Raising zombies", "Воскрешение зомби", "Zombies erwecken", "Résurrection de zombies", "Resucitar zombis", "Ressuscitar zumbis", "Wskrzeszanie zombie", "Zombi diriltme", "ゾンビの復活", "复活僵尸",
					"좀비 부활"
				}
			},
			{
				"ActResurrectionD",
				new string[11]
				{
					"The storm powers the tower, so have everything ready in advance.", "Гроза питает башню — приготовь всё заранее.", "Das Gewitter speist den Turm, also halte alles vorher bereit.", "L'orage alimente la tour : prépare tout à l'avance.", "La tormenta alimenta la torre: ten todo listo de antemano.", "A tempestade alimenta a torre: tenha tudo pronto antes.", "Burza zasila wieżę – przygotuj wszystko zawczasu.", "Fırtına kuleyi besler, her şeyi önceden hazırla.", "雷雨が塔に電力を送るので、あらかじめ全部そろえておきましょう。", "雷暴为塔供能,事先把东西都备好。",
					"폭풍이 탑에 전력을 공급하니 미리 모두 준비해 두세요."
				}
			},
			{
				"ActShip",
				new string[11]
				{
					"Merchant ship at the pier", "Корабль купца у пирса", "Handelsschiff am Pier", "Navire marchand au quai", "Barco mercante en el muelle", "Navio mercante no cais", "Statek kupiecki przy pomoście", "İskelede tüccar gemisi", "桟橋に商船", "码头有商船",
					"부두에 상선"
				}
			},
			{
				"ActShipD",
				new string[11]
				{
					"New exotic goods.", "Новые экзотические товары.", "Neue exotische Waren.", "De nouvelles marchandises exotiques.", "Nuevas mercancías exóticas.", "Novas mercadorias exóticas.", "Nowe egzotyczne towary.", "Yeni egzotik mallar.", "新しい異国の品が入ります。", "有新的异域货物。",
					"새 이국 물품이 들어옵니다."
				}
			},
			{
				"ActPrMachine",
				new string[11]
				{
					"PR machine", "ПИАР-машина", "PR-Maschine", "Machine de RP", "Máquina de RP", "Máquina de RP", "Maszyna PR", "PR makinesi", "PRマシン", "公关机器",
					"홍보 기계"
				}
			},
			{
				"ActPrMachineD",
				new string[11]
				{
					"Load newspapers and charged hypno devices to raise the week's limit.", "Заложи газеты и заряженные гипно-гаджеты, чтобы поднять недельный лимит.", "Zeitungen und geladene Hypno-Geräte einlegen, um das Wochenlimit zu heben.", "Chargez journaux et appareils hypno chargés pour relever la limite de la semaine.", "Carga periódicos y dispositivos hipnóticos cargados para subir el límite de la semana.", "Coloque jornais e dispositivos hipnóticos carregados para elevar o limite da semana.", "Włóż gazety i naładowane hipno-urządzenia, by podnieść limit tygodnia.", "Haftanın sınırını yükseltmek için gazete ve dolu hipno aygıtları yerleştir.", "新聞と充電済みの催眠装置を入れて、週の上限を上げましょう。", "放入报纸和充能的催眠装置,提高本周上限。",
					"신문과 충전된 최면 장치를 넣어 주간 한도를 올리세요."
				}
			},
			{
				"ActBattle",
				new string[11]
				{
					"Battle", "Бой", "Kampf", "Combat", "Combate", "Combate", "Walka", "Savaş", "戦闘", "战斗",
					"전투"
				}
			},
			{
				"ActLooters",
				new string[11]
				{
					"Looters take orders", "Мародёры принимают заказы", "Plünderer nehmen Aufträge an", "Les pillards prennent les commandes", "Los saqueadores aceptan encargos", "Os saqueadores aceitam encomendas", "Grabieżcy przyjmują zamówienia", "Yağmacılar sipariş alıyor", "泥棒が注文を受け付ける", "劫掠者接受订单",
					"약탈자가 주문을 받습니다"
				}
			},
			{
				"ActLootersShort",
				new string[11]
				{
					"Looters' orders", "Заказы мародёров", "Plünderer-Aufträge", "Commandes des pillards", "Encargos de saqueadores", "Encomendas dos saqueadores", "Zamówienia grabieżców", "Yağmacı siparişleri", "泥棒への注文", "劫掠者订单",
					"약탈자 주문"
				}
			},
			{
				"ActLootersD",
				new string[11]
				{
					"Davy the Dagger in the Dockside Club, for looter keys.", "Дейви Кинжал в «Портовом клубе», за ключи мародёров.", "Davey der Dolch im Hafen-Club, gegen Plündererschlüssel.", "Davy la Dague au Club des Docks, contre des Clés des Pillards.", "Davey Dagas en el Club Dársena, a cambio de llaves de saqueador.", "Orlando, Olha a Faca, no Clube do Cais, em troca de chaves.", "Dźgający Davy w klubie portowym, za klucze grabieżców.", "Rıhtım Kulübü'nde Hançer Davy, yağmacı anahtarları karşılığında.", "パブ⊙ミナトのダガーの達人デイヴィー。泥棒のカギと引き換え。", "码头俱乐部的匕首戴维,用劫掠者钥匙交换。",
					"부둣가 클럽의 단검잡이 데비, 약탈자 열쇠로."
				}
			},
			{
				"ActCorpses",
				new string[11]
				{
					"Order corpses for the week", "Заказ трупов на неделю", "Leichen für die Woche bestellen", "Commander les cadavres de la semaine", "Pedir los cadáveres de la semana", "Encomendar os corpos da semana", "Zamówienie zwłok na tydzień", "Haftalık ceset siparişi", "今週の死体を注文", "订购本周的尸体",
					"이번 주 시체 주문"
				}
			},
			{
				"ActCorpsesShort",
				new string[11]
				{
					"Corpse order", "Заказ трупов", "Leichenbestellung", "Commande de cadavres", "Pedido de cadáveres", "Pedido de corpos", "Zamówienie zwłok", "Ceset siparişi", "死体の注文", "尸体订单",
					"시체 주문"
				}
			},
			{
				"ActCorpsesD",
				new string[11]
				{
					"Agatha at the Crossroads.", "Агата на перекрёстке.", "Agatha an der Kreuzung.", "Agatha au Carrefour.", "Ágata en el cruce.", "Agatha na Encruzilhada.", "Agatha na rozdrożach.", "Dört Yol Ağzı'nda Agatha.", "十字路のアガサ。", "十字路口的阿加莎。",
					"갈림길의 애거서."
				}
			},
			{
				"ActNewPeople",
				new string[11]
				{
					"New people: green scrolls to Linda", "Новые жители: зелёные свитки Линде", "Neue Personen: grüne Schriftrollen zu Linda", "Nouveaux citoyens : Parchemins Verts à Linda", "Gente nueva: pergaminos verdes a Linda", "Gente nova: pergaminhos verdes para Linda", "Nowi ludzie: zielone zwoje dla Lindy", "Yeni insanlar: yeşil parşömenler Linda'ya", "新しい住民: グリーンの巻物をリンダへ", "新人:把绿卷轴交给琳达",
					"새로운 주민: 녹색 두루마리를 린다에게"
				}
			},
			{
				"ActNewPeopleShort",
				new string[11]
				{
					"Green scrolls", "Зелёные свитки", "Grüne Schriftrollen", "Parchemins Verts", "Pergaminos verdes", "Pergaminhos verdes", "Zielone zwoje", "Yeşil parşömenler", "グリーンの巻物", "绿卷轴",
					"녹색 두루마리"
				}
			},
			{
				"ActNewPeopleD",
				new string[11]
				{
					"Raises town reputation and the happiness limit.", "Растят репутацию горожан и лимит счастья.", "Hebt das Ansehen der Bürger und das Glückslimit.", "Augmente la réputation des citoyens et la limite de bonheur.", "Sube la reputación ciudadana y el límite de felicidad.", "Aumenta a reputação dos cidadãos e o limite de felicidade.", "Podnosi reputację mieszkańców i limit szczęścia.", "Vatandaş itibarını ve mutluluk sınırını artırır.", "住民の評判と幸福度の上限が上がります。", "提升居民声望和幸福上限。",
					"주민 평판과 행복 한도가 올라갑니다."
				}
			},
			{
				"UntilNight",
				new string[11]
				{
					"night in {0}", "до ночи {0}", "Nacht in {0}", "nuit dans {0}", "noche en {0}", "noite em {0}", "noc za {0}", "geceye {0}", "夜まで {0}", "距夜晚 {0}",
					"밤까지 {0}"
				}
			},
			{
				"UntilDay",
				new string[11]
				{
					"dawn in {0}", "до утра {0}", "Morgen in {0}", "aube dans {0}", "amanecer en {0}", "amanhecer em {0}", "świt za {0}", "sabaha {0}", "朝まで {0}", "距天亮 {0}",
					"아침까지 {0}"
				}
			},
			{
				"RealMin",
				new string[11]
				{
					"~{0} min", "~{0} мин", "~{0} Min.", "~{0} min", "~{0} min", "~{0} min", "~{0} min", "~{0} dk", "約{0}分", "约{0}分钟",
					"약 {0}분"
				}
			},
			{
				"RealLessMin",
				new string[11]
				{
					"<1 min", "<1 мин", "<1 Min.", "<1 min", "<1 min", "<1 min", "<1 min", "<1 dk", "1分未満", "不到1分钟",
					"1분 미만"
				}
			},
			{
				"ActTears",
				new string[11]
				{
					"The Goddess weeps blue crystals", "Богиня плачет синими кристаллами", "Die Göttin weint blaue Kristalle", "La Déesse pleure des cristaux bleus", "La Diosa llora cristales azules", "A Deusa chora cristais azuis", "Bogini płacze niebieskimi kryształami", "Tanrıça mavi kristaller ağlıyor", "女神が青いクリスタルの涙を流す", "女神流下蓝色水晶之泪",
					"여신이 푸른 수정 눈물을 흘립니다"
				}
			},
			{
				"ActTearsShort",
				new string[11]
				{
					"Blue crystals", "Синие кристаллы", "Blaue Kristalle", "Cristaux bleus", "Cristales azules", "Cristais azuis", "Niebieskie kryształy", "Mavi kristaller", "青いクリスタル", "蓝色水晶",
					"푸른 수정"
				}
			},
			{
				"ActTearsD",
				new string[11]
				{
					"At her swamp statue, for zombie collars.", "У статуи на болоте, для ошейников зомби.", "An ihrer Statue im Sumpf, für Zombie-Halsbänder.", "À sa statue du marais, pour les colliers de zombie.", "En su estatua del pantano, para collares de zombi.", "Na estátua dela no pântano, para coleiras de zumbi.", "Przy jej posągu na bagnach, na obroże zombie.", "Bataklıktaki heykelinde, zombi tasmaları için.", "沼の女神像のそば。ゾンビの首輪に使います。", "在沼泽的女神像旁,用于僵尸项圈。",
					"늪의 여신상 옆. 좀비 목걸이에 쓰입니다."
				}
			},
			{
				"TearsWaiting",
				new string[11]
				{
					"Blue crystals are waiting at the Goddess", "У Богини лежат синие кристаллы", "Bei der Göttin liegen blaue Kristalle", "Des cristaux bleus attendent chez la Déesse", "Hay cristales azules junto a la Diosa", "Há cristais azuis junto à Deusa", "U Bogini czekają niebieskie kryształy", "Tanrıça'nın yanında mavi kristaller var", "女神のもとに青いクリスタルが残っています", "女神那里还有蓝色水晶",
					"여신 곁에 푸른 수정이 남아 있습니다"
				}
			}
		};

		private static string _lang;

		private static int _idx;

		public static int Index
		{
			get
			{
				string text = null;
				try
				{
					text = LLBase.CurrentLang;
				}
				catch
				{
				}
				text = (text ?? "en").ToLowerInvariant();
				if (text != _lang)
				{
					_lang = text;
					_idx = 0;
					for (int i = 0; i < Langs.Length; i++)
					{
						if (text.StartsWith(Langs[i]))
						{
							_idx = i;
							break;
						}
					}
				}
				return _idx;
			}
		}

		public static string T(string key)
		{
			if (!Table.TryGetValue(key, out var value))
			{
				return key;
			}
			string text = value[Index];
			return (!string.IsNullOrEmpty(text)) ? text : value[0];
		}

		public static string F(string key, object arg)
		{
			return string.Format(T(key), arg);
		}
	}
	internal sealed class OrderInfo
	{
		public int Slot;

		public string VendorId;

		public string VendorName;

		public Sprite Portrait;

		public string ItemId;

		public int Need;

		public int Delivered;

		public int OnPallets;

		public bool Urgent;

		public bool Finished;

		public int Reward;

		public int Progress => Finished ? Need : ((!Urgent) ? (Delivered + OnPallets) : OnPallets);

		public bool Done => Finished || Progress >= Need;

		public bool WaitingForCount => !Finished && Progress >= Need;

		public int Left => Math.Max(0, Need - Progress);
	}
	internal static class Orders
	{
		public const string OrderDay = "day_pride";

		private const string WarehouseZone = "warehouse";

		private const string CellarZone = "warehouse_cellar";

		public const int WeekLength = 6;

		public static string[] DayIds()
		{
			try
			{
				return ConstDefs.AllDays ?? new string[0];
			}
			catch
			{
				return new string[0];
			}
		}

		public static int DayNumberOf(string dayId)
		{
			if (string.IsNullOrEmpty(dayId))
			{
				return -1;
			}
			try
			{
				ConstDef val = ConstDef.Get(dayId);
				if (val == null)
				{
					return -1;
				}
				int intValue = val.IntValue;
				return (intValue < 1 || intValue > 6) ? (-1) : intValue;
			}
			catch
			{
				return -1;
			}
		}

		public static int Today()
		{
			try
			{
				EnvironmentData val = Env();
				return (val != null) ? val.CurrentDayNumber : (-1);
			}
			catch
			{
				return -1;
			}
		}

		public static string TodayId()
		{
			int num = Today();
			if (num < 0)
			{
				return null;
			}
			string[] array = DayIds();
			foreach (string text in array)
			{
				if (DayNumberOf(text) == num)
				{
					return text;
				}
			}
			return null;
		}

		public static List<string> Week()
		{
			List<string> list = new List<string>();
			string[] array = new string[7];
			string[] array2 = DayIds();
			foreach (string text in array2)
			{
				int num = DayNumberOf(text);
				if (num >= 1 && num <= 6)
				{
					array[num] = text;
				}
			}
			for (int j = 1; j <= 6; j++)
			{
				if (array[j] != null)
				{
					list.Add(array[j]);
				}
			}
			return list;
		}

		public static int DaysUntil(string dayId)
		{
			int num = Today();
			int num2 = DayNumberOf(dayId);
			if (num < 0 || num2 < 0)
			{
				return -1;
			}
			return ((num2 - num) % 6 + 6) % 6;
		}

		public static bool OrderDayToday()
		{
			return DaysUntil("day_pride") == 0;
		}

		public static string DayIcon(string dayId)
		{
			if (string.IsNullOrEmpty(dayId))
			{
				return "";
			}
			try
			{
				return UIExtensions.FontIcon(dayId);
			}
			catch
			{
				return "";
			}
		}

		private static EnvironmentData Env()
		{
			MainGame instance = MainGame.Instance;
			return ((!((Object)(object)instance != (Object)null)) ? null : instance.GameSave)?.environmentData;
		}

		public static List<OrderInfo> Current()
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Invalid comparison between Unknown and I4
			List<OrderInfo> list = new List<OrderInfo>();
			try
			{
				MainGame instance = MainGame.Instance;
				VendorSystem val = ((!((Object)(object)instance != (Object)null)) ? null : instance.GameSave)?.vendorSystem;
				if (val == null)
				{
					return list;
				}
				List<(VendorOrderData, Vendor)> currentOrders = val.GetCurrentOrders();
				if (currentOrders == null)
				{
					return list;
				}
				for (int i = 0; i < currentOrders.Count; i++)
				{
					VendorOrderData item = currentOrders[i].Item1;
					Vendor item2 = currentOrders[i].Item2;
					if (item == null)
					{
						continue;
					}
					VendorOrderDef val2 = null;
					try
					{
						val2 = ((ObjectLinkedToDefinition<VendorOrderDef>)(object)item).Definition;
					}
					catch
					{
					}
					if (val2 != null && !string.IsNullOrEmpty(val2.itemId))
					{
						OrderInfo orderInfo = new OrderInfo();
						orderInfo.Slot = i;
						orderInfo.ItemId = val2.itemId;
						orderInfo.Need = val2.count;
						orderInfo.Urgent = val2.isUrgent;
						orderInfo.Finished = (int)item.State == 1;
						orderInfo.Delivered = Delivered(item);
						orderInfo.OnPallets = OnPallets(val2.itemId);
						orderInfo.Reward = Reward(val2);
						OrderInfo orderInfo2 = orderInfo;
						if (item2 != null)
						{
							orderInfo2.VendorId = ((ObjectLinkedToDefinition<VendorDef>)(object)item2).id;
							orderInfo2.VendorName = VendorName(item2);
							orderInfo2.Portrait = Portrait(item2);
						}
						list.Add(orderInfo2);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Orders: " + ex.Message));
			}
			return list;
		}

		private static int Delivered(VendorOrderData data)
		{
			try
			{
				return Math.Max(0, data.Count);
			}
			catch
			{
				return 0;
			}
		}

		private static int Reward(VendorOrderDef def)
		{
			try
			{
				return (def.happinessReward != null) ? def.happinessReward.EvaluateInt() : 0;
			}
			catch
			{
				return 0;
			}
		}

		public static int OnPallets(string itemId)
		{
			int num = 0;
			try
			{
				WorldData worldData = MainGame.WorldData;
				if (worldData == null)
				{
					return 0;
				}
				num += Count(worldData.GetWorldZoneDataById("warehouse"), itemId);
				num += Count(worldData.GetWorldZoneDataById("warehouse_cellar"), itemId);
			}
			catch
			{
			}
			return num;
		}

		private static int Count(WorldZoneData zone, string itemId)
		{
			try
			{
				return (zone != null) ? zone.CountItemsOnTownPalettes(itemId) : 0;
			}
			catch
			{
				return 0;
			}
		}

		public static string VendorName(Vendor vendor)
		{
			if (vendor == null)
			{
				return null;
			}
			string id = ((ObjectLinkedToDefinition<VendorDef>)(object)vendor).id;
			string text = GameApi.L(id);
			if (!string.IsNullOrEmpty(text) && text != id)
			{
				return text;
			}
			try
			{
				int num = Math.Max(1, vendor.CurTier);
				List<TownBuildingDef> townBuildingDefs = GameBalance.Me.townBuildingDefs;
				if (townBuildingDefs != null)
				{
					string text2 = null;
					string text3 = null;
					int num2 = 0;
					foreach (TownBuildingDef item in townBuildingDefs)
					{
						if (item != null && !(item.vendorId != id))
						{
							num2++;
							if (text2 == null)
							{
								text2 = ((BalanceBaseObject)item).id;
							}
							if (num2 == num)
							{
								text3 = ((BalanceBaseObject)item).id;
								break;
							}
						}
					}
					string text4 = text3 ?? text2;
					if (text4 != null)
					{
						string text5 = GameApi.L(text4);
						if (!string.IsNullOrEmpty(text5) && text5 != text4)
						{
							return text5;
						}
					}
				}
			}
			catch
			{
			}
			return id;
		}

		private static Sprite Portrait(Vendor vendor)
		{
			try
			{
				VendorDef definition = ((ObjectLinkedToDefinition<VendorDef>)(object)vendor).Definition;
				return (definition == null) ? null : definition.Icon;
			}
			catch
			{
				return null;
			}
		}

		public static List<string> UnlockedVendors()
		{
			try
			{
				MainGame instance = MainGame.Instance;
				List<string> list = (((!((Object)(object)instance != (Object)null)) ? null : instance.GameSave)?.knowledgeSystem)?.unlockedVendorsForOrders;
				return (list == null) ? new List<string>() : new List<string>(list);
			}
			catch
			{
				return new List<string>();
			}
		}
	}
	internal static class OtherMods
	{
		private static float _checkedAt = -100f;

		private static bool _sermon;

		private static bool _resurrection;

		public static bool SermonEveryDay
		{
			get
			{
				Refresh();
				return _sermon;
			}
		}

		public static bool ResurrectionEveryDay
		{
			get
			{
				Refresh();
				return _resurrection;
			}
		}

		private static void Refresh()
		{
			if (!(Time.unscaledTime - _checkedAt < 5f))
			{
				_checkedAt = Time.unscaledTime;
				_sermon = Active("sermon every day", "flexibleceremonies");
				_resurrection = Active("resurrect every day", "resurrecteveryday");
			}
		}

		private static bool Active(string name, string guidPart)
		{
			try
			{
				foreach (PluginInfo value in Chainloader.PluginInfos.Values)
				{
					BepInPlugin val = ((value == null) ? null : value.Metadata);
					if (val != null)
					{
						string text = (val.Name ?? "").ToLowerInvariant();
						string text2 = (val.GUID ?? "").ToLowerInvariant();
						if (text.Contains(name) || text2.Contains(guidPart))
						{
							return SwitchOn(value.Instance);
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool SwitchOn(BaseUnityPlugin plugin)
		{
			if ((Object)(object)plugin == (Object)null)
			{
				return true;
			}
			try
			{
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in plugin.Config)
				{
					if (item.Value is ConfigEntry<bool> val)
					{
						string text = item.Key.Key.ToLowerInvariant().Replace(" ", "");
						if (text.Contains("anyday") || text.Contains("everyday") || text.Contains("alldays"))
						{
							return val.Value;
						}
					}
				}
			}
			catch
			{
			}
			return true;
		}
	}
	internal static class Pad
	{
		public sealed class Chord
		{
			public readonly List<GameKey> Mods = new List<GameKey>();

			public GameKey Main = GameKey.None;

			public string Spec;

			public bool IsNone => Missing(Main);
		}

		private static bool _broken;

		private static FieldInfo _fPressed;

		private static FieldInfo _fHolded;

		private static FieldInfo _fDirection;

		private static FieldInfo _fInstance;

		private static bool _fieldsResolved;

		private static readonly List<GameKey> _downs = new List<GameKey>();

		private static readonly List<GameKey> _helds = new List<GameKey>();

		private static Vector2 _dir;

		public static bool Owning;

		private static FieldInfo[] _keyFields;

		private static readonly string[] ModifierNames = new string[3] { "LeftTrigger", "RightTrigger", "RightBumper" };

		private static List<GameKey> _modifiers;

		public static bool ExclusivePlain;

		private static float _repeatAt;

		private static int _lastX;

		private static int _lastY;

		public static bool Active
		{
			get
			{
				if (_broken)
				{
					return false;
				}
				try
				{
					return LazyInput.IsGamepadActive;
				}
				catch (Exception e)
				{
					Fail(e);
					return false;
				}
			}
		}

		private static bool Missing(GameKey key)
		{
			return object.ReferenceEquals(key, null) || (Enumeration)(object)key == (Enumeration)(object)GameKey.None;
		}

		public static bool Down(GameKey key)
		{
			if (_broken || Missing(key))
			{
				return false;
			}
			if (Owning)
			{
				return _downs.Contains(key);
			}
			try
			{
				return LazyInput.GetKeyDown(key);
			}
			catch (Exception e)
			{
				Fail(e);
				return false;
			}
		}

		public static bool Held(GameKey key)
		{
			if (_broken || Missing(key))
			{
				return false;
			}
			if (Owning)
			{
				return _helds.Contains(key);
			}
			try
			{
				return LazyInput.GetKey(key);
			}
			catch (Exception e)
			{
				Fail(e);
				return false;
			}
		}

		public static void Consume(GameKey key)
		{
			if (_broken || Missing(key))
			{
				return;
			}
			if (Owning)
			{
				_downs.Remove(key);
				_helds.Remove(key);
				return;
			}
			try
			{
				LazyInput.ClearKeyDown(key);
				LazyInput.ClearKey(key);
				LazyInput.WaitForRelease(key);
			}
			catch (Exception e)
			{
				Fail(e);
			}
		}

		private static void ResolveFields()
		{
			if (_fieldsResolved)
			{
				return;
			}
			_fieldsResolved = true;
			try
			{
				_fInstance = AccessTools.Field(typeof(LazyInput), "instance");
				_fPressed = AccessTools.Field(typeof(LazyInput), "pressedKeys");
				_fHolded = AccessTools.Field(typeof(LazyInput), "holdedKeys");
				_fDirection = AccessTools.Field(typeof(LazyInput), "direction");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Gamepad: input fields not found: " + ex.Message));
			}
		}

		public static void Intercept()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			if (_broken)
			{
				return;
			}
			if (!Owning)
			{
				if (_downs.Count > 0 || _helds.Count > 0)
				{
					_downs.Clear();
					_helds.Clear();
					_dir = Vector2.zero;
				}
				return;
			}
			ResolveFields();
			try
			{
				if (_fInstance == null)
				{
					return;
				}
				object value = _fInstance.GetValue(null);
				if (value != null)
				{
					_downs.Clear();
					_helds.Clear();
					_dir = Vector2.zero;
					if (_fPressed != null && _fPressed.GetValue(value) is List<GameKey> { Count: >0 } list)
					{
						_downs.AddRange(list);
						list.Clear();
					}
					if (_fHolded != null && _fHolded.GetValue(value) is List<GameKey> { Count: >0 } list2)
					{
						_helds.AddRange(list2);
						list2.Clear();
					}
					if (_fDirection != null)
					{
						_dir = (Vector2)_fDirection.GetValue(value);
						_fDirection.SetValue(value, Vector2.zero);
					}
				}
			}
			catch (Exception e)
			{
				Fail(e);
			}
		}

		public static Vector2 Direction()
		{
			//IL_0032: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (_broken)
			{
				return Vector2.zero;
			}
			if (Owning)
			{
				return _dir;
			}
			try
			{
				return LazyInput.GetDirection();
			}
			catch (Exception e)
			{
				Fail(e);
				return Vector2.zero;
			}
		}

		public static string Glyph(GameKey key)
		{
			if (_broken || Missing(key))
			{
				return "";
			}
			try
			{
				string iconId = ControllerIconLibrary.GetIconId(key, GameKeyIconType.Default, false);
				return (!string.IsNullOrEmpty(iconId)) ? iconId : "";
			}
			catch (Exception e)
			{
				Fail(e);
				return "";
			}
		}

		private static FieldInfo[] KeyFields()
		{
			if (_keyFields != null)
			{
				return _keyFields;
			}
			try
			{
				_keyFields = (from f in typeof(GameKey).GetFields(BindingFlags.Static | BindingFlags.Public)
					where f.FieldType == typeof(GameKey)
					select f).ToArray();
			}
			catch
			{
				_keyFields = new FieldInfo[0];
			}
			return _keyFields;
		}

		public static GameKey Parse(string name, GameKey fallback)
		{
			if (string.IsNullOrEmpty(name))
			{
				return fallback;
			}
			name = name.Trim();
			if (name.Length == 0)
			{
				return fallback;
			}
			try
			{
				GameKey byStaticFieldName = Enumeration.GetByStaticFieldName<GameKey>(name);
				if (!object.ReferenceEquals(byStaticFieldName, null))
				{
					return byStaticFieldName;
				}
			}
			catch
			{
			}
			FieldInfo[] array = KeyFields();
			foreach (FieldInfo fieldInfo in array)
			{
				if (string.Equals(fieldInfo.Name, name, StringComparison.OrdinalIgnoreCase))
				{
					object? value = fieldInfo.GetValue(null);
					GameKey val = (GameKey)((value is GameKey) ? value : null);
					if (!object.ReferenceEquals(val, null))
					{
						return val;
					}
				}
			}
			Plugin.Log.LogWarning((object)string.Concat("Gamepad: unknown action '", name, "', using ", fallback, ". Known: ", string.Join(", ", (from f in KeyFields()
				select f.Name).ToArray())));
			return fallback;
		}

		private static List<GameKey> Modifiers()
		{
			List<GameKey> list = new List<GameKey>();
			string[] modifierNames = ModifierNames;
			foreach (string name in modifierNames)
			{
				GameKey val = Parse(name, GameKey.None);
				if (!Missing(val))
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static Chord ParseChord(string spec, string fallbackSpec)
		{
			Chord chord = new Chord();
			chord.Spec = spec;
			Chord chord2 = chord;
			string text = (spec ?? "").Trim();
			if (text.Length == 0 || string.Equals(text, "None", StringComparison.OrdinalIgnoreCase))
			{
				return chord2;
			}
			string[] array = text.Split('+');
			for (int i = 0; i < array.Length; i++)
			{
				GameKey val = Parse(array[i], GameKey.None);
				if (!Missing(val))
				{
					if (i == array.Length - 1)
					{
						chord2.Main = val;
					}
					else
					{
						chord2.Mods.Add(val);
					}
				}
			}
			if (Missing(chord2.Main) && !string.IsNullOrEmpty(fallbackSpec))
			{
				return ParseChord(fallbackSpec, null);
			}
			return chord2;
		}

		public static bool ChordDown(Chord c)
		{
			if (c == null || c.IsNone)
			{
				return false;
			}
			foreach (GameKey mod in c.Mods)
			{
				if (!Held(mod))
				{
					return false;
				}
			}
			if (c.Mods.Count == 0 && ExclusivePlain)
			{
				if (_modifiers == null)
				{
					_modifiers = Modifiers();
				}
				foreach (GameKey modifier in _modifiers)
				{
					if (Held(modifier))
					{
						return false;
					}
				}
			}
			return Down(c.Main);
		}

		public static void ConsumeChord(Chord c)
		{
			if (c != null && !c.IsNone)
			{
				Consume(c.Main);
			}
		}

		public static string Glyphs(Chord c)
		{
			if (c == null || c.IsNone)
			{
				return "";
			}
			string text = "";
			foreach (GameKey mod in c.Mods)
			{
				text += Glyph(mod);
			}
			return text + Glyph(c.Main);
		}

		private static void Fail(Exception e)
		{
			_broken = true;
			Plugin.Log.LogWarning((object)("Gamepad support is off: " + e.Message));
		}

		public static void Nav(out int dx, out int dy)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			dx = 0;
			dy = 0;
			if (_broken)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			if (Held(GameKey.Left) || Held(GameKey.DpadLeft))
			{
				num = -1;
			}
			else if (Held(GameKey.Right) || Held(GameKey.DpadRight))
			{
				num = 1;
			}
			if (Held(GameKey.Up) || Held(GameKey.DpadUp))
			{
				num2 = -1;
			}
			else if (Held(GameKey.Down) || Held(GameKey.DpadDown))
			{
				num2 = 1;
			}
			if (num == 0 && num2 == 0)
			{
				Vector2 val = Direction();
				if (val.x < -0.5f)
				{
					num = -1;
				}
				else if (val.x > 0.5f)
				{
					num = 1;
				}
				if (val.y > 0.5f)
				{
					num2 = -1;
				}
				else if (val.y < -0.5f)
				{
					num2 = 1;
				}
			}
			if (num == 0 && num2 == 0)
			{
				_lastX = (_lastY = 0);
			}
			else if (num != _lastX || num2 != _lastY)
			{
				_repeatAt = Time.unscaledTime + 0.35f;
				_lastX = num;
				_lastY = num2;
				dx = num;
				dy = num2;
			}
			else if (!(Time.unscaledTime < _repeatAt))
			{
				_repeatAt = Time.unscaledTime + 0.12f;
				dx = num;
				dy = num2;
			}
		}

		public static void LogPressed()
		{
			if (_broken)
			{
				return;
			}
			List<string> list = new List<string>();
			FieldInfo[] array = KeyFields();
			foreach (FieldInfo fieldInfo in array)
			{
				try
				{
					object? value = fieldInfo.GetValue(null);
					GameKey key = (GameKey)((value is GameKey) ? value : null);
					if (!Missing(key) && Down(key))
					{
						list.Add(fieldInfo.Name);
					}
				}
				catch
				{
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			string text = "-";
			try
			{
				LazyWidgetBase activeWindow = LazyWindowsStackController.ActiveWindow;
				if ((Object)(object)activeWindow != (Object)null)
				{
					text = ((object)activeWindow).GetType().Name;
				}
			}
			catch
			{
			}
			Plugin.Log.LogInfo((object)("Gamepad down: " + string.Join(", ", list.ToArray()) + "   (window: " + text + ")"));
		}
	}
	[BepInPlugin("gk2.thoughtfulweek", "GK2 Thoughtful Week", "0.4.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "gk2.thoughtfulweek";

		public const string Version = "0.4.0";

		public const string DefaultPadWindow = "LeftTrigger+LeftStick";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal ConfigEntry<KeyboardShortcut> ToggleWindowKey;

		internal ConfigEntry<KeyboardShortcut> ThoughtKey;

		internal ConfigEntry<bool> MorningPopup;

		internal ConfigEntry<bool> MorningOnlyWhenSomething;

		internal ConfigEntry<bool> MorningShowEvents;

		internal ConfigEntry<bool> MorningShowOrders;

		internal ConfigEntry<bool> MorningOpensPanel;

		internal ConfigEntry<bool> MorningOnLoad;

		internal ConfigEntry<float> MorningTime;

		internal ConfigEntry<string> PadWindowKey;

		internal ConfigEntry<string> PadThoughtKey;

		internal ConfigEntry<bool> PadLogInput;

		internal ConfigEntry<bool> PadExclusive;

		internal readonly InputLock InputLock = new InputLock();

		private PlannerWindow _window;

		private string _uiLang;

		private int _shownForDay = int.MinValue;

		private string _shownForSlot;

		private bool _wantMorning;

		private float _loadSeenAt = -1f;

		private const float LoadDelay = 3f;

		private static readonly HashSet<string> BigWindows = new HashSet<string>
		{
			"CharacterWindow", "UIGamePauseWindow", "UIMainMenuWindow", "UIGameSettingsWindow", "UIGameBindingSettingsWindow", "UIMapWindow", "UISaveSlotsWindow", "UISaveSlotsWindowLimited", "UIDialogWindow", "UICreditsWindow",
			"UITutorialWindow"
		};

		private Pad.Chord _padThoughtChord;

		private string _padThoughtName;

		private Pad.Chord _padWindowChord;

		private string _padWindowName;

		private GameObject _overlay;

		private Canvas _overlayCanvas;

		private RectTransform _windowLayer;

		private Canvas _sampleCanvas;

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		private float _lastScale = -1f;

		private static readonly Dictionary<string, float> _logTimes = new Dictionary<string, float>();

		private Pad.Chord PadThought
		{
			get
			{
				if (_padThoughtName != PadThoughtKey.Value)
				{
					_padThoughtName = PadThoughtKey.Value;
					_padThoughtChord = Pad.ParseChord(_padThoughtName, "None");
				}
				return _padThoughtChord;
			}
		}

		private Pad.Chord PadWindow
		{
			get
			{
				if (_padWindowName != PadWindowKey.Value)
				{
					_padWindowName = PadWindowKey.Value;
					_padWindowChord = Pad.ParseChord(_padWindowName, "None");
				}
				return _padWindowChord;
			}
		}

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			ToggleWindowKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "ToggleWindow", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), Cm.D("Open/close the week panel at any time.", "Open the week", 10));
			ThoughtKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "ThoughtKey", new KeyboardShortcut((KeyCode)117, Array.Empty<KeyCode>()), Cm.D("Show today's thought bubble right now, whatever the time.", "Think about today", 9));
			MorningPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("Morning", "Enabled", true, Cm.D("Show a reminder by itself when a new day starts.", "Morning reminder", 50));
			MorningOnLoad = ((BaseUnityPlugin)this).Config.Bind<bool>("Morning", "OnLoad", true, Cm.D("Also show the reminder a few seconds after you load a save, so you know where you are in the week.", "After loading a save", 45));
			MorningOpensPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Morning", "OpenPanel", false, Cm.D("Open the full week panel in the morning instead of a thought bubble over your head. Off by default: the bubble says the same thing without taking the game away from you.", "Open the week instead of a thought", 10));
			MorningShowEvents = ((BaseUnityPlugin)this).Config.Bind<bool>("Morning", "ShowEvents", true, Cm.D("Say what the day is good for. Off leaves just the name of the day.", "Mention the day's event", 40));
			MorningShowOrders = ((BaseUnityPlugin)this).Config.Bind<bool>("Morning", "ShowOrders", true, Cm.D("Add a word about the town orders you are carrying.", "Mention town orders", 30));
			MorningTime = ((BaseUnityPlugin)this).Config.Bind<float>("Morning", "TimeOfDay", 0.05f, Cm.D("How far into the day the reminder waits before it appears, as a fraction of the day (0-1). The default is just after dawn, once you have the keeper back.", "When in the morning (part of the day)", 20, advanced: false, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f)));
			MorningOnlyWhenSomething = ((BaseUnityPlugin)this).Config.Bind<bool>("Morning", "OnlyWhenSomethingToDo", false, Cm.D("Only remind you when today allows something or an order is still open, so quiet days stay quiet.", "Only when there is something to do", 25));
			PadWindowKey = ((BaseUnityPlugin)this).Config.Bind<string>("Gamepad", "WindowKey", "LeftTrigger+LeftStick", Cm.D("Gamepad: opens and closes the week panel (a LazyInput GameKey name, \"None\" to leave it unbound).", "Open the week", 20));
			PadThoughtKey = ((BaseUnityPlugin)this).Config.Bind<string>("Gamepad", "ThoughtKey", "None", Cm.D("Gamepad: shows today's thought bubble (a LazyInput GameKey name, \"None\" to leave it unbound).", "Think about today", 19));
			PadExclusive = ((BaseUnityPlugin)this).Config.Bind<bool>("Gamepad", "ExclusivePlain", true, Cm.D("When on, a binding without a chord stays quiet while L2, R2 or R1 is held, so another mod can use that same button as a chord.", "Leave chords alone", 10, advanced: true));
			PadLogInput = ((BaseUnityPlugin)this).Config.Bind<bool>("Gamepad", "LogInput", false, Cm.D("Gamepad: write every pressed key to the log, to help pick a binding.", "Log pad input", 0, advanced: true));
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Internal", "PadDefaultsApplied", false, Cm.D("Set once the gamepad defaults of 0.4.0 have been applied.", "Pad defaults applied", 0, advanced: true, null, browsable: false));
			if (!val.Value)
			{
				if (string.Equals((PadWindowKey.Value ?? "").Trim(), "None", StringComparison.OrdinalIgnoreCase))
				{
					PadWindowKey.Value = "LeftTrigger+LeftStick";
				}
				if (!PadExclusive.Value)
				{
					PadExclusive.Value = true;
				}
				val.Value = true;
			}
			try
			{
				EnvironmentEngine.OnNewDayStartedWithDayNumber += OnNewDay;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("New-day event not hooked, falling back to polling: " + ex.Message));
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(LazyInput), "Update", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					Harmony val2 = new Harmony("gk2.thoughtfulweek");
					MethodInfo methodInfo2 = methodInfo;
					HarmonyMethod val3 = new HarmonyMethod(typeof(Plugin), "InputUpdated", (Type[])null);
					val2.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					Log.LogWarning((object)"LazyInput.Update not found: the gamepad cannot be taken from the game");
				}
			}
			catch (Exception ex2)
			{
				Log.LogWarning((object)("Input patch: " + ex2.Message));
			}
			Framework.TryRegister((BaseUnityPlugin)(object)this);
			Log.LogInfo((object)"GK2 Thoughtful Week 0.4.0 loaded");
		}

		private static void InputUpdated()
		{
			Pad.Intercept();
		}

		private void OnDestroy()
		{
			try
			{
				EnvironmentEngine.OnNewDayStartedWithDayNumber -= OnNewDay;
			}
			catch
			{
			}
			InputLock.Release();
		}

		private void OnNewDay(int dayNumber)
		{
			try
			{
				if (MorningPopup.Value)
				{
					_wantMorning = true;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("New day: " + ex.Message));
			}
		}

		private void Update()
		{
			try
			{
				Tick();
			}
			catch (Exception ex)
			{
				LogThrottled("Update: " + ex);
			}
		}

		private void Tick()
		{
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			if (!GameApi.InGame())
			{
				if (_window != null && _window.IsOpen)
				{
					_window.Close();
				}
				if ((Object)(object)_overlay != (Object)null && _overlay.activeSelf)
				{
					_overlay.SetActive(false);
				}
				_sampleCanvas = null;
				_wantMorning = false;
				_shownForSlot = null;
				_shownForDay = int.MinValue;
				_loadSeenAt = -1f;
				return;
			}
			if ((Object)(object)_overlay != (Object)null && !_overlay.activeSelf)
			{
				_overlay.SetActive(true);
			}
			if (!EnsureUi())
			{
				return;
			}
			string text = GameApi.Lang();
			if (_uiLang != null && text != _uiLang)
			{
				bool isOpen = _window.IsOpen;
				_window.Destroy();
				_window = new PlannerWindow((Transform)(object)_windowLayer);
				if (isOpen)
				{
					_window.Open();
				}
			}
			_uiLang = text;
			int num = Week.Today();
			string text2 = GameApi.SlotKey();
			if (num >= 0 && (text2 != _shownForSlot || num != _shownForDay))
			{
				if (_wantMorning)
				{
					if (MorningDue())
					{
						ShowMorning(num, text2);
					}
				}
				else if (MorningPopup.Value && MorningOnLoad.Value)
				{
					if (PlayerNotReady())
					{
						_loadSeenAt = -1f;
					}
					else if (_loadSeenAt < 0f)
					{
						_loadSeenAt = Time.unscaledTime;
					}
					if (_loadSeenAt >= 0f && Time.unscaledTime - _loadSeenAt >= 3f && !BigGameWindowOpen() && !StoryBusy())
					{
						ShowMorning(num, text2);
					}
				}
				else
				{
					_shownForDay = num;
					_shownForSlot = text2;
				}
			}
			KeyboardShortcut value = ToggleWindowKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_window.Toggle();
			}
			KeyboardShortcut value2 = ThoughtKey.Value;
			if (((KeyboardShortcut)(ref value2)).IsDown() && !TypingText())
			{
				ThinkNow();
			}
			if (_window.IsOpen && Input.GetKeyDown((KeyCode)27))
			{
				_window.Close();
			}
			Clock.Sample();
			TickGamepad();
			_window.Tick();
			_window.TickGamepad();
		}

		private bool MorningDue()
		{
			if (BigGameWindowOpen() || StoryBusy() || PlayerNotReady())
			{
				return false;
			}
			try
			{
				MainGame instance = MainGame.Instance;
				EnvironmentData val = ((!((Object)(object)instance != (Object)null)) ? null : instance.GameSave)?.environmentData;
				if (val == null)
				{
					return false;
				}
				return val.TimeOfDay >= Mathf.Clamp01(MorningTime.Value);
			}
			catch
			{
				return false;
			}
		}

		private void ShowMorning(int day, string slot)
		{
			_shownForDay = day;
			_shownForSlot = slot;
			_wantMorning = false;
			_loadSeenAt = -1f;
			if (MorningOnlyWhenSomething.Value && !SomethingToDo())
			{
				return;
			}
			if (MorningOpensPanel.Value)
			{
				if (!_window.IsOpen)
				{
					_window.Open();
				}
			}
			else
			{
				string text = Week.BubbleText(MorningShowEvents.Value, MorningShowOrders.Value);
				Thought.Say(text);
			}
		}

		private static bool TypingText()
		{
			try
			{
				EventSystem current = EventSystem.current;
				GameObject val = ((!((Object)(object)current != (Object)null)) ? null : current.currentSelectedGameObject);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				TMP_InputField component = val.GetComponent<TMP_InputField>();
				if ((Object)(object)component != (Object)null && component.isFocused)
				{
					return true;
				}
				InputField component2 = val.GetComponent<InputField>();
				return (Object)(object)component2 != (Object)null && component2.isFocused;
			}
			catch
			{
				return false;
			}
		}

		private void ThinkNow()
		{
			if (!StoryBusy() && !PlayerNotReady())
			{
				string text = Week.BubbleText(withEvent: true, withOrders: true);
				if (!Thought.Say(text))
				{
					Log.LogInfo((object)"Nothing to think about yet (not in a game?)");
				}
			}
		}

		private static bool SomethingToDo()
		{
			try
			{
				DayPlan dayPlan = Week.TodayPlan();
				if (dayPlan != null && dayPlan.Known && !string.IsNullOrEmpty(dayPlan.Activity))
				{
					return true;
				}
				if (Week.TearsLine(dayPlan) != null)
				{
					return true;
				}
				if (dayPlan != null && dayPlan.Extras.Any((DayExtra x) => x.Key != "ActTears"))
				{
					return true;
				}
				if (Week.OrdersWorthAWord())
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool StoryBusy()
		{
			try
			{
				PlayerController playerController = MainGame.PlayerController;
				if ((Object)(object)playerController == (Object)null)
				{
					return false;
				}
				MultiFlagAND<TakenControlType> value = Traverse.Create((object)playerController).Field("playerTakenControlMultiFlag").GetValue<MultiFlagAND<TakenControlType>>();
				if (value == null)
				{
					return false;
				}
				return !((MultiFlagBase<TakenControlType>)(object)value).GetFlag((TakenControlType)3) || !((MultiFlagBase<TakenControlType>)(object)value).GetFlag((TakenControlType)11);
			}
			catch (Exception ex)
			{
				LogThrottled("StoryBusy: " + ex.Message);
				return false;
			}
		}

		private static bool PlayerNotReady()
		{
			try
			{
				PlayerController playerController = MainGame.PlayerController;
				if ((Object)(object)playerController == (Object)null)
				{
					return true;
				}
				MultiFlagAND<DisabledStateType> value = Traverse.Create((object)playerController).Field("playerDisabledStateMultiFlag").GetValue<MultiFlagAND<DisabledStateType>>();
				if (value != null && !((MultiFlagBase<DisabledStateType>)(object)value).ResultFlag)
				{
					return true;
				}
				MultiFlagAND<TakenControlType> value2 = Traverse.Create((object)playerController).Field("playerTakenControlMultiFlag").GetValue<MultiFlagAND<TakenControlType>>();
				return value2 != null && !((MultiFlagBase<TakenControlType>)(object)value2).GetFlag((TakenControlType)4);
			}
			catch (Exception ex)
			{
				LogThrottled("PlayerNotReady: " + ex.Message);
				return false;
			}
		}

		private static bool BigGameWindowOpen()
		{
			try
			{
				LazyWidgetBase activeWindow = LazyWindowsStackController.ActiveWindow;
				return (Object)(object)activeWindow != (Object)null && BigWindows.Contains(((object)activeWindow).GetType().Name);
			}
			catch
			{
				return false;
			}
		}

		private void TickGamepad()
		{
			if (PadLogInput.Value)
			{
				Pad.LogPressed();
			}
			Pad.ExclusivePlain = PadExclusive.Value;
			if (Pad.Active)
			{
				if (Pad.ChordDown(PadWindow))
				{
					Pad.ConsumeChord(PadWindow);
					_window.Toggle();
				}
				if (Pad.ChordDown(PadThought))
				{
					Pad.ConsumeChord(PadThought);
					ThinkNow();
				}
			}
		}

		private bool EnsureUi()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: 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_01d8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_overlay != (Object)null && _window != null && (Object)(object)_sampleCanvas != (Object)null)
			{
				FitOverlay();
				return true;
			}
			if ((Object)(object)_sampleCanvas == (Object)null)
			{
				UIBuildingWindow val = ((IEnumerable<UIBuildingWindow>)Resources.FindObjectsOfTypeAll<UIBuildingWindow>()).FirstOrDefault((Func<UIBuildingWindow, bool>)delegate(UIBuildingWindow w)
				{
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					//IL_0017: Unknown result type (might be due to invalid IL or missing references)
					int result;
					if ((Object)(object)w != (Object)null)
					{
						Scene scene = ((Component)w).gameObject.scene;
						result = (((Scene)(ref scene)).IsValid() ? 1 : 0);
					}
					else
					{
						result = 0;
					}
					return (byte)result != 0;
				});
				_sampleCanvas = ((!((Object)(object)val != (Object)null)) ? null : ((Component)val).GetComponent<Canvas>());
				if ((Object)(object)_sampleCanvas == (Object)null)
				{
					return false;
				}
			}
			if ((Object)(object)_overlay == (Object)null)
			{
				if (_window != null)
				{
					_window.Destroy();
				}
				_window = null;
				UiKit.Reset();
				_overlay = new GameObject("GK2ThoughtfulWeek_Overlay", new Type[1] { typeof(RectTransform) });
				Object.DontDestroyOnLoad((Object)(object)_overlay);
				_overlayCanvas = _overlay.AddComponent<Canvas>();
				_overlayCanvas.renderMode = (RenderMode)0;
				_overlayCanvas.sortingOrder = 30010;
				_overlayCanvas.pixelPerfect = false;
				_overlayCanvas.referencePixelsPerUnit = _sampleCanvas.referencePixelsPerUnit;
				_overlay.AddComponent<GraphicRaycaster>();
				_windowLayer = UiKit.Rect("WindowLayer", _overlay.transform);
				_windowLayer.anchorMin = Vector2.zero;
				_windowLayer.anchorMax = Vector2.zero;
				_windowLayer.pivot = Vector2.zero;
				FitOverlay();
				_window = new PlannerWindow((Transform)(object)_windowLayer);
				Log.LogInfo((object)string.Concat("UI overlay built. Game UI canvas: ", _sampleCanvas.renderMode, ", refPPU ", _sampleCanvas.referencePixelsPerUnit));
			}
			return _window != null;
		}

		private void FitOverlay()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_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_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_sampleCanvas == (Object)null) && !((Object)(object)_overlayCanvas == (Object)null))
			{
				RectTransform val = (RectTransform)((Component)_sampleCanvas).transform;
				Camera val2 = ((!((Object)(object)_sampleCanvas.worldCamera != (Object)null)) ? Camera.main : _sampleCanvas.worldCamera);
				Rect rect = val.rect;
				float num = ((Rect)(ref rect)).width;
				Rect rect2 = val.rect;
				float num2 = ((Rect)(ref rect2)).height;
				if (num <= 1f || num2 <= 1f)
				{
					num = 960f;
					num2 = 540f;
				}
				Vector2 val3;
				Vector2 val4 = default(Vector2);
				if ((int)_sampleCanvas.renderMode == 0 || (Object)(object)val2 == (Object)null)
				{
					val3 = Vector2.zero;
					((Vector2)(ref val4))..ctor((float)Screen.width, (float)Screen.height);
				}
				else
				{
					val.GetWorldCorners(_corners);
					Vector2 val5 = Vector2.op_Implicit(val2.WorldToScreenPoint(_corners[0]));
					Vector2 val6 = Vector2.op_Implicit(val2.WorldToScreenPoint(_corners[2]));
					val3 = Vector2.Min(val5, val6);
					val4 = Vector2.Max(val5, val6);
				}
				Vector2 val7 = val4 - val3;
				if (val7.x <= 1f || val7.y <= 1f || val7.x > (float)Screen.width * 1.5f || val7.y > (float)Screen.height * 1.5f)
				{
					float num3 = Mathf.Min((float)Screen.width / num, (float)Screen.height / num2);
					((Vector2)(ref val7))..ctor(num * num3, num2 * num3);
					val3 = (new Vector2((float)Screen.width, (float)Screen.height) - val7) * 0.5f;
				}
				float num4 = val7.y / num2;
				if (Mathf.Abs(num4 - _lastScale) > 0.001f)
				{
					_lastScale = num4;
					_overlayCanvas.scaleFactor = num4;
				}
				if ((Object)(object)_windowLayer != (Object)null)
				{
					_windowLayer.anchoredPosition = val3 / num4;
					_windowLayer.sizeDelta = new Vector2(num, num2);
				}
			}
		}

		internal static void LogThrottled(string msg)
		{
			string key = ((msg.Length <= 80) ? msg : msg.Substring(0, 80));
			if (!_logTimes.TryGetValue(key, out var value) || !(Time.unscaledTime - value < 10f))
			{
				_logTimes[key] = Time.unscaledTime;
				Log.LogWarning((object)msg);
			}
		}
	}
	internal sealed class InputLock
	{
		private readonly List<ControllerMap> _disabled = new List<ControllerMap>();

		private bool _held;

		private bool _broken;

		public void Acquire()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (_held)
			{
				return;
			}
			_held = true;
			if (_broken)
			{
				return;
			}
			try
			{
				_disabled.Clear();
				if (!ReInput.isReady)
				{
					return;
				}
				foreach (Player allPlayer in ReInput.players.AllPlayers)
				{
					if (allPlayer == null)
					{
						continue;
					}
					ControllerType[] array = (ControllerType[])(object)new ControllerType[2]
					{
						default(ControllerType),
						(ControllerType)1
					};
					foreach (ControllerType val in array)
					{
						foreach (ControllerMap allMap in allPlayer.controllers.maps.GetAllMaps(val))
						{
							if (allMap != null && allMap.enabled)
							{
								allMap.enabled = false;
								_disabled.Add(allMap);
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				_broken = true;
				Plugin.Log.LogWarning((object)("Input lock failed: " + ex.Message));
			}
		}

		public void Release()
		{
			if (!_held)
			{
				return;
			}
			_held = false;
			foreach (ControllerMap item in _disabled)
			{
				try
				{
					item.enabled = true;
				}
				catch
				{
				}
			}
			_disabled.Clear();
		}
	}
	internal static class Thought
	{
		public static bool Say(string text)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			try
			{
				Bubble.Talk(new PhraseData(true, (WgoData)null, text, (Action)null, (SpeechBubblePreset)null, (SpeechBubbleType)0, (ForceCornerPosition)0, 0f, false));
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Thought bubble failed: " + ex.Message));
				return false;
			}
		}
	}
	internal static class UiKit
	{
		public static readonly Color TextName = new Color(0.878f, 0.667f, 0.424f, 1f);

		public static readonly Color TextHeader = Color.white;

		public static readonly Color TextDim = new Color(0.55f, 0.5f, 0.45f, 1f);

		public static readonly Color CountOk = new Color(1f, 0.765f, 0f, 1f);

		public static readonly Color CountLow = new Color(0.95f, 0.36f, 0.29f, 1f