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 Skidbladnir v1.0.0
Skidbladnir.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Skidbladnir { internal static class AdminCheats { [HarmonyPatch(typeof(Terminal), "IsCheatsEnabled")] private static class CheatsPatch { private static readonly FieldInfo Cheat = AccessTools.Field(typeof(Terminal), "m_cheat"); private static void Postfix(ref bool __result) { if (!(!SkidbladnirPlugin.AdminCheats.Value | __result) && (bool)Cheat.GetValue(null) && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { __result = ZNet.instance.LocalPlayerIsAdminOrHost(); } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class HostOnlyPatch { private static void Postfix() { if (!SkidbladnirPlugin.AdminCheats.Value) { return; } Dictionary<string, ConsoleCommand> dictionary = AccessTools.StaticFieldRefAccess<Terminal, Dictionary<string, ConsoleCommand>>("commands"); List<string> list = new List<string>(); string[] hostOnly = HostOnly; foreach (string text in hostOnly) { if (dictionary.TryGetValue(text, out var value) && value.OnlyServer) { value.OnlyServer = false; list.Add(text); } } if (list.Count > 0) { SkidbladnirPlugin.Log.LogInfo((object)("Admins on a server may use cheats, including " + string.Join(", ", list))); } } } private static readonly string[] HostOnly = new string[3] { "debugmode", "fly", "nocost" }; } internal class AutoTest : MonoBehaviour { [HarmonyPatch(typeof(GameCamera), "LateUpdate")] private static class CameraOverride { private static void Postfix(GameCamera __instance) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (CamPos.HasValue) { ((Component)__instance).transform.SetPositionAndRotation(CamPos.Value, CamRot); } } } [HarmonyPatch(typeof(FejdStartup), "Start")] private static class MenuStart { private static void Postfix(FejdStartup __instance) { if (Enabled && !_started) { ((MonoBehaviour)__instance).StartCoroutine(StartWorld(__instance)); } } } [HarmonyPatch(typeof(Player), "SetControls")] private static class WalkPatch { private static void Prefix(Player __instance, ref Vector3 movedir, ref bool run, ref bool block, ref bool blockHold, ref bool dodge) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { if (WalkDir.HasValue) { movedir = WalkDir.Value; run = false; } if (BlockHold) { block = true; blockHold = true; } if (DodgeOnce) { dodge = true; DodgeOnce = false; } } } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] private static class HoldIvaldi { private static bool Prefix(MonsterAI __instance, ref bool __result) { //IL_0023: 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) if (!IvaldiPose.HasValue || (Object)(object)((Component)__instance).GetComponent<IvaldiNpc>() == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent<Character>(); component.SetMoveDir(Vector3.zero); component.SetLookDir(IvaldiPose.Value, 0f); __result = false; return false; } } private class Cam { public Vector3 Pos; public Vector3 Look; public float Fov; public bool Collide; public Cam(Vector3 pos, Vector3 look, float fov = 50f, bool collide = true) { //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) Pos = pos; Look = look; Fov = fov; Collide = collide; } } private class TShot { public string Name; public float From; public float To; public Func<IEnumerator> Setup; public Func<float, float, Cam> Camera; public Action<float, float> Each; public Func<float, float> Slow; } [HarmonyPatch(typeof(GameCamera), "LateUpdate")] private static class TrailerFov { [HarmonyPriority(0)] private static void Postfix(GameCamera __instance) { if (CamFov.HasValue) { Camera component = ((Component)__instance).GetComponent<Camera>(); if ((Object)(object)component != (Object)null) { component.fieldOfView = CamFov.Value; } } } } [HarmonyPatch(typeof(MessageHud), "ShowMessage")] private static class TrailerQuiet { private static bool Prefix() { return TrailerFolder == null; } } [HarmonyPatch(typeof(Player), "SetControls")] private static class CrouchPatch { private static void Prefix(Player __instance, ref bool crouch) { if (CrouchHold && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { crouch = true; } } } public const string TriggerFile = "skidbladnir_autotest.txt"; public const string ReportFile = "SkidbladnirTest.txt"; private const string WorldName = "SkidTest"; private const string WorldSeed = "SkidTest1"; private const string ProfileName = "skidtest"; private const float TimeLimit = 900f; internal static bool Enabled; internal static int SiteIndex; internal static bool NoBlueprint; internal static string ShotFolder; internal static string TourFolder; internal static bool TourCatalog; internal static bool TourMist; internal static Vector3? CamPos; internal static Quaternion CamRot; internal static float? LiftOverride; private readonly List<string> _lines = new List<string>(); private int _pass; private int _fail; private string _shotDir; private bool _finished; private static bool _started; internal static Vector3? WalkDir; internal static string LastWalkState = ""; internal static bool BlockHold; internal static bool DodgeOnce; internal static string IvaldiFolder; internal static bool IvaldiHands; internal static bool IvaldiSweep; internal static bool IvaldiPoseRef; private static readonly (float, float, Vector2)[] SweepCases = new(float, float, Vector2)[6] { (2f, 20f, new Vector2(2f, 0f)), (2f, 20f, new Vector2(3f, 0f)), (2f, 20f, new Vector2(2f, 1.5f)), (2f, 20f, new Vector2(2f, -1.5f)), (2f, 28f, new Vector2(2f, 0f)), (1.8f, 20f, new Vector2(2f, 0f)) }; internal static Vector3? IvaldiPose; private static readonly FieldInfo VisRightInstance = AccessTools.Field(typeof(VisEquipment), "m_rightItemInstance"); private static readonly FieldInfo LookYaw = AccessTools.Field(typeof(Player), "m_lookYaw"); private static readonly string[] PropWords = new string[23] { "hammer", "sledge", "pickaxe", "lantern", "torch", "dverg", "helmet", "cape", "demister", "tankard", "hoe", "cultivator", "tool", "key", "scroll", "spyglass", "goggle", "chisel", "tong", "apron", "wrench", "mace", "hood" }; internal static string RefFolder; private static readonly string[] PhotoNames = new string[10] { "Mistlands_GuardTower1_new", "Mistlands_GuardTower2_new", "Mistlands_GuardTower3_new", "Mistlands_Lighthouse1_new", "Mistlands_Harbour1", "Mistlands_Excavation1", "Mistlands_Excavation2", "Mistlands_RoadPost1", "Mistlands_DvergrTownEntrance1", "Mistlands_Viaduct1" }; internal static string TrailerFolder; internal static float? CamFov; private const int Fps = 30; private static readonly string[] Solid = new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" }; private string _frameDir; private TowerAnchor _ta; private Vector3 _site; private Light _flash; private Character _elder; private int _framesSaved; private float _az1; private float _az2; private float _az5; private Vector3 _walkDir; private float _walkScore; private readonly List<Character> _extras = new List<Character>(); private Transform _focus; private float _nextSwing; private string _gear = ""; private Quaternion _ivaldiFrom; private Vector3 _mineDoor; internal static bool CrouchHold; private GameObject _sea; private GameObject _flyover; private GameObject _aimer; private Vector3 _ash; private Vector3 _seaStart; private Vector3 _seaDir; private ZeppelinFlight _zepFly; private Character _troll; private Vector3 _flyDir = Vector3.forward; private static int SolidMask => LayerMask.GetMask(Solid); private TowerAnchor A { get { if (!((Object)(object)_ta != (Object)null)) { return _ta = TowerAnchor.Instances.FirstOrDefault(); } return _ta; } } internal static void CheckTrigger(GameObject host) { try { string path = Path.Combine(Paths.BepInExRootPath, "skidbladnir_autotest.txt"); if (!File.Exists(path)) { return; } string[] array = File.ReadAllText(path).Trim().Split(new char[3] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length != 0 && array[0].ToLowerInvariant() == "tour") { TourFolder = ((array.Length > 1) ? array[1] : "tour"); TourCatalog = array.Any((string w) => w.ToLowerInvariant() == "catalog"); TourMist = array.Any((string w) => w.ToLowerInvariant() == "mist"); } if (array.Length != 0 && array[0].ToLowerInvariant() == "refs") { RefFolder = ((array.Length > 1) ? array[1] : "refs"); } if (array.Length != 0 && array[0].ToLowerInvariant() == "ivaldi") { IvaldiFolder = ((array.Length > 1) ? array[1] : "ivaldi"); IvaldiHands = array.Any((string w) => w.ToLowerInvariant() == "hands"); IvaldiSweep = array.Any((string w) => w.ToLowerInvariant() == "sweep"); IvaldiPoseRef = array.Any((string w) => w.ToLowerInvariant() == "pose"); if (IvaldiPoseRef) { IvaldiHands = true; } } if (array.Length > 1 && array[0].ToLowerInvariant() == "site" && int.TryParse(array[1], out var result)) { SiteIndex = result; ShotFolder = ((array.Length > 2) ? array[2] : null); } NoBlueprint = array.Any((string w) => w.ToLowerInvariant() == "noblueprint"); if (array.Length != 0 && array[0].ToLowerInvariant() == "trailer") { TrailerFolder = ((array.Length > 1) ? array[1] : "v1"); } File.Delete(path); Enabled = true; host.AddComponent<AutoTest>(); SkidbladnirPlugin.Log.LogInfo((object)"AUTOTEST: trigger found; the game will start the test world by itself"); } catch (Exception arg) { SkidbladnirPlugin.Log.LogError((object)$"AUTOTEST trigger check failed: {arg}"); } } private static IEnumerator StartWorld(FejdStartup menu) { _started = true; yield return (object)new WaitForSeconds(2f); try { PlayerProfile val = new PlayerProfile("skidtest", (FileSource)2); if (!val.Load()) { val.SetName("Skidtest"); } val.m_firstSpawn = false; val.Save(); Game.SetProfile("skidtest", (FileSource)2); World.RemoveWorld("SkidTest", (FileSource)2); SaveSystem.InvalidateCache((SaveDataType)0); World val2 = new World("SkidTest", "SkidTest1") { m_fileSource = (FileSource)2, m_needsDB = false }; SaveSystem.SetSaveNumber(0u); val2.SaveWorldFWLData(DateTime.Now); SaveSystem.InvalidateCache((SaveDataType)0); ZNet.SetServer(true, false, false, val2.m_name, "", val2); ZNet.ResetServerHost(); AccessTools.Field(typeof(FejdStartup), "m_startingWorld").SetValue(menu, true); SkidbladnirPlugin.Log.LogInfo((object)"AUTOTEST: starting world SkidTest (seed SkidTest1) as skidtest"); AccessTools.Method(typeof(FejdStartup), "TransitionToMainScene", (Type[])null, (Type[])null).Invoke(menu, null); } catch (Exception arg) { SkidbladnirPlugin.Log.LogError((object)$"AUTOTEST could not start the world: {arg}"); } } private void Start() { _shotDir = Path.Combine(Path.Combine(Paths.GameRootPath, "Skidbladnir"), "test"); if (TourFolder != null) { _shotDir = Path.Combine(_shotDir, TourFolder.Replace('/', Path.DirectorySeparatorChar)); } if (RefFolder != null) { _shotDir = Path.Combine(_shotDir, RefFolder.Replace('/', Path.DirectorySeparatorChar)); } if (IvaldiFolder != null) { _shotDir = Path.Combine(_shotDir, IvaldiFolder.Replace('/', Path.DirectorySeparatorChar)); } if (ShotFolder != null) { _shotDir = Path.Combine(_shotDir, ShotFolder.Replace('/', Path.DirectorySeparatorChar)); } try { Directory.CreateDirectory(_shotDir); string[] files = Directory.GetFiles(_shotDir, "*.png"); for (int i = 0; i < files.Length; i++) { File.Delete(files[i]); } } catch { } ((MonoBehaviour)this).StartCoroutine(Watchdog()); ((MonoBehaviour)this).StartCoroutine(Run()); } private IEnumerator Watchdog() { yield return (object)new WaitForSecondsRealtime((RefFolder != null || TrailerFolder != null) ? 2700f : 900f); if (!_finished) { Check("finished within the time limit", ok: false, $"{900f:F0} s"); Finish(); } } private void Check(string what, bool ok, string detail = "") { if (ok) { _pass++; } else { _fail++; } string text = (ok ? "PASS" : "FAIL") + " " + what + ((detail.Length > 0) ? (" (" + detail + ")") : ""); _lines.Add(text); SkidbladnirPlugin.Log.LogInfo((object)("AUTOTEST " + text)); WriteReport(done: false); } private void Note(string text) { _lines.Add(" " + text); SkidbladnirPlugin.Log.LogInfo((object)("AUTOTEST " + text)); } private void WriteReport(bool done) { try { List<string> first = new List<string> { string.Format("Skidbladnir autotest {0}, {1:yyyy-MM-dd HH:mm:ss}", "1.0.0", DateTime.Now), done ? string.Format("RESULT: {0} ({1} passed, {2} failed)", (_fail == 0) ? "PASS" : "FAIL", _pass, _fail) : $"RUNNING ({_pass} passed, {_fail} failed so far)", "" }; File.WriteAllLines(Path.Combine(Paths.BepInExRootPath, "SkidbladnirTest.txt"), first.Concat(_lines).ToArray()); } catch (Exception ex) { SkidbladnirPlugin.Log.LogWarning((object)("AUTOTEST report write failed: " + ex.Message)); } } private void Finish() { if (!_finished) { _finished = true; LiftOverride = null; WriteReport(done: true); SkidbladnirPlugin.Log.LogInfo((object)$"AUTOTEST finished: {_pass} passed, {_fail} failed; quitting"); ((MonoBehaviour)this).StartCoroutine(Quit()); } } private IEnumerator Quit() { yield return (object)new WaitForSecondsRealtime(2f); Application.Quit(); } private IEnumerator Shot(string name) { yield return (object)new WaitForEndOfFrame(); try { Texture2D val = new Texture2D(Screen.width, Screen.height, (TextureFormat)3, false); val.ReadPixels(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), 0, 0); val.Apply(); File.WriteAllBytes(Path.Combine(_shotDir, name + ".png"), ImageConversion.EncodeToPNG(val)); Object.Destroy((Object)(object)val); Note("screenshot " + name + ".png"); } catch (Exception ex) { Note("screenshot " + name + " failed: " + ex.Message); } } private static IEnumerator WaitFor(Func<bool> cond, float timeout) { float t = 0f; while (!cond() && t < timeout) { t += Time.deltaTime; yield return null; } } private static IEnumerator Tp(Player p, Vector3 pos, bool distant = false) { //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) float t = 0f; while (!((Character)p).TeleportTo(pos, ((Component)p).transform.rotation, distant) && t < 10f) { t += 0.25f; yield return (object)new WaitForSeconds(0.25f); } yield return (object)new WaitForSeconds(0.2f); yield return WaitFor(() => !((Character)p).IsTeleporting(), 120f); yield return (object)new WaitForSeconds(1.5f); } private static void Look(Player p, Vector3 at) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_001e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = at - ((Character)p).GetEyePoint(); if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { ((Character)p).SetLookDir(((Vector3)(ref val)).normalized, 0f); } } private IEnumerator Run() { yield return WaitFor(() => (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ZNetScene.instance != (Object)null && !((Character)Player.m_localPlayer).IsTeleporting(), 600f); Player player = Player.m_localPlayer; if ((Object)(object)player == (Object)null) { Check("world loaded with a player", ok: false); Finish(); yield break; } yield return (object)new WaitForSeconds(5f); player.SetGodMode(true); Check("world loaded with a player", ok: true, string.Format("{0}, at {1}", "SkidTest", ((Component)player).transform.position)); IEnumerator body = null; try { body = ((TrailerFolder != null) ? Trailer(player) : ((IvaldiFolder != null) ? IvaldiTour(player) : ((RefFolder != null) ? Refs(player) : ((TourFolder != null) ? Tour(player) : Steps(player))))); } catch (Exception ex) { Check("test steps", ok: false, ex.ToString()); } if (body != null) { while (true) { object current; try { if (!body.MoveNext()) { break; } current = body.Current; goto IL_01bb; } catch (Exception ex2) { Check("no exceptions during the test", ok: false, ex2.ToString()); } break; IL_01bb: yield return current; } } Finish(); } private IEnumerator Tour(Player player) { yield return WaitFor(() => SkidWorld.SitesReady, 300f); if (SkidWorld.Sites.Count == 0) { Check("tower sites", ok: false); yield break; } Vector3 val = SkidWorld.Sites.OrderByDescending(MistShare).First(); Note($"tour site {SkidWorld.Sites.IndexOf(val)} at {val}: {MistShare(val):P0} Mistlands within 200 m"); yield return Tp(player, val + new Vector3(0f, 5f, -40f), distant: true); yield return WaitFor(() => TowerAnchor.Instances.Count > 0 && TowerAnchor.Instances[0].Built, 90f); TowerAnchor anchor = TowerAnchor.Instances.FirstOrDefault(); Check("tower raised and built", (Object)(object)anchor != (Object)null && anchor.Built, $"{TowerPrefab.PieceCount} pieces"); if ((Object)(object)anchor == (Object)null) { yield break; } EnvMan env = EnvMan.instance; env.m_debugEnv = "Clear"; env.m_debugTimeOfDay = true; env.m_debugTime = 0.5f; if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.m_userHidden = true; } GameObject value = Traverse.Create((object)player).Field("m_visual").GetValue<GameObject>(); if ((Object)(object)value != (Object)null) { value.SetActive(false); } if (TourCatalog) { float deck = 40.5f; GameObject cat = TowerPrefab.Catalog(anchor.World(new Vector3(-7f, deck, -17f)), ((Component)anchor).transform.rotation * Quaternion.Euler(0f, -90f, 0f), flat: true); yield return Tp(player, anchor.World(new Vector3(0f, deck + 0.5f, 0f))); (string, float)[] array = new(string, float)[2] { ("0_catalog_a", -9f), ("0_catalog_b", 9f) }; for (int num = 0; num < array.Length; num++) { (string, float) tuple = array[num]; string name = tuple.Item1; float item = tuple.Item2; CamPos = anchor.World(new Vector3(5f, deck + 3f, item)); CamRot = Quaternion.LookRotation(anchor.World(new Vector3(-7f, deck + 1f, item)) - CamPos.Value); yield return (object)new WaitForSeconds(4f); yield return Shot(name); } CamPos = null; Object.Destroy((Object)(object)cat); } anchor.SetStage(3); yield return WaitFor(() => (Object)(object)anchor.Zeppelin != (Object)null, 15f); Check("ship moored", (Object)(object)anchor.Zeppelin != (Object)null); Vector3 turretCentre = TowerPrefab.TurretCentre; List<(string, Vector3, Vector3, float, bool)> list = new List<(string, Vector3, Vector3, float, bool)> { ("1_far", new Vector3(-62f, 42f, -66f), new Vector3(0f, 26f, 0f), 0.5f, true), ("2_mid", new Vector3(-30f, 14f, -27f), new Vector3(0f, 24f, 0f), 0.42f, true), ("3_base", new Vector3(-16f, 3f, -24f), new Vector3(0f, 9f, 0f), 0.5f, true), ("4_stair", turretCentre + new Vector3(1.6f, 2.2f, -1.6f), turretCentre + new Vector3(0f, 22f, 0f), 0.5f, false), ("5_deck", new Vector3(16f, 50f, -27f), new Vector3(0f, 42f, 0f), 0.5f, true), ("6_night", new Vector3(-30f, 14f, -27f), new Vector3(0f, 24f, 0f), 0.02f, true), ("7_turret", new Vector3(38f, 14f, -32f), turretCentre + new Vector3(0f, 22f, 0f), 0.45f, true), ("8_side", new Vector3(34f, 10f, 30f), new Vector3(0f, 22f, 0f), 0.4f, true) }; int mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "terrain", "piece", "vehicle" }); RaycastHit val6 = default(RaycastHit); foreach (var v in list) { Vector3 cam = anchor.World(v.Item2); Vector3 target = anchor.World(v.Item3); float deck = ZoneSystem.instance.GetGroundHeight(cam); Vector3 val2 = cam; val2.y = deck + 0.3f; CamPos = null; yield return Tp(player, val2 + ((Component)anchor).transform.rotation * new Vector3(0f, 0f, -2f)); yield return (object)new WaitForSeconds(2f); deck = ZoneSystem.instance.GetGroundHeight(cam); if (cam.y < deck + 1.6f) { cam.y = deck + 1.6f; } if (v.Item5) { int num2 = 0; Vector3 val3 = target - cam; RaycastHit[] array2 = Physics.SphereCastAll(cam, 7f, ((Vector3)(ref val3)).normalized, ((Vector3)(ref val3)).magnitude); for (int num3 = 0; num3 < array2.Length; num3++) { RaycastHit val4 = array2[num3]; ZNetView val5 = (((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<ZNetView>() : null); if (!((Object)(object)val5 == (Object)null) && val5.IsValid() && !((Component)val5).transform.IsChildOf(((Component)anchor).transform) && (!((Object)(object)((Component)val5).GetComponent<TreeBase>() == (Object)null) || !((Object)(object)((Component)val5).GetComponent<TreeLog>() == (Object)null) || !((Object)(object)((Component)val5).GetComponent<Destructible>() == (Object)null))) { val5.ClaimOwnership(); ZNetScene.instance.Destroy(((Component)val5).gameObject); num2++; } } if (num2 > 0) { Note($"{v.Item1}: {num2} trees felled for the view"); yield return (object)new WaitForSeconds(0.5f); } } int num4 = 0; while (v.Item5 && num4 < 16 && Physics.Linecast(cam, target, ref val6, mask) && !((Component)((RaycastHit)(ref val6)).collider).transform.IsChildOf(((Component)anchor).transform) && (!((Object)(object)anchor.Zeppelin != (Object)null) || !((Component)((RaycastHit)(ref val6)).collider).transform.IsChildOf(((Component)anchor.Zeppelin).transform))) { cam.y += 5f; num4++; } if (v.Item5) { Note($"{v.Item1}: camera {cam.y - deck:F0} m above ground"); } env.m_debugTime = v.Item4; CamPos = cam; CamRot = Quaternion.LookRotation(target - cam); yield return (object)new WaitForSeconds(6f); yield return Shot(v.Item1); } CamPos = null; } private static float MistShare(Vector3 p) { //IL_0025: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 int num = 0; int num2 = 0; for (float num3 = 50f; num3 <= 200f; num3 += 50f) { int num4 = 0; while (num4 < 16) { float num5 = (float)num4 * (float)Math.PI / 8f; if ((int)WorldGenerator.instance.GetBiome(p + new Vector3(Mathf.Cos(num5) * num3, 0f, Mathf.Sin(num5) * num3)) == 512) { num2++; } num4++; num++; } } return (float)num2 / (float)num; } private IEnumerator Steps(Player player) { ZNetScene instance = ZNetScene.instance; Check("zeppelin prefab", (Object)(object)instance.GetPrefab("Skidbladnir") != (Object)null); Check("tower prefab", (Object)(object)instance.GetPrefab("Skidbladnir_Tower") != (Object)null, $"{TowerPrefab.PieceCount} pieces" + ((TowerPrefab.Missing.Count > 0) ? (", missing " + string.Join("/", TowerPrefab.Missing)) : "")); Check("tower has all its piece kinds", TowerPrefab.Missing.Count == 0 || (TowerPrefab.Missing.Count == 1 && TowerPrefab.Missing[0] == "tip")); Check("Ivaldi prefab", (Object)(object)instance.GetPrefab("Skidbladnir_Ivaldi") != (Object)null); Check("elder gjall prefab", (Object)(object)instance.GetPrefab("Skidbladnir_ElderGjall") != (Object)null); Check("grappling hook item", (Object)(object)ObjectDB.instance.GetItemPrefab(Items.HookPrefabName) != (Object)null, Items.HookPrefabName + " (" + Items.HookItemName + ")"); Recipe val = ((IEnumerable<Recipe>)ObjectDB.instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => (Object)(object)r != (Object)null && (Object)(object)r.m_item != (Object)null && ((Object)r.m_item).name == Items.HookPrefabName)); AutoTest autoTest = this; bool ok = (Object)(object)val != (Object)null && val.m_resources.Length != 0; object detail; if (!((Object)(object)val == (Object)null)) { CraftingStation craftingStation = val.m_craftingStation; detail = (((craftingStation != null) ? ((Object)craftingStation).name : null) ?? "no station") + ": " + string.Join(", ", val.m_resources.Select((Requirement r) => $"{r.m_amount} {((Object)r.m_resItem).name}")); } else { detail = ""; } autoTest.Check("grappling hook recipe", ok, (string)detail); Items.Need questHook = Items.QuestHook; Check("Ivaldi's hook ingredient found", questHook != null && ((Object)questHook.Item).name == SkidbladnirPlugin.HookItem.Value, (questHook != null) ? $"{questHook.Amount} {((Object)questHook.Item).name} ({questHook.Name} = {Loc.L(questHook.Name)})" : (SkidbladnirPlugin.HookItem.Value + " missing")); List<Items.Need> toxin = Items.Toxin; Check("the toxin is one Ashlands item, found", toxin.Count == 1 && ((Object)toxin[0].Item).name == SkidbladnirPlugin.ToxinItem.Value, string.Join(", ", toxin.Select((Items.Need n) => $"{n.Amount} {((Object)n.Item).name} ({n.Name} = {Loc.L(n.Name)})")) + ((toxin.Count == 0) ? (SkidbladnirPlugin.ToxinItem.Value + " missing") : "")); List<Items.Need> recipeCost = Items.RecipeCost; Check("ship recipe cost all found", recipeCost.Count == SkidbladnirPlugin.RecipeCost.Value.Split(',').Length, string.Join(", ", recipeCost.Select((Items.Need n) => $"{n.Amount} {((Object)n.Item).name} ({Loc.L(n.Name)})"))); Piece keelPiece = (((Object)(object)ZeppelinKeel.Prefab != (Object)null) ? ZeppelinKeel.Prefab.GetComponent<Piece>() : null); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer"); bool flag = itemPrefab != null && itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces?.m_pieces.Contains(ZeppelinKeel.Prefab) == true; AutoTest autoTest2 = this; bool ok2 = (Object)(object)keelPiece != (Object)null && flag && keelPiece.m_resources.Length == recipeCost.Count && (Object)(object)keelPiece.m_craftingStation != (Object)null; object detail2; if (!((Object)(object)keelPiece == (Object)null)) { CraftingStation craftingStation2 = keelPiece.m_craftingStation; detail2 = string.Format("station {0}, {1} resources", ((craftingStation2 != null) ? ((Object)craftingStation2).name : null) ?? "none", keelPiece.m_resources.Length); } else { detail2 = "no piece"; } autoTest2.Check("ship piece on the hammer, with a station and cost", ok2, (string)detail2); Check("ship recipe locked in a new world", !TowerAnchor.RecipeUnlocked && (Object)(object)keelPiece != (Object)null && !player.HaveRequirements(keelPiece, (RequirementMode)1)); Check("no tower before anyone finds it", TowerAnchor.Instances.Count == 0 && SkidWorld.Tower == null); yield return WaitFor(() => SkidWorld.SitesReady, 300f); Check("five tower sites picked", SkidWorld.Sites.Count == 5, SkidWorld.SiteReport); if (SkidWorld.Sites.Count == 0) { yield break; } bool flag2 = SkidWorld.Sites.All((Vector3 s) => (int)WorldGenerator.instance.GetBiome(s) == 512); float num = float.MaxValue; for (int num2 = 0; num2 < SkidWorld.Sites.Count; num2++) { for (int num3 = num2 + 1; num3 < SkidWorld.Sites.Count; num3++) { num = Mathf.Min(num, Vector3.Distance(SkidWorld.Sites[num2], SkidWorld.Sites[num3])); } } Check("sites are in the Mistlands, 1 km apart", flag2 && num >= 999f, $"closest pair {num:F0} m"); int num4 = Mathf.Clamp(SiteIndex, 0, SkidWorld.Sites.Count - 1); Vector3 site = SkidWorld.Sites[num4]; Note($"testing at site {num4}"); yield return Tp(player, site + new Vector3(60f, 5f, 60f), distant: true); yield return WaitFor(() => TowerAnchor.Instances.Count > 0, 60f); TowerAnchor anchor = TowerAnchor.Instances.FirstOrDefault(); Check("tower raised when a player comes near a site", (Object)(object)anchor != (Object)null, ((Object)(object)anchor != (Object)null) ? $"at {((Component)anchor).transform.position}" : ""); if ((Object)(object)anchor == (Object)null) { yield break; } Vector3 val2 = ((Component)anchor).transform.position - site; AutoTest autoTest3 = this; Vector2 val3 = new Vector2(val2.x, val2.z); autoTest3.Check("tower raised at the site the player found", ((Vector2)(ref val3)).magnitude < 1f, $"seated {val2.y:F2} m from the site's height"); yield return WaitFor(() => anchor.Built && Object.FindObjectsOfType<IvaldiNpc>().Length != 0, 60f); Check("tower built: Ivaldi on the deck, no ship yet", anchor.Built && Object.FindObjectsOfType<IvaldiNpc>().Length != 0 && (Object)(object)anchor.Zeppelin == (Object)null && anchor.Stage == 0); IvaldiNpc ivaldi = Object.FindObjectsOfType<IvaldiNpc>().FirstOrDefault(); if ((Object)(object)ivaldi == (Object)null) { yield break; } yield return (object)new WaitForSeconds(2f); IvaldiLook component = ((Component)ivaldi).GetComponent<IvaldiLook>(); List<Transform> list = (from t in ((Component)ivaldi).GetComponentsInChildren<Transform>(true) where ((Object)t).name.StartsWith("ivaldi_") select t).ToList(); Check("Ivaldi at his configured size", (Object)(object)component != (Object)null && Mathf.Abs(component.CurrentScale - IvaldiLook.Scale) < 0.01f, ((Object)(object)component != (Object)null) ? $"scale {component.CurrentScale:F2}" : "no look"); Check("his smith's look is on, look-only", !SkidbladnirPlugin.IvaldiCustomLook.Value || (list.Count > 0 && list.All((Transform t) => ((Component)t).GetComponentsInChildren<Collider>(true).Length == 0 && ((Component)t).GetComponentsInChildren<ZNetView>(true).Length == 0 && ((Component)t).GetComponentsInChildren<Rigidbody>(true).Length == 0)), $"{list.Count} props; {IvaldiLook.Report}"); List<string> list2 = (from i in ((Component)ivaldi).GetComponent<Humanoid>().GetInventory().GetAllItems() where i.m_equipped select (!((Object)(object)i.m_dropPrefab != (Object)null)) ? i.m_shared.m_name : ((Object)i.m_dropPrefab).name).ToList(); Check("he holds his hammer (equipped, scaled down, nothing he can drop)", !SkidbladnirPlugin.IvaldiCustomLook.Value || ((Object)(object)component.HammerInstance != (Object)null && component.HammerInstance.GetComponentsInChildren<Collider>(true).All((Collider val30) => !val30.enabled) && (Object)(object)((Component)ivaldi).GetComponent<CharacterDrop>() == (Object)null), IvaldiLook.HammerReport + "; equipped " + string.Join(", ", list2)); Check("he has his beard (the male dvergr hair)", list2.Contains("DvergerHairMale"), string.Join(", ", list2)); float num5 = ((Component)anchor).transform.InverseTransformPoint(((Component)ivaldi).transform.position).y - 40.5f; Check("Ivaldi stands on his deck", ((Component)ivaldi).GetComponent<Character>().IsOnGround() && Mathf.Abs(num5) < 0.5f, $"{num5:F2} m from deck height"); Inventory inv = ((Humanoid)player).GetInventory(); int num6 = inv.CountItems(Items.QuestHookName, -1, true); if (num6 > 0) { inv.RemoveItem(Items.QuestHookName, num6, -1, true); Note($"removed {num6} grappling hook(s) left from an earlier run"); } List<Items.Need> hull = Items.Hull; Check("hull cost found", hull.Count > 0, string.Join(", ", hull.Select((Items.Need n) => $"{n.Amount} {((Object)n.Item).name}"))); string said = IvaldiNpc.Converse(player, anchor, give: false); Note("Ivaldi: " + said); foreach (Items.Need item in hull) { inv.AddItem(((Object)item.Item).name, item.Amount, 1, 0, 0L, "", false, false); } said = IvaldiNpc.Converse(player, anchor, give: true); Note("Ivaldi: " + said); yield return WaitFor(() => (Object)(object)anchor.Zeppelin != (Object)null, 20f); Check("he takes the plates and builds the hull", anchor.HullDone && anchor.Stage == 1 && (Object)(object)anchor.Zeppelin != (Object)null && hull.All((Items.Need n) => inv.CountItems(n.Name, -1, true) == 0)); ZeppelinFlight zep = anchor.Zeppelin; if ((Object)(object)zep == (Object)null) { yield break; } yield return (object)new WaitForSeconds(1.5f); Check("new hull has no ballistas", Ballistas(zep).All((BallistaMount ballistaMount) => !((Component)ballistaMount).gameObject.activeSelf)); Check("only one tower in the world", TowerAnchor.Instances.Count == 1 && SkidWorld.Tower != null); int num7 = Object.FindObjectsOfType<TreeBase>().Count((TreeBase t) => InFootprint(anchor, ((Component)t).transform.position)); Check("footprint cleared of trees", num7 == 0, $"{num7} left"); yield return WaitFor(() => !anchor.Leveling, 90f); yield return (object)new WaitForSeconds(2f); Vector3 tcen = TowerPrefab.TurretCentre; List<float> list3 = new List<float>(); List<float> list4 = new List<float>(); List<float> list5 = new List<float>(); for (float num8 = -3f; num8 <= 3f; num8 += 1f) { for (float num9 = -3f; num9 <= 3f; num9 += 1f) { if (num8 * num8 + num9 * num9 <= 10.240001f) { list3.Add(Ground(tcen + new Vector3(num8, 0f, num9))); } } } for (float num10 = -10f; num10 <= 10f; num10 += 2.5f) { for (float num11 = -10f; num11 <= 10f; num11 += 2.5f) { if (num10 * num10 + num11 * num11 < 110f) { list4.Add(Ground(new Vector3(num10, 0f, num11))); } } } for (float num12 = 4.5f; num12 <= 8f; num12 += 0.75f) { list5.Add(Ground(tcen + TowerPrefab.DoorDir * num12)); } Note($"ground vs base: turret {list3.Min():F2}..{list3.Max():F2}, tower {list4.Min():F2}..{list4.Max():F2}, door approach {list5.Min():F2}..{list5.Max():F2} (turret floor top {0.5f})"); Check("ground inside the turret is under its floor", list3.Max() <= 0.05f, $"highest {list3.Max():F2} m above the base"); Check("ground under the tower is level with its base", list4.Max() <= 0.05f && list4.Min() > -0.6f, $"{list4.Min():F2}..{list4.Max():F2} m"); float num13 = 0f; List<string> list6 = new List<string>(); for (float num14 = 4.5f; num14 + 1.5f <= anchor.RampEnd; num14 += 1.5f) { float num15 = Ground(tcen + TowerPrefab.DoorDir * num14); float num16 = Ground(tcen + TowerPrefab.DoorDir * (num14 + 1.5f)); num13 = Mathf.Max(num13, Mathf.Atan2(Mathf.Abs(num16 - num15), 1.5f) * 57.29578f); list6.Add($"{num15:F1}"); } Note($"ground beyond the ramp's end ({anchor.RampEnd:F0} m out): " + string.Join(" ", from i in Enumerable.Range(0, 7) select $"{Ground(tcen + TowerPrefab.DoorDir * (anchor.RampEnd + (float)i)):F1}")); Check("the ramp from the door to the land is walkable", num13 < 35f, string.Format("steepest {0:F0}°; heights out from the door: {1}", num13, string.Join(" ", list6))); Check("the door's approach meets the turret floor", list5.Max() <= 0.52f && list5.Min() > -0.3f, $"{list5.Min():F2}..{list5.Max():F2} m"); yield return (object)new WaitForSeconds(5f); float num17 = Vector3.Distance(((Component)zep).transform.position, anchor.World(TowerAnchor.MoorLocal)); Check("moored zeppelin stays put", num17 < 1.5f, $"{num17:F2} m from its mooring"); Check("zeppelin not operational yet", !zep.Operational); Vector3 val4 = ((Component)anchor).transform.position + ((Component)anchor).transform.rotation * new Vector3(55f, 0f, -45f); val4.y = ZoneSystem.instance.GetGroundHeight(val4) + 1f; yield return Tp(player, val4); yield return (object)new WaitForSeconds(2f); Look(player, ((Component)anchor).transform.position + Vector3.up * 30f); yield return (object)new WaitForSeconds(1.5f); yield return Shot("1_tower"); Vector3 c0 = TowerPrefab.TurretCentre; Vector3 val5 = c0 + TowerPrefab.DoorDir * 11f; CamPos = anchor.World(val5 + Vector3.up * 2.2f); CamRot = Quaternion.LookRotation(anchor.World(c0 + Vector3.up * 1.5f) - CamPos.Value); yield return (object)new WaitForSeconds(1f); yield return Shot("stair_door"); Vector3 val6 = TowerPrefab.QuadrantDir(-1); Vector3 normalized = ((Vector3)(ref val6)).normalized; CamPos = anchor.World(c0 + TowerPrefab.DoorDir * 2.6f + Vector3.up * 1.7f); CamRot = Quaternion.LookRotation(anchor.World(c0 + normalized * 1.2f + Vector3.up * 0.6f) - CamPos.Value); yield return (object)new WaitForSeconds(1f); yield return Shot("stair_base"); CamPos = null; List<string> list7 = new List<string>(); for (float num18 = 3f; num18 <= 12f; num18 += 1f) { Vector3 val7 = anchor.World(c0 + TowerPrefab.DoorDir * num18); val7.y = ZoneSystem.instance.GetGroundHeight(val7); Collider[] array = Physics.OverlapCapsule(val7 + Vector3.up * 0.6f, val7 + Vector3.up * 1.7f, 0.4f); foreach (Collider val8 in array) { if ((Object)(object)val8 == (Object)null || val8.isTrigger || (Object)(object)val8.attachedRigidbody == (Object)(object)((Component)player).GetComponent<Rigidbody>() || LayerMask.LayerToName(((Component)val8).gameObject.layer) == "terrain") { continue; } Transform val9 = ((Component)val8).transform; string text = ((Object)val8).name; for (int num20 = 0; num20 < 3; num20++) { if (!((Object)(object)val9.parent != (Object)null)) { break; } val9 = val9.parent; text = ((Object)val9).name + "/" + text; } list7.Add($"{num18:F0}m: {text} ({LayerMask.LayerToName(((Component)val8).gameObject.layer)})"); } } Note("solid things on the door's approach: " + ((list7.Count == 0) ? "none" : string.Join("; ", list7.Distinct()))); yield return Tp(player, anchor.World(c0 + TowerPrefab.DoorDir * 9f + Vector3.up * 1f)); yield return (object)new WaitForSeconds(1.5f); Transform val10 = ((Component)anchor).transform.Find("Geometry"); List<Vector3> list8 = (((Object)(object)val10 == (Object)null) ? new List<Vector3>() : (from l in (from t in ((Component)val10).GetComponentsInChildren<Transform>(true) where ((Object)t).name == "piece_dvergr_spiralstair" select t).Select(delegate(Transform t) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)t).GetComponentsInChildren<Renderer>(true); Bounds val30 = (Bounds)((componentsInChildren.Length != 0) ? componentsInChildren.Select((Renderer r) => r.bounds).Aggregate(delegate(Bounds x, Bounds y) { //IL_0002: 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) ((Bounds)(ref x)).Encapsulate(y); return x; }) : new Bounds(t.position, Vector3.zero)); return ((Component)anchor).transform.InverseTransformPoint(((Bounds)(ref val30)).center); }) orderby l.y select l).ToList()); List<Vector3> route = new List<Vector3> { c0 + TowerPrefab.DoorDir * 7f, c0 + TowerPrefab.DoorDir * 4.6f, c0 + TowerPrefab.DoorDir * 2.4f }; if (list8.Count > 1) { Vector3 val11 = list8[0] - c0; val11.y = 0f; Vector3 val12 = list8[1] - c0; val12.y = 0f; float num21 = Mathf.Sign(TowerPrefab.SpiralDelta); Vector3 val13 = Quaternion.Euler(0f, (0f - num21) * 45f, 0f) * ((Vector3)(ref val11)).normalized; float num22 = Vector3.SignedAngle(TowerPrefab.DoorDir, val13, Vector3.up); for (float num23 = 30f; num23 < Mathf.Abs(num22); num23 += 30f) { route.Add(c0 + Quaternion.Euler(0f, Mathf.Sign(num22) * num23, 0f) * TowerPrefab.DoorDir * 2.2f); } route.Add(c0 + val13 * 1.2f); } int reached = 0; float bestY = -99f; List<string> walkLog = new List<string>(); Note("stair steps (angle°/radius/height from the turret centre): " + string.Join(" ", list8.Take(6).Select(delegate(Vector3 s) { //IL_0005: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_006b: 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_007d: Unknown result type (might be due to invalid IL or missing references) object arg2 = Vector3.SignedAngle(Vector3.forward, new Vector3(s.x - c0.x, 0f, s.z - c0.z), Vector3.up); Vector2 val30 = new Vector2(s.x - c0.x, s.z - c0.z); return $"{arg2:F0}°/{((Vector2)(ref val30)).magnitude:F2}/{s.y:F1}"; }))); foreach (Vector3 wp in route) { bool ok3 = false; yield return WalkTo(player, anchor, wp, 6f, delegate(bool r) { ok3 = r; }); if (!ok3 && reached == 0) { yield return (object)new WaitForSeconds(2f); yield return WalkTo(player, anchor, wp, 8f, delegate(bool r) { ok3 = r; }); } bestY = Mathf.Max(bestY, ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position).y); Vector3 val14 = ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position) - c0; object[] obj = new object[6] { reached, ok3 ? "ok" : "STUCK", Vector3.SignedAngle(Vector3.forward, new Vector3(val14.x, 0f, val14.z), Vector3.up), null, null, null }; val3 = new Vector2(val14.x, val14.z); obj[3] = ((Vector2)(ref val3)).magnitude; obj[4] = val14.y; obj[5] = Vector3.SignedAngle(Vector3.forward, new Vector3(wp.x - c0.x, 0f, wp.z - c0.z), Vector3.up); walkLog.Add(string.Format("{0}:{1} at {2:F0}°/{3:F1}m/y{4:F1} (wp {5:F0}°)", obj)); if (!ok3) { break; } reached++; } if (reached == route.Count) { float spin = Mathf.Sign(TowerPrefab.SpiralDelta); float climbT = 0f; float lastGain = 0f; float lastY = -99f; while (climbT < 60f) { Vector3 val15 = ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position); if (val15.y > 10.5f) { break; } if (val15.y > lastY + 0.3f) { lastY = val15.y; lastGain = climbT; } if (climbT - lastGain > 6f) { Vector3 val16 = val15 - c0; object arg = Vector3.SignedAngle(Vector3.forward, new Vector3(val16.x, 0f, val16.z), Vector3.up); val3 = new Vector2(val16.x, val16.z); walkLog.Add($"climb STUCK at {arg:F0}°/{((Vector2)(ref val3)).magnitude:F1}m/y{val15.y:F1}"); break; } Vector3 val17 = val15 - c0; val17.y = 0f; Vector3 normalized2 = ((Vector3)(ref val17)).normalized; Vector3 val18 = Quaternion.Euler(0f, spin * 90f, 0f) * normalized2 + normalized2 * Mathf.Clamp((1.2f - ((Vector3)(ref val17)).magnitude) * 3f, -1f, 1f); Vector3 val19 = ((Component)anchor).transform.TransformDirection(val18); val19.y = 0f; WalkDir = ((Vector3)(ref val19)).normalized; Look(player, ((Character)player).GetEyePoint() + ((Vector3)(ref val19)).normalized); climbT += Time.deltaTime; yield return null; } WalkDir = null; bestY = Mathf.Max(bestY, ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position).y); walkLog.Add($"climbed to y{((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position).y:F1} in {climbT:F0} s"); reached++; } route.Add(Vector3.zero); float walkedUp = ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position).y; Check("walk in from outside, through the door and onto the stair", reached == route.Count && bestY >= 1.5f, $"{reached}/{route.Count} legs, up to {bestY:F1} m above the base"); Note($"the walking bot's full climb reached {walkedUp:F1} m (the spiral itself is checked step by step below)"); Note("walk: " + string.Join("; ", walkLog) + ((LastWalkState.Length > 0) ? (" | stalled: " + LastWalkState) : "")); if (reached < route.Count || walkedUp <= 9.5f) { yield return Shot("stair_stuck"); Vector3 val20 = ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position) - c0; val20.y = 0f; CamPos = anchor.World(c0 - ((Vector3)(ref val20)).normalized * 3f + Vector3.up * (walkedUp + 1.6f)); CamRot = Quaternion.LookRotation(((Component)player).transform.position + Vector3.up * 0.8f - CamPos.Value); yield return (object)new WaitForSeconds(0.5f); yield return Shot("stair_stuck_view"); CamPos = null; } int bad = 0; int headBumps = 0; List<string> notes = new List<string>(); int solid = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" }); for (int k = 1; k < 40; k += 3) { Vector3 val21 = Quaternion.Euler(0f, TowerPrefab.SpiralStart + (float)k * TowerPrefab.SpiralDelta, 0f) * TowerPrefab.SpiralQuarter; val21.y = 0f; Vector3 wp = c0 + ((Vector3)(ref val21)).normalized * 1.25f + Vector3.up * (0.5f + (float)k + 0.6f); yield return Tp(player, anchor.World(wp + Vector3.up * 0.4f)); yield return (object)new WaitForSeconds(1f); float num24 = ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position).y - wp.y; if (!((Character)player).IsOnGround() || !(Mathf.Abs(num24) < 1.2f)) { bad++; notes.Add(string.Format("step {0}: {1}, {2:F1} m off", k, ((Character)player).IsOnGround() ? "grounded" : "not grounded", num24)); } if (Physics.Raycast(((Component)player).transform.position + Vector3.up * 0.3f, Vector3.up, 2f, solid)) { headBumps++; notes.Add($"step {k}: low ceiling"); } } Check("the spiral stair holds you at every step", bad == 0, (bad == 0) ? $"{40} steps, checked every 3rd" : string.Join("; ", notes)); Check("headroom all the way up the stair", headBumps == 0, string.Join("; ", notes.Where((string n) => n.Contains("ceiling")))); (string, Vector3)[] array2 = new(string, Vector3)[3] { ("top landing", c0 + TowerPrefab.QuadrantDir(40) + Vector3.up * 40.5f), ("bridge to the deck", new Vector3(12f, 40.5f, -10f)), ("deck", new Vector3(5f, 40.5f, -10f)) }; for (int k = 0; k < array2.Length; k++) { var (what, val22) = array2[k]; yield return Tp(player, anchor.World(val22 + Vector3.up * 0.5f)); yield return (object)new WaitForSeconds(2f); float num25 = ((Component)anchor).transform.InverseTransformPoint(((Component)player).transform.position).y - 40.5f; Check("stand on the " + what, ((Character)player).IsOnGround() && Mathf.Abs(num25) < 1f, $"{num25:F1} m from deck height"); } Boarding componentInChildren = ((Component)anchor).GetComponentInChildren<Boarding>(); Check("hook and chain to climb aboard", (Object)(object)componentInChildren != (Object)null && componentInChildren.GetHoverText().Length > 0); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.Interact((Humanoid)(object)player, hold: false, alt: false)) { yield return WaitFor(() => !((Character)player).IsTeleporting(), 20f); yield return (object)new WaitForSeconds(2f); Check("E at the chain puts you aboard", (Object)(object)((Character)player).GetStandingOnShip() == (Object)(object)zep.Ship); yield return Tp(player, anchor.World(new Vector3(5f, 41f, -10f))); } said = IvaldiNpc.Converse(player, anchor, give: false); Note("Ivaldi: " + said); Check("Ivaldi asks for hooks after the hull", anchor.Hooks == 0 && anchor.Stage == 1); AddHooks(inv, 3); IvaldiNpc.Converse(player, anchor, give: false); Check("talking (E) takes nothing", anchor.Hooks == 0 && inv.CountItems(Items.QuestHookName, -1, true) == 3); said = IvaldiNpc.Converse(player, anchor, give: true); Note("Ivaldi: " + said); yield return (object)new WaitForSeconds(1f); Check("he takes 3 hooks", anchor.Hooks == 3 && inv.CountItems(Items.QuestHookName, -1, true) == 0, $"hooks {anchor.Hooks}"); AddHooks(inv, 2); said = IvaldiNpc.Converse(player, anchor, give: true); Note("Ivaldi: " + said); yield return (object)new WaitForSeconds(1f); Check("he takes only the 4th hook", anchor.Hooks == 4 && inv.CountItems(Items.QuestHookName, -1, true) == 1, $"hooks {anchor.Hooks}, left in bag {inv.CountItems(Items.QuestHookName, -1, true)}"); said = IvaldiNpc.Converse(player, anchor, give: true); Note("Ivaldi: " + said); Check("without the stone there's no toxin", !anchor.Toxin && anchor.Stage == 2); yield return (object)new WaitForSeconds(1.5f); Check("hooks fitted: ballistas shown, empty", Ballistas(zep).All((BallistaMount ballistaMount) => ((Component)ballistaMount).gameObject.activeSelf && Armed(ballistaMount) == false), BallistaState(zep)); foreach (Items.Need item2 in toxin) { inv.AddItem(((Object)item2.Item).name, item2.Amount, 1, 0, 0L, "", false, false); } said = IvaldiNpc.Converse(player, anchor, give: true); Note("Ivaldi: " + said); yield return (object)new WaitForSeconds(1f); Check("he takes the toxin: armed", anchor.Toxin && anchor.Armed && anchor.Stage == 3 && toxin.All((Items.Need n) => inv.CountItems(n.Name, -1, true) == 0)); yield return (object)new WaitForSeconds(1.5f); Check("armed: ballistas loaded", Ballistas(zep).All((BallistaMount ballistaMount) => ((Component)ballistaMount).gameObject.activeSelf && Armed(ballistaMount) != false), BallistaState(zep)); anchor.SetStage(0); yield return (object)new WaitForSeconds(2f); Check("skid_stage 0: no ship, nothing delivered", anchor.Stage == 0 && (Object)(object)anchor.Zeppelin == (Object)null && anchor.Hooks == 0 && !anchor.Toxin); anchor.SetStage(3); yield return WaitFor(() => (Object)(object)anchor.Zeppelin != (Object)null, 10f); zep = anchor.Zeppelin; yield return (object)new WaitForSeconds(1.5f); Check("skid_stage 3: ship moored, ballistas loaded", anchor.Stage == 3 && (Object)(object)zep != (Object)null && Ballistas(zep).All((BallistaMount ballistaMount) => ((Component)ballistaMount).gameObject.activeSelf && Armed(ballistaMount) != false), ((Object)(object)zep != (Object)null) ? BallistaState(zep) : "no ship"); if ((Object)(object)zep == (Object)null) { yield break; } yield return (object)new WaitForSeconds(4f); ivaldi.Say(said); Look(player, ((Component)ivaldi).transform.position + Vector3.up * 1.2f); yield return (object)new WaitForSeconds(1f); yield return Shot("2_ivaldi"); Character ic = ((Component)ivaldi).GetComponent<Character>(); float health = ic.GetHealth(); HitData val23 = new HitData(); val23.m_damage.m_blunt = 500f; val23.m_point = ic.GetCenterPoint(); ic.Damage(val23); yield return (object)new WaitForSeconds(1f); Check("Ivaldi can't be hurt", (Object)(object)ic != (Object)null && !ic.IsDead() && ic.GetHealth() >= health, $"health {health:F0} -> {ic.GetHealth():F0}"); int before = anchor.EldersNearby(); Character spawned = anchor.SpawnElder(); yield return (object)new WaitForSeconds(1f); Check("elder gjall spawner works", (Object)(object)spawned != (Object)null && anchor.EldersNearby() == before + 1, ((Object)(object)spawned != (Object)null) ? $"at {Vector3.Distance(((Component)spawned).transform.position, ((Component)anchor).transform.position):F0} m, scale {((Component)spawned).transform.localScale.x:F1}, health {spawned.GetMaxHealth():F0}" : ""); if ((Object)(object)spawned != (Object)null) { ZNetScene.instance.Destroy(((Component)spawned).gameObject); } ZeppelinCapture cap = ((Component)zep).GetComponent<ZeppelinCapture>(); for (int k = 0; k < 2; k++) { string what = ((k == 0) ? "port" : "starboard"); Transform val24 = cap.Harness(k); Vector3 val25 = ((Component)zep).transform.right * ((k == 0) ? (-1f) : 1f); Character elder = anchor.SpawnElder(val24.position + val25 * 12f + Vector3.up * 4f); if (k == 0 && (Object)(object)elder != (Object)null) { Look(player, ((Component)elder).transform.position); yield return (object)new WaitForSeconds(1.2f); yield return Shot("3_capture_port"); } string key = ((k == 0) ? "skid_gjall_p" : "skid_gjall_s"); yield return WaitFor(() => ((Component)zep).GetComponent<ZNetView>().GetZDO().GetBool(key, false), 30f); Check("elder gjall captured on the " + what + " side", ((Component)zep).GetComponent<ZNetView>().GetZDO().GetBool(key, false)); yield return (object)new WaitForSeconds(1f); Check("the live " + what + " gjall is gone", (Object)(object)elder == (Object)null); } Check("zeppelin operational after both captures", zep.Operational && anchor.Stage == 5); yield return WaitFor(() => anchor.Done && TowerAnchor.RecipeUnlocked, 10f); Check("the first ship ends the quest and unlocks the recipe for the world", anchor.Done && TowerAnchor.RecipeUnlocked); said = IvaldiNpc.Converse(player, anchor, give: true); Note("Ivaldi: " + said); Check("afterwards Ivaldi only says farewell", said == Loc.L("$skid_say_farewell")); Check("the ship piece shows on the hammer now", (Object)(object)keelPiece != (Object)null && player.HaveRequirements(keelPiece, (RequirementMode)1)); yield return (object)new WaitForSeconds(1f); Vector3 pos = ((Component)anchor).transform.position + ((Component)anchor).transform.rotation * new Vector3(-60f, 0f, 25f); pos.y = ((Component)anchor).transform.position.y + 40.5f + 5f; yield return Tp(player, pos); Look(player, ((Component)zep).transform.position + Vector3.up * 6f); yield return (object)new WaitForSeconds(0.5f); yield return Shot("4_harnessed"); Ship ship = zep.Ship; Vector3 seat = (((Object)(object)ship.m_shipControlls.m_attachPoint != (Object)null) ? ship.m_shipControlls.m_attachPoint.position : ((Component)ship.m_shipControlls).transform.position); yield return Tp(player, seat + ((Component)zep).transform.forward * 1.5f + Vector3.up * 0.4f); yield return (object)new WaitForSeconds(1f); Check("teleported aboard, standing on the ship", (Object)(object)((Character)player).GetStandingOnShip() == (Object)(object)ship, $"{Vector3.Distance(((Component)player).transform.position, seat):F1} m from the helm"); ship.m_shipControlls.Interact((Humanoid)(object)player, false, false); yield return (object)new WaitForSeconds(1f); Check("player at the helm", (Object)(object)player.GetControlledShip() == (Object)(object)ship); for (int k = 0; k < 3; k++) { ship.Forward(); yield return (object)new WaitForSeconds(0.4f); } Check("speed set to full", (int)ship.GetSpeedSetting() == 4, ((object)ship.GetSpeedSetting()/*cast due to .constrained prefix*/).ToString()); LiftOverride = 1f; Vector3 p0 = ((Component)zep).transform.position; yield return (object)new WaitForSeconds(10f); Look(player, ((Component)zep).transform.position + ((Component)zep).transform.forward * 30f); yield return Shot("5_flying"); yield return (object)new WaitForSeconds(10f); Vector3 position = ((Component)zep).transform.position; LiftOverride = 0f; val3 = new Vector2(position.x - p0.x, position.z - p0.z); float num26 = ((Vector2)(ref val3)).magnitude / 20f; float num27 = position.y - p0.y; Check("flies forward at full speed", num26 > SkidbladnirPlugin.SpeedFull.Value * 0.45f, $"{num26:F1} m/s average over 20 s (full = {SkidbladnirPlugin.SpeedFull.Value})"); Check("climbs with Jump held", num27 > 20f, $"{num27:F1} m in 20 s (climb rate {SkidbladnirPlugin.ClimbSpeed.Value} m/s)"); Check("player still aboard after flying", Vector3.Distance(((Component)player).transform.position, ((Component)zep).transform.position) < 25f); ship.Stop(); yield return (object)new WaitForSeconds(6f); val6 = ((Component)zep).GetComponent<Rigidbody>().linearVelocity; float magnitude = ((Vector3)(ref val6)).magnitude; Check("stops and hovers", magnitude < 2f, $"{magnitude:F1} m/s after 6 s"); LiftOverride = null; ZeppelinBombing bombing = ((Component)zep).GetComponent<ZeppelinBombing>(); Transform obj2 = ((Component)zep).transform.Find(ZeppelinPrefab.BallistaNames[0]); BallistaReapply portBallista = ((obj2 != null) ? ((Component)obj2).GetComponent<BallistaReapply>() : null); Check("ballistas offer 'reapply toxin' when flying", (Object)(object)portBallista != (Object)null && portBallista.GetHoverText().Length > 0, ((Object)(object)portBallista != (Object)null) ? portBallista.GetHoverText().Replace("\n", " | ") : "none"); int drops0 = ZeppelinBombing.DropsDone; int bursts0 = ZeppelinBombing.BurstsDone; int hits0 = ZeppelinBombing.HitsDone; bool ok4 = (Object)(object)portBallista != (Object)null && portBallista.Interact((Humanoid)(object)player, hold: false, alt: false); Check("reapply accepted", ok4); yield return WaitFor(() => ZeppelinBombing.BurstsDone - bursts0 >= SkidbladnirPlugin.BombTicks.Value, 30f); Check("the gjall drops ticks", ZeppelinBombing.DropsDone > drops0); Check("every tick bursts on impact", ZeppelinBombing.BurstsDone - bursts0 >= SkidbladnirPlugin.BombTicks.Value, $"{ZeppelinBombing.BurstsDone - bursts0} bursts, {ZeppelinBombing.HitsDone - hits0} things hit"); Check("the ship took no harm", (Object)(object)zep != (Object)null && ((Component)zep).GetComponent<ZNetView>().IsValid()); Check("a second dose waits for the cooldown", (Object)(object)bombing != (Object)null && bombing.CooldownLeft(0) > 0f && !portBallista.Interact((Humanoid)(object)player, hold: false, alt: false), $"{bombing?.CooldownLeft(0):F0} s left"); if (ship.IsPlayerInBoat(player)) { ship.m_shipControlls.Interact((Humanoid)(object)player, false, false); } ((Character)player).AttachStop(); Vector3 yard = ((Component)anchor).transform.position + ((Component)anchor).transform.rotation * new Vector3(70f, 0f, 60f); yard.y = ZoneSystem.instance.GetGroundHeight(yard); yield return Tp(player, yard + new Vector3(0f, 1f, -30f)); yield return (object)new WaitForSeconds(2f); yard.y = ZoneSystem.instance.GetGroundHeight(yard); int built0 = ZeppelinKeel.Built; int ships0 = ZeppelinFlight.Instances.Count; if ((Object)(object)ZeppelinKeel.Prefab != (Object)null) { Object.Instantiate<GameObject>(ZeppelinKeel.Prefab, yard, Quaternion.identity); } yield return WaitFor(() => ZeppelinKeel.Built > built0, 10f); yield return (object)new WaitForSeconds(1f); ZeppelinFlight second = (from f in ZeppelinFlight.Instances where (Object)(object)f != (Object)null && (Object)(object)f != (Object)(object)zep orderby Vector3.Distance(((Component)f).transform.position, yard) select f).FirstOrDefault(); Vector3 val26 = (((Object)(object)second != (Object)null) ? (((Component)second).transform.position - yard) : Vector3.zero); AutoTest autoTest4 = this; int ok5; if (ZeppelinKeel.Built > built0 && (Object)(object)second != (Object)null) { val3 = new Vector2(val26.x, val26.z); if (((Vector2)(ref val3)).magnitude < 15f && val26.y > -2f) { ok5 = ((val26.y < 90f) ? 1 : 0); goto IL_4534; } } ok5 = 0; goto IL_4534; IL_4534: object detail3; if (!((Object)(object)second != (Object)null)) { detail3 = "none"; } else { object[] array3 = new object[4]; val3 = new Vector2(val26.x, val26.z); array3[0] = ((Vector2)(ref val3)).magnitude; array3[1] = val26.y; array3[2] = ships0; array3[3] = ZeppelinFlight.Instances.Count; detail3 = string.Format("{0:F1} m across and {1:F1} m above the frame (risen clear of the trees); ships {2} -> {3}", array3); } autoTest4.Check("a placed frame becomes a new Skidbladnir", (byte)ok5 != 0, (string)detail3); Check("the frame is gone", Object.FindObjectsOfType<ZeppelinKeel>().All((ZeppelinKeel zeppelinKeel) => (Object)(object)((Component)zeppelinKeel).GetComponent<ZNetView>() == (Object)null || !((Component)zeppelinKeel).GetComponent<ZNetView>().IsValid())); if ((Object)(object)second == (Object)null) { yield break; } Check("the new ship is flight-ready and its own", second.Operational && (Object)(object)zep != (Object)null && zep.Operational && ((Component)second).GetComponent<ZNetView>().GetZDO() != ((Component)zep).GetComponent<ZNetView>().GetZDO() && ((Component)second).GetComponent<ZNetView>().GetZDO().GetVec3("skid_moor_pos", Vector3.zero) == Vector3.zero); Look(player, ((Component)second).transform.position + Vector3.up * 4f); yield return (object)new WaitForSeconds(1f); yield return Shot("6_second_ship"); Ship ship2 = second.Ship; Vector3 val27 = (((Object)(object)ship2.m_shipControlls.m_attachPoint != (Object)null) ? ship2.m_shipControlls.m_attachPoint.position : ((Component)ship2.m_shipControlls).transform.position); yield return Tp(player, val27 + ((Component)second).transform.forward * 1.5f + Vector3.up * 0.4f); yield return (object)new WaitForSeconds(1f); Check("standing on the second ship", (Object)(object)((Character)player).GetStandingOnShip() == (Object)(object)ship2, "standing on " + (((Object)(object)((Character)player).GetStandingOnShip() == (Object)null) ? "nothing" : (((Object)(object)((Character)player).GetStandingOnShip() == (Object)(object)ship) ? "the first ship" : "?"))); ship2.m_shipControlls.Interact((Humanoid)(object)player, false, false); yield return (object)new WaitForSeconds(1f); Check("at the second ship's helm", (Object)(object)player.GetControlledShip() == (Object)(object)ship2); for (int k = 0; k < 3; k++) { ship2.Forward(); yield return (object)new WaitForSeconds(0.4f); } Rigidbody component2 = ((Component)second).GetComponent<Rigidbody>(); Note($"second ship: owner {((Component)second).GetComponent<ZNetView>().IsOwner()}, speed {ship2.GetSpeedSetting()}, aboard {ship2.IsPlayerInBoat(player)}, " + $"kinematic {((component2 != null) ? new bool?(component2.isKinematic) : ((bool?)null))}, sleeping {((component2 != null) ? new bool?(component2.IsSleeping()) : ((bool?)null))}, at {((Component)second).transform.position}"); LiftOverride = 1f; Vector3 q0 = ((Component)second).transform.position; Vector3 first0 = ((Component)zep).transform.position; yield return (object)new WaitForSeconds(12f); Vector3 position2 = ((Component)second).transform.position; LiftOverride = null; val3 = new Vector2(position2.x - q0.x, position2.z - q0.z); float num28 = ((Vector2)(ref val3)).magnitude / 12f; Check("the second ship flies", num28 > SkidbladnirPlugin.SpeedFull.Value * 0.35f && position2.y - q0.y > 8f, $"{num28:F1} m/s, climbed {position2.y - q0.y:F1} m in 12 s"); Vector3 val28 = ((Component)second).transform.TransformPoint(second.HullCenter); IEnumerable<string> values = (from h in Physics.OverlapBox(val28, second.HullExtents + Vector3.one * 0.5f, ((Component)second).transform.rotation) where (Object)(object)h != (Object)null && !h.isTrigger && !((Component)h).transform.IsChildOf(((Component)second).transform) && (Object)(object)h.attachedRigidbody != (Object)(object)((Component)player).GetComponent<Rigidbody>() select h).Select(delegate(Collider h) { ZNetView componentInParent = ((Component)h).GetComponentInParent<ZNetView>(); return (((componentInParent != null) ? ((Object)componentInParent).name : null) ?? ((Object)h).name) + "/" + LayerMask.LayerToName(((Component)h).gameObject.layer); }).Distinct().Take(12); Note("second ship hull touches: " + string.Join(", ", values) + $"; ground {ZoneSystem.instance.GetGroundHeight(val28):F1}, hull centre {val28.y:F1}"); Check("the first ship stays where it was left", (Object)(object)zep != (Object)null && Vector3.Distance(((Component)zep).transform.position, first0) < 3f, ((Object)(object)zep != (Object)null) ? $"{Vector3.Distance(((Component)zep).transform.position, first0):F1} m" : "gone"); ship2.Stop(); if (ship2.IsPlayerInBoat(player)) { ship2.m_shipControlls.Interact((Humanoid)(object)player, false, false); } ((Character)player).AttachStop(); Vector3 val29 = A0(anchor) + ((Component)anchor).transform.rotation * new Vector3(-70f, 0f, -60f); val29.y = ZoneSystem.instance.GetGroundHeight(val29) + 1f; yield return Tp(player, val29); yield return (object)new WaitForSeconds(1f); FieldInfo ghostField = AccessTools.Field(typeof(Player), "m_placementGhost"); object oldGhost = ghostField.GetValue(player); ghostField.SetValue(player, ZeppelinKeel.Prefab); CamPos = ((Character)player).GetEyePoint(); CamRot = Quaternion.LookRotation(((Component)player).transform.forward.Flat() + Vector3.up * 1.2f); yield return null; yield return null; object[] array4 = new object[6] { Vector3.zero, Vector3.zero, null, null, null, false }; bool flag3 = (bool)AccessTools.Method(typeof(Player), "PieceRayTest", (Type[])null, (Type[])null).Invoke(player, array4); ghostField.SetValue(player, oldGhost); CamPos = null; Vector3 airPoint = (Vector3)array4[0]; float num29 = airPoint.y - ZoneSystem.instance.GetGroundHeight(airPoint); Check("aiming at the sky with the ship frame gives a spot in the air", flag3 && num29 > 8f, $"{num29:F1} m above the ground, {Vector3.Distance(((Character)player).GetEyePoint(), airPoint):F1} m out"); if (flag3 && (Object)(object)ZeppelinKeel.Prefab != (Object)null) { int b0 = ZeppelinKeel.Built; Object.Instantiate<GameObject>(ZeppelinKeel.Prefab, airPoint, Quaternion.LookRotation(((Component)player).transform.forward.Flat())); yield return WaitFor(() => ZeppelinKeel.Built > b0, 10f); yield return (object)new WaitForSeconds(1f); ZeppelinFlight zeppelinFlight = (from f in ZeppelinFlight.Instances where (Object)(object)f != (Object)null orderby Vector3.Distance(((Component)f).transform.position, airPoint) select f).FirstOrDefault(); float num30 = (((Object)(object)zeppelinFlight != (Object)null) ? (((Component)zeppelinFlight).transform.position.y - ZoneSystem.instance.GetGroundHeight(((Component)zeppelinFlight).transform.position)) : 0f); Check("a frame placed in the air makes a ship up there", (Object)(object)zeppelinFlight != (Object)null && zeppelinFlight.Operational && Vector3.Distance(((Component)zeppelinFlight).transform.position, airPoint) < 12f && num30 > 6f, ((Object)(object)zeppelinFlight != (Object)null) ? $"{Vector3.Distance(((Component)zeppelinFlight).transform.position, airPoint):F1} m from the frame, {num30:F1} m above the ground" : "none"); } float Ground(Vector3 local) { //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_0021: Unknown result type (might be due to invalid IL or missing references) return ZoneSystem.instance.GetGroundHeight(anchor.World(local)) - ((Component)anchor).transform.position.y; } } private static Vector3 A0(TowerAnchor a) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((Component)a).transform.position; } private static IEnumerator WalkTo(Player p, TowerAnchor a, Vector3 local, float timeout, Action<bool> done) { //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) Vector3 target = a.World(local); float t = 0f; bool ok = false; while (t < timeout) { Vector3 val = target - ((Component)p).transform.position; val.y = 0f; if (((Vector3)(ref val)).magnitude < 0.4f) { ok = true; break; } WalkDir = ((Vector3)(ref val)).normalized; Look(p, ((Character)p).GetEyePoint() + ((Vector3)(ref val)).normalized); t += Time.deltaTime; yield return null; } WalkDir = null; if (!ok) { object value = AccessTools.Field(typeof(Character), "m_moveDir").GetValue(p); object[] obj = new object[8] { ((Character)p).IsOnGround(), null, null, null, null, null, null, null }; Vector3 velocity = ((Character)p).GetVelocity(); obj[1] = ((Vector3)(ref velocity)).magnitude; obj[2] = value; obj[3] = ((Character)p).IsAttached(); obj[4] = ((Character)p).IsTeleporting(); obj[5] = ((Character)p).IsEncumbered(); obj[6] = ((Character)p).IsDead(); obj[7] = ((Character)p).InWater(); LastWalkState = string.Format("onGround {0}, vel {1:F1}, moveDir {2}, attached {3}, teleporting {4}, encumbered {5}, dead {6}, inWater {7}", obj); } done(ok); } private static BallistaMount[] Ballistas(ZeppelinFlight zep) { return ((Component)zep).GetComponentsInChildren<BallistaMount>(true); } private static bool? Armed(BallistaMount b) { if (!((Object)(object)b.Armed != (Object)null)) { if (!((Object)(object)b.Unarmed != (Object)null)) { return null; } return !b.Unarmed.activeSelf; } return b.Armed.activeSelf; } private static string BallistaState(ZeppelinFlight zep) { return string.Join(", ", from b in Ballistas(zep) select ((Object)b).name + ": " + (((Component)b).gameObject.activeSelf ? "shown" : "hidden") + "/" + ((!Armed(b).HasValue) ? "?" : ((Armed(b) == true) ? "loaded" : "empty"))); } private static void AddHooks(Inventory inv, int n) { for (int i = 0; i < n; i++) { inv.AddItem(Items.QuestHookPrefab, 1, 1, 0, 0L, "", false, false); } } private static bool InFootprint(TowerAnchor a, Vector3 p) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_000d: 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) Vector3 val = ((Component)a).transform.InverseTransformPoint(p); if (Mathf.Abs(val.x) < 10f) { return Mathf.Abs(val.z) < 18f; } return false; } private IEnumerator IvaldiTour(Player player) { yield return WaitFor(() => SkidWorld.SitesReady, 300f); if (SkidWorld.Sites.Count == 0) { Check("tower sites", ok: false); yield break; } Vector3 val = SkidWorld.Sites.OrderByDescending(MistShare).First(); yield return Tp(player, val + new Vector3(0f, 5f, -40f), distant: true); yield return WaitFor(() => TowerAnchor.Instances.Count > 0 && TowerAnchor.Instances[0].Built, 90f); TowerAnchor anchor = TowerAnchor.Instances.FirstOrDefault(); Check("tower raised and built", (Object)(object)anchor != (Object)null && anchor.Built); if ((Object)(object)anchor == (Object)null) { yield break; } anchor.SetStage(3); yield return WaitFor(() => (Object)(object)anchor.Zeppelin != (Object)null && Object.FindObjectsOfType<IvaldiNpc>().Length != 0, 30f); IvaldiNpc iv = Object.FindObjectsOfType<IvaldiNpc>().FirstOrDefault(); Check("ship moored, Ivaldi on the deck", (Object)(object)anchor.Zeppelin != (Object)null && (Object)(object)iv != (Object)null); if ((Object)(object)iv == (Object)null) { yield break; } float deck = 40.5f; yield return Tp(player, anchor.World(new Vector3(-6f, deck + 0.5f, -14f))); yield return (object)new WaitForSeconds(3f); try { File.WriteAllText(Path.Combine(_shotDir, "dverger.txt"), DumpDverger(((Component)iv).gameObject)); Note("dverger.txt written"); } catch (Exception ex) { Note("dump failed: " + ex); } EnvMan env = EnvMan.instance; env.m_debugEnv = "Clear"; env.m_debugTimeOfDay = true; if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.m_userHidden = true; } GameObject visual = Traverse.Create((object)player).Field("m_visual").GetValue<GameObject>(); if ((Object)(object)visual != (Object)null) { visual.SetActive(false); } Vector3 home = anchor.World(TowerPrefab.IvaldiHome); Vector3 face = ((Component)anchor).transform.rotation * Vector3.back; (string name, float angle, float dist, float camH, float atH)[] views = new(string, float, float, float, float)[3] { ("front", 0f, 1.9f, 1f, 0.9f), ("threequarter", 40f, 1.9f, 1.05f, 0.9f), ("side", 90f, 1.9f, 1f, 0.9f) }; List<(float t, Vector3 dir)> suns = new List<(float, Vector3)>(); for (float t = 0.33f; t <= 0.671f; t += 0.02f) { env.m_debugTime = t; yield return null; yield return null; Vector3 val2 = (((Object)(object)env.m_dirLight != (Object)null) ? ((Component)env.m_dirLight).transform.forward : Vector3.down); float num = Mathf.Asin(Mathf.Clamp(0f - val2.y, -1f, 1f)) * 57.29578f; if (num >= 15f && num <= 40f) { suns.Add((t, val2)); } } if (suns.Count == 0) { suns.Add((0.38f, Vector3.down)); } int mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" }); float ss = IvaldiLook.Scale; float bestT = suns[0].t; float num2 = float.MinValue; Vector3 val3 = face; Vector3 val5; foreach (var item3 in suns) { float item = item3.t; Vector3 item2 = item3.dir; for (int num3 = -90; num3 <= 90; num3 += 15) { Vector3 val4 = Quaternion.AngleAxis((float)num3, Vector3.up) * face; val5 = new Vector3(item2.x, 0f, item2.z); float num4 = Vector3.Dot(((Vector3)(ref val5)).normalized, -val4) - (float)Mathf.Abs(num3) / 1800f; if (num4 > num2 && Clear(val4)) { num2 = num4; bestT = item; val3 = val4; } } } env.m_debugTime = bestT; face = val3; yield return null; Vector3 val6 = (((Object)(object)env.m_dirLight != (Object)null) ? ((Component)env.m_dirLight).transform.forward : Vector3.down); AutoTest autoTest = this; string text = $"photo light: time {bestT:F2}, sun {Mathf.Asin(Mathf.Clamp(0f - val6.y, -1f, 1f)) * 57.29578f:F0}° up, "; val5 = new Vector3(val6.x, 0f, val6.z); autoTest.Note(text + $"{Vector3.Dot(((Vector3)(ref val5)).normalized, -face):F2} onto his front, turned {Vector3.SignedAngle(((Component)anchor).transform.rotation * Vector3.back, face, Vector3.up):F0}° from the deck's line"); IvaldiPose = face; IvaldiLook.LookOverride = true; Rigidbody component = ((Component)iv).GetComponent<Rigidbody>(); ((Component)iv).transform.position = home; if ((Object)(object)component != (Object)null) { component.position = home; component.linearVelocity = Vector3.zero; } ((Component)iv).transform.rotation = Quaternion.LookRotation(face); yield return (object)new WaitForSeconds(4f); IvaldiLook look = ((Component)iv).GetComponent<IvaldiLook>(); float s = (((Object)(object)look != (Object)null) ? look.CurrentScale : 1f); Character component2 = ((Component)iv).GetComponent<Character>(); float num5 = ((Component)anchor).transform.InverseTransformPoint(((Component)iv).transform.position).y - deck; Check("Ivaldi at his size, standing on the deck", Mathf.Abs(s - IvaldiLook.Scale) < 0.01f && component2.IsOnGround() && Mathf.Abs(num5) < 0.5f, string.Format("scale {0:F2}, {1:F2} m from deck height, {2}", s, num5, component2.IsOnGround() ? "grounded" : "not grounded")); Check("he holds the hammer (equipped, scaled)", (Object)(object)look != (Object)null && (Object)(object)look.HammerInstance != (Object)null, IvaldiLook.HammerReport); bool free; string text2 = Clearance(iv, anchor, out free); Note(text2); Check("Ivaldi clears the ship and the tower wherever he wanders", free, text2); if (IvaldiPoseRef) { yield return PoseCompare(player, visual, iv, look, home, face, s); } IvaldiLook.HeadOverride = "Hood"; yield return (object)new WaitForSeconds(2f); Note("grip: " + IvaldiLook.GripBones + "; " + IvaldiLook.HammerReport); (string name, float angle, float up, float dist)[] array = new(string, float, float, float)[6] { ("hand_side", 90f, 0.05f, 0.5f), ("hand_front", 15f, 0.05f, 0.5f), ("hand_threequarter", 50f, 0.12f, 0.5f), ("hand_below", 70f, -0.35f, 0.45f), ("hand_behind", 140f, 0.05f, 0.5f), ("hand_above", 60f, 0.4f, 0.4f) }; for (int num6 = 0; num6 < array.Length; num6++) { (string name, float angle, float up, float dist) v = array[num6]; Vector3 val7 = (((Object)(object)look != (Object)null && look.FistCentre.HasValue) ? look.FistCentre.Value : (((Component)iv).transform.position + Vector3.up * 0.6f * s)); Vector3 val8 = Quaternion.AngleAxis(v.angle, Vector3.up) * face; CamPos = val7 + val8 * v.dist * s + Vector3.up * v.up * s; CamRot = Quaternion.LookRotation(val7 - CamPos.Value); yield return (object)new WaitForSeconds(1.5f); yield return Shot(v.name); } if (IvaldiSweep && !IvaldiPoseRef && (Object)(object)look != (Object)null) { bestT = SkidbladnirPlugin.IvaldiHammerThickness.Value; float t = IvaldiLook.FingerCurl; Vector2 shift0 = IvaldiLook.GripShift; (float, float, Vector2)[] sweepCases = SweepCases; for (int num6 = 0; num6 < sweepCases.Length; num6++) { var (num7, num8, val9) = sweepCases[num6]; SkidbladnirPlugin.IvaldiHammerThickness.Value = num7; IvaldiLook.FingerCurl = num8; IvaldiLook.GripShift = val9; string tag = $"sweep_t{num7 * 10f:F0}_c{num8:F0}_k{val9.x:F0}_f{val9.y:F0}"; yield return (object)new WaitForSeconds(0.5f); array = new(string, float, float, float)[5] { ("front", 15f, 0.05f, 0.45f), ("threequarter", 50f, 0.12f, 0.45f), ("side", 90f, 0.05f, 0.45f), ("below", 70f, -0.3f, 0.4f), ("body", 90f, 0.4f, 1.9f) }; for (int num9 = 0; num9 < array.Length; num9++) { (string name, float angle, float up, float dist) v = array[num9]; Vector3 val10 = (Vector3)(((??)look.FistCentre) ?? (((Component)iv).transform.position + Vector3.up * 0.6f * s)); Vector3 val11 = ((v.name == "body") ? (((Component)iv).transform.position + Vector3.up * 0.9f * s) : val10); CamPos = ((v.name == "body") ? ((Component)iv).transform.position : val10) + Quaternion.AngleAxis(v.angle, Vector3.up) * face * v.dist * s + Vector3.up * v.up * s; CamRot = Quaternion.LookRotation(val11 - CamPos.Value); yield return (object)new WaitForSeconds(1f); yield return Shot(tag + "_" + v.name); } } SkidbladnirPlugin.IvaldiHammerThickness.Value = bestT; IvaldiLook.FingerCurl = t; IvaldiLook.GripShift = shift0; yield return (object)new WaitForSeconds(0.5f); } string[] array2 = ((!IvaldiHands) ? new string[3] { "Bare", "Hood", "Circlet" } : new string[1] { "Hood" }); for (int num6 = 0; num6 < array2.Length; num6++) { string tag = (IvaldiLook.HeadOverride = array2[num6]); yield return (object)new WaitForSeconds(2f); Note(tag + ": " + IvaldiLook.Report); (string name, float angle, float dist, float camH, float atH)[] array3 = views; for (int num9 = 0; num9 < array3.Length; num9++) { (string name, float angle, float dist, float camH, float atH) v2 = array3[num9]; Vector3 position = ((Component)iv).transform.position; Vector3 val12 = Quaternion.AngleAxis(v2.angle, Vector3.up) * face; CamPos = position + val12 * v2.dist * s + Vector3.up * v2.camH * s; CamRot = Quaternion.LookRotation(position + Vector3.up * v2.atH * s - CamPos.Value); yield return (object)new WaitForSeconds(2f); yield return Shot(tag.ToLowerInvariant() + "_" + v2.name); } } array2 = new string[3] { "Bare", "Hood", "Circlet" }; for (int num6 = 0; num6 < array2.Length; num6++) { string tag = (IvaldiLook.HeadOverride = array2[num6]); yield return (object)new WaitForSeconds(1.5f); Vector3 position2 = ((Component)iv).transform.position; CamPos = position2 + Quaternion.AngleAxis(30f, Vector3.up) * face * 1.4f * s + Vector3.up * 1.35f * s; CamRot = Quaternion.LookRotation(position2 + Vector3.up * 1.15f * s - CamPos.Value); yield return (object)new WaitForSeconds(1.5f); yield return Shot(tag.ToLowerInvariant() + "_head"); } IvaldiLook.HeadOverride = null; bool[] array4 = (IvaldiHands ? new bool[1] : new bool[2] { false, true }); foreach (bool back in array4) { IvaldiLook.BackToolOverride = back; yield return (object)new WaitForSeconds(2f); Vector3 position3 = ((Component)iv).transform.position; CamPos = position3 + Quaternion.AngleAxis(150f, Vector3.up) * face * 1.9f * s + Vector3.up * 1.1f * s; CamRot = Quaternion.LookRotation(position3 + Vector3.up * 0.9f * s - CamPos.Value); yield return (object)new WaitForSeconds(2f); yield return Shot(back ? "default_back_pickaxe" : "default_back"); } IvaldiLook.BackToolOverride = null; yield return (object)new WaitForSeconds(1f); Vector3 position4 = ((Component)iv).transform.position; CamPos = position4 + Quaternion.AngleAxis(25f, Vector3.up) * face * 1.1f * s + Vector3.up * 1.25f * s; CamRot = Quaternion.LookRotation(position4 + Vector3.up * 1.05f * s - CamPos.Value); yield return (object)new WaitForSeconds(2f); yield return Shot("default_close"); CamPos = anchor.World(new Vector3(2f, deck + 2.4f, -21f)); CamRot = Quaternion.LookRotation(anchor.World(new Vector3(6.5f, deck + 2.4f, -8f)) - CamPos.Value); yield return (object)new WaitForSeconds(3f); yield return Shot("default_ship_wide"); Note("default: " + IvaldiLook.Report); CamPos = null; IvaldiPose = null; IvaldiLook.LookOverride = null; IvaldiLook.ScaleOverride = null; bool Clear(Vector3 f) { //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) return views.Concat<(string, float, float, float, float)>(new(string, float, float, float, float)[1] { ("back", 150f, 1.9f, 1.1f, 0.9f) }).All(delegate((string, float, float, float, float) tuple2) { //IL_000b: 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_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_0026: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0056: 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_006b: 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_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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) Vector3 val13 = home + Quaternion.AngleAxis(tuple2.Item2, Vector3.up) * f * tuple2.Item3 * ss + Vector3.up * tuple2.Item4 * ss; return !Physics.Linecast(home + Vector3.up * tuple2.Item5 * ss, val13, mask) && !Physics.CheckSphere(val13, 0.3f, mask); }); } } private IEnumerator PoseCompare(Player player, GameObject visual, IvaldiNpc iv, IvaldiLook look, Vector3 home, Vector3 face, float s) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) string[] array = new string[4] { "SledgeDemolisher", "Hammer", "MaceIron", "MaceSilver" }; foreach (string text in array) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val != (Object)null) { Note($"{text}: type {val.m_itemData.m_shared.m_itemType}, skill {val.m_itemData.m_shared.m_skillType}, animation {val.m_itemData.m_shared.m_animationState}"); } } Vector3 start = ((Component)player).transform.position; Rigidbody pbody = ((Component)player).GetComponent<Rigidbody>(); int mask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "vehicle" }); if ((Object)(object)visual != (Object)null) { visual.SetActive(true); } (string name, float angle)[] views = new(string, float)[3] { ("front", 0f), ("side", 90f), ("threequarter", 40f) }; string[] array2 = new string[2] { "Hammer", "MaceIron" }; foreach (string itemName in array2) { GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(itemName); if ((Object)(object)itemPrefab2 == (Object)null) { Note(itemName + " not found"); continue; } ItemData item = itemPrefab2.GetComponent<ItemDrop>().m_itemData.Clone(); item.m_dropPrefab = itemPrefab2; item.m_stack = 1; item.m_durability = item.GetMaxDurability(); ((Humanoid)player).GetInventory().AddItem(item); ((Humanoid)player).EquipItem(item, false); string tag = itemName.ToLowerInvariant(); (string name, float angle)[] array3 = views; for (int k = 0; k < array3.Length; k++) { (string name, float angle) v = array3[k]; var (pos, dist) = Beside(v.angle, 3.6f); Place(pos); yield return (object)new WaitForSeconds(2.5f); Vector3 dir = Quaternion.AngleAxis(v.angle, Vector3.up) * face; CamPos = pos + dir * Mathf.Min(2.2f, dist) + Vector3.up * 1.1f; CamRot = Quaternion.LookRotation(pos + Vector3.up * 0.95f - CamPos.Value); Place(pos); yield return (object)new WaitForSeconds(1f); yield return Shot("ref_player_" + tag + "_" + v.name); if (v.name == "front") { Note($"player at rest with {itemName} (facing {Vector3.Angle(((Component)player).transform.forward, face):F0}° off his line): " + MeasurePlayer(player)); Transform val2 = PlayerBone(player, "RightHand"); if ((Object)(object)val2 != (Object)null) { CamPos = val2.position + (((Component)player).transform.right * 0.8f + ((Component)player).transform.forward * 0.3f) + Vector3.up * 0.1f; CamRot = Quaternion.LookRotation(val2.position - CamPos.Value); yield return (object)new WaitForSeconds(1f); yield return Shot("ref_player_" + tag + "_hand"); } } if (!(itemName != "MaceIron")) { Vector3 val3 = (home + pos) * 0.5f; Place(pos); CamPos = val3 + dir * dist + Vector3.up * 1.1f; CamRot = Quaternion.LookRotation(val3 + Vector3.up * 0.85f - CamPos.Value); yield return (object)new WaitForSeconds(1f); yield return Shot("compare_" + v.name); if (v.name == "front") { Note($"player facing {Vector3.Angle(((Component)player).transform.forward, face):F0}° off his line in compare_front"); } } } ((Humanoid)player).UnequipItem(item, false); ((Humanoid)player).GetInventory().RemoveItem(item); } Note("Ivaldi at rest: " + MeasureIvaldi(iv, look)); Transform[] bones = ((Component)iv).GetComponent<VisEquipment>().m_bodyModel.bones; AutoTest autoTest = this; Transform transform = ((Component)iv).transform; Transform upper = B("l.upperarm"); Transform fore = B("l.lowerarm"); Transform hand = B("l.hand"); Transform obj = B("l.hand"); autoTest.Note("Ivaldi's left arm (mirror source): " + Measure(transform, upper, fore, hand, (obj != null) ? obj.Find("l.middle1") : null, B("hip"), B("head"), null, Vector3.zero)); Note("arm: " + IvaldiLook.ArmBones); Place(start); if ((Object)(object)visual != (Object)null) { visual.SetActive(false); } yield return (object)new WaitForSeconds(1f); if (!IvaldiSweep) { yield break; } float back0 = IvaldiLook.ArmBack; float in0 = IvaldiLook.ArmIn; float drop0 = IvaldiLook.ForeDrop; Vector3 hang0 = IvaldiLook.HammerHang; (float, float, float)[] array4 = new(float, float, float)[5] { (40f, 0f, 0f), (40f, 12f, 0f), (40f, 24f, 0f), (40f, 12f, 0.4f), (40f, 24f, 0.4f) }; for (int j = 0; j < array4.Length; j++) { (float, float, float) tuple2 = array4[j]; float item2 = tuple2.Item1; float item3 = tuple2.Item2; float item4 = tuple2.Item3; IvaldiLook.ArmBack = item2; IvaldiLook.ArmIn = item3; IvaldiLook.ForeDrop = item4; _ = IvaldiLook.HammerHang; string itemName = $"pose_b{item2:F0}_i{item3:F0}_d{item4 * 10f:F0}"; yield return (object)new WaitForSeconds(0.5f); (string name, float angle)[] array3 = new(string, float)[3] { ("front", 0f), ("side", 90f), ("threequarter", 40f) }; for (int k = 0; k < array3.Length; k++) { (string, float) tuple3 = array3[k]; string tag = tuple3.Item1; float item5 = tuple3.Item2; Vector3 position = ((Component)iv).transform.position; CamPos = position + Quaternion.AngleAxis(item5, Vector3.up) * face * 1.9f * s + Vector3.up * 1f * s; CamRot = Quaternion.LookRotation(position + Vector3.up * 0.8f * s - CamPos.Value); yield return (object)new WaitForSeconds(1f); yield return Shot(itemName + "_" + tag); } Note(itemName + ": " + MeasureIvaldi(iv, look)); } IvaldiLook.ArmBack = back0; IvaldiLook.ArmIn = in0; IvaldiLook.ForeDrop = drop0; IvaldiLook.HammerHang = hang0; yield return (object)new WaitForSeconds(0.5f); Transform B(string n) { return ((IEnumerable<Transform>)bones).FirstOrDefault((Func<Transform, bool>)((Transform b) => (Object)(object)b != (Object)null && ((Object)b).name == n)); } (Vector3 pos, float dist) Beside(float angle, float want) { //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_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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_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_0134: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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) //IL_00e3: 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_0119: Unknown result type (might be due to invalid IL or missing references) Vector3 val4 = Quaternion.AngleAxis(angle, Vector3.up) * face; Vector3 val5 = Vector3.Cross(Vector3.up, val4); Vector3 normalized = ((Vector3)(ref val5)).normalized; float[] array5 = new float[2] { 1f, -1f }; RaycastHit val7 = default(RaycastHit); foreach (float num in array5) { Vector3 val6 = home + normalized * num * 1.35f; if (!Physics.CheckCapsule(val6 + Vector3.up * 0.55f, val6 + Vector3.up * 1.5f, 0.4f, mask)) { float item6 = (Physics.Raycast((home + val6) * 0.5f + Vector3.up * 0.9f, val4 + Vector3.up * 0.06f, ref val7, want, mask) ? Mathf.Max(((RaycastHit)(ref val7)).distance - 0.3f, 1.5f) : want); return (pos: val6, dist: item6); } } return (pos: home - face * 1.35f, dist: want); } void Place(Vector3 val4) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) ((Component)player).transform.SetPositionAndRotation(val4, Quaternion.LookRotation(face)); if ((Object)(object)pbody != (Object)null) { pbody.position = val4; pbody.rotation = Quaternion.LookRotation(face); pbody.linearVelocity = Vector3.zero; } ((Character)player).SetLookDir(face, 0f); if (LookYaw != null && LookYaw.FieldType == typeof(Quaternion)) { LookYaw.SetValue(player, Quaternion.LookRotation(face)); } } } private static Transform PlayerBone(Player p, string name) { return ((IEnumerable<Transform>)((Component)p).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == name && !((Component)t).GetComponentsInParent<Transform>(true).Any((Transform a) => ((Object)a).name.StartsWith("attach_skin")))); } private static string MeasurePlayer(Player p) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) VisEquipment component = ((Component)p).GetComponent<VisEquipment>(); GameObject val = (GameObject)(((Object)(object)component != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); List<string> list = new string[6] { "RightArm", "RightForeArm", "RightHand", "RightHandMiddle1", "Hips", "Head" }.Where((string n) => (Object)(object)PlayerBone(p, n) == (Object)null).ToList(); Transform val2 = PlayerBone(p, "RightHand"); if ((Object)(object)val2 != (Object)null) { SkidbladnirPlugin.Log.LogInfo((object)($"player hand bone {BonePath(val2, ((Component)p).transform)} at {((Component)p).transform.InverseTransformPoint