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 Norse Sense v0.13.0
NorseSense.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [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: AssemblyCompany("NorseSense")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.13.0.0")] [assembly: AssemblyInformationalVersion("0.13.0+f84dd43f9f0873a92b7ecad47b73b6cb596cde0d")] [assembly: AssemblyProduct("NorseSense")] [assembly: AssemblyTitle("NorseSense")] [assembly: AssemblyVersion("0.13.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 NorseSense { internal class AreaTools : MonoBehaviour { internal enum Kind { None, Plant, Terrain } private const float ValidateInterval = 0.1f; private const float ScrollCooldown = 0.08f; private const float TileSpacing = 1f; private static readonly int[,] PlantShapes = new int[5, 2] { { 1, 1 }, { 1, 3 }, { 1, 5 }, { 3, 3 }, { 5, 5 } }; private static readonly int[,] TerrainShapes = new int[5, 2] { { 1, 1 }, { 1, 3 }, { 2, 2 }, { 3, 3 }, { 4, 4 } }; private static readonly FieldRef<Player, GameObject> PlacementGhost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost"); private static readonly FieldRef<Player, PieceTable> BuildPieces = AccessTools.FieldRefAccess<Player, PieceTable>("m_buildPieces"); private static readonly FieldRef<Player, int> BuildRemoveDebt = AccessTools.FieldRefAccess<Player, int>("m_buildRemoveDebt"); private static readonly Func<Player, float> GetBuildStamina = AccessTools.MethodDelegate<Func<Player, float>>(AccessTools.Method(typeof(Player), "GetBuildStamina", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Player, ItemData, float> GetPlaceDurability = AccessTools.MethodDelegate<Func<Player, ItemData, float>>(AccessTools.Method(typeof(Player), "GetPlaceDurability", (Type[])null, (Type[])null), (object)null, true); private static readonly Color GoodColor = new Color(0.45f, 1f, 0.45f, 0.9f); private static readonly Color BadColor = new Color(1f, 0.3f, 0.2f, 0.9f); private static readonly Color AreaColor = new Color(1f, 0.85f, 0.4f, 0.9f); private static int _plantShape; private static int _terrainShape; internal static Kind Current; internal static int Columns = 1; internal static int Rows = 1; internal static int Valid; private static readonly List<Vector3> Cells = new List<Vector3>(25); private static readonly List<bool> CellOk = new List<bool>(25); private static Quaternion _gridRotation; private static int _centerIndex; private static float _spacing; private static float _tileRadius; private static float _growRadius; private static float _stableYaw = float.NaN; private static float _scrollReadyAt; private static bool _raiseGrid; private static Piece _pending; private static readonly List<Vector3> PendingCells = new List<Vector3>(25); private static Quaternion _pendingRotation; private static Vector3 _pendingCenter; private readonly List<LineRenderer> _rings = new List<LineRenderer>(); private readonly List<Vector3> _ringDrawnAt = new List<Vector3>(); private LineRenderer _outline; private float _timer; internal static bool ModifierHeld() { //IL_0011: 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) if (ServerLimits.Allowed(Plugin.AreaToolsEnabled) && (int)Plugin.AreaModifier.Value != 0) { return UnityInput.Current.GetKey(Plugin.AreaModifier.Value); } return false; } private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) _outline = SpawnView.CreateLine(((Component)this).transform, "AreaOutline", AreaColor, 0.06f); ((Component)_outline).gameObject.SetActive(false); } private void Update() { HandleScroll(); _timer -= Time.deltaTime; bool flag = _timer <= 0f; if (flag) { _timer = 0.1f; } Refresh(Player.m_localPlayer, flag); DrawPreview(); } private static void HandleScroll() { if (ScrollCaptured() && !Plugin.IsTyping() && !Hud.IsPieceSelectionVisible() && !(Time.time < _scrollReadyAt)) { float mouseScrollWheel = ZInput.GetMouseScrollWheel(); if (!(Mathf.Abs(mouseScrollWheel) < 0.001f)) { _scrollReadyAt = Time.time + 0.08f; StepSize((mouseScrollWheel > 0f) ? 1 : (-1)); } } } internal static bool ScrollCaptured() { if (Current != Kind.None) { return ModifierHeld(); } return false; } private void OnDisable() { Current = Kind.None; Cells.Clear(); DrawPreview(); } private static Kind KindOf(Player player, out Piece piece, out GameObject ghost) { piece = null; ghost = (((Object)(object)player != (Object)null && ((Character)player).InPlaceMode()) ? PlacementGhost.Invoke(player) : null); if (!ServerLimits.Allowed(Plugin.AreaToolsEnabled) || (Object)(object)ghost == (Object)null || !ghost.activeInHierarchy) { return Kind.None; } piece = player.GetSelectedPiece(); if ((Object)(object)piece == (Object)null) { return Kind.None; } if ((Object)(object)((Component)piece).GetComponent<Plant>() != (Object)null) { if (Compat.AreaPlantingDisabledBy != null) { return Kind.None; } return Kind.Plant; } if ((Object)(object)((Component)piece).GetComponent<TerrainOp>() != (Object)null && ServerLimits.Allowed(Plugin.AreaTerrain) && Compat.AreaTerrainDisabledBy == null) { return Kind.Terrain; } return Kind.None; } private static void Refresh(Player player, bool validate) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) int count = Cells.Count; Cells.Clear(); if (validate || count == 0) { CellOk.Clear(); } Valid = 0; Current = KindOf(player, out var piece, out var ghost); if (Current == Kind.None) { return; } int[,] obj = ((Current == Kind.Plant) ? PlantShapes : TerrainShapes); int num = ((Current == Kind.Plant) ? MaxShape(PlantShapes, ServerLimits.Max(Plugin.MaxPlantGrid)) : MaxShape(TerrainShapes, ServerLimits.Max(Plugin.MaxHoeSize))); int num2 = Mathf.Clamp((Current == Kind.Plant) ? _plantShape : _terrainShape, 0, num); Columns = obj[num2, 0]; Rows = obj[num2, 1]; Vector3 position = ghost.transform.position; if (Current == Kind.Plant) { Plant component = ghost.GetComponent<Plant>(); _growRadius = component.m_growRadius; _spacing = component.m_growRadius * 2f + 0.05f; _gridRotation = (piece.m_randomInitBuildRotation ? StableViewYaw() : Quaternion.Euler(0f, ghost.transform.eulerAngles.y, 0f)); } else { _tileRadius = CoverRadius(((Component)piece).GetComponent<TerrainOp>().m_settings); _spacing = _tileRadius * 1f; _gridRotation = ((Columns == 1 && Rows > 1) ? StableViewYaw() : Quaternion.Euler(0f, ghost.transform.eulerAngles.y, 0f)); } bool flag = Current == Kind.Terrain && ((Component)piece).GetComponent<TerrainOp>().m_settings.m_level; _raiseGrid = Current == Kind.Terrain && ((Component)piece).GetComponent<TerrainOp>().m_settings.m_raise; Vector3 val = default(Vector3); float y = default(float); for (int i = 0; i < Rows; i++) { for (int j = 0; j < Columns; j++) { ((Vector3)(ref val))..ctor((float)(j - (Columns - 1) / 2) * _spacing, 0f, (float)(i - (Rows - 1) / 2) * _spacing); if (val == Vector3.zero) { _centerIndex = Cells.Count; } Vector3 val2 = position + _gridRotation * val; if (!flag && (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val2, ref y)) { val2.y = y; } else if (flag) { val2.y = position.y; } int count2 = Cells.Count; Cells.Add(val2); if (count2 >= CellOk.Count) { CellOk.Add(val == Vector3.zero || CellAllowed(Current, ghost, val2)); } if (CellOk[count2]) { Valid++; } } } } private static float CoverRadius(Settings s) { if (s.m_raise) { return s.m_raiseRadius; } if (s.m_level) { return s.m_levelRadius; } if (s.m_paintCleared) { return s.m_paintRadius; } if (s.m_smooth) { return s.m_smoothRadius; } return s.GetRadius(); } private static bool CellAllowed(Kind kind, GameObject ghost, Vector3 p) { //IL_0000: 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_0023: Unknown result type (might be due to invalid IL or missing references) if (Location.IsInsideNoBuildLocation(p) || !PrivateArea.CheckAccess(p, 0f, false, false)) { return false; } if (kind == Kind.Plant) { return PlantPreview.WhyWontGrow(ghost.GetComponent<Plant>(), p) == null; } return true; } private static Quaternion StableViewYaw() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) float num = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.eulerAngles.y : 0f); if (float.IsNaN(_stableYaw) || Mathf.Abs(Mathf.DeltaAngle(num, _stableYaw)) > 35f) { _stableYaw = Mathf.Round(num / 45f) * 45f; } return Quaternion.Euler(0f, _stableYaw, 0f); } private void DrawPreview() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) bool flag = Current != Kind.None && Cells.Count > 1; int num = ((flag && Current == Kind.Plant) ? Cells.Count : 0); while (_rings.Count < num) { _rings.Add(SpawnView.CreateLine(((Component)this).transform, "AreaCell", GoodColor, 0.04f)); _ringDrawnAt.Add(Vector3.positiveInfinity); } for (int i = 0; i < _rings.Count; i++) { LineRenderer val = _rings[i]; bool flag2 = i < num && i != _centerIndex; if (((Component)val).gameObject.activeSelf != flag2) { ((Component)val).gameObject.SetActive(flag2); } if (!flag2) { _ringDrawnAt[i] = Vector3.positiveInfinity; continue; } Color startColor = (val.endColor = (CellOk[i] ? GoodColor : BadColor)); val.startColor = startColor; Vector3 val3 = Cells[i] - _ringDrawnAt[i]; if (!(((Vector3)(ref val3)).sqrMagnitude < 0.0001f)) { DrawFlatRing(val, Cells[i], _growRadius); _ringDrawnAt[i] = Cells[i]; } } bool flag3 = flag && Current == Kind.Terrain; if (((Component)_outline).gameObject.activeSelf != flag3) { ((Component)_outline).gameObject.SetActive(flag3); } if (flag3) { DrawSquare(_outline, AreaCenter(), (float)(Columns - 1) * 0.5f * _spacing + _tileRadius, (float)(Rows - 1) * 0.5f * _spacing + _tileRadius, _gridRotation); } } private static Vector3 AreaCenter() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; foreach (Vector3 cell in Cells) { val += cell; } Vector3 result = val / (float)Cells.Count; result.y = Cells[_centerIndex].y; return result; } private static void DrawFlatRing(LineRenderer lr, Vector3 center, float radius) { //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) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) lr.positionCount = 20; for (int i = 0; i < 20; i++) { float num = (float)i * (float)Math.PI * 2f / 20f; lr.SetPosition(i, new Vector3(center.x + Mathf.Cos(num) * radius, center.y + 0.08f, center.z + Mathf.Sin(num) * radius)); } } private static void DrawSquare(LineRenderer lr, Vector3 center, float halfX, float halfZ, Quaternion rotation) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) lr.positionCount = 48; Vector3[] array = (Vector3[])(object)new Vector3[4] { new Vector3(0f - halfX, 0f, 0f - halfZ), new Vector3(0f - halfX, 0f, halfZ), new Vector3(halfX, 0f, halfZ), new Vector3(halfX, 0f, 0f - halfZ) }; float y = default(float); for (int i = 0; i < 4; i++) { for (int j = 0; j < 12; j++) { Vector3 val = Vector3.Lerp(array[i], array[(i + 1) % 4], (float)j / 12f); Vector3 val2 = center + rotation * val; if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val2, ref y)) { val2.y = y; } val2.y += 0.3f; lr.SetPosition(i * 12 + j, val2); } } } internal static void StepSize(int direction) { if (Current == Kind.Plant) { _plantShape = Mathf.Clamp(_plantShape + direction, 0, MaxShape(PlantShapes, ServerLimits.Max(Plugin.MaxPlantGrid))); } else if (Current == Kind.Terrain) { _terrainShape = Mathf.Clamp(_terrainShape + direction, 0, MaxShape(TerrainShapes, ServerLimits.Max(Plugin.MaxHoeSize))); } } private static int MaxShape(int[,] shapes, int maxSide) { int result = 0; for (int i = 0; i < shapes.GetLength(0); i++) { if (shapes[i, 0] <= maxSide && shapes[i, 1] <= maxSide) { result = i; } } return result; } internal static void AddRows(InfoLines lines) { if (Current != Kind.None && Cells.Count > 1) { string arg = ((Columns == 1) ? $"Row of {Rows}" : $"{Columns} × {Rows}"); if (Current == Kind.Plant) { lines.Add(null, "Area", $"{arg}, {Valid} of {Cells.Count} can grow", "one seed and stamina each", (Valid == Cells.Count) ? Tone.Good : Tone.Warn); } else { lines.Add(null, "Area", $"{arg}, {Cells.Count} tiles", _raiseGrid ? "raised, then levelled flat: two hoe uses per tile" : "stamina and durability per tile", (Valid != Cells.Count) ? Tone.Warn : Tone.None); } } } internal static void AddHint(InfoLines lines) { //IL_0019: 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) if (Current != Kind.None && lines.HintKeys.Count == 0 && (int)Plugin.AreaModifier.Value != 0) { lines.Hint(Ui.KeyName(Plugin.AreaModifier.Value) + " + Scroll", "Area size"); } } internal static void OnPlaced(Player player, Piece piece) { //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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) _pending = null; Refresh(player, validate: true); if (Current == Kind.None || Cells.Count <= 1) { return; } PendingCells.Clear(); Vector3 center = Cells[_centerIndex]; for (int i = 0; i < Cells.Count; i++) { if (Cells[i] != center) { PendingCells.Add(Cells[i]); } } PendingCells.Sort(delegate(Vector3 a, Vector3 b) { //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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Vector3 val = a - center; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = b - center; return sqrMagnitude.CompareTo(((Vector3)(ref val)).sqrMagnitude); }); _pending = piece; _pendingCenter = center; _pendingRotation = PlacementGhost.Invoke(player).transform.rotation; } internal static void PlacePending(Player player) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) Piece pending = _pending; _pending = null; if ((Object)(object)pending == (Object)null) { return; } GameObject val = PlacementGhost.Invoke(player); ItemData tool = StaminaPatches.RightItem.Invoke((Humanoid)(object)player); PieceTable table = BuildPieces.Invoke(player); Kind kind = (((Object)(object)((Component)pending).GetComponent<Plant>() != (Object)null) ? Kind.Plant : Kind.Terrain); int num = 0; string text = null; foreach (Vector3 pendingCell in PendingCells) { if (!((Object)(object)val == (Object)null) && CellAllowed(kind, val, pendingCell)) { Quaternion rotation = ((kind == Kind.Plant) ? Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) : _pendingRotation); text = PlaceOne(player, pending, pendingCell, rotation, tool, table); if (text != null) { break; } num++; } } TerrainOp component = ((Component)pending).GetComponent<TerrainOp>(); Piece val2 = (((Object)(object)component != (Object)null && component.m_settings.m_raise && text == null) ? LevelPiece(table) : null); if ((Object)(object)val2 != (Object)null) { float num2 = _pendingCenter.y + component.m_settings.m_raiseDelta; List<Vector3> list = new List<Vector3>(PendingCells.Count + 1); list.Add(_pendingCenter); list.AddRange(PendingCells); foreach (Vector3 item in list) { if (CellAllowed(Kind.Terrain, val, item)) { text = PlaceOne(player, val2, new Vector3(item.x, num2, item.z), _pendingRotation, tool, table); if (text != null) { break; } } } } if (text != null) { Plugin.Tell("Area", $"placed {num + 1} of {PendingCells.Count + 1}, {text}", Tone.Warn); } } private static string PlaceOne(Player player, Piece piece, Vector3 pos, Quaternion rotation, ItemData tool, PieceTable table) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) bool placementCostDisabled = player.PlacementCostDisabled; if (!placementCostDisabled && !player.HaveRequirements(piece, (RequirementMode)0)) { return "out of materials"; } float num = GetBuildStamina(player); if (player.GetStamina() < num) { return "out of stamina"; } if (tool != null && tool.m_shared.m_useDurability && tool.m_durability <= 0f) { return "tool broken"; } player.PlacePiece(piece, pos, rotation, false, false); if (!placementCostDisabled && !ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey())) { player.ConsumeResources(piece.m_resources, 0, -1, 1); } ((Character)player).UseStamina(num); if ((Object)(object)table != (Object)null && (int)table.m_skill != 0) { if (BuildRemoveDebt.Invoke(player) > 0) { BuildRemoveDebt.Invoke(player)--; } else { ((Character)player).RaiseSkill(table.m_skill, 1f); } } if (tool != null && tool.m_shared.m_useDurability) { tool.m_durability -= GetPlaceDurability(player, tool) * Game.m_durabilityRate; } return null; } private static Piece LevelPiece(PieceTable table) { if ((Object)(object)table == (Object)null) { return null; } foreach (GameObject piece in table.m_pieces) { TerrainOp val = (((Object)(object)piece != (Object)null) ? piece.GetComponent<TerrainOp>() : null); if ((Object)(object)val != (Object)null && val.m_settings.m_level && !val.m_settings.m_raise) { return piece.GetComponent<Piece>(); } } return null; } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] internal static class AreaToolsPlacementPatch { private static void Prefix(Player __instance, out int __state) { __state = BuildHelpers.PlaceRotation.Invoke(__instance); } private static void Postfix(Player __instance, int __state) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { if (AreaTools.ScrollCaptured()) { BuildHelpers.PlaceRotation.Invoke(__instance) = __state; } AreaTools.PlacePending(__instance); } } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class AreaToolsZoomPatch { private static readonly FieldRef<GameCamera, float> Distance = AccessTools.FieldRefAccess<GameCamera, float>("m_distance"); private static void Prefix(GameCamera __instance, out float __state) { __state = Distance.Invoke(__instance); } private static void Postfix(GameCamera __instance, float __state) { if (AreaTools.ScrollCaptured()) { Distance.Invoke(__instance) = __state; } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class AreaToolsCrouchPatch { private static void Prefix(Player __instance, ref bool crouch) { if (crouch && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && AreaTools.Current != AreaTools.Kind.None && AreaTools.ModifierHeld()) { crouch = false; } } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] internal static class AreaToolsClickPatch { private static void Postfix(Player __instance, Piece piece, bool __result) { if (__result && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { AreaTools.OnPlaced(__instance, piece); } } } internal enum ViewMode { Off, Spawns, Repairs, Comfort } [Flags] internal enum ViewModes { None = 0, Spawns = 1, Repairs = 2, Comfort = 4, All = 7 } internal static class BaseView { internal class Legend { internal readonly List<KeyValuePair<Color, string>> Lines = new List<KeyValuePair<Color, string>>(12); internal string BarText; internal float BarFraction = -1f; internal Color BarColor; internal void Clear() { Lines.Clear(); BarText = null; BarFraction = -1f; } internal void Add(Color swatch, string text) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Lines.Add(new KeyValuePair<Color, string>(swatch, text)); } internal void Add(string text) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Lines.Add(new KeyValuePair<Color, string>(Color.clear, text)); } } private static readonly ViewMode[] Order = new ViewMode[3] { ViewMode.Spawns, ViewMode.Repairs, ViewMode.Comfort }; internal static Rect LegendRect; internal static float LegendDrawnAt = -10f; private static readonly PanelMotion LegendMotion = new PanelMotion(); internal const float Edge = 10f; internal static ViewMode Mode => Plugin.BaseViewMode.Value; internal static bool LegendShowing => Time.unscaledTime - LegendDrawnAt < 0.25f; internal static bool LegendVisible { get { if (Plugin.ShowLegend.Value && (Object)(object)Player.m_localPlayer != (Object)null && !Hud.IsUserHidden() && !Menu.IsVisible() && !InventoryGui.IsVisible()) { return !Minimap.IsOpen(); } return false; } } private static bool InCycle(ViewMode mode) { ViewModes value = Plugin.BaseViewModes.Value; return mode switch { ViewMode.Spawns => (value & ViewModes.Spawns) != 0, ViewMode.Repairs => (value & ViewModes.Repairs) != 0, ViewMode.Comfort => (value & ViewModes.Comfort) != 0, _ => false, }; } internal static void Cycle() { int num = Array.IndexOf(Order, Mode); ViewMode value = ViewMode.Off; for (int i = num + 1; i < Order.Length; i++) { if (InCycle(Order[i])) { value = Order[i]; break; } } Plugin.BaseViewMode.Value = value; } internal static string Name(ViewMode mode) { return mode.ToString(); } internal static void DrawLegend(Legend legend) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) float width; float height; Matrix4x4 matrix = Ui.BeginScaled(out width, out height); int num = 0; foreach (KeyValuePair<Color, string> line in legend.Lines) { if (line.Key.a > 0f) { num++; } } int num2 = legend.Lines.Count - num; bool flag = legend.BarFraction >= 0f; float num3 = TabsWidth(); if (flag) { num3 = Mathf.Max(num3, Ui.LineWidth(legend.BarText, Ui.Small)); } foreach (KeyValuePair<Color, string> line2 in legend.Lines) { num3 = Mathf.Max(num3, Ui.LineWidth(line2.Value, Ui.Text) + ((line2.Key.a > 0f) ? 22f : 0f)); } float num4 = Mathf.Clamp(num3 + 24f + 4f, 300f, 520f); float h = 58f + (flag ? 37f : 0f) + (float)legend.Lines.Count * 22f + ((num2 > 0 && num > 0) ? 9f : 0f); LegendRect = PlaceLegend(num4, h, width, height); LegendDrawnAt = Time.unscaledTime; Rect val = LegendMotion.Step(LegendRect); Color color = GUI.color; GUI.color = new Color(color.r, color.g, color.b, color.a * LegendMotion.Alpha); Ui.Panel(val); GUI.BeginClip(val); float num5 = 12f; float num6 = 12f; float num7 = num4 - 24f; DrawTabs(num5, num6, num7, 28f); num6 += 28f; Ui.Divider(num5, num6 + 2f, num7); num6 += 6f; if (flag) { Ui.Label(new Rect(num5, num6, num7, 18f), legend.BarText, Ui.Small); Ui.Bar(new Rect(num5, num6 + 19f, num7, 12f), legend.BarFraction, legend.BarColor); num6 += 37f; } bool flag2 = num == 0; foreach (KeyValuePair<Color, string> line3 in legend.Lines) { float num8 = num5; if (line3.Key.a > 0f) { Ui.Swatch(new Rect(num5 + 1f, num6 + 5f, 12f, 12f), line3.Key); num8 += 22f; } else if (!flag2) { flag2 = true; Ui.Divider(num5, num6 + 4f, num7); num6 += 9f; } Ui.Label(new Rect(num8, num6, num7 - (num8 - num5), 22f), line3.Value, Ui.Text); num6 += 22f; } GUI.EndClip(); GUI.color = color; GUI.matrix = matrix; } internal static Rect PlaceLegend(float w, float h, float sw, float sh) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) return Ui.FromFraction(Plugin.LegendX.Value, Plugin.LegendY.Value, w, h, sw, sh, 10f); } internal static void SaveLegendPlace(Rect r, float sw, float sh) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Ui.ToFraction(r, sw, sh, 10f, out var fx, out var fy); Plugin.LegendX.Value = fx; Plugin.LegendY.Value = fy; } private static float TabsWidth() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) float num = Ui.KeycapWidth(Ui.KeyName(Plugin.ToggleKey.Value)) + 6f + Ui.LineWidth("Next", Ui.Small) + 16f; ViewMode[] order = Order; foreach (ViewMode mode in order) { if (InCycle(mode)) { num += Ui.LineWidth("<b>" + Name(mode) + "</b>", Ui.Title) + 16f; } } return num; } private static void DrawTabs(float x, float y, float width, float height) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) string key = Ui.KeyName(Plugin.ToggleKey.Value); float num = Ui.KeycapWidth(key); float num2 = num + 6f + Ui.LineWidth("Next", Ui.Small); Ui.Keycap(new Rect(x + width - num2, y + (height - 18f) * 0.5f, 0f, 18f), key); Ui.Label(new Rect(x + width - num2 + num + 6f, y, num2, height), "Next", Ui.Small); float num3 = x; ViewMode[] order = Order; foreach (ViewMode viewMode in order) { if (InCycle(viewMode)) { bool num4 = viewMode == Mode; string text = (num4 ? ("<b>" + Name(viewMode) + "</b>") : ("<color=#b9ad98>" + Name(viewMode) + "</color>")); GUIStyle style = (num4 ? Ui.Title : Ui.Text); float num5 = Ui.LineWidth(text, style); Ui.Label(new Rect(num3, y, num5 + 4f, height), text, style); if (num4) { Ui.Accent(new Rect(num3, y + height - 3f, num5, 2f), Ui.GoldColor); } num3 += num5 + 16f; } } } } internal class BuildHelpers : MonoBehaviour { internal static readonly FieldRef<Player, int> PlaceRotation = AccessTools.FieldRefAccess<Player, int>("m_placeRotation"); internal static readonly FieldRef<Player, float> PlaceRotationDegrees = AccessTools.FieldRefAccess<Player, float>("m_placeRotationDegrees"); private static readonly FieldRef<Player, GameObject> PlacementGhost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost"); internal static float FineOffset; internal static float RotationShownUntil; private const float RotationShowTime = 2.5f; private static readonly List<ComfortInfo.Entry> Entries = new List<ComfortInfo.Entry>(); private const float TipTime = 7f; private static bool _tipShown; private static float _tipUntil; private int _comfortNow; private int _comfortAfter; private bool _showComfort; private bool _inShelter; private float _comfortTimer; private string _noGainReason; private InfoRow _shelterLine; private InfoRow _stationLine; private InfoRow _supportLine; private InfoRow _hoverLine; private float _shelterTimer; private static readonly InfoLines Lines = new InfoLines(); internal static bool FineModifierHeld() { //IL_000c: 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) if (!Compat.FineRotationDisabled && (int)Plugin.FineRotationModifier.Value != 0) { return UnityInput.Current.GetKey(Plugin.FineRotationModifier.Value); } return false; } private void Update() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InPlaceMode() && !_tipShown && Plugin.ShowKeyTips.Value) { _tipShown = true; _tipUntil = Time.time + 7f; } if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode()) { _showComfort = false; _shelterLine = null; _supportLine = null; _stationLine = null; _hoverLine = null; return; } if (!Compat.FineRotationDisabled) { KeyboardShortcut value = Plugin.MatchRotationKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !Hud.IsPieceSelectionVisible() && !Plugin.IsTyping()) { MatchOrResetRotation(localPlayer); } } _comfortTimer -= Time.deltaTime; if (_comfortTimer <= 0f) { _comfortTimer = 0.25f; UpdateComfort(localPlayer); Piece hoveringPiece = localPlayer.GetHoveringPiece(); _supportLine = (Plugin.ShowSupportInfo.Value ? SupportInfo.Describe(hoveringPiece) : null); _hoverLine = HoverInfo.Describe(hoveringPiece); GameObject val = PlacementGhost.Invoke(localPlayer); StationExtension val2 = ((Plugin.ShowStationInfo.Value && (Object)(object)val != (Object)null && val.activeInHierarchy) ? val.GetComponent<StationExtension>() : null); _stationLine = (((Object)(object)val2 != (Object)null) ? StationInfo.DescribeGhost(val2, val.transform.position) : null); } _shelterTimer -= Time.deltaTime; if (_shelterTimer <= 0f) { _shelterTimer = 1f; _shelterLine = ((Plugin.ShowShelterInfo.Value && PlantPreview.Line == null) ? ShelterInfo.Describe(localPlayer, _showComfort) : null); } } private static void MatchOrResetRotation(Player player) { //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_003c: Unknown result type (might be due to invalid IL or missing references) RotationShownUntil = Time.time + 2.5f; Piece hoveringPiece = player.GetHoveringPiece(); float num = PlaceRotationDegrees.Invoke(player); if ((Object)(object)hoveringPiece != (Object)null) { Quaternion rotation = ((Component)hoveringPiece).transform.rotation; float y = ((Quaternion)(ref rotation)).eulerAngles.y; int num2 = Mathf.RoundToInt(y / num); PlaceRotation.Invoke(player) = num2; FineOffset = y - (float)num2 * num; Plugin.Tell("Rotation", $"matched, {y:0.#}°", Tone.Good); } else { FineOffset = 0f; Plugin.Tell("Rotation", "fine steps reset"); } } internal static float CurrentYaw(Player player) { return Mathf.Repeat(PlaceRotationDegrees.Invoke(player) * (float)PlaceRotation.Invoke(player) + FineOffset, 360f); } private void UpdateComfort(Player player) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) _showComfort = false; if (!Plugin.ShowComfortPreview.Value) { return; } GameObject val = PlacementGhost.Invoke(player); Piece val2 = (((Object)(object)val != (Object)null && val.activeInHierarchy) ? val.GetComponent<Piece>() : null); if ((Object)(object)val2 == (Object)null || val2.m_comfort <= 0) { return; } Vector3 position = ((Component)player).transform.position; _inShelter = player.InShelter(); _comfortNow = ComfortInfo.Calculate(_inShelter, position, null, Entries); _comfortAfter = _comfortNow; _noGainReason = null; if (_inShelter && Vector3.Distance(position, val.transform.position) >= 10f) { _noGainReason = $"too far from you, comfort counts within {10f:0} m"; } else if (_inShelter) { _comfortAfter = ComfortInfo.Calculate(inShelter: true, position, val2, Entries); if (_comfortAfter <= _comfortNow) { foreach (ComfortInfo.Entry entry in Entries) { if ((Object)(object)entry.Piece == (Object)(object)val2) { if (entry.Skipped.Count != 0) { _noGainReason = entry.Skipped[0] + " nearby already gives the same"; break; } } else if (((int)val2.m_comfortGroup != 0 && entry.Piece.m_comfortGroup == val2.m_comfortGroup) || entry.Piece.m_name == val2.m_name) { string arg = (((int)val2.m_comfortGroup != 0) ? ((object)Unsafe.As<ComfortGroup, ComfortGroup>(ref val2.m_comfortGroup)/*cast due to .constrained prefix*/).ToString().ToLowerInvariant() : "piece"); _noGainReason = $"{Localization.instance.Localize(entry.Piece.m_name)} (+{entry.Value}) already counts as your {arg}"; break; } } } } _showComfort = true; } private void OnGUI() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Plugin.ShowBuildInfo.Value || (Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode() || Hud.IsUserHidden() || Hud.IsPieceSelectionVisible() || Menu.IsVisible()) { return; } bool flag = FineModifierHeld() || Time.time < RotationShownUntil; InfoRow line = PlantPreview.Line; InfoRow row = ((line == null) ? PlacementInfo.Line : null); InfoRow infoRow = ((line == null) ? _shelterLine : null); InfoLines lines = Lines; lines.Clear(); Sprite icon = localPlayer.GetSelectedPiece()?.m_icon; if (RemovalLockPatch.Locked) { lines.Add(null, "Removal", "Locked", Ui.KeyName(Plugin.RemovalLockKey.Value) + " to unlock", Tone.Warn); } if (Freecam.Active) { Freecam.AddRows(lines, localPlayer); } lines.Add(line, icon); lines.Add(row, icon); AreaTools.AddRows(lines); lines.Add(_stationLine, icon); lines.Add(TerrainInfo.Line, icon); if (flag) { lines.Add(icon, "Rotation", $"<b>{CurrentYaw(localPlayer):0.#}°</b>", $"{Plugin.FineRotationStep.Value:0.#}° fine steps"); } lines.Add(PrecisionInfo.SnapLine, icon); lines.Add(PrecisionInfo.HeightLine, icon); if (_showComfort) { AddComfort(lines); } bool flag2 = FineModifierHeld(); if (infoRow != null && infoRow.Tone == Tone.Good && !_showComfort && !flag2) { infoRow = null; } lines.Add(infoRow); lines.Add(_hoverLine); if (_supportLine != null && (flag2 || _supportLine.Tone == Tone.Warn || _supportLine.Tone == Tone.Bad)) { lines.Add(_supportLine); } lines.Add(RemovalPreview.Line); if (Freecam.Active) { Freecam.AddHints(lines); } else if (flag && !Compat.FineRotationDisabled) { if ((int)Plugin.FineRotationModifier.Value != 0) { lines.Hint(Ui.KeyName(Plugin.FineRotationModifier.Value) + " + Scroll", "Fine rotate"); } lines.Hint(Ui.KeyName(Plugin.MatchRotationKey.Value), "Match / reset"); lines.Hint(Ui.KeyName(Plugin.BuildInfoToggleKey.Value), "Hide"); } else if (Time.time < _tipUntil) { if (!Compat.FreecamDisabled) { lines.Hint(Ui.KeyName(Plugin.FreecamKey.Value), "Freecam"); } if (!Compat.FineRotationDisabled && (int)Plugin.FineRotationModifier.Value != 0) { lines.Hint(Ui.KeyName(Plugin.FineRotationModifier.Value) + " + Scroll", "Fine rotate"); } lines.Hint(Ui.KeyName(Plugin.RemovalLockKey.Value), "Lock removal"); lines.Hint(Ui.KeyName(Plugin.ToggleKey.Value), "Base view"); lines.Hint(Ui.KeyName(Plugin.BuildInfoToggleKey.Value), "Hide this"); } AreaTools.AddHint(lines); if (lines.Count != 0 || lines.HintKeys.Count != 0) { InfoBox.Draw(lines); } } private void AddComfort(InfoLines lines) { Sprite icon = Ui.StatusIcon(SEMan.s_statusEffectRested); if (!_inShelter) { lines.Add(icon, "Comfort", "Not sheltered here", "comfort pieces only count under a roof", Tone.Warn); } else if (_comfortAfter > _comfortNow) { lines.Add(icon, "Comfort", $"{_comfortNow} » <b>{_comfortAfter}</b>", null, Tone.Good); } else { lines.Add(icon, "Comfort", $"{_comfortNow}, no gain", _noGainReason); } } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] internal static class FineRotationInputPatch { private static void Prefix(Player __instance, out int __state) { __state = BuildHelpers.PlaceRotation.Invoke(__instance); } private static void Postfix(Player __instance, int __state) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { int num = BuildHelpers.PlaceRotation.Invoke(__instance); if (num != __state && BuildHelpers.FineModifierHeld()) { BuildHelpers.PlaceRotation.Invoke(__instance) = __state; BuildHelpers.RotationShownUntil = Time.time + 2.5f; BuildHelpers.FineOffset = Mathf.Repeat(BuildHelpers.FineOffset + (float)(num - __state) * Plugin.FineRotationStep.Value, 360f); } } } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class FineRotationGhostPatch { private static float _savedDegrees; private static int _savedRotation; private static void Prefix(Player __instance, out bool __state) { __state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && !Mathf.Approximately(BuildHelpers.FineOffset, 0f); if (__state) { _savedDegrees = BuildHelpers.PlaceRotationDegrees.Invoke(__instance); _savedRotation = BuildHelpers.PlaceRotation.Invoke(__instance); BuildHelpers.PlaceRotationDegrees.Invoke(__instance) = _savedDegrees * (float)_savedRotation + BuildHelpers.FineOffset; BuildHelpers.PlaceRotation.Invoke(__instance) = 1; } } private static void Finalizer(Player __instance, bool __state) { if (__state) { BuildHelpers.PlaceRotationDegrees.Invoke(__instance) = _savedDegrees; BuildHelpers.PlaceRotation.Invoke(__instance) = _savedRotation; } } } [HarmonyPatch(typeof(Player), "CopyPiece")] internal static class CopyPiecePatch { private static void Postfix(bool __result) { if (__result) { BuildHelpers.FineOffset = 0f; } } } internal enum MarkerImport { All, Filtered, None } [HarmonyPatch(typeof(Minimap), "AddSharedMapData")] internal static class TableImportPatch { private static readonly FieldRef<Minimap, List<PinData>> Pins = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); private static int _skippedChecked; private static int _skippedDuplicate; private static int _skippedType; private static int _skippedAll; private static int _updated; internal static bool Bypass; internal static bool Silent; private static void Prefix(Minimap __instance, ref byte[] dataArray) { _skippedChecked = (_skippedDuplicate = (_skippedType = (_skippedAll = (_updated = 0)))); if ((Object)(object)Player.m_localPlayer == (Object)null || dataArray == null) { return; } bool flag = !Bypass && Plugin.MarkerImportMode.Value != MarkerImport.All; bool flag2 = Plugin.UpdateSharedMarkers.Value && !Compat.CartographyManagerDisabled; if (!flag && !flag2) { return; } try { TableData tableData = TableData.Parse(dataArray, __instance); if (tableData != null) { if (flag && Filter(__instance, tableData)) { dataArray = tableData.Write(); } if (flag2) { RefreshChanged(__instance, tableData); } } } catch (Exception ex) { Debug.LogWarning((object)("[Norse Sense] Couldn't process cartography table markers, importing as vanilla: " + ex.Message)); } } private static void Postfix() { if (!Silent && !((Object)(object)Player.m_localPlayer == (Object)null) && Plugin.ShowImportSummary.Value) { List<string> list = new List<string>(); if (_skippedAll > 0) { list.Add($"{_skippedAll} (markers off)"); } if (_skippedChecked > 0) { list.Add($"{_skippedChecked} crossed out"); } if (_skippedDuplicate > 0) { list.Add($"{_skippedDuplicate} duplicates"); } if (_skippedType > 0) { list.Add($"{_skippedType} filtered types"); } int num = _skippedChecked + _skippedDuplicate + _skippedType + _skippedAll; string text = ((num > 0) ? string.Format("skipped {0} markers ({1})", num, string.Join(", ", list)) : null); if (_updated > 0) { text = ((text == null) ? "" : (text + ", ")) + $"updated {_updated}"; } if (text != null) { Plugin.Tell("Map table", text); } } } private static bool Filter(Minimap map, TableData table) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) long playerID = Player.m_localPlayer.GetPlayerID(); bool flag = Plugin.MarkerImportMode.Value == MarkerImport.None; HashSet<PinType> hashSet = ParseTypes(Plugin.SkipMarkerTypes.Value); float value = Plugin.DuplicateMergeDistance.Value; List<PinData> existing = Pins.Invoke(map); List<TableMarker> list = new List<TableMarker>(table.Markers.Count); foreach (TableMarker marker in table.Markers) { if (marker.Owner == playerID) { list.Add(marker); } else if (flag) { _skippedAll++; } else if (hashSet.Contains(marker.Type)) { _skippedType++; } else if (marker.Checked && Plugin.SkipCrossedOutMarkers.Value) { _skippedChecked++; } else if (value > 0f && IsDuplicate(marker, existing, list, value)) { _skippedDuplicate++; } else { list.Add(marker); } } if (list.Count == table.Markers.Count) { return false; } table.Markers = list; return true; } private static void RefreshChanged(Minimap map, TableData table) { //IL_0061: 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_006c: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) long playerID = Player.m_localPlayer.GetPlayerID(); List<PinData> list = Pins.Invoke(map); foreach (TableMarker marker in table.Markers) { if (marker.Owner == playerID) { continue; } for (int num = list.Count - 1; num >= 0; num--) { PinData val = list[num]; if (val.m_ownerID != 0L) { Vector3 val2 = val.m_pos - marker.Pos; if (!(((Vector3)(ref val2)).sqrMagnitude > 1f)) { if (val.m_name != marker.Name || val.m_type != marker.Type || val.m_checked != marker.Checked) { map.RemovePin(val); _updated++; } break; } } } } } private static bool IsDuplicate(TableMarker marker, List<PinData> existing, List<TableMarker> kept, float radius) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0097: 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) float num = radius * radius; Vector3 val; foreach (PinData item in existing) { if (item.m_ownerID == 0L && item.m_save && item.m_type == marker.Type) { val = item.m_pos - marker.Pos; if (((Vector3)(ref val)).sqrMagnitude <= num) { return true; } } } foreach (TableMarker item2 in kept) { if (item2.Type == marker.Type) { val = item2.Pos - marker.Pos; if (((Vector3)(ref val)).sqrMagnitude <= num) { return true; } } } return false; } internal static HashSet<PinType> ParseTypes(string list) { //IL_0173: Unknown result type (might be due to invalid IL or missing references) HashSet<PinType> hashSet = new HashSet<PinType>(); string[] array = list.Split(new char[3] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { switch (text.Trim().ToLowerInvariant()) { case "fire": hashSet.Add((PinType)0); continue; case "home": case "house": hashSet.Add((PinType)1); continue; case "hammer": hashSet.Add((PinType)2); continue; case "circle": case "dot": hashSet.Add((PinType)3); continue; case "rune": case "portal": hashSet.Add((PinType)6); continue; } if (Enum.TryParse<PinType>(text.Trim(), ignoreCase: true, out PinType result)) { hashSet.Add(result); } } return hashSet; } } [HarmonyPatch(typeof(MapTable), "OnWrite")] internal static class TableWritePatch { private static void Prefix() { TableImportPatch.Bypass = true; } private static void Finalizer() { TableImportPatch.Bypass = false; if (Plugin.MarkerImportMode.Value != MarkerImport.All && !((Object)(object)Minimap.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { ReimportOwnMap(); } } internal static void ReimportOwnMap() { TableImportPatch.Silent = true; try { Minimap.instance.AddSharedMapData(Minimap.instance.GetSharedMapData((byte[])null)); } finally { TableImportPatch.Silent = false; } } } internal class ComfortInfo : MonoBehaviour { internal class Entry { internal Piece Piece; internal int Value; internal readonly List<string> Skipped = new List<string>(2); } internal const float Radius = 10f; private const float RefreshInterval = 1f; private static readonly List<Piece> TempPieces = new List<Piece>(); private static Piece _ghost; private readonly List<Entry> _entries = new List<Entry>(); private bool _show; private bool _inShelter; private int _level; private InfoRow _shelterReason; private float _timer; private const float Pad = 10f; private const float HeaderH = 24f; private const float CellH = 30f; private const float IconSize = 26f; private const float Gap = 12f; private const float FootH = 18f; private readonly PanelMotion _motion = new PanelMotion(); internal static Rect LastRect; private const int PerRow = 6; internal const float Margin = 10f; internal static int Calculate(bool inShelter, Vector3 pos, Piece ghost, List<Entry> entries) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) entries.Clear(); if (!inShelter) { return 1; } TempPieces.Clear(); Piece.GetAllComfortPiecesInRadius(pos, 10f, TempPieces); if ((Object)(object)ghost != (Object)null) { TempPieces.Add(ghost); } _ghost = ghost; TempPieces.Sort(ComfortSort); int num = 2; Entry entry = null; for (int i = 0; i < TempPieces.Count; i++) { Piece val = TempPieces[i]; if (i > 0) { Piece val2 = TempPieces[i - 1]; if (((int)val.m_comfortGroup != 0 && val.m_comfortGroup == val2.m_comfortGroup) || val.m_name == val2.m_name) { string item = Localization.instance.Localize(val.m_name); if (entry != null && !entry.Skipped.Contains(item)) { entry.Skipped.Add(item); } continue; } } entry = new Entry { Piece = val, Value = Value(val) }; entries.Add(entry); num += entry.Value; } _ghost = null; return num; } private static int Value(Piece piece) { if (!((Object)(object)piece == (Object)(object)_ghost)) { return piece.GetComfort(); } return piece.m_comfort; } private static int ComfortSort(Piece x, Piece y) { //IL_0001: 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_0015: Unknown result type (might be due to invalid IL or missing references) if (x.m_comfortGroup != y.m_comfortGroup) { ref ComfortGroup comfortGroup = ref x.m_comfortGroup; object target = y.m_comfortGroup; return ((Enum)Unsafe.As<ComfortGroup, ComfortGroup>(ref comfortGroup)/*cast due to .constrained prefix*/).CompareTo(target); } float num = Value(x); float num2 = Value(y); if (num != num2) { return num2.CompareTo(num); } return y.m_name.CompareTo(x.m_name); } internal static float RestedMinutes(int comfort) { SE_Rested val = (SE_Rested)(((Object)(object)ObjectDB.instance != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); float num = (((Object)(object)val != (Object)null) ? val.m_baseTTL : 300f); float num2 = (((Object)(object)val != (Object)null) ? val.m_TTLPerComfortLevel : 60f); return (num + (float)(comfort - 1) * num2) / 60f; } private void Update() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; _show = Plugin.ShowComfortBreakdown.Value && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).InPlaceMode() && ((Character)localPlayer).IsSitting() && !((Character)localPlayer).IsAttachedToShip(); if (!_show) { _timer = 0f; return; } _timer -= Time.deltaTime; if (!(_timer > 0f)) { _timer = 1f; _inShelter = localPlayer.InShelter(); _level = Calculate(_inShelter, ((Component)localPlayer).transform.position, null, _entries); _shelterReason = (_inShelter ? null : ShelterInfo.Describe(localPlayer, always: true)); } } private void OnGUI() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) if (!_show || Hud.IsUserHidden() || Menu.IsVisible() || InventoryGui.IsVisible() || Minimap.IsOpen()) { return; } float width; float height; Matrix4x4 matrix = Ui.BeginScaled(out width, out height); float scale = (float)Screen.height / height; string text = string.Format("<color={0}>Comfort</color> <b>{1}</b>", "#e8c77e", _level); string text2 = (_inShelter ? $"Rested {RestedMinutes(_level):0} min" : "<color=#f0b04a>not sheltered</color>"); int num = 0; foreach (Entry entry2 in _entries) { num += entry2.Skipped.Count; } string text3 = (_inShelter ? ((num > 0) ? $"{num} more nearby don't count (same kind)" : null) : ((_shelterReason != null) ? (char.ToUpper(ShelterInfo.Summary[0]) + ShelterInfo.Summary.Substring(1)) : null)); int num2 = (_inShelter ? (_entries.Count + 1) : 0); int num3 = (num2 + 6 - 1) / 6; float num4 = 31f + Ui.LineWidth("<b>+3</b>", Ui.Small) + 12f; float num5 = Mathf.Max(Ui.LineWidth(text, Ui.Text) + 16f + Ui.LineWidth(text2, Ui.Small), (float)Mathf.Min(num2, 6) * num4 - 12f); if (text3 != null) { num5 = Mathf.Max(num5, Ui.LineWidth(text3, Ui.Small)); } num5 = Mathf.Min(num5, width * 0.4f) + 20f; float h = 44f + (float)num3 * 30f + ((text3 != null) ? 18f : 0f); Rect target = (LastRect = Place(num5, h, width, height, scale)); Rect val = _motion.Step(target); Color color = GUI.color; GUI.color = new Color(color.r, color.g, color.b, color.a * _motion.Alpha); Ui.Panel(val); GUI.BeginClip(val); float num6 = 10f; float num7 = 10f; Ui.Label(new Rect(num6, num7, num5, 24f), text, Ui.Text); Ui.Label(new Rect(num5 - 10f - Ui.LineWidth(text2, Ui.Small) - 2f, num7, num5, 24f), text2, Ui.Small); num7 += 24f; for (int i = 0; i < num2; i++) { float num8 = num6 + (float)(i % 6) * num4; float num9 = num7 + (float)(i / 6) * 30f; Sprite sprite; string text4; if (i == 0) { sprite = Ui.StatusIcon(SEMan.s_statusEffectShelter); text4 = "<b>+1</b>"; } else { Entry entry = _entries[i - 1]; sprite = entry.Piece.m_icon; text4 = ((entry.Value > 0) ? $"<b>+{entry.Value}</b>" : "<color=#f0b04a>+0</color>"); } Ui.SlotIcon(new Rect(num8, num9 + 2f, 26f, 26f), sprite); Ui.Label(new Rect(num8 + 26f + 5f, num9, num4, 30f), text4, Ui.Small); } num7 += (float)num3 * 30f; if (text3 != null) { Ui.Label(new Rect(num6, num7, num5 - 20f, 18f), text3, Ui.Small); } GUI.EndClip(); GUI.color = color; GUI.matrix = matrix; } internal static void SavePlace(Rect r, float sw, float sh) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Ui.ToFraction(r, sw, sh, 10f, out var fx, out var fy); Plugin.ComfortX.Value = fx; Plugin.ComfortY.Value = fy; } internal static Rect Place(float w, float h, float sw, float sh, float scale) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ComfortX.Value >= 0f && Plugin.ComfortY.Value >= 0f) { return Ui.FromFraction(Plugin.ComfortX.Value, Plugin.ComfortY.Value, w, h, sw, sh, 10f); } float num = sw - 24f; float num2 = sh * 0.4f; Hud instance = Hud.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_statusEffectListRoot != (Object)null && InfoBox.ContentRect(((Component)instance.m_statusEffectListRoot).gameObject, scale, out var r)) { num = ((Rect)(ref r)).xMax; num2 = ((Rect)(ref r)).yMax + 10f; } Rect result = default(Rect); ((Rect)(ref result))..ctor(num - w, num2, w, h); if (BaseView.LegendShowing && ((Rect)(ref result)).Overlaps(BaseView.LegendRect)) { ((Rect)(ref result)).y = ((Rect)(ref BaseView.LegendRect)).yMax + 10f; if (((Rect)(ref result)).yMax > sh - 10f) { ((Rect)(ref result)).y = ((Rect)(ref BaseView.LegendRect)).yMin - h - 10f; } } ((Rect)(ref result)).y = Mathf.Clamp(((Rect)(ref result)).y, 10f, sh - h - 10f); return result; } } internal class ComfortView : MonoBehaviour { private const float Radius = 12f; private const float Cell = 1f; private const float StandHeight = 1f; private const float NeedCover = 0.8f; private const float FloorOffset = 0.06f; private const float RefreshInterval = 3f; private const int CellsPerFrame = 60; internal static readonly Color NoShelterColor = Color.clear; internal static readonly Color LowColor = Ui.Alpha(Ui.WarnColor, 0.35f); internal static readonly Color HighColor = Ui.Alpha(Ui.GoodColor, 0.45f); private static int _floorMask; private GameObject _root; private Mesh _mesh; private LineRenderer _bestRing; private Vector3[] _verts; private Color[] _colors; private int[] _levels; private int _n; private bool _active; private bool _scanning; private float _timer; private Vector3 _scanCenter; private int _best; private int _here; private int _sheltered; private readonly BaseView.Legend _legend = new BaseView.Legend(); private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0038: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) _root = new GameObject("ComfortView"); _root.transform.SetParent(((Component)this).transform, false); _root.SetActive(false); GameObject val = new GameObject("Grid"); val.transform.SetParent(_root.transform, false); _mesh = new Mesh { name = "NorseSense_ComfortGrid", indexFormat = (IndexFormat)1 }; _mesh.MarkDynamic(); val.AddComponent<MeshFilter>().sharedMesh = _mesh; MeshRenderer obj = val.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = SpawnView.GetMaterial(); ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; _bestRing = SpawnView.CreateLine(_root.transform, "Best", HighColor, 0.08f); ((Component)_bestRing).gameObject.SetActive(false); } private void OnDestroy() { if ((Object)(object)_mesh != (Object)null) { Object.Destroy((Object)(object)_mesh); } } private void OnDisable() { ((MonoBehaviour)this).StopAllCoroutines(); _scanning = false; _active = false; if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } private void Update() { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; bool flag = BaseView.Mode == ViewMode.Comfort && (Object)(object)localPlayer != (Object)null && (Object)(object)ZoneSystem.instance != (Object)null; if (flag != _active) { _active = flag; _root.SetActive(flag); if (!flag) { ((MonoBehaviour)this).StopAllCoroutines(); _scanning = false; _mesh.Clear(); _n = 0; } _timer = 0f; } if (flag) { _here = localPlayer.GetComfortLevel(); _timer -= Time.deltaTime; if (!_scanning && (_timer <= 0f || Utils.DistanceXZ(((Component)localPlayer).transform.position, _scanCenter) > 3f)) { _timer = 3f; ((MonoBehaviour)this).StartCoroutine(Scan(((Component)localPlayer).transform.position)); } } } private IEnumerator Scan(Vector3 center) { //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) _scanning = true; _scanCenter = center; if (_floorMask == 0) { _floorMask = LayerMask.GetMask(new string[4] { "piece", "terrain", "Default", "static_solid" }); } int n = Mathf.CeilToInt(24f); if (n != _n) { Allocate(n); } float originX = Mathf.Floor(center.x / 1f) * 1f - (float)(n / 2) * 1f; float originZ = Mathf.Floor(center.z / 1f) * 1f - (float)(n / 2) * 1f; int best = 0; int sheltered = 0; int bestCell = -1; float[] floors = new float[n * n]; Vector3 val = default(Vector3); RaycastHit val2 = default(RaycastHit); float num3 = default(float); bool flag = default(bool); for (int c = 0; c < n * n; c++) { if (c > 0 && c % 60 == 0) { yield return null; if ((Object)(object)Player.m_localPlayer == (Object)null) { _scanning = false; yield break; } } int num = c % n; int num2 = c / n; ((Vector3)(ref val))..ctor(originX + ((float)num + 0.5f) * 1f, center.y, originZ + ((float)num2 + 0.5f) * 1f); _levels[c] = -1; floors[c] = float.NaN; if (Utils.DistanceXZ(val, center) > 12f || !Physics.Raycast(val + Vector3.up * 1.4f, Vector3.down, ref val2, 4.5f, _floorMask) || ((RaycastHit)(ref val2)).normal.y < 0.7f) { continue; } floors[c] = ((RaycastHit)(ref val2)).point.y; Cover.GetCoverForPoint(((RaycastHit)(ref val2)).point + Vector3.up * 1f, ref num3, ref flag, 0.5f); bool flag2 = flag && num3 >= 0.8f; int num4 = SE_Rested.CalculateComfortLevel(flag2, ((RaycastHit)(ref val2)).point); _levels[c] = (flag2 ? num4 : 0); if (flag2) { sheltered++; if (num4 > best) { best = num4; bestCell = c; } } } int num5 = 2; for (int i = 0; i < n * n; i++) { int num6 = i % n; int num7 = i / n; int num8 = i * 4; float num9 = originX + (float)num6 * 1f; float num10 = originZ + (float)num7 * 1f; Color val3 = Color.clear; float num11 = (float.IsNaN(floors[i]) ? (center.y - 100f) : (floors[i] + 0.06f)); if (_levels[i] == 0) { val3 = NoShelterColor; } else if (_levels[i] > 0) { val3 = Color.Lerp(LowColor, HighColor, (best > num5) ? ((float)(_levels[i] - num5) / (float)(best - num5)) : 1f); } _verts[num8] = new Vector3(num9 + 0.05f, num11, num10 + 0.05f); _verts[num8 + 1] = new Vector3(num9 + 0.05f, num11, num10 + 1f - 0.05f); _verts[num8 + 2] = new Vector3(num9 + 1f - 0.05f, num11, num10 + 1f - 0.05f); _verts[num8 + 3] = new Vector3(num9 + 1f - 0.05f, num11, num10 + 0.05f); _colors[num8] = (_colors[num8 + 1] = (_colors[num8 + 2] = (_colors[num8 + 3] = val3))); } _mesh.vertices = _verts; _mesh.colors = _colors; _mesh.RecalculateBounds(); ((Component)_bestRing).gameObject.SetActive(bestCell >= 0); if (bestCell >= 0) { Vector3 center2 = default(Vector3); ((Vector3)(ref center2))..ctor(originX + ((float)(bestCell % n) + 0.5f) * 1f, floors[bestCell] + 0.06f, originZ + ((float)(bestCell / n) + 0.5f) * 1f); DrawFlatRing(_bestRing, center2, 0.6f); } _best = best; _sheltered = sheltered; _scanning = false; } private void Allocate(int n) { _n = n; _verts = (Vector3[])(object)new Vector3[n * n * 4]; _colors = (Color[])(object)new Color[n * n * 4]; _levels = new int[n * n]; int[] array = new int[n * n * 6]; for (int i = 0; i < n * n; i++) { int num = i * 4; int num2 = i * 6; array[num2] = num; array[num2 + 1] = num + 1; array[num2 + 2] = num + 2; array[num2 + 3] = num; array[num2 + 4] = num + 2; array[num2 + 5] = num + 3; } _mesh.Clear(); _mesh.vertices = _verts; _mesh.colors = _colors; _mesh.triangles = array; } private static void DrawFlatRing(LineRenderer lr, Vector3 center, float radius) { //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) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) lr.positionCount = 24; for (int i = 0; i < 24; i++) { float num = (float)i * (float)Math.PI * 2f / 24f; lr.SetPosition(i, new Vector3(center.x + Mathf.Cos(num) * radius, center.y + 0.05f, center.z + Mathf.Sin(num) * radius)); } } private void OnGUI() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (_active && BaseView.LegendVisible) { if ((int)Event.current.type == 8) { BuildLegend(); } BaseView.DrawLegend(_legend); } } private void BuildLegend() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) _legend.Clear(); if (_best > 0) { _legend.BarFraction = Mathf.Clamp01((float)_here / (float)_best); _legend.BarText = string.Format("Here <b>{0}</b>, best <b>{1}</b> <size=12><color={2}>(Rested {3:0} min)</color></size>", _here, _best, "#b9ad98", ComfortInfo.RestedMinutes(_best)); _legend.BarColor = Color.Lerp(LowColor, HighColor, _legend.BarFraction); } if (_sheltered == 0) { _legend.Add("<color=#b9ad98>No sheltered floor nearby. Comfort only counts under a roof.</color>"); return; } _legend.Add(HighColor, "Most comfort (ringed)"); _legend.Add(LowColor, "Less comfort"); } } internal static class Compat { internal static bool Checked; internal static bool FineRotationDisabled; internal static bool PlayerTweaksDisabled; internal static bool CartographyManagerDisabled; internal static bool FreecamDisabled; internal static string FreecamDisabledBy; internal static string AreaPlantingDisabledBy; internal static string AreaTerrainDisabledBy; internal static string SpawnRulesChangedBy; internal static string RaidRulesChangedBy; internal static string PlantRulesChangedBy; internal static string TerrainRulesChangedBy; private static readonly string[] RotationMods = new string[1] { "gizmo" }; private static readonly string[] PlayerTweakMods = new string[3] { "valheim_plus", "valheimplus", "valheim plus" }; private static readonly string[] SpawnMods = new string[5] { "spawn_that", "spawnthat", "spawn that", "expand_world_spawns", "expand world spawns" }; private static readonly string[] TableManagerMods = new string[2] { "cartographyadmin", "cartography admin" }; private static readonly string[] CameraBuildMods = new string[6] { "buildcamera", "build camera", "build_camera", "freecam", "free cam", "freebuildcam" }; private static readonly string[] PlantingMods = new string[4] { "planteasily", "plant easily", "massfarming", "mass farming" }; private static readonly string[] TerrainRadiusMods = new string[5] { "advancedterrainmodifiers", "advanced terrain", "terraintools", "terrain tools", "hoeradius" }; private static readonly string[] RaidMods = new string[5] { "custom_raids", "customraids", "custom raids", "expand_world_events", "expand world events" }; internal static void Run(string ownHarmonyId, ManualLogSource log) { Checked = true; bool value = Plugin.AutoCompat.Value; List<string> list = new List<string>(); string text = FindPlugin(RotationMods); if (text != null && value) { FineRotationDisabled = true; list.Add("Fine rotation is off because " + text + " handles piece rotation."); } string text2 = FindPlugin(TableManagerMods); if (text2 != null && value) { CartographyManagerDisabled = true; list.Add("The table marker manager is off because " + text2 + " provides one."); } string text3 = FindPlugin(CameraBuildMods); if (text3 != null && value) { FreecamDisabled = true; FreecamDisabledBy = text3; list.Add("Freecam building is off because " + text3 + " provides a build camera."); } string text4 = FindPlugin(PlantingMods); if (text4 != null && value) { AreaPlantingDisabledBy = text4; list.Add("Area planting and harvesting are off because " + text4 + " does them."); } string text5 = FindPlugin(TerrainRadiusMods); if (text5 != null && value) { AreaTerrainDisabledBy = text5; list.Add("The bigger hoe is off because " + text5 + " changes the hoe's area."); } string text6 = FindPlugin(PlayerTweakMods); if (text6 != null) { if (value) { PlayerTweaksDisabled = true; } list.Add(value ? ("Build distance and pickup range are left to " + text6 + ".") : (text6 + " may also change build distance and pickup range.")); if (Plugin.BuildStaminaMultiplier.Value < 1f || Plugin.SowStaminaMultiplier.Value < 1f) { list.Add(text6 + " may also change build stamina; the reductions will stack."); } } SpawnRulesChangedBy = FindPlugin(SpawnMods) ?? PatchOwners(ownHarmonyId, Method(typeof(SpawnSystem), "IsSpawnPointGood"), Method(typeof(SpawnSystem), "FindBaseSpawnPoint"), Method(typeof(EffectArea), "IsPointInsideArea"), Method(typeof(ZoneSystem), "IsBlocked")); if (SpawnRulesChangedBy != null) { list.Add(SpawnRulesChangedBy + " changes spawn rules, so the spawn view may not be exact."); } RaidRulesChangedBy = FindPlugin(RaidMods) ?? PatchOwners(ownHarmonyId, Method(typeof(RandEventSystem), "CheckBase"), Method(typeof(RandEventSystem), "GetValidEventPoints"), Method(typeof(EffectArea), "GetBaseValue")); if (RaidRulesChangedBy != null) { list.Add(RaidRulesChangedBy + " changes raid rules, so the raid info may not be exact."); } PlantRulesChangedBy = PatchOwners(ownHarmonyId, Method(typeof(Plant), "UpdateHealth"), Method(typeof(Plant), "HaveGrowSpace"), Method(typeof(Plant), "HaveRoof")); if (PlantRulesChangedBy != null) { list.Add(PlantRulesChangedBy + " changes how plants grow, so the planting preview may not be exact."); } TerrainRulesChangedBy = PatchOwners(ownHarmonyId, Method(typeof(TerrainComp), "ApplyToHeightmap"), Method(typeof(TerrainComp), "RaiseTerrain"), Method(typeof(TerrainComp), "LevelTerrain")); if (TerrainRulesChangedBy != null) { list.Add(TerrainRulesChangedBy + " changes terrain editing, so the terrain limits may not be exact."); } string text7 = PatchOwners(ownHarmonyId, Method(typeof(Player), "UpdatePlacementGhost")); if (text7 != null && !FineRotationDisabled) { log.LogInfo((object)("Also patching build placement: " + text7 + ". If fine rotation misbehaves, set the fine rotation modifier to None.")); } string text8 = PatchOwners(ownHarmonyId, Method(typeof(Player), "GetBuildStamina"), Method(typeof(Player), "HaveStamina")); if (text8 != null) { log.LogInfo((object)("Also patching stamina: " + text8 + ". Stamina multipliers will combine with theirs.")); } string text9 = PatchOwners(ownHarmonyId, Method(typeof(Minimap), "AddSharedMapData")); if (text9 != null) { log.LogInfo((object)("Also patching cartography table reading: " + text9 + ". Marker filters run alongside it.")); } foreach (string item in list) { log.LogWarning((object)item); } if (list.Count == 0) { log.LogInfo((object)"No overlapping mods found."); } if (!Plugin.ShowCompatWarnings.Value || !((Object)(object)Player.m_localPlayer != (Object)null)) { return; } foreach (string item2 in list) { Plugin.Tell("Norse Sense", item2, Tone.Warn); } } private static MethodBase Method(Type type, string name) { return AccessTools.Method(type, name, (Type[])null, (Type[])null); } private static string FindPlugin(string[] keys) { foreach (PluginInfo value in Chainloader.PluginInfos.Values) { string guid = value.Metadata.GUID.ToLowerInvariant(); string name = value.Metadata.Name.ToLowerInvariant(); if (keys.Any((string k) => guid.Contains(k) || name.Contains(k))) { return value.Metadata.Name; } } return null; } private static string PatchOwners(string ownHarmonyId, params MethodBase[] methods) { HashSet<string> hashSet = new HashSet<string>(); foreach (MethodBase methodBase in methods) { if (methodBase == null) { continue; } Patches patchInfo = Harmony.GetPatchInfo(methodBase); if (patchInfo == null) { continue; } foreach (string owner in patchInfo.Owners) { if (owner != ownHarmonyId) { hashSet.Add(PluginName(owner)); } } } if (hashSet.Count <= 0) { return null; } return string.Join(", ", hashSet); } private static string PluginName(string harmonyId) { if (!Chainloader.PluginInfos.TryGetValue(harmonyId, out var value)) { return harmonyId; } return value.Metadata.Name; } } internal sealed class ConfigurationManagerAttributes { public int? Order; public bool? IsAdvanced; public bool? Browsable; } internal class Freecam : MonoBehaviour { private const float RunMultiplier = 3f; private const float GroundClearance = 0.4f; private const float CameraRadius = 0.3f; private static int _solidMask; internal static bool Active; internal static Vector3 Position; private static readonly FieldRef<Player, int> RemoveRayMask = AccessTools.FieldRefAccess<Player, int>("m_removeRayMask"); private static Player _player; private static float _savedPlaceDistance; private const float ResumeDistance = 2f; private static bool _hasLast; private static Vector3 _lastCamera; private static Vector3 _lastBody; private Vector3 _velocity; private float _lastHealth; private void Update() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Active) { string text = WhyStop(localPlayer); if (text != null) { Exit(text); return; } } if ((Object)(object)localPlayer == (Object)null || Plugin.IsTyping()) { return; } KeyboardShortcut value = Plugin.FreecamKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (Active) { Exit(null); } else { Enter(localPlayer); } } if (!Active) { return; } float health = ((Character)localPlayer).GetHealth(); if (health < _lastHealth - 0.01f && health < ((Character)localPlayer).GetMaxHealth() - 0.01f) { Exit("you took damage"); return; } _lastHealth = health; float num = ServerLimits.Max(Plugin.FreecamRange) + ServerLimits.Max(Plugin.FreecamReach) + 2f; if (!Mathf.Approximately(localPlayer.m_maxPlaceDistance, num)) { localPlayer.m_maxPlaceDistance = num; } Move(localPlayer, Time.unscaledDeltaTime); if (DistanceFromPlayer(localPlayer) > ServerLimits.Max(Plugin.FreecamRange) + 2f) { Exit("too far from you"); } } private void Enter(Player player) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (!ServerLimits.Allowed(Plugin.FreecamAllowed)) { Plugin.Tell("Freecam", (ServerLimits.Active && Plugin.FreecamAllowed.Value) ? "off on this server" : "turned off in the settings", Tone.Warn); } else if (Compat.FreecamDisabled) { Plugin.Tell("Freecam", "off, " + Compat.FreecamDisabledBy + " provides one", Tone.Warn); } else if (!((Character)player).InPlaceMode() || (Object)(object)GameCamera.instance == (Object)null) { Plugin.Tell("Freecam", "works in build mode: equip a hammer, hoe or cultivator", Tone.Warn); } else if (WhyStop(player) == null) { Active = true; _player = player; _savedPlaceDistance = player.m_maxPlaceDistance; _lastHealth = ((Character)player).GetHealth(); _velocity = Vector3.zero; Position = ((Component)GameCamera.instance).transform.position; if (_hasLast && Vector3.Distance(((Component)player).transform.position, _lastBody) < 2f) { Position = (ThroughWalls() ? _lastCamera : Sweep(Position, _lastCamera)); } } } internal static void Exit(string why) { //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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (Active) { Active = false; _hasLast = (Object)(object)_player != (Object)null; if (_hasLast) { _lastCamera = Position; _lastBody = ((Component)_player).transform.position; } if ((Object)(object)_player != (Object)null) { _player.m_maxPlaceDistance = _savedPlaceDistance; } _player = null; PlayerTweaks.Apply(); if ((Object)(object)Player.m_localPlayer != (Object)null && why != null) { Plugin.Tell("Freecam", "off, " + why, Tone.Warn); } } } private static string WhyStop(Player player) { if ((Object)(object)player == (Object)null || (Active && (Object)(object)player != (Object)(object)_player)) { return "player changed"; } if (((Character)player).IsDead()) { return "you died"; } if (!((Character)player).InPlaceMode()) { return "left build mode"; } if (((Character)player).IsAttached() || ((Character)player).IsTeleporting() || ((Character)player).InCutscene()) { return "busy"; } return null; } private void Move(Player player, float dt) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) Vector3 zero = Vector3.zero; bool flag = false; if (!InventoryGui.IsVisible() && !Minimap.IsOpen() && !Hud.IsPieceSelectionVisible() && !Menu.IsVisible()) { if (ZInput.GetButton("Forward")) { zero.z += 1f; } if (ZInput.GetButton("Backward")) { zero.z -= 1f; } if (ZInput.GetButton("Left")) { zero.x -= 1f; } if (ZInput.GetButton("Right")) { zero.x += 1f; } if (ZInput.GetButton("Jump")) { zero.y += 1f; } if (ZInput.GetButton("Crouch")) { zero.y -= 1f; } flag = ZInput.GetButton("Run"); } Transform transform = ((Component)GameCamera.instance).transform; Vector3 val = Vector3.ProjectOnPlane(transform.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; val = Vector3.ProjectOnPlane(transform.right, Vector3.up); Vector3 normalized2 = ((Vector3)(ref val)).normalized; Vector3 val2 = normalized * zero.z + normalized2 * zero.x + Vector3.up * zero.y; if (((Vector3)(ref val2)).sqrMagnitude > 1f) { ((Vector3)(ref val2)).Normalize(); } Vector3 val3 = val2 * Plugin.FreecamSpeed.Value * (flag ? 3f : 1f); _velocity = Vector3.Lerp(_velocity, val3, 1f - Mathf.Exp(-12f * dt)); Vector3 val4 = Position + _velocity * dt; Vector3 centerPoint = ((Character)player).GetCenterPoint(); Vector3 val5 = val4 - centerPoint; if (((Vector3)(ref val5)).magnitude > ServerLimits.Max(Plugin.FreecamRange)) { val4 = centerPoint + ((Vector3)(ref val5)).normalized * ServerLimits.Max(Plugin.FreecamRange); } if ((Object)(object)ZoneSystem.instance != (Object)null) { val4.y = Mathf.Max(val4.y, ZoneSystem.instance.GetGroundHeight(val4) + 0.4f); } Position = (ThroughWalls() ? val4 : Sweep(Position, val4)); } private static bool ThroughWalls() { return ServerLimits.Allowed(Plugin.FreecamThroughWalls); } private static Vector3 Sweep(Vector3 from, Vector3 to) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or m