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 Uter the Porter v1.0.1
UterPorter.dll
Decompiled 6 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("UterPorter")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("UterPorter")] [assembly: AssemblyTitle("UterPorter")] [assembly: AssemblyVersion("1.0.0.0")] namespace UterPorter; public static class Home { private static string Key => "uter_home_" + (Object.op_Implicit((Object)(object)ZNet.instance) ? ZNet.instance.GetWorldUID().ToString() : "0"); public static bool TryGet(Player player, out Vector3 home) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) home = Vector3.zero; if (Object.op_Implicit((Object)(object)player) && player.m_customData.TryGetValue(Key, out var value)) { string[] array = value.Split(new char[1] { '|' }); CultureInfo invariantCulture = CultureInfo.InvariantCulture; NumberStyles style = NumberStyles.Float; if (array.Length == 3 && float.TryParse(array[0], style, invariantCulture, out var result) && float.TryParse(array[1], style, invariantCulture, out var result2) && float.TryParse(array[2], style, invariantCulture, out var result3)) { home = new Vector3(result, result2, result3); return true; } } PlayerProfile val = (Object.op_Implicit((Object)(object)Game.instance) ? Game.instance.GetPlayerProfile() : null); if (val != null && val.HaveCustomSpawnPoint()) { home = val.GetCustomSpawnPoint(); return true; } return false; } public static void SetHere(Player player) { //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) Vector3 position = ((Component)player).transform.position; CultureInfo invariantCulture = CultureInfo.InvariantCulture; player.m_customData[Key] = position.x.ToString("R", invariantCulture) + "|" + position.y.ToString("R", invariantCulture) + "|" + position.z.ToString("R", invariantCulture); } public static void Clear(Player player) { player.m_customData.Remove(Key); } } public static class Lines { public static readonly string[] Hello = new string[10] { "You rang? Where to?", "Taxi for one Viking, is it?", "Again? Right. Hop on.", "{name}'s here. Try not to wriggle.", "Back already? Climb aboard.", "Did someone call an {name}?", "Your {name} has arrived. Look for the grumpy Dverger.", "Your driver, {name}, is now arriving. Grey cloak, bad mood.", "{name} here. Five stars, or I drop you in a bog.", "Surge pricing's on, mind. It's raining greylings." }; public static readonly string[] PickUp = new string[7] { "Up you get. Mind the beard.", "Fine. But I'm telling the other Dvergr about this.", "Climb on. Gently. I'm a porter, not a cart.", "Odin's eye, what have you been eating?", "Right. Hold on, and keep your elbows to yourself.", "On you hop, your majesty.", "If anyone asks, you're a very large sack of turnips." }; public static readonly string[] Riding = new string[22] { "You know you have legs, yes? Two of them. Working ones.", "Lighter on the left, please. My left. Your other left.", "Stop kicking. I'm not a horse.", "Is that your knee in my kidney, or have you brought a hammer?", "Heavier than a troll and twice as chatty.", "Mighty Viking warrior, this one. Can't even walk home.", "Next time get a lox. The lox can carry you.", "If you dribble on my helmet, you're walking.", "Great heroes of the tenth world, chapter one: the piggyback.", "Don't pull my beard to steer. I know the way.", "Comfy up there? Wonderful. Delighted for you.", "Valhalla's halls will sing of this. Mockingly.", "Grip a bit looser. I'd like to breathe.", "You smell of greyling. Just so you know.", "Rate your {name} experience later. Hold on now.", "No, I don't take coin. I take complaints, and then I ignore them.", "Estimated arrival: whenever my knees say so.", "This is {name} Pool, by the way. Anyone we pass is getting on too.", "Please keep your arms inside the Dverger at all times.", "Your route has been updated. I've decided to go round the bog.", "Music? No. You get my breathing, and you'll like it.", "If you wanted luxury you should've booked {name} Black." }; public static readonly string[] Jump = new string[4] { "Hup! Hold on!", "Oof. You felt that? So did I.", "Over we go. My knees send their regards.", "Log. Jumped it. You're welcome." }; public static readonly string[] Home = new string[8] { "Home. Mind your step getting down.", "Here we are. Off. Off! My back is filing a complaint.", "Delivered. No tip expected. Some gratitude would be nice.", "There. Home. Next time, you carry me.", "Home at last. I can't feel my shoulders.", "You have arrived at your destination. Mind the step.", "That's the end of your {name}. Don't forget to rate me.", "Destination reached. I'll take my tip in mead." }; public static readonly string[] Grave = new string[7] { "Here's where you died. Try not to make a habit of it.", "Your things are in there somewhere. Good luck.", "Smells like defeat round here. Grab your gear.", "There's your stone. I'd not hang about if I were you.", "Here lies you, apparently. Off you get.", "Destination: your own tombstone. Bit grim for a five-star trip.", "This isn't {name} Eats, but something round here clearly ate you." }; public static readonly string[] OffEarly = new string[6] { "Oh, NOW you want to walk.", "Off already? My back thanks you.", "Right, legs work again, do they? Marvellous.", "Suit yourself. I wasn't enjoying it anyway.", "Cancelling the ride? There's a fee for that.", "Getting out early? I'm still charging the full trip." }; public static readonly string[] Farewell = new string[8] { "Right, I'm off.", "Call me when you need hauling again.", "My back's going home now. Alone.", "Don't wave. I know you'll miss me.", "I'll call you an {name}. Oh wait, that's me. Bye.", "{name} out. Leave me a review.", "Off to my next pickup.", "Next time you need a ride, you know who to call." }; } [BepInPlugin("com.wpkenny.uterporter", "Uter the Porter", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.wpkenny.uterporter"; public const string PluginName = "Uter the Porter"; public const string PluginVersion = "1.0.1"; public const string PrefabName = "UterPorter"; public static ManualLogSource Log; public static ConfigEntry<string> PorterName; public static ConfigEntry<KeyboardShortcut> HomeKey; public static ConfigEntry<KeyboardShortcut> GraveKey; public static ConfigEntry<float> SpeedBoost; public static ConfigEntry<bool> Chatty; public static ConfigEntry<float> SeatHeight; public static ConfigEntry<float> SeatBehind; private Harmony _harmony; private void Awake() { //IL_0045: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; PorterName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Name", "Uter", "What the porter is called. Start a chat message with this name to call him, e.g. \"Uter, take me home\"."); HomeKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "TakeMeHome", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Optional key to call him for a ride home. Unset by default."); GraveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "TakeMeToMyGrave", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Optional key to call him for a ride to your nearest gravestone. Unset by default."); SpeedBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Ride", "SpeedBoost", 1.3f, "How much faster than a normal run he goes with you on his back (1 = normal running speed)."); Chatty = ((BaseUnityPlugin)this).Config.Bind<bool>("Ride", "Grumbling", true, "Sarcastic remarks while he carries you. Turn off for a quiet ride."); SeatHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Ride", "SeatHeight", 0.75f, "How high (metres) you sit on his back."); SeatBehind = ((BaseUnityPlugin)this).Config.Bind<float>("Ride", "SeatBehind", -0.18f, "How far behind him (metres) you sit. Below 0 moves you forward, onto his back as he leans into a run."); CreatureManager.OnVanillaCreaturesAvailable += RegisterPorter; _harmony = new Harmony("com.wpkenny.uterporter"); _harmony.PatchAll(); Log.LogInfo((object)"Uter the Porter 1.0.1 loaded"); } private void RegisterPorter() { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) try { CustomCreature val = new CustomCreature("UterPorter", "Dverger", new CreatureConfig { Name = PorterName.Value, Faction = (Faction)0 }); GameObject prefab = val.Prefab; Character component = prefab.GetComponent<Character>(); component.m_name = PorterName.Value; component.m_faction = (Faction)0; component.m_boss = false; CharacterDrop component2 = prefab.GetComponent<CharacterDrop>(); if (Object.op_Implicit((Object)(object)component2)) { Object.DestroyImmediate((Object)(object)component2); } MonsterAI component3 = prefab.GetComponent<MonsterAI>(); if (Object.op_Implicit((Object)(object)component3)) { component3.m_enableHuntPlayer = false; component3.m_attackPlayerObjects = false; ((BaseAI)component3).m_aggravatable = false; } prefab.AddComponent<Uter>(); CreatureManager.Instance.AddCreature(val); Log.LogInfo((object)"Registered the porter 'UterPorter'"); } catch (Exception ex) { Log.LogError((object)("Couldn't register the porter: " + ex)); } finally { CreatureManager.OnVanillaCreaturesAvailable -= RegisterPorter; } } private void Update() { //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_002b: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || TypingOrInMenu()) { return; } KeyboardShortcut value = HomeKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0) { value = HomeKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Call(Destination.Home); } } value = GraveKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0) { value = GraveKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Call(Destination.Grave); } } } private static bool TypingOrInMenu() { if ((!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen()) { return StoreGui.IsVisible(); } return true; } public static void Call(Destination to) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) Player player = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)player)) { return; } Uter uter = Uter.All.FirstOrDefault((Uter u) => Object.op_Implicit((Object)(object)u) && u.IsFor(player)); if (Object.op_Implicit((Object)(object)uter)) { uter.Begin(to); return; } GameObject prefab = PrefabManager.Instance.GetPrefab("UterPorter"); if (!Object.op_Implicit((Object)(object)prefab)) { ShowMessage(PorterName.Value + " isn't ready yet. Try again in a moment."); return; } Uter.Pending = to; Vector3 val = ((Component)player).transform.position - ((Component)player).transform.forward * 2.5f + ((Component)player).transform.right * 1f; float num = default(float); if (Heightmap.GetHeight(val, ref num)) { val.y = Mathf.Max(num, ((Component)player).transform.position.y - 1f) + 0.2f; } Uter component = Object.Instantiate<GameObject>(prefab, val, Quaternion.LookRotation(((Component)player).transform.forward)).GetComponent<Uter>(); if (Object.op_Implicit((Object)(object)component)) { component.SetRider(player); } } public static void ShowMessage(string text) { if (Object.op_Implicit((Object)(object)MessageHud.instance)) { MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, true); } } } public enum Destination { Home, Grave } [HarmonyPatch(typeof(Chat), "SendText")] public static class ChatPatch { private static bool Prefix(string text) { if (string.IsNullOrWhiteSpace(text)) { return true; } string text2 = Plugin.PorterName.Value.Trim(); string text3 = text.Trim().TrimStart(new char[1] { '@' }); if (!text3.StartsWith(text2, StringComparison.OrdinalIgnoreCase)) { return true; } if (text3.Length > text2.Length && char.IsLetterOrDigit(text3[text2.Length])) { return true; } string text4 = text3.Substring(text2.Length).ToLowerInvariant(); Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return true; } if (text4.Contains("this is home") || text4.Contains("set home") || text4.Contains("home is here") || text4.Contains("make this home")) { Home.SetHere(localPlayer); Plugin.ShowMessage(text2 + ": Right, this is home now. I'll bring you here."); } else if (text4.Contains("use my bed") || text4.Contains("bed is home") || text4.Contains("forget home")) { Home.Clear(localPlayer); Plugin.ShowMessage(text2 + ": Fine, home's your bed again."); } else if (new string[5] { "grave", "tomb", "body", "corpse", "where i died" }.Any(text4.Contains)) { Plugin.Call(Destination.Grave); } else if (new string[3] { "home", "base", "bed" }.Any(text4.Contains)) { Plugin.Call(Destination.Home); } else { Plugin.ShowMessage(text2 + " only does rides: \"" + text2 + ", take me home\" or \"" + text2 + ", take me to my grave\"."); } return true; } } [HarmonyPatch(typeof(Character), "RPC_Damage")] public static class UnhurtablePatch { private static bool Prefix(Character __instance) { return !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Uter>()); } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] public static class PorterMovementPatch { private static bool Prefix(MonsterAI __instance, float dt, ref bool __result) { Uter component = ((Component)__instance).GetComponent<Uter>(); if (!Object.op_Implicit((Object)(object)component)) { return true; } component.DriveMovement(dt); __result = true; return false; } } public static class RoutePlanner { public class Result { public bool Done; public bool Found; public List<Vector3> Path = new List<Vector3>(); } private class MinHeap { private readonly List<(int item, float pri)> _h = new List<(int, float)>(); public int Count => _h.Count; public void Push(int item, float pri) { _h.Add((item, pri)); int num = _h.Count - 1; while (num > 0) { int num2 = (num - 1) / 2; if (!(_h[num2].pri <= _h[num].pri)) { List<(int item, float pri)> h = _h; int index = num2; List<(int, float)> h2 = _h; int index2 = num; (int, float) tuple = _h[num]; (int, float) tuple2 = _h[num2]; (int, float) tuple3 = (h[index] = tuple); tuple3 = (h2[index2] = tuple2); num = num2; continue; } break; } } public int Pop() { int item = _h[0].item; _h[0] = _h[_h.Count - 1]; _h.RemoveAt(_h.Count - 1); int num = 0; while (true) { int num2 = num * 2 + 1; int num3 = num2 + 1; int num4 = num; if (num2 < _h.Count && _h[num2].pri < _h[num4].pri) { num4 = num2; } if (num3 < _h.Count && _h[num3].pri < _h[num4].pri) { num4 = num3; } if (num4 == num) { break; } List<(int item, float pri)> h = _h; int index = num4; List<(int, float)> h2 = _h; int index2 = num; (int, float) tuple = _h[num]; (int, float) tuple2 = _h[num4]; (int, float) tuple3 = (h[index] = tuple); tuple3 = (h2[index2] = tuple2); num = num4; } return item; } } public const float Cell = 8f; private const float Margin = 200f; private const int MaxExpansions = 120000; private const float WadeDepth = 0.6f; private const float MaxClimbPerCell = 6.5f; public static IEnumerator Plan(Vector3 from, Vector3 to, Result result) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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) WorldGenerator wg = WorldGenerator.instance; float water = (Object.op_Implicit((Object)(object)ZoneSystem.instance) ? ZoneSystem.instance.m_waterLevel : 30f); float minX = Mathf.Min(from.x, to.x) - 200f; float minZ = Mathf.Min(from.z, to.z) - 200f; int w = Mathf.CeilToInt((Mathf.Abs(from.x - to.x) + 400f) / 8f) + 1; int h = Mathf.CeilToInt((Mathf.Abs(from.z - to.z) + 400f) / 8f) + 1; Dictionary<int, float> heights = new Dictionary<int, float>(); Vector2Int start = ToCell(from); Vector2Int goal = ToCell(to); Dictionary<int, int> cameFrom = new Dictionary<int, int>(); Dictionary<int, float> cost = new Dictionary<int, float> { [((Vector2Int)(ref start)).y * w + ((Vector2Int)(ref start)).x] = 0f }; MinHeap open = new MinHeap(); open.Push(((Vector2Int)(ref start)).y * w + ((Vector2Int)(ref start)).x, Vector2Int.Distance(start, goal) * 8f); HashSet<int> closed = new HashSet<int>(); int expansions = 0; int reached = -1; Vector2Int val = default(Vector2Int); while (open.Count > 0) { int cur = open.Pop(); if (!closed.Add(cur)) { continue; } Vector2Int c = new Vector2Int(cur % w, cur / w); if (Mathf.Abs(((Vector2Int)(ref c)).x - ((Vector2Int)(ref goal)).x) <= 1 && Mathf.Abs(((Vector2Int)(ref c)).y - ((Vector2Int)(ref goal)).y) <= 1) { reached = cur; break; } int key = expansions + 1; expansions = key; if (key > 120000) { break; } if (expansions % 2000 == 0) { yield return null; } float num = HeightAt(c); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i == 0 && j == 0) { continue; } ((Vector2Int)(ref val))..ctor(((Vector2Int)(ref c)).x + i, ((Vector2Int)(ref c)).y + j); if (((Vector2Int)(ref val)).x < 0 || ((Vector2Int)(ref val)).y < 0 || ((Vector2Int)(ref val)).x >= w || ((Vector2Int)(ref val)).y >= h) { continue; } int num2 = ((Vector2Int)(ref val)).y * w + ((Vector2Int)(ref val)).x; if (closed.Contains(num2)) { continue; } float num3 = HeightAt(val); bool flag = Mathf.Abs(((Vector2Int)(ref val)).x - ((Vector2Int)(ref goal)).x) <= 1 && Mathf.Abs(((Vector2Int)(ref val)).y - ((Vector2Int)(ref goal)).y) <= 1; if (!flag && Blocked(val, num3)) { continue; } float num4 = ((i != 0 && j != 0) ? 1.414f : 1f) * 8f; float num5 = Mathf.Abs(num3 - num); if (!(num5 > 6.5f * (num4 / 8f)) || flag) { float num6 = num5 * 2.5f; if (num3 < water + 0.3f) { num6 += num4 * 2f; } float num7 = cost[cur] + num4 + num6; if (!cost.TryGetValue(num2, out var value) || !(value <= num7)) { cost[num2] = num7; cameFrom[num2] = cur; open.Push(num2, num7 + Vector2Int.Distance(val, goal) * 8f); } } } } c = default(Vector2Int); } if (reached >= 0) { List<int> list = new List<int>(); int num8 = reached; while (num8 != ((Vector2Int)(ref start)).y * w + ((Vector2Int)(ref start)).x && cameFrom.ContainsKey(num8)) { list.Add(num8); num8 = cameFrom[num8]; } list.Reverse(); Vector2Int c2 = default(Vector2Int); for (int k = 2; k < list.Count; k += 3) { ((Vector2Int)(ref c2))..ctor(list[k] % w, list[k] / w); Vector3 item = ToWorld(c2); item.y = HeightAt(c2); result.Path.Add(item); } result.Path.Add(to); result.Found = true; } result.Done = true; bool Blocked(Vector2Int c3, float ht) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (ht < water - 0.6f) { return true; } Vector3 val2 = ToWorld(c3); Heightmap val3 = Heightmap.FindHeightmap(val2); if (Object.op_Implicit((Object)(object)val3) && val3.IsLava(val2, 0.6f)) { return true; } return false; } float HeightAt(Vector2Int c3) { //IL_0029: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) int key2 = ((Vector2Int)(ref c3)).y * w + ((Vector2Int)(ref c3)).x; if (heights.TryGetValue(key2, out var value2)) { return value2; } Vector3 val2 = ToWorld(c3); if (!Heightmap.GetHeight(val2, ref value2)) { value2 = ((wg != null) ? wg.GetHeight(val2.x, val2.z) : (water + 1f)); } heights[key2] = value2; return value2; } Vector2Int ToCell(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) return new Vector2Int(Mathf.Clamp(Mathf.RoundToInt((p.x - minX) / 8f), 0, w - 1), Mathf.Clamp(Mathf.RoundToInt((p.z - minZ) / 8f), 0, h - 1)); } Vector3 ToWorld(Vector2Int val2) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) return new Vector3(minX + (float)((Vector2Int)(ref val2)).x * 8f, 0f, minZ + (float)((Vector2Int)(ref val2)).y * 8f); } } } public class Uter : MonoBehaviour { public static readonly List<Uter> All = new List<Uter>(); public static Destination? Pending; private const string ZdoRider = "uter_rider"; private ZNetView _nview; private Character _character; private BaseAI _ai; private Transform _seat; private static readonly MethodInfo MoveTo = AccessTools.Method(typeof(BaseAI), "MoveTo", new Type[4] { typeof(float), typeof(Vector3), typeof(float), typeof(bool) }, (Type[])null); private float _leaveAt; private bool _carrying; private float _normalRunSpeed = -1f; private bool _leaving; private Coroutine _job; private int _jobGen; private Vector3? _moveTarget; private float _moveDist = 1.5f; private bool _arrived; private const float StuckSeconds = 6f; private static int _solidMask = -1; private float _nextJumpCheck; private float _stillSince; private float _lastJumpLine = -999f; private Vector3 _lastMovePos; private float _nextGrumble; private long RiderId { get { if (!Object.op_Implicit((Object)(object)_nview) || !_nview.IsValid()) { return 0L; } return _nview.GetZDO().GetLong("uter_rider", 0L); } } private Transform Seat { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_seat)) { return _seat; } _seat = new GameObject("uter_seat").transform; _seat.SetParent(((Component)this).transform, false); _seat.localRotation = Quaternion.identity; return _seat; } } private static int SolidMask { get { if (_solidMask < 0) { return _solidMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "vehicle" }); } return _solidMask; } } public void SetRider(Player p) { if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid() && Object.op_Implicit((Object)(object)p)) { _nview.GetZDO().Set("uter_rider", p.GetPlayerID()); } } public bool IsFor(Player p) { if (Object.op_Implicit((Object)(object)p)) { return RiderId == p.GetPlayerID(); } return false; } private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _character = ((Component)this).GetComponent<Character>(); _ai = ((Component)this).GetComponent<BaseAI>(); All.Add(this); } private void OnDestroy() { All.Remove(this); if (_carrying) { ReleaseRider(); } } private void Start() { if (Object.op_Implicit((Object)(object)_character)) { _character.m_name = Plugin.PorterName.Value; } _leaveAt = Time.time + 30f; if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid() && _nview.IsOwner()) { Destination? pending = Pending; Pending = null; if (pending.HasValue) { ((MonoBehaviour)this).StartCoroutine(BeginSoon(pending.Value)); } else if (RiderId == 0L) { Vanish(); } } } private IEnumerator BeginSoon(Destination to) { yield return (object)new WaitForSeconds(0.5f); Say(Pick(Lines.Hello)); Begin(to); } private void Update() { if (!Object.op_Implicit((Object)(object)_nview) || !_nview.IsValid()) { return; } if (!_nview.IsOwner()) { if (!IsFor(Player.m_localPlayer)) { return; } _nview.ClaimOwnership(); } UpdateRide(); if (_job == null && Time.time > _leaveAt) { Leave(); } } public void Begin(Destination to) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { SetRider(localPlayer); _leaving = false; Vector3 dest; string text = Problem(localPlayer, to, out dest); if (text != null) { Say(text); Leave(); } else { StartJob(RideJob(localPlayer, dest, to)); } } } private static string Problem(Player player, Destination to, out Vector3 dest) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) dest = Vector3.zero; if (((Component)player).transform.position.y > 3000f) { return "Not down here. Get us outside first."; } if (((Character)player).IsAttached()) { return "You're already sat on something."; } if (to == Destination.Home) { if (!Home.TryGet(player, out dest)) { return "Home? You haven't got a bed. Sleep in one, or tell me \"this is home\" somewhere."; } } else { if (!NearestGrave(player, out dest)) { return "You've no gravestone out there. Lucky you."; } if (dest.y > 3000f) { return "Your gravestone's down in a dungeon. I'm not running you down there."; } } if (Vector3.Distance(Flat(((Component)player).transform.position), Flat(dest)) < 10f) { if (to != Destination.Home) { return "Your gravestone's right here."; } return "We're already home."; } return null; } private static bool NearestGrave(Player player, out Vector3 pos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) pos = Vector3.zero; if (ZDOMan.instance == null) { return false; } List<ZDO> list = new List<ZDO>(); int num = 0; while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("Player_tombstone", list, ref num)) { } long me = player.GetPlayerID(); ZDO val = (from z in list where z != null && z.GetLong(ZDOVars.s_owner, 0L) == me orderby Vector3.Distance(z.GetPosition(), ((Component)player).transform.position) select z).FirstOrDefault(); if (val == null) { return false; } pos = val.GetPosition(); return true; } private IEnumerator RideJob(Player player, Vector3 dest, Destination to) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) string where = ((to == Destination.Home) ? "home" : "your gravestone"); yield return GoTo(((Component)player).transform.position, 1.5f); if (!Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead() || ((Character)player).IsAttached()) { Leave(); yield break; } Transform transform = ((Component)this).transform; Vector3 val = Flat(dest - ((Component)this).transform.position); transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized); Seat.localPosition = new Vector3(0f, Plugin.SeatHeight.Value, 0f - Plugin.SeatBehind.Value); ((Character)player).AttachStart(Seat, ((Component)this).gameObject, true, false, false, "attach_lox", new Vector3(0f, 0.3f, -1f), (Transform)null); _carrying = true; if (Object.op_Implicit((Object)(object)_character)) { _normalRunSpeed = _character.m_runSpeed; Character character = _character; character.m_runSpeed *= Mathf.Max(0.5f, Plugin.SpeedBoost.Value); } Plugin.ShowMessage("Press Jump to climb off."); Grumble(Lines.PickUp); RoutePlanner.Result route = new RoutePlanner.Result(); yield return RoutePlanner.Plan(((Component)this).transform.position, dest, route); Plugin.Log.LogInfo((object)("Route to " + where + ": " + (route.Found ? $"{route.Path.Count} waypoints" : "none found"))); int next = 0; int noProgress = 0; int replans = 0; while (_carrying && Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && ((Character)player).IsAttached()) { if (Vector3.Distance(Flat(((Component)this).transform.position), Flat(dest)) < 8f) { Say((to == Destination.Home) ? Pick(Lines.Home) : Pick(Lines.Grave)); ReleaseRider(); Leave(); yield break; } if (!route.Found) { Say("I can't find a way to " + where + " over land from here. You'll have to swim or sail for it."); ReleaseRider(); Leave(); yield break; } if (Time.time >= _nextGrumble) { Grumble(Lines.Riding); } for (; next < route.Path.Count - 1 && Vector3.Distance(Flat(((Component)this).transform.position), Flat(route.Path[next])) < 5f; next++) { } Vector3 target = route.Path[Mathf.Min(next, route.Path.Count - 1)]; Vector3 before = ((Component)this).transform.position; yield return GoTo(target, 3f); if (Vector3.Distance(Flat(before), Flat(((Component)this).transform.position)) > 2f) { noProgress = 0; continue; } int num = noProgress + 1; noProgress = num; if (num >= 2) { num = replans + 1; replans = num; if (num > 3) { Say("I'm stuck, I can't get past here. Off you get."); ReleaseRider(); Leave(); yield break; } route = new RoutePlanner.Result(); yield return RoutePlanner.Plan(((Component)this).transform.position, dest, route); next = 0; noProgress = 0; } } if (_carrying) { Say(Pick(Lines.OffEarly)); ReleaseRider(); } Leave(); } private void UpdateRide() { if (_carrying) { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead()) { ReleaseRider(); Leave(); } else if (ZInput.GetButtonDown("Jump") || ZInput.GetButtonDown("JoyJump")) { Say(Pick(Lines.OffEarly)); ReleaseRider(); Leave(); } } } private void ReleaseRider() { if (_carrying) { _carrying = false; if (Object.op_Implicit((Object)(object)_character) && _normalRunSpeed > 0f) { _character.m_runSpeed = _normalRunSpeed; } _normalRunSpeed = -1f; Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && ((Character)localPlayer).IsAttached()) { ((Character)localPlayer).AttachStop(); } } } private void Leave() { if (!_leaving) { _leaving = true; Say(Pick(Lines.Farewell)); StartJob(LeaveJob()); } } private IEnumerator LeaveJob() { float giveUp = Time.time + 30f; float y = default(float); for (int leg = 0; leg < 6; leg++) { if (!(Time.time < giveUp)) { break; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || Vector3.Distance(((Component)this).transform.position, ((Component)localPlayer).transform.position) > 45f) { break; } Vector3 val = Flat(((Component)this).transform.position - ((Component)localPlayer).transform.position); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = -((Component)localPlayer).transform.forward; } Vector3 val2 = ((Component)this).transform.position + ((Vector3)(ref val)).normalized * 20f; if (Heightmap.GetHeight(val2, ref y)) { val2.y = y; } yield return GoTo(val2, 3f); } Vanish(); } private void Vanish() { ReleaseRider(); if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid()) { if (!_nview.IsOwner()) { _nview.ClaimOwnership(); } _nview.Destroy(); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void StartJob(IEnumerator routine) { if (_job != null) { ((MonoBehaviour)this).StopCoroutine(_job); } _moveTarget = null; _job = ((MonoBehaviour)this).StartCoroutine(RunJob(routine, ++_jobGen)); } private IEnumerator RunJob(IEnumerator routine, int gen) { Stack<IEnumerator> steps = new Stack<IEnumerator>(); steps.Push(routine); while (steps.Count > 0) { IEnumerator enumerator = steps.Peek(); bool flag; try { flag = enumerator.MoveNext(); } catch (Exception ex) { Plugin.Log.LogError((object)("Porter job failed: " + ex)); break; } if (gen != _jobGen) { yield break; } if (!flag) { steps.Pop(); continue; } if (enumerator.Current is IEnumerator item) { steps.Push(item); continue; } yield return enumerator.Current; if (gen == _jobGen) { continue; } yield break; } if (gen == _jobGen) { _job = null; } } public void DriveMovement(float dt) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_ai)) { return; } if (!_moveTarget.HasValue) { _ai.StopMoving(); return; } bool flag = Vector3.Distance(Flat(((Component)this).transform.position), Flat(_moveTarget.Value)) > 6f || _carrying || _leaving; bool flag2 = MoveTo != null && (bool)MoveTo.Invoke(_ai, new object[4] { dt, _moveTarget.Value, _moveDist, flag }); Vector3 val = _moveTarget.Value - ((Component)this).transform.position; val.y = 0f; if (flag2 && ((Vector3)(ref val)).magnitude > _moveDist + 0.5f) { flag2 = false; _ai.MoveTowards(((Vector3)(ref val)).normalized, flag); } if (flag2) { _arrived = true; _moveTarget = null; _ai.StopMoving(); } else { JumpIfBlocked(); } } private IEnumerator GoTo(Vector3 target, float dist) { //IL_000e: 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) if (Vector3.Distance(Flat(((Component)this).transform.position), Flat(target)) <= dist) { yield break; } _arrived = false; _moveDist = dist; _moveTarget = target; _stillSince = Time.time; _lastMovePos = ((Component)this).transform.position; float best = Vector3.Distance(Flat(((Component)this).transform.position), Flat(target)); float lastProgress = Time.time; float giveUp = Time.time + 20f + best * 1.5f; while (!_arrived && Time.time - lastProgress < 6f && Time.time < giveUp) { float num = Vector3.Distance(Flat(((Component)this).transform.position), Flat(target)); if (num < best - 0.5f) { best = num; lastProgress = Time.time; } yield return null; } if (!_arrived) { Teleport(FreeSpotNear(target, Mathf.Max(dist * 0.8f, 1f))); _moveTarget = null; _ai.StopMoving(); } } private void Teleport(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) float num = default(float); if (Heightmap.GetHeight(pos, ref num) && pos.y < num) { pos.y = num + 0.2f; } Rigidbody component = ((Component)this).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component)) { component.linearVelocity = Vector3.zero; component.position = pos; } ((Component)this).transform.position = pos; if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid() && _nview.IsOwner()) { _nview.GetZDO().SetPosition(pos); } } private Vector3 FreeSpotNear(Vector3 target, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0176: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Flat(((Component)this).transform.position - target); Vector3 val2 = ((Vector3)(ref val)).normalized; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector3.forward; } Vector3? val3 = null; float num = float.MaxValue; float[] array = new float[4] { radius, radius + 1f, radius + 2f, radius + 3.5f }; float num3 = default(float); foreach (float num2 in array) { for (int j = 0; j < 360; j += 30) { Vector3 val4 = target + Quaternion.Euler(0f, (float)j, 0f) * val2 * num2; if (!Heightmap.GetHeight(val4, ref num3)) { continue; } val4.y = num3 + 0.05f; if (!(Mathf.Abs(num3 - target.y) > 4f) && !Physics.CheckCapsule(val4 + Vector3.up * 0.5f, val4 + Vector3.up * 1.6f, 0.35f, SolidMask)) { float num4 = (float)j * 0.01f + num2 + Mathf.Abs(num3 - target.y); if (num4 < num) { num = num4; val3 = val4; } } } } if (val3.HasValue) { return val3.Value; } Vector3 val5 = target + val2 * radius; float num5 = default(float); if (Heightmap.GetHeight(val5, ref num5)) { val5.y = Mathf.Max(num5, target.y); } return val5; } private void JumpIfBlocked() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (Time.time < _nextJumpCheck || !Object.op_Implicit((Object)(object)_character)) { return; } _nextJumpCheck = Time.time + 0.25f; if (Vector3.Distance(Flat(((Component)this).transform.position), Flat(_lastMovePos)) > 0.3f) { _lastMovePos = ((Component)this).transform.position; _stillSince = Time.time; } if (!_character.IsOnGround()) { return; } Vector3 forward = ((Component)this).transform.forward; bool num = Physics.Raycast(((Component)this).transform.position + Vector3.up * 0.4f, forward, 1.3f, SolidMask) && !Physics.Raycast(((Component)this).transform.position + Vector3.up * 1.7f, forward, 1.6f, SolidMask); bool flag = Time.time - _stillSince > 1.2f; if (num || flag) { _character.Jump(true); _stillSince = Time.time; _nextJumpCheck = Time.time + 1f; if (_carrying && Time.time - _lastJumpLine > 40f && Random.value < 0.5f) { _lastJumpLine = Time.time; Say(Pick(Lines.Jump)); } } } private void Grumble(params string[][] sets) { _nextGrumble = Time.time + Random.Range(25f, 40f); if (Plugin.Chatty.Value) { Say(Pick(sets)); } } private string Pick(params string[][] sets) { string[] array = sets.SelectMany((string[] s) => s).ToArray(); return array[Random.Range(0, array.Length)].Replace("{name}", Plugin.PorterName.Value); } private void Say(string text) { //IL_0020: 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) if (!string.IsNullOrWhiteSpace(text)) { if (Object.op_Implicit((Object)(object)Chat.instance)) { Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 2.2f, 30f, 10f, "", text, false); } Plugin.ShowMessage(Plugin.PorterName.Value + ": " + text); } } private static Vector3 Flat(Vector3 v) { //IL_0000: 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_0011: Unknown result type (might be due to invalid IL or missing references) return new Vector3(v.x, 0f, v.z); } }