Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FjordFolk v1.0.0
plugins/FjordFolk.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FjordFolk.Beggar; using FjordFolk.Fisher; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FjordFolk")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FjordFolk")] [assembly: AssemblyTitle("FjordFolk")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FjordFolk { internal static class Loc { private const string Prefix = "fjordfolk_"; private static readonly string[] Languages = new string[2] { "English", "Russian" }; public static void Register() { string[] languages = Languages; for (int i = 0; i < languages.Length; i++) { string text = languages[i]; string text2 = "FjordFolk.Localization." + text + ".txt"; using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text2); if (stream == null) { FjordFolkPlugin.Log.LogError((object)("embedded " + text2 + " not found")); continue; } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); Dictionary<string, string> dictionary = Parse(streamReader.ReadToEnd()); LocalizationManager.Instance.GetLocalization().AddTranslation(ref text, dictionary); } } public static string Token(string key) { return "$fjordfolk_" + key; } public static string T(string key) { if (Localization.instance == null) { return key; } return Localization.instance.Localize(Token(key)); } public static string T(string key, params object[] args) { return string.Format(T(key), args); } private static Dictionary<string, string> Parse(string text) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); string[] array = text.Split('\n'); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim().TrimStart('\ufeff'); if (text2.Length != 0 && !text2.StartsWith("#")) { int num = text2.IndexOf('='); if (num > 0) { string text3 = text2.Substring(0, num).Trim(); string value = text2.Substring(num + 1).Trim().Replace("\\n", "\n"); dictionary["fjordfolk_" + text3] = value; } } } return dictionary; } } public class NpcActor : MonoBehaviour, Hoverable, Interactable { public int m_presetId; [NonSerialized] public bool m_portrait; private static readonly int s_appearanceVersion = StringExtensionMethods.GetStableHashCode("fjordfolk_appearance_v1"); private ZNetView m_nview; private VisEquipment m_vis; private FisherWorkplace m_work; private BeggarBehaviour m_beggar; private NpcPreset m_preset; private NpcEmotes m_emotes; private void Awake() { FjordFolkPlugin.Guard("NpcActor.Awake", delegate { m_nview = ((Component)this).GetComponent<ZNetView>(); m_vis = ((Component)this).GetComponent<VisEquipment>(); m_work = ((Component)this).GetComponent<FisherWorkplace>(); m_beggar = ((Component)this).GetComponent<BeggarBehaviour>(); m_preset = NpcPresets.Get(m_presetId); if ((Object)(object)m_vis == (Object)null || m_preset == null) { FjordFolkPlugin.Log.LogWarning((object)$"{((Object)this).name}: missing VisEquipment or preset {m_presetId}"); } else { ZDO val = (((Object)(object)m_nview != (Object)null) ? m_nview.GetZDO() : null); if (val == null) { DressGhost(m_preset); } else if (m_nview.IsOwner() && !val.GetBool(s_appearanceVersion, false)) { WriteAppearance(val, m_preset); val.Set(s_appearanceVersion, true); } } }); } private void Start() { FjordFolkPlugin.Guard("NpcActor.Start", delegate { Animator componentInChildren = ((Component)this).GetComponentInChildren<Animator>(); if (!((Object)(object)componentInChildren == (Object)null) && m_preset != null) { m_emotes = new NpcEmotes(componentInChildren); m_emotes.SkipWakeup(); if (!m_portrait) { ApplyPose(); } } }); } private void WriteAppearance(ZDO zdo, NpcPreset p) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) zdo.Set(ZDOVars.s_modelIndex, p.Model, false); zdo.Set(ZDOVars.s_skinColor, p.SkinColor); zdo.Set(ZDOVars.s_hairColor, p.HairColor); zdo.Set(ZDOVars.s_hairItem, ItemHash(HairName(p)), false); zdo.Set(ZDOVars.s_beardItem, ItemHash(BeardName(p)), false); zdo.Set(ZDOVars.s_chestItem, ItemHash(p.Chest), false); zdo.Set(ZDOVars.s_legItem, ItemHash(p.Legs), false); zdo.Set(ZDOVars.s_helmetItem, ItemHash(p.Helmet), false); zdo.Set(ZDOVars.s_shoulderItem, ItemHash(p.Shoulder), false); zdo.Set(ZDOVars.s_rightItem, ItemHash(p.RightItem), false); zdo.Set(ZDOVars.s_leftItem, ItemHash(p.LeftItem), false); } private void DressGhost(NpcPreset p) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) m_vis.m_modelIndex = p.Model; m_vis.m_skinColor = p.SkinColor; m_vis.m_hairColor = p.HairColor; m_vis.m_hairItem = ItemHash(HairName(p)); m_vis.m_beardItem = ItemHash(BeardName(p)); m_vis.m_chestItem = ItemHash(p.Chest); m_vis.m_legItem = ItemHash(p.Legs); m_vis.m_helmetItem = ItemHash(p.Helmet); m_vis.m_shoulderItem = ItemHash(p.Shoulder); m_vis.m_rightItem = ItemHash(p.RightItem); m_vis.m_leftItem = ItemHash(p.LeftItem); } private static string HairName(NpcPreset p) { return Customization("Hair", p.HairIndex); } private static string BeardName(NpcPreset p) { return Customization("Beard", p.BeardIndex); } private static string Customization(string prefix, int index) { if (index <= 0 || (Object)(object)ObjectDB.instance == (Object)null) { return ""; } List<string> list = (from i in ObjectDB.instance.GetAllItems((ItemType)10, prefix) where (Object)(object)i != (Object)null && !((Object)i).name.EndsWith("None") select ((Object)i).name into n orderby n.Length, n select n).ToList(); if (list.Count != 0) { return list[Mathf.Clamp(index, 1, list.Count) - 1]; } return ""; } private int ItemHash(string itemName) { if (string.IsNullOrEmpty(itemName)) { return 0; } if ((Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ObjectDB.instance.GetItemPrefab(itemName) == (Object)null) { FjordFolkPlugin.Log.LogWarning((object)(((Object)this).name + ": item '" + itemName + "' does not exist, slot left empty")); return 0; } return StringExtensionMethods.GetStableHashCode(itemName); } private void ApplyPose() { if (m_emotes != null && m_preset != null) { ((MonoBehaviour)this).CancelInvoke("ApplyPose"); if (string.IsNullOrEmpty(m_preset.Pose)) { m_emotes.StopAll(); } else if (m_emotes.Play(m_preset.Pose) == "missing") { FjordFolkPlugin.Log.LogWarning((object)(((Object)this).name + ": pose '" + m_preset.Pose + "' not in animator")); } } } public void PlayGestureLocal(string emote, float returnAfter = 3.5f) { if (m_emotes != null && !string.IsNullOrEmpty(emote)) { ((MonoBehaviour)this).CancelInvoke("ApplyPose"); m_emotes.Play(emote); if (returnAfter > 0f) { ((MonoBehaviour)this).Invoke("ApplyPose", returnAfter); } } } public void ReturnToPose() { ApplyPose(); } public string GetHoverName() { if (m_preset == null) { return ""; } return m_preset.Name; } public string GetHoverText() { if (m_preset == null) { return ""; } if ((Object)(object)m_work != (Object)null && m_work.IsLive) { return m_work.HoverText(m_preset.Name); } if ((Object)(object)m_beggar != (Object)null && m_beggar.IsLive) { return m_beggar.HoverText(m_preset.Name); } return m_preset.Name; } public float GetHoverOffset() { return 0f; } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold || m_preset == null) { return false; } FjordFolkPlugin.Guard("NpcActor.Interact", delegate { if ((Object)(object)m_work != (Object)null) { if (m_work.IsLive && !FisherPanel.JustClosed) { FisherPanel.Open(m_work); } } else if ((Object)(object)m_beggar != (Object)null) { m_beggar.GiveCoin(user); } }); return true; } public bool UseItem(Humanoid user, ItemData item) { if ((Object)(object)m_beggar == (Object)null || !m_beggar.IsLive || !BeggarBehaviour.IsCoin(item)) { return false; } FjordFolkPlugin.Guard("NpcActor.UseItem", delegate { m_beggar.GiveCoin(user); }); return true; } public void Say(string text) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 2.1f, 25f, 6f, "", text, false); } } internal sealed class NpcDialogue { private const string EmbeddedPrefix = "FjordFolk.Dialogue."; private static readonly string[] FallbackLanguages = new string[2] { "English", "Russian" }; private static readonly Dictionary<string, NpcDialogue> s_cache = new Dictionary<string, NpcDialogue>(); private static readonly Random s_random = new Random(); private readonly Dictionary<string, List<string>> m_sections; private readonly Dictionary<string, Queue<string>> m_bags = new Dictionary<string, Queue<string>>(); private readonly Dictionary<string, string> m_lastPicked = new Dictionary<string, string>(); public string Source { get; } private NpcDialogue(Dictionary<string, List<string>> sections, string source) { m_sections = sections; Source = source; } public static NpcDialogue For(string dialogueId) { string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English"); string key = dialogueId + "|" + text; if (s_cache.TryGetValue(key, out var value)) { return value; } NpcDialogue npcDialogue = Load(dialogueId, text); s_cache[key] = npcDialogue; FjordFolkPlugin.Log.LogDebug((object)("dialogue '" + dialogueId + "' for " + text + ": " + npcDialogue.Source + ", " + $"{npcDialogue.m_sections.Count} sections, {Total(npcDialogue.m_sections)} lines")); return npcDialogue; } public bool Has(string section) { if (m_sections.TryGetValue(section, out var value)) { return value.Count > 0; } return false; } public string Pick(string section) { if (!Has(section)) { return null; } if (!m_bags.TryGetValue(section, out var value) || value.Count == 0) { value = Refill(section); m_bags[section] = value; } string text = value.Dequeue(); m_lastPicked[section] = text; return text; } private Queue<string> Refill(string section) { List<string> list = new List<string>(m_sections[section]); for (int num = list.Count - 1; num > 0; num--) { int num2 = s_random.Next(num + 1); List<string> list2 = list; int index = num; List<string> list3 = list; int index2 = num2; string value = list[num2]; string value2 = list[num]; list2[index] = value; list3[index2] = value2; } if (list.Count > 1 && m_lastPicked.TryGetValue(section, out var value3) && list[0] == value3) { List<string> list3 = list; List<string> list2 = list; int index2 = list.Count - 1; string value2 = list[list.Count - 1]; string value = list[0]; list3[0] = value2; list2[index2] = value; } return new Queue<string>(list); } private static NpcDialogue Load(string dialogueId, string language) { List<string> list = new List<string> { language }; string[] fallbackLanguages = FallbackLanguages; foreach (string item in fallbackLanguages) { if (!list.Contains(item)) { list.Add(item); } } foreach (string item2 in list) { string text = dialogueId + "." + item2 + ".txt"; string text2 = Path.Combine(Paths.ConfigPath, "FjordFolk", "dialogue", text); if (File.Exists(text2)) { return new NpcDialogue(Parse(File.ReadAllText(text2, Encoding.UTF8)), "override " + text2); } using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FjordFolk.Dialogue." + text); if (stream == null) { continue; } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); string source = ((item2 == language) ? ("embedded " + text) : ("embedded " + text + " (no " + language + " translation)")); return new NpcDialogue(Parse(streamReader.ReadToEnd()), source); } FjordFolkPlugin.Log.LogWarning((object)("no dialogue file for '" + dialogueId + "' in any language")); return new NpcDialogue(new Dictionary<string, List<string>>(), "none"); } private static Dictionary<string, List<string>> Parse(string text) { Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); List<string> value = null; string[] array = text.Split('\n'); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim().TrimStart('\ufeff'); if (text2.Length == 0 || text2.StartsWith("#")) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { string key = text2.Substring(1, text2.Length - 2).Trim(); if (!dictionary.TryGetValue(key, out value)) { value = (dictionary[key] = new List<string>()); } } else { value?.Add(text2); } } return dictionary; } private static int Total(Dictionary<string, List<string>> sections) { int num = 0; foreach (List<string> value in sections.Values) { num += value.Count; } return num; } } internal sealed class NpcEmotes { private static bool s_parametersLogged; private readonly Animator m_animator; private readonly Dictionary<string, AnimatorControllerParameter> m_params = new Dictionary<string, AnimatorControllerParameter>(); private string m_activeLoop; public NpcEmotes(Animator animator) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) m_animator = animator; AnimatorControllerParameter[] parameters = animator.parameters; foreach (AnimatorControllerParameter val in parameters) { m_params[val.name.ToLowerInvariant()] = val; } if (!s_parametersLogged) { s_parametersLogged = true; List<string> list = new List<string>(); parameters = animator.parameters; foreach (AnimatorControllerParameter val2 in parameters) { list.Add($"{val2.name}:{val2.type}"); } FjordFolkPlugin.Log.LogDebug((object)string.Format("animator parameters ({0}): {1}", list.Count, string.Join(", ", list))); } } public void SkipWakeup() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (m_params.TryGetValue("wakeup", out var value) && (int)value.type == 4) { m_animator.SetBool(value.name, false); } } public string Play(string emote) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Invalid comparison between Unknown and I4 if (!m_params.TryGetValue("emote_" + emote.ToLowerInvariant(), out var value)) { return "missing"; } StopLoop(); if (m_params.TryGetValue("emote_stop", out var value2)) { m_animator.ResetTrigger(value2.name); } AnimatorControllerParameterType type = value.type; if ((int)type != 4) { if ((int)type == 9) { m_animator.SetTrigger(value.name); return "once"; } return "missing"; } m_animator.SetBool(value.name, true); m_activeLoop = value.name; return "loop"; } public void StopAll() { StopLoop(); if (m_params.TryGetValue("emote_stop", out var value)) { m_animator.SetTrigger(value.name); } } private void StopLoop() { if (!string.IsNullOrEmpty(m_activeLoop)) { m_animator.SetBool(m_activeLoop, false); m_activeLoop = null; if (m_params.TryGetValue("emote_stop", out var value)) { m_animator.SetTrigger(value.name); } } } } public class NpcGreeter : MonoBehaviour { public string m_dialogueId = ""; public float m_greetRange = 5f; public float m_byeRange = 9f; public string m_gesture = "wave"; public bool m_holdGesture; private const float CheckInterval = 0.25f; private const float QuickReturnWindow = 120f; private const float PestWindow = 150f; private const int PestVisits = 2; private const float ShortVisit = 6f; private ZNetView m_nview; private NpcActor m_actor; private bool m_near; private float m_nearSince; private float m_leftAt = -9999f; private readonly List<float> m_visits = new List<float>(); private float m_nextCheck; private string m_pending; private float m_pendingAt; private void Awake() { m_nview = ((Component)this).GetComponent<ZNetView>(); m_actor = ((Component)this).GetComponent<NpcActor>(); } private void Update() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || string.IsNullOrEmpty(m_dialogueId)) { return; } if (m_pending != null && Time.time >= m_pendingAt) { string action = m_pending; m_pending = null; FjordFolkPlugin.Guard("NpcGreeter." + action, delegate { Perform(action); }); } if (!(Time.time < m_nextCheck)) { m_nextCheck = Time.time + 0.25f; FjordFolkPlugin.Guard("NpcGreeter.Update", CheckPlayer); } } private void CheckPlayer() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { return; } float num = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position); if (!m_near && num < m_greetRange) { m_near = true; m_nearSince = Time.time; Schedule("greet", Random.Range(0.35f, 1.1f)); } else if (m_near && num > m_byeRange) { m_near = false; if (m_pending == "greet") { m_pending = null; return; } m_leftAt = Time.time; Schedule("bye", Random.Range(0.2f, 0.7f)); } } private void Schedule(string action, float delay) { m_pending = action; m_pendingAt = Time.time + delay; } private void Perform(string action) { NpcDialogue dialogue = NpcDialogue.For(m_dialogueId); if (action == "greet") { Greet(dialogue); } else { Goodbye(dialogue); } } private void Greet(NpcDialogue dialogue) { m_visits.RemoveAll((float t) => Time.time - t > 150f); int count = m_visits.Count; m_visits.Add(Time.time); string text = ((count >= 2) ? "greet_pest" : ((!(Time.time - m_leftAt < 120f)) ? (Lore(dialogue) ?? Situational("greet", "greet_first", dialogue)) : "greet_again")); bool flag = text == "greet_pest"; bool num = flag || m_holdGesture || Random.value < 0.85f; bool flag2 = !string.IsNullOrEmpty(m_gesture) && (m_holdGesture || (!flag && Random.value < 0.8f)); if (flag2) { m_actor?.PlayGestureLocal(m_gesture, m_holdGesture ? 0f : 3.5f); } string text2 = (num ? (dialogue.Pick(text) ?? dialogue.Pick("greet_first")) : null); if (text2 != null) { m_actor?.Say(text2); } Report("greet", text, flag2, text2); } private void Goodbye(NpcDialogue dialogue) { if (m_holdGesture) { m_actor?.ReturnToPose(); } string section = ((Time.time - m_nearSince < 6f && Random.value < 0.7f) ? "bye_short" : Situational("bye", "bye", dialogue)); string text = ((Random.value < 0.7f) ? (dialogue.Pick(section) ?? dialogue.Pick("bye")) : null); if (text != null) { m_actor?.Say(text); } Report("bye", section, gestured: false, text); } private static string Lore(NpcDialogue dialogue) { if (dialogue.Has("greet_brother") && BeggarLore.MetRecently && Random.value < 0.5f) { return "greet_brother"; } if (dialogue.Has("greet_hired") && Random.value < 0.35f && FisherRules.FishermanExists()) { return "greet_hired"; } return null; } private static string Situational(string prefix, string plain, NpcDialogue dialogue) { EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null) { return plain; } float dayFraction = instance.GetDayFraction(); return Try("rain", EnvMan.IsWet(), 0.45f) ?? Try("night", EnvMan.IsNight(), 0.4f) ?? Try("morning", dayFraction > 0.22f && dayFraction < 0.38f, 0.35f) ?? Try("evening", dayFraction > 0.62f && dayFraction < 0.76f, 0.35f) ?? plain; string Try(string suffix, bool when, float chance) { string text = prefix + "_" + suffix; if (!when || !dialogue.Has(text) || !(Random.value < chance)) { return null; } return text; } } private void Report(string action, string section, bool gestured, string line) { string text = ((line == null) ? "(silent)" : ("\"" + line + "\"")); FjordFolkPlugin.Log.LogDebug((object)(m_dialogueId + " " + action + ": [" + section + "]" + (gestured ? (" +" + m_gesture) : "") + " " + text)); } } internal sealed class NpcIcons : MonoBehaviour { private static readonly List<string> s_prefabs = new List<string>(); private static bool s_started; public static void Add(string prefabName) { if (!s_prefabs.Contains(prefabName)) { s_prefabs.Add(prefabName); } } private void Update() { if (!s_started && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null)) { s_started = true; ((MonoBehaviour)this).StartCoroutine(RenderAll()); } } private IEnumerator RenderAll() { yield return (object)new WaitForSeconds(3f); int rendered = 0; foreach (string name in s_prefabs) { GameObject prefab = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null); Piece piece = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null); if ((Object)(object)piece == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { continue; } GameObject stage = null; FjordFolkPlugin.Guard("NpcIcons.Stage", delegate { stage = Stage(prefab); }); if ((Object)(object)stage == (Object)null) { continue; } yield return (object)new WaitForSeconds(1.5f); FjordFolkPlugin.Guard("NpcIcons.Render", delegate { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) bool value = DebugConfig.ExportIcons.Value; int num = (value ? 512 : 128); Sprite val = RenderManager.Instance.Render(new RenderRequest(stage) { Width = num, Height = num, Rotation = Quaternion.Euler(8f, -30f, 0f), UseCache = false }); if (!((Object)(object)val == (Object)null)) { Rect rect = val.rect; if (!(((Rect)(ref rect)).width <= 1f)) { piece.m_icon = val; int num2 = rendered; rendered = num2 + 1; if (value) { string text = Path.Combine(Paths.ConfigPath, "FjordFolk"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "icon_" + name + ".png"); File.WriteAllBytes(text2, ImageConversion.EncodeToPNG(val.texture)); FjordFolkPlugin.Log.LogInfo((object)("icon saved to " + text2)); } } } }); Object.Destroy((Object)(object)stage); } FjordFolkPlugin.Log.LogDebug((object)$"NPC icons rendered: {rendered} of {s_prefabs.Count}"); } private static GameObject Stage(GameObject prefab) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)Player.m_localPlayer).transform.position + new Vector3(0f, 600f, 0f); ZNetView.m_forceDisableInit = true; GameObject val2; try { val2 = Object.Instantiate<GameObject>(prefab, val, Quaternion.identity); } finally { ZNetView.m_forceDisableInit = false; } NpcActor component = val2.GetComponent<NpcActor>(); if ((Object)(object)component != (Object)null) { component.m_portrait = true; } Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } Animator[] componentsInChildren2 = val2.GetComponentsInChildren<Animator>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].cullingMode = (AnimatorCullingMode)0; } return val2; } } internal static class NpcPieces { private static readonly HashSet<string> KeepTypes = new HashSet<string> { "Transform", "ZNetView", "VisEquipment", "Animator", "SkinnedMeshRenderer", "MeshRenderer", "MeshFilter", "LODGroup", "CapsuleCollider", "SphereCollider", "BoxCollider", "MeshCollider", "MagicaCloth", "MagicaCapsuleCollider", "MagicaSphereCollider", "MagicaPlaneCollider" }; public static void RegisterAll() { GameObject prefab = PrefabManager.Instance.GetPrefab("Player"); if ((Object)(object)prefab == (Object)null) { FjordFolkPlugin.Log.LogError((object)"vanilla 'Player' prefab not found, nothing registered"); return; } FisherPieces.Register(prefab); BeggarPieces.Register(prefab); } internal static GameObject BuildNpc(GameObject player, string prefabName, int presetId) { GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, player); Strip(val); ZNetView component = val.GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null) { FjordFolkPlugin.Log.LogError((object)(prefabName + ": ZNetView lost during strip")); return null; } component.m_persistent = true; val.AddComponent<NpcActor>().m_presetId = presetId; NpcPreset npcPreset = NpcPresets.Get(presetId); if (npcPreset != null && !string.IsNullOrEmpty(npcPreset.DialogueId)) { NpcGreeter npcGreeter = val.AddComponent<NpcGreeter>(); npcGreeter.m_dialogueId = npcPreset.DialogueId; npcGreeter.m_gesture = npcPreset.Greet; npcGreeter.m_holdGesture = npcPreset.HoldGreet; } if ((Object)(object)val.GetComponent<Piece>() == (Object)null) { val.AddComponent<Piece>(); } return val; } internal static void AddToHammer(GameObject prefab, string nameToken, string descriptionToken, string iconItem, RequirementConfig[] requirements) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (!((Object)(object)prefab == (Object)null)) { PieceConfig val = new PieceConfig { Name = nameToken, Description = descriptionToken, PieceTable = "Hammer", Category = "Misc", Icon = IconOf(iconItem), Requirements = requirements }; PieceManager.Instance.AddPiece(new CustomPiece(prefab, false, val)); NpcIcons.Add(((Object)prefab).name); FjordFolkPlugin.Log.LogDebug((object)("registered " + ((Object)prefab).name)); } } private static void Strip(GameObject prefab) { for (int i = 0; i < 10; i++) { List<Component> list = (from c in prefab.GetComponentsInChildren<Component>(true) where (Object)(object)c != (Object)null && !KeepTypes.Contains(((object)c).GetType().Name) orderby (!(c is MonoBehaviour)) ? 1 : 0 select c).ToList(); if (list.Count == 0) { break; } foreach (Component item in list) { Object.DestroyImmediate((Object)(object)item); } int num = prefab.GetComponentsInChildren<Component>(true).Count((Component c) => (Object)(object)c != (Object)null && !KeepTypes.Contains(((object)c).GetType().Name)); if (num == list.Count) { FjordFolkPlugin.Log.LogWarning((object)$"{((Object)prefab).name}: {num} components could not be removed"); break; } } int num2 = LayerMask.NameToLayer("piece"); Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if (val.isTrigger) { Object.DestroyImmediate((Object)(object)val); } else if (num2 >= 0) { ((Component)val).gameObject.layer = num2; } } } internal static Sprite IconOf(string itemName) { GameObject prefab = PrefabManager.Instance.GetPrefab(itemName); Sprite[] array = ((!((Object)(object)prefab != (Object)null)) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons); if (array == null || array.Length == 0) { return null; } return array[0]; } } internal sealed class NpcPreset { public int Id; public string NameKey; public int Model; public Vector3 SkinColor; public Vector3 HairColor; public int HairIndex; public int BeardIndex; public string Chest = ""; public string Legs = ""; public string Helmet = ""; public string Shoulder = ""; public string RightItem = ""; public string LeftItem = ""; public string Pose = ""; public string Greet = ""; public bool HoldGreet; public string DialogueId = ""; public string Name => Loc.T(NameKey); } internal static class NpcPresets { public const int FishermanId = 1; public const int BeggarId = 2; private static readonly NpcPreset[] All = new NpcPreset[2] { new NpcPreset { Id = 1, NameKey = "knut_name", Model = 0, SkinColor = new Vector3(0.85f, 0.72f, 0.6f), HairColor = new Vector3(0.62f, 0.28f, 0.12f), HairIndex = 9, BeardIndex = 2, Chest = "ArmorRagsChest", Legs = "ArmorRagsLegs", Helmet = "HelmetFishingHat", RightItem = "FishingRod", Pose = "sit", Greet = "wave", DialogueId = "fisher" }, new NpcPreset { Id = 2, NameKey = "ulv_name", Model = 0, SkinColor = new Vector3(0.85f, 0.72f, 0.6f), HairColor = new Vector3(0.45f, 0.34f, 0.22f), HairIndex = 8, BeardIndex = 10, Chest = "ArmorRagsChest", Legs = "ArmorRagsLegs", Helmet = "HelmetSweatBand", Pose = "sit", Greet = "cower", HoldGreet = true, DialogueId = "beggar" } }; public static NpcPreset Get(int id) { NpcPreset[] all = All; foreach (NpcPreset npcPreset in all) { if (npcPreset.Id == id) { return npcPreset; } } return null; } } [BepInPlugin("fedorovdgap.fjordfolk", "Fjord Folk", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("valheim.exe")] public class FjordFolkPlugin : BaseUnityPlugin { public const string PluginId = "fedorovdgap.fjordfolk"; public const string PluginName = "Fjord Folk"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private static readonly HashSet<string> s_failedOnce = new HashSet<string>(); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; FisherConfig.Bind(((BaseUnityPlugin)this).Config); BeggarConfig.Bind(((BaseUnityPlugin)this).Config); DebugConfig.Bind(((BaseUnityPlugin)this).Config); Guard("Loc.Register", Loc.Register); Guard("Harmony", delegate { //IL_0005: Unknown result type (might be due to invalid IL or missing references) new Harmony("fedorovdgap.fjordfolk").PatchAll(typeof(FjordFolkPlugin).Assembly); }); ((Component)this).gameObject.AddComponent<BeggarSpawner>(); ((Component)this).gameObject.AddComponent<NpcIcons>(); PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; } private void OnVanillaPrefabsAvailable() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; Guard("RegisterAll", NpcPieces.RegisterAll); } internal static void Guard(string where, Action action) { try { action(); } catch (Exception arg) { if (s_failedOnce.Add(where)) { Log.LogError((object)$"{where} failed (repeats are not logged): {arg}"); } } } } internal static class DebugConfig { public static ConfigEntry<bool> TestChest; public static ConfigEntry<bool> WriteUiLayout; public static ConfigEntry<bool> ExportIcons; public static void Bind(ConfigFile config) { TestChest = config.Bind<bool>("Debug", "TestChest", false, "Adds a chest for one wood to the hammer that fills itself with everything needed to test the fisherman. Restart the game after changing."); WriteUiLayout = config.Bind<bool>("Debug", "WriteUiLayout", false, "Writes the layout of the fisherman's window to the config folder when it first opens."); ExportIcons = config.Bind<bool>("Debug", "ExportIcons", false, "Saves the rendered hammer icons as PNG files to the config folder."); } } internal static class VanillaUi { public sealed class Window { public RectTransform Root; public float Width; public TMP_Text Title; public Image Icon; public TMP_Text LevelText; public UITooltip LevelTooltip; public readonly List<Button> Tabs = new List<Button>(); public Rect ContentArea; public GameObject List; public RectTransform ListRoot; public float ListSpacing; public GameObject Details; public Image DetailsIcon; public TMP_Text DetailsName; public TMP_Text DetailsText; public TMP_Text DetailsFooter; public readonly List<Tile> Requirements = new List<Tile>(); public TMP_Text RequirementLevel; public UITooltip RequirementLevelTooltip; public Button ActionButton; } public sealed class ListEntry { public GameObject Root; public Image Icon; public TMP_Text Name; public TMP_Text Badge; public GameObject Selected; public Button Button; } public enum TextStyle { Header, Body, Big } public sealed class Slot { public RectTransform Rect; public Image Icon; public TMP_Text Amount; public GameObject Selected; public Button Button; public UITooltip Tooltip; public void Show(Sprite icon, int amount, bool dim) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Icon != (Object)null) { Icon.sprite = icon; ((Behaviour)Icon).enabled = (Object)(object)icon != (Object)null; ((Graphic)Icon).color = (Color)(dim ? new Color(1f, 1f, 1f, 0.45f) : Color.white); } if ((Object)(object)Amount != (Object)null) { Amount.text = ((amount > 0) ? amount.ToString() : ""); ((Component)Amount).gameObject.SetActive(amount > 0); } } } public sealed class Tile { public GameObject Root; public Image Icon; public TMP_Text Name; public TMP_Text Amount; public UITooltip Tooltip; } private static readonly HashSet<string> Behaviours = new HashSet<string> { "SkillsDialog", "UIGroupHandler", "UIGamePad", "Localize", "UIInputHandler", "UIDragHandler", "InventoryElement", "ScrollRectEnsureVisible", "EventTrigger" }; private static readonly HashSet<string> Layouts = new HashSet<string> { "ContentSizeFitter", "LayoutElement", "VerticalLayoutGroup", "HorizontalLayoutGroup", "GridLayoutGroup" }; public static readonly Color Red = new Color(1f, 0.25f, 0.25f); private static GameObject s_holder; private static bool s_dumped; public static Vector2 ButtonSize => SizeOf((RectTransform)((Component)InventoryGui.instance.m_takeAllButton).transform, new Vector2(133f, 40f)); public static float SlotNaturalSize => SizeOf((RectTransform)InventoryGui.instance.m_playerGrid.m_elementPrefab.transform, new Vector2(64f, 64f)).x; public static float SlotSpacing => Mathf.Max(SlotNaturalSize, InventoryGui.instance.m_playerGrid.m_elementSpace); public static string MissingPart() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { return "InventoryGui"; } if ((Object)(object)instance.m_crafting == (Object)null || (Object)(object)instance.m_craftingStationName == (Object)null) { return "crafting panel"; } if ((Object)(object)instance.m_tabCraft == (Object)null || (Object)(object)instance.m_tabUpgrade == (Object)null) { return "tabs"; } if ((Object)(object)instance.m_recipeListRoot == (Object)null || (Object)(object)instance.m_recipeElementPrefab == (Object)null) { return "recipe list"; } if ((Object)(object)instance.m_recipeName == (Object)null || (Object)(object)instance.m_recipeDecription == (Object)null || (Object)(object)instance.m_itemCraftType == (Object)null) { return "description"; } if (instance.m_recipeRequirementList == null || instance.m_recipeRequirementList.Length == 0) { return "requirements"; } if ((Object)(object)instance.m_craftButton == (Object)null || (Object)(object)instance.m_takeAllButton == (Object)null) { return "buttons"; } if ((Object)(object)instance.m_playerGrid == (Object)null || (Object)(object)instance.m_playerGrid.m_elementPrefab == (Object)null) { return "inventory slot"; } return null; } public static Transform GuiRoot() { Canvas val = (((Object)(object)InventoryGui.instance != (Object)null) ? ((Component)InventoryGui.instance).GetComponentInParent<Canvas>(true) : null); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val.rootCanvas).transform; } public static Window CreateWindow(Transform parent, string title, IList<string> tabs, Action<int> onTab) { //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04e4: Expected O, but got Unknown //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Unknown result type (might be due to invalid IL or missing references) //IL_06d0: Expected O, but got Unknown //IL_07e1: Unknown result type (might be due to invalid IL or missing references) //IL_07e8: Unknown result type (might be due to invalid IL or missing references) //IL_07fb: Unknown result type (might be due to invalid IL or missing references) //IL_0807: Unknown result type (might be due to invalid IL or missing references) //IL_080f: Unknown result type (might be due to invalid IL or missing references) //IL_081b: Unknown result type (might be due to invalid IL or missing references) //IL_08d5: Unknown result type (might be due to invalid IL or missing references) //IL_08e1: Unknown result type (might be due to invalid IL or missing references) //IL_08ed: Unknown result type (might be due to invalid IL or missing references) //IL_08f2: Unknown result type (might be due to invalid IL or missing references) //IL_0861: Unknown result type (might be due to invalid IL or missing references) //IL_086b: Expected O, but got Unknown //IL_0866: Unknown result type (might be due to invalid IL or missing references) //IL_086b: Unknown result type (might be due to invalid IL or missing references) //IL_087b: Unknown result type (might be due to invalid IL or missing references) //IL_0885: Expected O, but got Unknown //IL_0880: Unknown result type (might be due to invalid IL or missing references) //IL_0885: Unknown result type (might be due to invalid IL or missing references) //IL_08bd: Unknown result type (might be due to invalid IL or missing references) //IL_08c2: Unknown result type (might be due to invalid IL or missing references) //IL_0730: Unknown result type (might be due to invalid IL or missing references) //IL_073a: Expected O, but got Unknown //IL_0749: Unknown result type (might be due to invalid IL or missing references) //IL_0753: Expected O, but got Unknown InventoryGui instance = InventoryGui.instance; RectTransform source = instance.m_crafting; var anon = new { Title = PathOf((Component)(object)instance.m_craftingStationName), Icon = PathOf((Component)(object)instance.m_craftingStationIcon), Level = PathOf((Component)(object)instance.m_craftingStationLevelRoot), LevelText = PathOf((Component)(object)instance.m_craftingStationLevel), Tabs = new string[2] { PathOf((Component)(object)instance.m_tabCraft), PathOf((Component)(object)instance.m_tabUpgrade) }, List = TopOf((Component)(object)instance.m_recipeListRoot), ListRoot = PathOf((Component)(object)instance.m_recipeListRoot), Details = TopOf((Component)(object)instance.m_recipeName), DetailsIcon = PathOf((Component)(object)instance.m_recipeIcon), DetailsName = PathOf((Component)(object)instance.m_recipeName), DetailsText = PathOf((Component)(object)instance.m_recipeDecription), DetailsFooter = PathOf((Component)(object)instance.m_itemCraftType), Requirements = instance.m_recipeRequirementList.Select((GameObject r) => (!((Object)(object)r != (Object)null)) ? null : PathFrom((Transform)(object)source, r.transform)).ToArray(), RequirementLevel = PathOf((Component)(object)instance.m_minStationLevelText), RequirementLevelIcon = PathOf((Component)(object)instance.m_minStationLevelIcon), Action = PathOf((Component)(object)instance.m_craftButton), Hidden = new string[4] { PathOf((Component)(object)instance.m_variantButton), PathOf((Component)(object)instance.m_qualityPanel), PathOf((Component)(object)instance.m_craftProgressPanel), PathOf((Component)(object)instance.m_upgradeItemName)?.Split('/').Take(2).Aggregate((string a, string b) => a + "/" + b) }, Removed = new string[2] { TopOf((Component)(object)instance.m_repairButton), TopOf((Component)(object)instance.m_repairPanel) } }; Rect rect = source.rect; Vector2 size = ((Rect)(ref rect)).size; GameObject val = CloneInactive(((Component)source).gameObject); ((Object)val).name = "fjordfolk_window"; HashSet<string> hashSet = new HashSet<string>(from p in new string[5] { anon.Title, anon.Icon, anon.Level, anon.List, anon.Details }.Concat(anon.Tabs) where !string.IsNullOrEmpty(p) select p.Split('/')[0]); foreach (Transform item in ((IEnumerable)val.transform).Cast<Transform>().ToList()) { Image component = ((Component)item).GetComponent<Image>(); Sprite val2 = ((component != null) ? component.sprite : null); bool num = (Object)(object)val2 != (Object)null && ((Object)val2).name.Contains("repair"); bool flag = !((Component)item).gameObject.activeSelf && !hashSet.Contains(((Object)item).name); if (num || flag || anon.Removed.Contains(((Object)item).name)) { Object.DestroyImmediate((Object)(object)((Component)item).gameObject); } } foreach (string item2 in new string[14] { anon.Title, anon.Icon, anon.Level, anon.LevelText, anon.List, anon.ListRoot, anon.Details, anon.DetailsIcon, anon.DetailsName, anon.DetailsText, anon.DetailsFooter, anon.RequirementLevel, anon.RequirementLevelIcon, anon.Action }.Concat(anon.Tabs).Concat(anon.Requirements)) { SwitchOn(val, item2); } foreach (string item3 in anon.Hidden.Where((string p) => !string.IsNullOrEmpty(p))) { Transform obj = val.transform.Find(item3); if (obj != null) { ((Component)obj).gameObject.SetActive(false); } } RectTransform val3 = Find<RectTransform>(val, anon.ListRoot); if ((Object)(object)val3 != (Object)null) { foreach (Transform item4 in ((IEnumerable)val3).Cast<Transform>().ToList()) { Object.DestroyImmediate((Object)(object)((Component)item4).gameObject); } } Strip(val); Window obj2 = new Window { Root = (RectTransform)val.transform, Width = size.x, Title = Find<TMP_Text>(val, anon.Title), Icon = Find<Image>(val, anon.Icon), LevelText = Find<TMP_Text>(val, anon.LevelText), LevelTooltip = Find<UITooltip>(val, anon.Level) }; Transform obj3 = val.transform.Find(anon.List ?? ""); obj2.List = ((obj3 != null) ? ((Component)obj3).gameObject : null); obj2.ListRoot = val3; obj2.ListSpacing = ((instance.m_recipeListSpace > 1f) ? instance.m_recipeListSpace : 32f); Transform obj4 = val.transform.Find(anon.Details ?? ""); obj2.Details = ((obj4 != null) ? ((Component)obj4).gameObject : null); obj2.DetailsIcon = Find<Image>(val, anon.DetailsIcon); obj2.DetailsName = Find<TMP_Text>(val, anon.DetailsName); obj2.DetailsText = Find<TMP_Text>(val, anon.DetailsText); obj2.DetailsFooter = Find<TMP_Text>(val, anon.DetailsFooter); obj2.RequirementLevel = Find<TMP_Text>(val, anon.RequirementLevel); obj2.RequirementLevelTooltip = Find<UITooltip>(val, anon.RequirementLevelIcon); obj2.ActionButton = Find<Button>(val, anon.Action); Window window = obj2; string[] requirements = anon.Requirements; foreach (string path in requirements) { RectTransform val4 = Find<RectTransform>(val, path); if ((Object)(object)val4 != (Object)null) { window.Requirements.Add(TileOf(((Component)val4).gameObject)); } } if ((Object)(object)window.Title != (Object)null) { window.Title.text = title; } if ((Object)(object)window.ActionButton != (Object)null) { window.ActionButton.onClick = new ButtonClickedEvent(); } for (int num3 = 0; num3 < anon.Tabs.Length; num3++) { Button val5 = Find<Button>(val, anon.Tabs[num3]); if ((Object)(object)val5 == (Object)null) { continue; } if (tabs == null || num3 >= tabs.Count) { ((Component)val5).gameObject.SetActive(false); continue; } int index = num3; val5.onClick = new ButtonClickedEvent(); ((UnityEvent)val5.onClick).AddListener((UnityAction)delegate { FjordFolkPlugin.Guard("VanillaUi.Tab", delegate { onTab(index); }); }); Transform obj5 = ((Component)val5).transform.Find("Text"); TMP_Text val6 = ((obj5 != null) ? ((Component)obj5).GetComponent<TMP_Text>() : null) ?? ((Component)val5).GetComponentInChildren<TMP_Text>(true); if ((Object)(object)val6 != (Object)null) { val6.text = tabs[num3]; } window.Tabs.Add(val5); } RectTransform root = window.Root; ((Transform)root).SetParent(parent, false); Vector2 val7 = default(Vector2); ((Vector2)(ref val7))..ctor(0.5f, 0.5f); root.anchorMax = val7; root.anchorMin = val7; root.pivot = new Vector2(0.5f, 0.5f); root.sizeDelta = size; root.anchoredPosition = Vector2.zero; ((Transform)root).localScale = Vector3.one; val.SetActive(true); Canvas.ForceUpdateCanvases(); if ((Object)(object)window.List != (Object)null && (Object)(object)window.Details != (Object)null) { Rect val8 = FromTopLeft(root, (RectTransform)window.List.transform); Rect val9 = FromTopLeft(root, (RectTransform)window.Details.transform); window.ContentArea = Rect.MinMaxRect(((Rect)(ref val8)).xMin, Mathf.Min(((Rect)(ref val8)).yMin, ((Rect)(ref val9)).yMin), ((Rect)(ref val9)).xMax, Mathf.Max(((Rect)(ref val8)).yMax, ((Rect)(ref val9)).yMax)); } else { window.ContentArea = new Rect(10f, 101f, size.x - 20f, size.y - 105f); } return window; string PathOf(Component c) { if (!((Object)(object)c != (Object)null)) { return null; } return PathFrom((Transform)(object)source, c.transform); } string TopOf(Component c) { string text = PathOf(c); if (text == null) { return null; } return text.Split('/')[0]; } } public static ListEntry AddListEntry(Window window, int index, Action onClick) { //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown GameObject val = CloneInactive(InventoryGui.instance.m_recipeElementPrefab); ((Object)val).name = "fjordfolk_listentry"; ListEntry obj = new ListEntry { Root = val }; Transform obj2 = val.transform.Find("icon"); obj.Icon = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null); Transform obj3 = val.transform.Find("name"); obj.Name = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null); Transform obj4 = val.transform.Find("QualityLevel"); obj.Badge = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null); Transform obj5 = val.transform.Find("selected"); obj.Selected = ((obj5 != null) ? ((Component)obj5).gameObject : null); obj.Button = val.GetComponent<Button>(); ListEntry listEntry = obj; Transform obj6 = val.transform.Find("Durability"); if (obj6 != null) { ((Component)obj6).gameObject.SetActive(false); } GameObject selected = listEntry.Selected; if (selected != null) { selected.SetActive(false); } Strip(val); if ((Object)(object)listEntry.Button != (Object)null) { listEntry.Button.onClick = new ButtonClickedEvent(); ((UnityEvent)listEntry.Button.onClick).AddListener((UnityAction)delegate { FjordFolkPlugin.Guard("VanillaUi.ListEntry", onClick.Invoke); }); } RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)window.ListRoot, false); val2.anchoredPosition = new Vector2(0f, (float)(-index) * window.ListSpacing); val.SetActive(true); float num = (float)(index + 1) * window.ListSpacing; Rect rect = window.ListRoot.rect; if (((Rect)(ref rect)).height < num) { window.ListRoot.SetSizeWithCurrentAnchors((Axis)1, num); } return listEntry; } public static Image Panel(Transform parent, float x, float y, float width, float height) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown Image component = ((Component)InventoryGui.instance.m_recipeName.transform.parent).GetComponent<Image>(); GameObject val = new GameObject("fjordfolk_panel", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); Image component2 = val.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { component2.sprite = component.sprite; component2.type = component.type; ((Graphic)component2).color = ((Graphic)component).color; ((Graphic)component2).material = ((Graphic)component).material; component2.pixelsPerUnitMultiplier = component.pixelsPerUnitMultiplier; } else { ((Graphic)component2).color = new Color(0f, 0f, 0f, 0.56f); } ((Graphic)component2).raycastTarget = false; Place((RectTransform)val.transform, parent, x, y, new Vector2(width, height)); return component2; } public static TMP_Text Text(Transform parent, TextStyle style, string text, float x, float y, float width, float height, TextAlignmentOptions alignment = (TextAlignmentOptions)513, float size = 0f) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_010a: Expected O, but got Unknown InventoryGui instance = InventoryGui.instance; GameObject val = CloneInactive(((Component)(style switch { TextStyle.Big => instance.m_recipeName, TextStyle.Header => instance.m_itemCraftType, _ => instance.m_recipeDecription, })).gameObject); ((Object)val).name = "fjordfolk_text"; foreach (Transform item in ((IEnumerable)val.transform).Cast<Transform>().ToList()) { Object.DestroyImmediate((Object)(object)((Component)item).gameObject); } Strip(val); StripLayouts(val, includeChildren: true); TMP_Text component = val.GetComponent<TMP_Text>(); component.text = text; component.alignment = alignment; component.textWrappingMode = (TextWrappingModes)1; component.overflowMode = (TextOverflowModes)0; component.enableAutoSizing = false; component.richText = true; ((Graphic)component).raycastTarget = false; component.fontSize = ((size > 0f) ? size : (style switch { TextStyle.Big => 30f, TextStyle.Header => 20f, _ => 17f, })); Place((RectTransform)val.transform, parent, x, y, new Vector2(width, height)); val.SetActive(true); return component; } public static Button Button(Transform parent, string label, float x, float y, float width, float height, Action onClick) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown GameObject val = CloneInactive(((Component)InventoryGui.instance.m_takeAllButton).gameObject); ((Object)val).name = "fjordfolk_button"; Strip(val); StripLayouts(val, includeChildren: true); Button component = val.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { FjordFolkPlugin.Guard("VanillaUi.Button " + label, onClick.Invoke); }); ((Selectable)component).interactable = true; Transform obj = val.transform.Find("Text"); TMP_Text val2 = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null) ?? val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)val2 != (Object)null) { val2.text = label; val2.textWrappingMode = (TextWrappingModes)0; } Place((RectTransform)val.transform, parent, x, y, new Vector2(width, height)); val.SetActive(true); return component; } public static void SetButtonLabel(Button button, string label) { object obj; if (!((Object)(object)button != (Object)null)) { obj = null; } else { Transform obj2 = ((Component)button).transform.Find("Text"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null) ?? ((Component)button).GetComponentInChildren<TMP_Text>(true); } TMP_Text val = (TMP_Text)obj; if ((Object)(object)val != (Object)null) { val.text = label; } } public static UITooltip TooltipOf(Component c) { if (!((Object)(object)c != (Object)null)) { return null; } return c.GetComponentInChildren<UITooltip>(true); } public static void SetTooltip(UITooltip tooltip, string topic, string text) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)tooltip != (Object)null) { tooltip.Set(topic, text, (RectTransform)null, Vector2.zero); } } public static Slot InventorySlot(Transform parent, float x, float y, float size, Action onClick) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown GameObject val = CloneInactive(InventoryGui.instance.m_playerGrid.m_elementPrefab); ((Object)val).name = "fjordfolk_slot"; InventoryElement component = val.GetComponent<InventoryElement>(); Slot slot = new Slot { Rect = (RectTransform)val.transform, Icon = (((Object)(object)component != (Object)null) ? component.m_icon : null), Amount = (((Object)(object)component != (Object)null) ? component.m_amount : null), Selected = (((Object)(object)component != (Object)null) ? component.m_selected : null), Button = (((Object)(object)component != (Object)null && (Object)(object)component.m_button != (Object)null) ? component.m_button : val.GetComponent<Button>()), Tooltip = val.GetComponentInChildren<UITooltip>(true) }; if ((Object)(object)component != (Object)null) { Component[] array = (Component[])(object)new Component[7] { (Component)component.m_quality, (Component)component.m_equiped, (Component)component.m_queued, (Component)component.m_noteleport, (Component)component.m_food, (Component)component.m_durability, (Component)component.m_dropFocus }; foreach (Component val2 in array) { if ((Object)(object)val2 != (Object)null) { val2.gameObject.SetActive(false); } } } Transform obj = val.transform.Find("binding"); if (obj != null) { ((Component)obj).gameObject.SetActive(false); } GameObject selected = slot.Selected; if (selected != null) { selected.SetActive(false); } Strip(val); if ((Object)(object)slot.Button != (Object)null) { slot.Button.onClick = new ButtonClickedEvent(); if (onClick != null) { ((UnityEvent)slot.Button.onClick).AddListener((UnityAction)delegate { FjordFolkPlugin.Guard("VanillaUi.Slot", onClick.Invoke); }); } } float slotNaturalSize = SlotNaturalSize; Place(slot.Rect, parent, x, y, new Vector2(slotNaturalSize, slotNaturalSize)); ((Transform)slot.Rect).localScale = Vector3.one * (size / slotNaturalSize); val.SetActive(true); return slot; } private static Tile TileOf(GameObject go) { Tile obj = new Tile { Root = go }; Transform obj2 = go.transform.Find("res_icon"); obj.Icon = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null); Transform obj3 = go.transform.Find("res_name"); obj.Name = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null); Transform obj4 = go.transform.Find("res_amount"); obj.Amount = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null); obj.Tooltip = go.GetComponent<UITooltip>(); return obj; } public static void ShowRequirement(Tile tile, Sprite icon, string name, int have, int need, string tooltip) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) Component[] array = (Component[])(object)new Component[3] { (Component)tile.Icon, (Component)tile.Name, (Component)tile.Amount }; foreach (Component obj in array) { if (obj != null) { obj.gameObject.SetActive(true); } } if ((Object)(object)tile.Icon != (Object)null) { tile.Icon.sprite = icon; ((Graphic)tile.Icon).color = Color.white; } if ((Object)(object)tile.Name != (Object)null) { tile.Name.text = name; } if ((Object)(object)tile.Amount != (Object)null) { tile.Amount.text = $"{have}/{need}"; ((Graphic)tile.Amount).color = ((have >= need) ? Color.white : Red); } SetTooltip(tile.Tooltip, name, tooltip); } public static void HideRequirement(Tile tile) { Component[] array = (Component[])(object)new Component[3] { (Component)tile.Icon, (Component)tile.Name, (Component)tile.Amount }; foreach (Component obj in array) { if (obj != null) { obj.gameObject.SetActive(false); } } SetTooltip(tile.Tooltip, "", ""); } private static GameObject CloneInactive(GameObject source) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)s_holder == (Object)null) { s_holder = new GameObject("fjordfolk_ui_holder"); s_holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)s_holder); } GameObject obj = Object.Instantiate<GameObject>(source, s_holder.transform, false); obj.SetActive(true); return obj; } private static void Strip(GameObject go) { UIGamePad[] componentsInChildren = go.GetComponentsInChildren<UIGamePad>(true); foreach (UIGamePad val in componentsInChildren) { if ((Object)(object)val.m_hint != (Object)null) { Object.DestroyImmediate((Object)(object)val.m_hint); } } foreach (GameObject item in (from b in go.GetComponentsInChildren<MonoBehaviour>(true) where (Object)(object)b != (Object)null && ((object)b).GetType().Name == "UIInputHint" select ((Component)b).gameObject).Distinct().ToList()) { if ((Object)(object)item != (Object)null) { Object.DestroyImmediate((Object)(object)item); } } MonoBehaviour[] componentsInChildren2 = go.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null && Behaviours.Contains(((object)val2).GetType().Name)) { Object.DestroyImmediate((Object)(object)val2); } } } private static void StripLayouts(GameObject go, bool includeChildren) { Component[] array = (includeChildren ? go.GetComponentsInChildren<Component>(true) : go.GetComponents<Component>()); foreach (Component val in array) { if ((Object)(object)val != (Object)null && Layouts.Contains(((object)val).GetType().Name)) { Object.DestroyImmediate((Object)(object)val); } } } public static void Place(RectTransform rect, Transform parent, float x, float y, Vector2 size) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) ((Transform)rect).SetParent(parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 1f); rect.anchorMax = val; rect.anchorMin = val; rect.pivot = new Vector2(0f, 1f); rect.sizeDelta = size; rect.anchoredPosition = new Vector2(x, 0f - y); ((Transform)rect).localScale = Vector3.one; } public static RectTransform Group(Transform parent, string name, float x, float y, float width, float height) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0036: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; Place(val, parent, x, y, new Vector2(width, height)); return val; } private static Rect FromTopLeft(RectTransform root, RectTransform child) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4]; child.GetWorldCorners(array); Rect rect = root.rect; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(float.MaxValue, float.MaxValue); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(float.MinValue, float.MinValue); Vector3[] array2 = array; Vector2 val5 = default(Vector2); foreach (Vector3 val3 in array2) { Vector3 val4 = ((Transform)root).InverseTransformPoint(val3); ((Vector2)(ref val5))..ctor(val4.x - ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax - val4.y); val = Vector2.Min(val, val5); val2 = Vector2.Max(val2, val5); } return Rect.MinMaxRect(val.x, val.y, val2.x, val2.y); } private static void SwitchOn(GameObject root, string path) { if (string.IsNullOrEmpty(path)) { return; } Transform val = root.transform.Find(path); Transform val2 = val; while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)root.transform) { ((Component)val2).gameObject.SetActive(true); val2 = val2.parent; } if (!((Object)(object)val == (Object)null)) { Graphic[] components = ((Component)val).GetComponents<Graphic>(); for (int i = 0; i < components.Length; i++) { ((Behaviour)components[i]).enabled = true; } } } private static T Find<T>(GameObject root, string path) where T : Component { if (string.IsNullOrEmpty(path)) { return default(T); } Transform val = root.transform.Find(path); if (!((Object)(object)val != (Object)null)) { return default(T); } return ((Component)val).GetComponent<T>(); } private static Vector2 SizeOf(RectTransform rect, Vector2 fallback) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rect == (Object)null) { return fallback; } Rect rect2 = rect.rect; Vector2 val = ((Rect)(ref rect2)).size; if (val.x <= 1f || val.y <= 1f) { val = ((rect.anchorMin == rect.anchorMax) ? rect.sizeDelta : fallback); } return new Vector2((val.x > 1f) ? val.x : fallback.x, (val.y > 1f) ? val.y : fallback.y); } private static string PathFrom(Transform root, Transform target) { if ((Object)(object)target == (Object)null) { return null; } List<string> list = new List<string>(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } public static void DumpOnce(Transform ours) { if (!s_dumped) { s_dumped = true; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"# UI dump {DateTime.Now:yyyy-MM-dd HH:mm:ss}, screen {Screen.width}x{Screen.height}"); Canvas componentInParent = ((Component)ours).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { stringBuilder.AppendLine($"# canvas {((Object)componentInParent).name} scale {componentInParent.scaleFactor:0.###}"); } stringBuilder.AppendLine().AppendLine("== our window"); Describe(stringBuilder, ours, 0); string text = Path.Combine(Paths.ConfigPath, "fjordfolk_ui_dump.txt"); File.WriteAllText(text, stringBuilder.ToString(), Encoding.UTF8); FjordFolkPlugin.Log.LogDebug((object)("UI layout written to " + text)); } } private static void Describe(StringBuilder sb, Transform t, int depth) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_013a: 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_0152: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Expected O, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) if (depth > 9) { return; } StringBuilder stringBuilder = new StringBuilder(new string(' ', depth * 2) + ((Object)t).name + (((Component)t).gameObject.activeSelf ? "" : " (off)")); RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null); if (val != null) { object[] array = new object[4]; Rect rect = val.rect; array[0] = ((Rect)(ref rect)).width; rect = val.rect; array[1] = ((Rect)(ref rect)).height; array[2] = val.anchoredPosition.x; array[3] = val.anchoredPosition.y; stringBuilder.Append(string.Format(" rect={0:0}x{1:0} pos={2:0},{3:0} ", array) + $"anchors={val.anchorMin.x:0.##},{val.anchorMin.y:0.##}-{val.anchorMax.x:0.##},{val.anchorMax.y:0.##} pivot={val.pivot.x:0.##},{val.pivot.y:0.##}"); if (((Transform)val).localScale != Vector3.one) { stringBuilder.Append($" scale={((Transform)val).localScale.x:0.##}"); } } IEnumerable<string> values = from c in ((Component)t).GetComponents<Component>() where (Object)(object)c != (Object)null && !(c is Transform) select ((object)c).GetType().Name; stringBuilder.Append(" [").Append(string.Join(",", values)).Append(']'); TMP_Text component = ((Component)t).GetComponent<TMP_Text>(); if ((Object)(object)component != (Object)null) { string text = component.text ?? ""; string arg = ((text.Length > 40) ? text.Substring(0, 40) : text).Replace("\n", " "); TMP_FontAsset font = component.font; stringBuilder.Append($" text='{arg}' font={((font != null) ? ((Object)font).name : null)} size={component.fontSize:0.#}" + string.Format("{0} color=#{1} align={2}", component.enableAutoSizing ? $" auto {component.fontSizeMin:0}-{component.fontSizeMax:0}" : "", ColorUtility.ToHtmlStringRGBA(((Graphic)component).color), component.alignment)); } Image component2 = ((Component)t).GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { Sprite sprite = component2.sprite; stringBuilder.Append($" sprite={((sprite != null) ? ((Object)sprite).name : null)} type={component2.type} color=#{ColorUtility.ToHtmlStringRGBA(((Graphic)component2).color)}"); } sb.AppendLine(stringBuilder.ToString()); foreach (Transform item in t) { Transform val2 = item; if (!(((Object)val2).name == "fjordfolk_slot") || val2.GetSiblingIndex() <= 0 || !(((Object)t.GetChild(val2.GetSiblingIndex() - 1)).name == "fjordfolk_slot")) { Describe(sb, val2, depth + 1); } } } } } namespace FjordFolk.Fisher { internal static class FisherConfig { public static ConfigEntry<float> SecondsPerCatch; public static ConfigEntry<int> BasketCapacity; public static ConfigEntry<float> MaxCatchUpSeconds; public static ConfigEntry<float> WaterSearchRadius; public static ConfigEntry<float> NoviceBaseCost; public static ConfigEntry<float> NoviceTierStep; public static ConfigEntry<float> MasterBaseCost; public static ConfigEntry<float> MasterTierStep; public static ConfigEntry<float> LuckSpread; public static ConfigEntry<int> WorkplaceCoins; public static void Bind(ConfigFile config) { SecondsPerCatch = config.Bind<float>("Fisherman.Work", "SecondsPerCatch", 120f, "Average real seconds per caught fish, jittered by ±25%."); BasketCapacity = config.Bind<int>("Fisherman.Work", "BasketCapacity", 60, "Fish the basket holds before he stops working."); MaxCatchUpSeconds = config.Bind<float>("Fisherman.Work", "MaxCatchUpSeconds", 1800f, "Longest absence that is worked off on return, like a beehive. 1800 s is one game day."); WaterSearchRadius = config.Bind<float>("Fisherman.Work", "WaterSearchRadius", 8f, "Horizontal distance within which water must exist to place the workplace. Height is ignored."); NoviceBaseCost = config.Bind<float>("Fisherman.Economy", "NoviceBaseCost", 8f, "Average coins per fish at mastery 0 for the basic bait. Mastery goes one level per biome, eight in all."); NoviceTierStep = config.Bind<float>("Fisherman.Economy", "NoviceTierStep", 2f, "Extra average coins per bait tier above basic, at mastery 0."); MasterBaseCost = config.Bind<float>("Fisherman.Economy", "MasterBaseCost", 4f, "Average coins per fish at max mastery for the basic bait."); MasterTierStep = config.Bind<float>("Fisherman.Economy", "MasterTierStep", 1f, "Extra average coins per bait tier above basic, at max mastery."); LuckSpread = config.Bind<float>("Fisherman.Economy", "LuckSpread", 0.3f, "How far a single fish's price strays from the average: 0.3 means up to ±30% (8 ± 2 for a novice, 4 ± 1 for a master), most often close to the average."); WorkplaceCoins = config.Bind<int>("Fisherman.Progress", "WorkplaceCoins", 300, "Coins in the workplace recipe. Takes effect after restarting the game."); } } internal static class FisherData { public sealed class Step { public Biome Biome; public string Icon; public (string Trophy, int Amount)[] Trophies; public string BiomeName { get { string text = "biome_" + ((object)Unsafe.As<Biome, Biome>(ref Biome)/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(); string text2 = ((Localization.instance != null) ? Localization.instance.Localize("$" + text) : null); if (!string.IsNullOrEmpty(text2) && !text2.StartsWith("[")) { return text2; } return Loc.T(text); } } } public static readonly (string Bait, int Tier)[] Baits = new(string, int)[9] { ("FishingBait", 0), ("FishingBaitForest", 1), ("FishingBaitSwamp", 2), ("FishingBaitCave", 3), ("FishingBaitPlains", 4), ("FishingBaitOcean", 4), ("FishingBaitMistlands", 5), ("FishingBaitAshlands", 6), ("FishingBaitDeepNorth", 7) }; public static readonly Step[] Steps = new Step[8] { new Step { Biome = (Biome)1, Icon = "TrophyDeer", Trophies = new(string, int)[3] { ("TrophyDeer", 8), ("TrophyBoar", 4), ("TrophyNeck", 2) } }, new Step { Biome = (Biome)8, Icon = "TrophyGreydwarf", Trophies = new(string, int)[3] { ("TrophyGreydwarf", 8), ("TrophySkeleton", 4), ("TrophyGreydwarfBrute", 2) } }, new Step { Biome = (Biome)2, Icon = "TrophyDraugr", Trophies = new(string, int)[3] { ("TrophyDraugr", 8), ("TrophyBlob", 4), ("TrophyLeech", 2) } }, new Step { Biome = (Biome)4, Icon = "TrophyWolf", Trophies = new(string, int)[3] { ("TrophyWolf", 8), ("TrophyHatchling", 4), ("TrophyFenring", 2) } }, new Step { Biome = (Biome)16, Icon = "TrophyGoblin", Trophies = new(string, int)[3] { ("TrophyGoblin", 8), ("TrophyLox", 4), ("TrophyDeathsquito", 2) } }, new Step { Biome = (Biome)512, Icon = "TrophySeeker", Trophies = new(string, int)[3] { ("TrophySeeker", 8), ("TrophyHare", 4), ("TrophyTick", 2) } }, new Step { Biome = (Biome)32, Icon = "TrophyCharredMelee", Trophies = new(string, int)[3] { ("TrophyCharredMelee", 8), ("TrophyAsksvin", 4), ("TrophyVolture", 2) } }, new Step { Biome = (Biome)64, Icon = "TrophyMoose", Trophies = new(string, int)[3] { ("TrophyDeerWhite", 8), ("TrophySeal", 4), ("TrophyMoose", 2) } } }; private static readonly Dictionary<string, string> s_baitToFish = new Dictionary<string, string>(); private static bool s_resolved; public static int MaxLevel => Steps.Length; public static string Rank(int level) { return Loc.T("rank_" + Mathf.Clamp(level, 0, MaxLevel)); } public static int TierOfBait(string bait) { (string, int)[] baits = Baits; for (int i = 0; i < baits.Length; i++) { (string, int) tuple = baits[i]; if (tuple.Item1 == bait) { return tuple.Item2; } } return 0; } public static string FishForBait(string bait) { EnsureResolved(); if (bait == null || !s_baitToFish.TryGetValue(bait, out var value)) { return null; } return value; } public static IEnumerable<string> AllFish() { EnsureResolved(); return (from b in Baits select FishForBait(b.Bait) into f where f != null select f).Distinct(); } public static float AveragePrice(int level, int baitTier) { float num = Mathf.Clamp01((float)level / (float)MaxLevel); float num2 = Mathf.Lerp(FisherConfig.NoviceBaseCost.Value, FisherConfig.MasterBaseCost.Value, num); float num3 = Mathf.Lerp(FisherConfig.NoviceTierStep.Value, FisherConfig.MasterTierStep.Value, num); return num2 + num3 * (float)baitTier; } public static int FeeDiscountPercent(int level) { float num = AveragePrice(0, 0); if (!(num <= 0f)) { return Mathf.RoundToInt((1f - AveragePrice(level, 0) / num) * 100f); } return 0; } public static GameObject ItemPrefab(string name) { if (!((Object)(object)ObjectDB.instance != (Object)null)) { return null; } return ObjectDB.instance.GetItemPrefab(name); } public static string DisplayName(string prefabName) { GameObject obj = ItemPrefab(prefabName); string text = ((obj != null) ? obj.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_name; if (text == null || Localization.instance == null) { return prefabName; } return Localization.instance.Localize(text); } public static Sprite Icon(string prefabName) { GameObject obj = ItemPrefab(prefabName); if (obj == null) { return null; } ItemDrop component = obj.GetComponent<ItemDrop>(); if (component == null) { return null; } ItemData itemData = component.m_itemData; if (itemData == null) { return null; } return itemData.GetIcon(); } private static void EnsureResolved() { if (s_resolved || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return; } s_resolved = true; ResolveBaits(); List<string> list = (from n in Steps.SelectMany((Step s) => s.Trophies.Select(((string Trophy, int Amount) t) => t.Trophy).Append(s.Icon)).Distinct() where (Object)(object)ItemPrefab(n) == (Object)null select n).ToList(); if (list.Count > 0) { FjordFolkPlugin.Log.LogWarning((object)("fisher mastery uses unknown trophies: " + string.Join(", ", list))); } } private static void ResolveBaits() { Dictionary<string, (string, float)> dictionary = new Dictionary<string, (string, float)>(); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { Fish val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Fish>() : null); if (val?.m_baits == null) { continue; } foreach (BaitSetting bait in val.m_baits) { if (!((Object)(object)bait?.m_bait == (Object)null)) { string name = ((Object)bait.m_bait).name; if (!dictionary.TryGetValue(name, out var value) || bait.m_chance > value.Item2) { dictionary[name] = (((Object)prefab).name, bait.m_chance); } } } } (string, int)[] baits = Baits; for (int i = 0; i < baits.Length; i++) { (string, int) tuple = baits[i]; if (dictionary.TryGetValue(tuple.Item1, out var value2)) { s_baitToFish[tuple.Item1] = value2.Item1; } } FjordFolkPlugin.Log.LogDebug((object)("fisher bait → fish: " + string.Join(", ", Baits.Select(((string Bait, int Tier) b) => string.Format("{0}(tier {1}) → {2}", b.Bait, b.Tier, s_baitToFish.TryGetValue(b.Bait, out var value3) ? value3 : "none"))))); } } internal sealed class FisherPanel : MonoBehaviour { private const float MaxDistance = 6f; private const float Inset = 14f; private const float Gap = 8f; private const string Heading = "#FFB75C"; private const string Warning = "#FF9C4A"; private const string Muted = "#8C8C8C"; private static FisherPanel s_open; private static float s_closedAt = -999f; private static int s_lastTab; private FisherWorkplace m_place; private VanillaUi.Window m_window; private GameObject m_workPage; private int m_tab; private int m_selectedStep = -1; private float m_openedAt; private float m_nextRefresh; private TMP_Text m_status; private TMP_Text m_summary; private VanillaUi.Slot m_coins; private TMP_Text m_basketText; private readonly List<(string Bait, VanillaUi.Slot Slot)> m_baitSlots = new List<(string, VanillaUi.Slot)>(); private readonly List<(string Fish, VanillaUi.Slot Slot)> m_fishSlots = new List<(string, VanillaUi.Slot)>(); private readonly List<VanillaUi.ListEntry> m_steps = new List<VanillaUi.ListEntry>(); public static bool IsOpen => (Object)(object)s_open != (Object)null; public static bool JustClosed => Time.time - s_closedAt < 0.3f; public static void Open(FisherWorkplace place) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_open != (Object)null) { s_open.Close(); } string text = VanillaUi.MissingPart(); Transform val = VanillaUi.GuiRoot() ?? (((Object)(object)GUIManager.CustomGUIFront != (Object)null) ? GUIManager.CustomGUIFront.transform : null); if (text != null || (Object)(object)val == (Object)null) { FjordFolkPlugin.Log.LogWarning((object)("fisher window not opened: game UI part missing (" + (text ?? "GUI canvas") + ")")); return; } GameObject val2 = new GameObject("fjordfolk_fisher_panel", new Type[1] { typeof(RectTransform) }); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent(val, false); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; Vector2 offsetMin = (val3.offsetMax = Vector2.zero); val3.offsetMin = offsetMin; ((Transform)val3).SetAsLastSibling(); FisherPanel panel = val2.AddComponent<FisherPanel>(); panel.m_place = place; panel.m_openedAt = Time.time; try { panel.Build(); } catch (Exception arg) { FjordFolkPlugin.Log.LogError((object)$"fisher window failed to build: {arg}"); Object.Destroy((Object)(object)val2); return; } s_open = panel; GUIManager.BlockInput(true); Chat instance = Chat.instance; if (instance != null) { instance.ClearNpcText(((Component)place).gameObject); } if (DebugConfig.WriteUiLayout.Value) { FjordFolkPlugin.Guard("VanillaUi.DumpOnce", delegate { VanillaUi.DumpOnce((Transform)(object)panel.m_window.Root); }); } } private void Close() { if ((Object)(object)s_open == (Object)(object)this) { s_open = null; s_closedAt = Time.time; GUIManager.BlockInput(false); } Object.Destroy((Object)(object)((Component)this).gameObject); } private void OnDestroy() { if ((Object)(object)s_open == (Object)(object)this) { s_open = null; s_closedAt = Time.time; GUIManager.BlockInput(false); } } private void LateUpdate() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)m_place == (Object)null || !m_place.IsLive || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)m_place).transform.position) > 6f) { Close(); return; } if (Time.time - m_openedAt > 0.25f && (ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("Use"))) { Close(); return; } GameObject tooltip = UITooltip.m_tooltip; if ((Object)(object)tooltip != (Object)null && tooltip.activeSelf && (Object)(object)tooltip.transform.parent == (Object)(object)((Component)this).transform.parent && tooltip.transform.GetSiblingIndex() < ((Component)this).transform.GetSiblingIndex()) { tooltip.transform.SetAsLastSibling(); } if (Time.time >= m_nextRefresh) { m_nextRefresh = Time.time + 0.5f; FjordFolkPlugin.Guard("FisherPanel.Refresh", Refresh); } } private void Build() { m_window = VanillaUi.CreateWindow(((Component)this).transform, Loc.T("knut_name"), new string[2] { Loc.T("tab_work"), Loc.T("tab_upgrade") }, ShowTab); if ((Object)(object)m_window.Icon != (Object)null) { m_window.Icon.sprite = Portrait(); } BuildWorkPage(); BuildUpgradePage(); ShowTab(s_lastTab); } private void BuildWorkPage() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_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_01fa: 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_025a: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) Rect contentArea = m_window.ContentArea; RectTransform val = VanillaUi.Group((Transform)(object)m_window.Root, "fjordfolk_work", ((Rect)(ref contentArea)).x, ((Rect)(ref contentArea)).y, ((Rect)(ref contentArea)).width, ((Rect)(ref contentArea)).height); m_workPage = ((Component)val).gameObject; float width = ((Rect)(ref contentArea)).width; float num = width - 28f; float slotNaturalSize = VanillaUi.SlotNaturalSize; Vector2 buttonSize = VanillaUi.ButtonSize; float num2 = 0f; float num3 = 64f; VanillaUi.Panel((Transform)(object)val, 0f, num2, width, num3); m_status = VanillaUi.Text((Transform)(object)val, VanillaUi.TextStyle.Header, "", 14f, num2 + 8f, num, 26f, (TextAlignmentOptions)513); m_status.textWrappingMode = (TextWrappingModes)0; m_status.enableAutoSizing = true; m_status.fontSizeMin = 12f; m_status.fontSizeMax = 20f; m_summary = VanillaUi.Text((Transform)(object)val, VanillaUi.TextStyle.Body, "", 14f, num2 + 34f, num, 24f, (TextAlignmentOptions)513, 15f); m_summary.textWrappingMode = (TextWrappingModes)0; m_summary.enableAutoSizing = true; m_summary.fontSizeMin = 11f; m_summary.fontSizeMax = 15f; num2 += num3 + 8f; num3 = 40f + slotNaturalSize + 14f; VanillaUi.Panel((Transform)(object)val, 0f, num2, width, num3); Header((Transform)(object)val, Loc.T("wage"), Loc.T("wage_hint"), num2, num); m_coins = VanillaUi.InventorySlot((Transform)(object)val, 14f, num2 + 40f, slotNaturalSize, null); VanillaUi.SetTooltip(m_coins.Tooltip, Loc.T("wage_tip_title"), Loc.T("wage_tip")); float num4 = 14f + slotNaturalSize + 14f; float y = num2 + 40f + (slotNaturalSize - buttonSize.y) / 2f; float width2 = width - 14f - num4 - 246f; VanillaUi.Button((Transform)(object)val, "+10", num4, y, 74f, buttonSize.y, delegate { OnGiveCoins(10); }); VanillaUi.Button((Transform)(object)val, "+100", num4 + 82f, y, 74f, buttonSize.y, delegate { OnGiveCoins(100); }); VanillaUi.Button((Transform)(object)val, Loc.T("btn_all"), num4 + 164f, y, 74f, buttonSize.y, delegate { OnGiveCoins(-1); }); VanillaUi.Button((Transform)(object)val, Loc.T("btn_take"), num4 + 246f, y, width2, buttonSize.y, OnTakeCoins); num2 += num3 + 8f; List<string> list = (from b in FisherData.Baits where FisherData.FishForBait(b.Bait) != null select b.Bait).ToList(); float num5 = RowSlotSize(list.Count, num); num3 = 40f + num5 + 10f + buttonSize.y + 12f; VanillaUi.Panel((Transform)(object)val, 0f, num2, width, num3); Header((Transform)(object)val, Loc.T("bait"), Loc.T("bait_hint"), num2, num); SlotRow((Transform)(object)val, list, num2 + 40f, num, num5, delegate(string bait) { OnSelectBait(bait); }, m_baitSlots, (string bait) => (Topic: FisherData.DisplayName(bait), Text: Loc.T("bait_tip", FisherData.DisplayName(FisherData.FishForBait(bait))))); float num6 = (num - 8f) / 2f; float y2 = num2 + 40f + num5 + 10f; VanillaUi.Button((Transform)(object)val, Loc.T("btn_give_bait"), 14f, y2, num6, buttonSize.y, OnGiveBait); VanillaUi.Button((Transform)(object)val, Loc.T("btn_take_bait"), 14f + num6 + 8f, y2, num6, buttonSize.y, OnTakeBait); num2 += num3 + 8f; List<string> list2 = FisherData.AllFish().ToList(); float num7 = RowSlotSize(list2.Count, num); num3 = Mathf.Max(40f + num7 + 10f + buttonSize.y + 12f, ((Rect)(ref contentArea)).height - num2); VanillaUi.Panel((Transform)(object)val, 0f, num2, width, num3); Header((Transform)(object)val, Loc.T("catch"), null, num2, num); m_basketText = VanillaUi.Text((Transform)(object)val, VanillaUi.TextStyle.Body, "", 14f, num2 + 9f, num, 26f, (TextAlignmentOptions)516, 16f); SlotRow((Transform)(object)val, list2, num2 + 40f, num, num7, null, m_fishSlots, (string fish) => (Topic: FisherData.DisplayName(fish), Text: Loc.T("catch_tip"))); VanillaUi.Button((Transform)(object)val, Loc.T("btn_take_catch"), 14f + (num - 260f) / 2f, num2 + 40f + num7 + 10f, 260f, buttonSize.y, OnTakeFish); } private void BuildUpgradePage() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown for (int i = 0; i < FisherData.MaxLevel; i++) { int index = i; m_steps.Add(VanillaUi.AddListEntry(m_window, i, delegate { m_selectedStep = index; Refresh(); })); } if ((Object)(object)m_window.ActionButton != (Object)null) { ((UnityEvent)m_window.ActionButton.onClick).AddListener((UnityAction)delegate { FjordFolkPlugin.Guard("FisherPanel.Upgrade", OnUpgrade); }); VanillaUi.SetButtonLabel(m_window.ActionButton, Loc.T("btn_upgrade")); } } private static void Header(Transform page, string title, string hint, float y, float inner) { VanillaUi.Text(page, VanillaUi.TextStyle.Header, title, 14f, y + 8f, inner, 28f, (TextAlignmentOptions)513); if (hint != null) { VanillaUi.Text(page, VanillaUi.TextStyle.Body, hint, 14f, y + 10f, inner, 26f, (TextAlignmentOptions)516, 15f); } } private static float RowSlotSize(int count, float inner) { float num = Mathf.Min(VanillaUi.SlotSpacing, inner / (float)Mathf.Max(1, count)); return Mathf.Min(VanillaUi.SlotNaturalSize, num - 4f); } private static void SlotRow(Transform page, List<string> items, float y, float inner, float size, Action<string> onClick, List<(string, VanillaUi.Slot)> into, Func<string, (string Topic, string Text)> tooltip) { float num = size + 4f; float num2 = 14f + (inner - num * (float)items.Count + 4f) / 2f; for (int i = 0; i < items.Count; i++) { string item = items[i]; VanillaUi.Slot slot = VanillaUi.InventorySlot(page, num2 + (float)i * num, y, size, (onClick != null) ? ((Action)de