Decompiled source of InstrumentDisplay v3.0.2

InstrumentDisplay.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace MarinersHUD;

[BepInPlugin("com.dixiecapt.sailwind.marinershud", "InstrumentDisplay", "3.0.2")]
public class MarinersHUDPlugin : BaseUnityPlugin
{
	public static class PluginInfo
	{
		public const string GUID = "com.dixiecapt.sailwind.marinershud";

		public const string Name = "InstrumentDisplay";

		public const string Version = "3.0.2";
	}

	private class InstrumentFlags
	{
		public bool Chronometer;

		public bool ChronoCompass;

		public bool Quadrant;

		public bool Sextant;

		public bool Barometer;

		public bool Thermometer;

		public bool Inclinometer;
	}

	private struct HudLine
	{
		public string Text;

		public Color Color;
	}

	private class HudSection
	{
		public string Name;

		public ConfigEntry<bool> Toggle;

		public List<HudLine> Lines = new List<HudLine>();
	}

	public static BoatDamage CurrentBoatDamage;

	private static readonly FieldInfo SelfMassField = AccessTools.Field(typeof(BoatMass), "selfMass");

	private static readonly FieldInfo PartsMassField = AccessTools.Field(typeof(BoatMass), "partsMass");

	private static readonly FieldInfo ItemsOnBoatField = AccessTools.Field(typeof(BoatMass), "itemsOnBoat");

	private static readonly FieldInfo CloudyBorderField = AccessTools.Field(typeof(WeatherStorms), "cloudyBorder");

	private static readonly FieldInfo RainBorderField = AccessTools.Field(typeof(WeatherStorms), "rainBorder");

	private const float PlayerMassLbs = 160f;

	private static readonly string[] CompassPoints = new string[32]
	{
		"N", "NbE", "NNE", "NEbN", "NE", "NEbE", "ENE", "EbN", "E", "EbS",
		"ESE", "SEbE", "SE", "SEbS", "SSE", "SbE", "S", "SbW", "SSW", "SWbS",
		"SW", "SWbW", "WSW", "WbS", "W", "WbN", "WNW", "NWbW", "NW", "NWbN",
		"NNW", "NbW"
	};

	private ConfigEntry<float> _fbLightConfig;

	private ConfigEntry<float> _fbTrimConfig;

	private ConfigEntry<float> _fbLadenConfig;

	private ConfigEntry<float> _fbWeatherlyConfig;

	private ConfigEntry<float> _fbDeepConfig;

	private ConfigEntry<float> _fbOverburdenedConfig;

	private ConfigEntry<string> _burdenModeConfig;

	private ConfigEntry<float> _tenderBelowGMBeamConfig;

	private ConfigEntry<float> _dangerBelowGMBeamConfig;

	private ConfigEntry<bool> _listFloodWarnConfig;

	private ConfigEntry<float> _listOverloadedFractionConfig;

	private ConfigEntry<float> _listLoadedFractionConfig;

	private ConfigEntry<bool> _bilgeFloodWarnConfig;

	private ConfigEntry<float> _bilgeFloodPctConfig;

	private ConfigEntry<float> _burdenDebounceConfig;

	private ConfigEntry<bool> _debugReadoutConfig;

	private ConfigEntry<bool> _hudVisibleConfig;

	private ConfigEntry<bool> _showInstrumentsConfig;

	private ConfigEntry<bool> _showCargoConfig;

	private ConfigEntry<bool> _showSoundingConfig;

	private ConfigEntry<bool> _showStatusConfig;

	private ConfigEntry<bool> _showWeatherConfig;

	private ConfigEntry<KeyCode> _hudToggleKeyConfig;

	private ConfigEntry<KeyCode> _instrumentsToggleKeyConfig;

	private ConfigEntry<KeyCode> _cargoToggleKeyConfig;

	private ConfigEntry<KeyCode> _soundingToggleKeyConfig;

	private ConfigEntry<KeyCode> _statusToggleKeyConfig;

	private ConfigEntry<KeyCode> _weatherToggleKeyConfig;

	private ConfigEntry<string> _fontNameConfig;

	private ConfigEntry<int> _fontSizeConfig;

	private ConfigEntry<float> _panelAlphaConfig;

	private ConfigEntry<float> _textAlphaConfig;

	private ConfigEntry<bool> _textShadowConfig;

	private ConfigEntry<bool> _requireChipLogConfig;

	private ConfigEntry<bool> _requireCompassConfig;

	private ConfigEntry<bool> _requireWindIndicatorConfig;

	private ConfigEntry<string> _chipLogNamesConfig;

	private ConfigEntry<string> _compassNamesConfig;

	private ConfigEntry<string> _windIndicatorNamesConfig;

	private ConfigEntry<bool> _hideWhenAshoreConfig;

	private ConfigEntry<bool> _showPositionConfig;

	private ConfigEntry<KeyCode> _positionToggleKeyConfig;

	private ConfigEntry<bool> _requireBarometerForConditionsConfig;

	private ConfigEntry<bool> _requireThermometerForTemperatureConfig;

	private ConfigEntry<bool> _requireInclinometerForHeelConfig;

	private ConfigEntry<bool> _requireChronometerForTimeConfig;

	private ConfigEntry<string> _chronometerNamesConfig;

	private ConfigEntry<string> _chronoCompassNamesConfig;

	private ConfigEntry<string> _quadrantNamesConfig;

	private ConfigEntry<string> _sextantNamesConfig;

	private ConfigEntry<string> _barometerNamesConfig;

	private ConfigEntry<string> _thermometerNamesConfig;

	private ConfigEntry<string> _inclinometerNamesConfig;

	private ConfigEntry<bool> _showTimeConfig;

	private ConfigEntry<bool> _showTemperatureConfig;

	private ConfigEntry<bool> _preferLocalTimeConfig;

	private ConfigEntry<string> _temperatureUnitConfig;

	private ConfigEntry<string> _quadrantWindowConfig;

	private ConfigEntry<string> _chronoCompassWindowConfig;

	private ConfigEntry<string> _sextantNoonWindowConfig;

	private ConfigEntry<string> _sextantTimeSightWindowsConfig;

	private ConfigEntry<string> _sextantPolarisWindowConfig;

	private ConfigEntry<string> _sextantTwilightWindowsConfig;

	private ConfigEntry<bool> _polarisNorthOnlyConfig;

	private ConfigEntry<string> _coordLatAxisConfig;

	private ConfigEntry<string> _coordLonAxisConfig;

	private ConfigEntry<float> _coordUnitsPerDegreeConfig;

	private ConfigEntry<bool> _coordFlipLatConfig;

	private ConfigEntry<bool> _coordFlipLonConfig;

	private ConfigEntry<bool> _fogBlocksSightsConfig;

	private ConfigEntry<string> _coordFormatConfig;

	private bool _snapValid;

	private float _snapSpeedKts;

	private float _snapHeadingDeg;

	private float _snapHeel;

	private bool _snapHeelPort;

	private float _snapHeelLimit;

	private float _snapWindKts;

	private float _snapWindFromDeg;

	private float _snapHullDamagePct;

	private float _snapBilgePct;

	private bool _snapSunk;

	private float _snapDeadweightLbs;

	private float _snapBilgeEqLbs;

	private float _snapSelfMass;

	private float _snapPartsMass;

	private string _snapBoatName = string.Empty;

	private int _snapConditionSeverity;

	private float _stormProximity = 1f;

	private bool _stormProximityInit;

	private float _conditionHoldTimer;

	private float _keelTimer;

	private float _snapKeelClearance = 999f;

	private float _snapSeaDepth = 999f;

	private bool _snapGrounded;

	private bool _groundedLoggedState;

	private string _dbgGroundInfo = "(none)";

	private string _snapKeelHitName = "(no hit)";

	private float _snapFreeboard;

	private float _snapHullHeight;

	private float _snapDraft;

	private bool _freeboardInitialized;

	private Transform _hullGeomBoat;

	private float _deckTopLocalStable = float.NaN;

	private float _keelBottomLocalStable = float.NaN;

	private float _beamStable = float.NaN;

	private Type _buoyancyType;

	private FieldInfo _buoyancyBlobsField;

	private Component[] _buoyComps;

	private string _buoyDbg = string.Empty;

	private Transform _buoyBoat;

	private float _buoyBeam = float.NaN;

	private float _buoyDepth = float.NaN;

	private float _buoyKeelLocalUp = float.NaN;

	private string _snapBeamSource = string.Empty;

	private float _snapImmersionDeg = -1f;

	private float _snapListRatio = -1f;

	private bool _snapBilgeRising;

	private float _bilgePrevSample;

	private float _heelSmooth = -1f;

	private int _burdenDispSev = -99;

	private string _burdenDispLabel = "Light";

	private int _burdenPendSev = -99;

	private string _burdenPendLabel = "Light";

	private float _burdenPendSince;

	private float _maxFreeboardSeen;

	private int _burdenSevHeld = -2;

	private int _burdenSevCandidate = -2;

	private float _burdenSevTimer;

	private string _burdenLabelHeld = "---";

	private Color _burdenColorHeld = Color.gray;

	private float _snapKeelY;

	private bool _snapStabilityValid;

	private float _snapGM;

	private float _snapGMoverBeam;

	private float _snapCGaboveKeel;

	private float _equipScanTimer;

	private bool _hasChipLog;

	private bool _hasCompass;

	private bool _hasWindIndicator;

	private bool _hasChronometer;

	private bool _hasChronoCompass;

	private bool _hasQuadrant;

	private bool _hasSextant;

	private bool _hasBarometer;

	private bool _hasThermometer;

	private bool _hasInclinometer;

	private bool _snapPressureValid;

	private float _snapPressureMb;

	private int _snapPressureTrend;

	private float _pressureTrendRef;

	private float _pressureTrendTimer;

	private bool _pressureTrendInit;

	private bool _snapTimeValid;

	private string _snapTimeText = string.Empty;

	private bool _snapTempValid;

	private string _snapTempText = string.Empty;

	private float _navLatDeg;

	private float _navLonDeg;

	private bool _navLatEverFixed;

	private bool _navLonEverFixed;

	private bool _navLatFresh;

	private bool _navLonFresh;

	private string _navLatFixTimeText = string.Empty;

	private string _navLonFixTimeText = string.Empty;

	private Type _sunType;

	private FieldInfo _sunGlobalTimeField;

	private FieldInfo _sunLocalTimeField;

	private Object _sunObj;

	private Type _fomType;

	private FieldInfo _fomInstanceField;

	private PropertyInfo _fomInstanceProp;

	private MethodInfo _fomGetGlobeCoords;

	private MethodInfo _climGetPressureMb;

	private MethodInfo _climGetTempC;

	private MethodInfo _climGetTempF;

	private bool _climateResolved;

	private float _climateResolveTimer;

	private int _climateResolveAttempts;

	private string _climateUnit;

	private bool _fomCoordsTakesTransform;

	private object _lastCoordsRaw;

	private bool _climPressureNeedsCoords;

	private bool _climTempCNeedsCoords;

	private bool _climTempFNeedsCoords;

	private Type _invSlotType;

	private FieldInfo _invSlotsField;

	private FieldInfo _invCurrentItemField;

	private MethodInfo _fogIsRunningGetter;

	private bool _fogResolved;

	private int _fogResolveAttempts;

	private bool _snapFogRunning;

	private string _dbgCoordsRaw = "(none)";

	private string _dbgSunRaw = "(none)";

	private Font _gameFont;

	private bool _fontSearched;

	private static readonly string[] RiggingTokens = new string[14]
	{
		"mast", "stay", "shroud", "sail", "yard", "boom", "gaff", "sprit", "rigg", "halyard",
		"sheet", "vang", "spar", "topmast"
	};

	private static readonly string[] HullDeckTokens = new string[7] { "hull", "deck", "gunwale", "gunnel", "bulwark", "reinforced", "walk" };

	private static readonly string[] NonHullTokens = new string[17]
	{
		"shadow", "fender", "trigger", "sensor", "detect", "zone", "region", "bound", "wind", "cloth",
		"flag", "rudder", "anchor", "oar", "ladder", "rope", "cannon"
	};

	private Transform _meshBeamBoat;

	private float _meshBeam = float.NaN;

	private float _meshKeel = float.NaN;

	private int _meshBeamTries;

	private Texture2D _panelTexture;

	private float _panelTextureAlpha = -1f;

	private void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		try
		{
			BindConfig();
			InitReflection();
			Harmony val = new Harmony("com.dixiecapt.sailwind.marinershud");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[InstrumentDisplay] Telemetry system successfully initialized.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[InstrumentDisplay] Critical failure hook mapping: " + ex.Message));
		}
	}

	private void BindConfig()
	{
		_fbLightConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "DepthFrac_Light", 0.5f, "Weight ladder: at/above this freeboard/hull-depth fraction she reads 'Light' (riding high).");
		_fbTrimConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "DepthFrac_Trim", 0.42f, "Weight ladder: at/above this she reads 'Trim' (ideal draft).");
		_fbLadenConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "DepthFrac_Laden", 0.34f, "Weight ladder: at/above this she reads 'Laden' (full standard cargo).");
		_fbWeatherlyConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "DepthFrac_Weatherly", 0.26f, "Weight ladder: at/above this she reads 'Weatherly' (over-laden but still weather-safe).");
		_fbDeepConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "DepthFrac_Deep", 0.17f, "Weight ladder: at/above this she reads 'Deep' (yellow - sitting low, mind the weather / bilge).");
		_fbOverburdenedConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "DepthFrac_Overburdened", 0.08f, "Weight ladder: at/above this she reads 'Overburdened' (red - freeboard critically low). Below it she reads 'Awash' (sea over the deck).");
		_burdenModeConfig = ((BaseUnityPlugin)this).Config.Bind<string>("LoadStatusThresholds", "BurdenMode", "stability", "'stability' (recommended) combines BOTH axes: how deep she sits (weight) AND how tippy she is (centre of gravity vs beam/draft, plus off-centre list). The weight ladder (Light/Trim/Laden/Weatherly/Deep) fills the safe range; if her stability becomes the bigger worry the word switches to Tender then Crank. 'freeboard' uses the weight ladder only (no stability). Both are physics-based, no per-ship setup.");
		_tenderBelowGMBeamConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "TenderBelowGMBeam", 0.06f, "Stability: below this metacentric-height/beam ratio she is getting top-heavy and reads 'Tender' (yellow).");
		_dangerBelowGMBeamConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "CrankBelowGMBeam", 0.03f, "Stability: below this GM/beam ratio she is dangerously top-heavy (near capsize) and reads 'Crank' (red). Enable DebugMassReadout to see the live GM/beam and tune these.");
		_listFloodWarnConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("LoadStatusThresholds", "ListFloodWarning", true, "Also judge stability from an OFF-CENTRE load that heels her toward the point where the low rail submerges (a capsize/flood mode upright GM can't see). The rail goes under at heel ~ atan(freeboard / half-beam). Self-gating: a light ship (high freeboard) sailing hard won't trip it.");
		_listOverloadedFractionConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "ListCrankHeelFraction", 0.82f, "List: at this fraction of the rail-immersion angle she reads 'Crank' (red - rail nearly under). At/above 1.0 she reads 'Awash'.");
		_listLoadedFractionConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "ListTenderHeelFraction", 0.6f, "List: at this fraction of the rail-immersion angle she reads 'Tender' (yellow - heeling hard).");
		_burdenDebounceConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "BurdenDebounceSeconds", 1.5f, "A change in the Burden word must hold this many seconds before it shows, so wave rolls and single-frame glitches can't flash a false warning. Lower = snappier, higher = steadier.");
		_bilgeFloodWarnConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("LoadStatusThresholds", "BilgeFloodWarning", true, "Geometry-independent safety net: if bilge water is climbing while the hull is undamaged, she's shipping water from being awash/overloaded (not a leak), so escalate to Crank/Awash. This catches single-collider boats (some modded dinghies) whose deck edge can't be measured, guaranteeing an alarm before they sink even if the geometry read can't see it.");
		_bilgeFloodPctConfig = ((BaseUnityPlugin)this).Config.Bind<float>("LoadStatusThresholds", "BilgeFloodPercent", 1.5f, "Bilge safety net: once the bilge is at least this % full AND still rising (with the hull undamaged, so it's water coming aboard, not a leak) she reads Crank; at this + 3.5% she reads Awash. Kept low on purpose so it's an EARLY warning - by the time the bilge is deep she is already foundering. Raise it only if you find rough weather genuinely trips a false alarm.");
		_debugReadoutConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugMassReadout", false, "Adds raw hull/parts/total mass, boat internal name, the stability figures (GM, GM/beam, CG height, beam, draft), the sounding-ray hit, and logs the game font names found (for the FontName setting).");
		_hudVisibleConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "HudVisible", true, "Master switch for the whole HUD.");
		_showInstrumentsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "ShowInstruments", true, "Instruments section (Speed / Heading / Heel).");
		_showCargoConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "ShowCargo", true, "Cargo section (Deadweight / Freeboard / Burden).");
		_showSoundingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "ShowSounding", true, "Sounding section (Sea Depth / Keel Clearance).");
		_showStatusConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "ShowStatus", true, "Status section (Hull Integrity / Bilge Water).");
		_showWeatherConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "ShowWeather", true, "Weather section (Wind / Conditions).");
		_hudToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "HudToggleKey", (KeyCode)289, "Key that shows/hides the entire HUD. None to disable.");
		_instrumentsToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "InstrumentsToggleKey", (KeyCode)0, "Optional collapse key.");
		_cargoToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "CargoToggleKey", (KeyCode)0, "Optional collapse key.");
		_soundingToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "SoundingToggleKey", (KeyCode)0, "Optional collapse key.");
		_statusToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "StatusToggleKey", (KeyCode)0, "Optional collapse key.");
		_weatherToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "WeatherToggleKey", (KeyCode)0, "Optional collapse key.");
		_fontNameConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "FontName", "auto", "Font for the HUD. 'auto' picks the first non-Arial font loaded by the game (usually Sailwind's own sign/UI font). 'default' forces the plain IMGUI font. Or give part of a font name - enable DebugMassReadout once to log the available font names to the BepInEx console.");
		_fontSizeConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Appearance", "FontSize", 13, "HUD text size.");
		_panelAlphaConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "PanelAlpha", 0.18f, "Opacity of the section background panels (0 = invisible, 1 = solid).");
		_textAlphaConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "TextAlpha", 0.95f, "Opacity of the HUD text.");
		_textShadowConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "TextShadow", true, "Draw a subtle dark drop-shadow behind the text. Makes the HUD readable against a bright daytime sky without making the panels darker.");
		_requireChipLogConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireChipLogForSpeed", true, "Only show Speed when a chip log is aboard.");
		_requireCompassConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireCompassForHeading", true, "Only show Heading when a compass is aboard.");
		_requireWindIndicatorConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireWindIndicatorForWind", true, "Only show Wind when a wind indicator (shipyard windicator, tell tale, wind compass) is on the ship.");
		_chipLogNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "ChipLogItemNames", "chip log,chiplog", "Comma-separated name fragments identifying a chip log item aboard.");
		_compassNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "CompassItemNames", "compass", "Comma-separated name fragments identifying a compass item aboard.");
		_windIndicatorNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "WindIndicatorNames", "windicator,tell tale,telltale,wind indicator,wind compass,windsock", "Comma-separated name fragments identifying a wind indicator anywhere on the boat or its model.");
		_hideWhenAshoreConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "HideWhenAshore", true, "Hide the whole HUD while you are not aboard a boat (walking on land, on a dock, swimming, or in a shop). It reappears the instant you board.");
		_showPositionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "ShowPosition", true, "Position section (Latitude / Longitude from celestial navigation). The section only appears when a navigation instrument (quadrant, chronocompass, sextant) is aboard.");
		_positionToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "PositionToggleKey", (KeyCode)0, "Optional collapse key for the Position section.");
		_requireBarometerForConditionsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireBarometerForConditions", true, "Only show the Conditions line when a barometer (Climate mod) is aboard. With the Climate mod present, the wording follows the barometer card (Stormy / Rain / Change / Fair / Very Dry) plus a rising/falling trend. Set false to restore the always-on v1 line.");
		_requireThermometerForTemperatureConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireThermometerForTemperature", true, "Only show Temperature when a thermometer (Climate mod) is aboard.");
		_requireInclinometerForHeelConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireInclinometerForHeel", true, "Only show Heel when an inclinometer (Inclinometer mod) is aboard. Set false to restore the always-on v1 behavior.");
		_requireChronometerForTimeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("EquipmentRequirements", "RequireChronometerForTime", true, "Only show Time when a chronometer (clock) or chronocompass is aboard.");
		_chronometerNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "ChronometerItemNames", "chronometer,clock,chronocompass", "Comma-separated name fragments identifying a chronometer aboard. The stock clock is '170 clock A'; a chronocompass also satisfies the chronometer requirement.");
		_chronoCompassNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "ChronoCompassItemNames", "chronocompass,83 chronometer", "Comma-separated name fragments identifying a chronocompass (the stock item prefab is '83 chronometer A').");
		_quadrantNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "QuadrantItemNames", "quadrant", "Comma-separated name fragments identifying a quadrant aboard.");
		_sextantNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "SextantItemNames", "quintant,sextant", "Comma-separated name fragments identifying a sextant aboard (RealisticSkies adds '702 quintant').");
		_barometerNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "BarometerItemNames", "barometer", "Comma-separated name fragments identifying a barometer aboard (Climate mod).");
		_thermometerNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "ThermometerItemNames", "thermometer", "Comma-separated name fragments identifying a thermometer aboard (Climate mod).");
		_inclinometerNamesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("EquipmentRequirements", "InclinometerItemNames", "inclinometer", "Comma-separated name fragments identifying an inclinometer on the boat (Inclinometer mod).");
		_showTimeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Environment", "ShowTime", true, "Show a Time line in the Weather section (requires a chronometer aboard unless RequireChronometerForTime is off).");
		_showTemperatureConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Environment", "ShowTemperature", true, "Show a Temperature line in the Weather section (requires the Climate mod and a thermometer aboard unless RequireThermometerForTemperature is off).");
		_preferLocalTimeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Environment", "PreferLocalTime", false, "Show longitude-adjusted local time instead of Global (GMT) time.");
		_temperatureUnitConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Environment", "TemperatureUnit", "auto", "'auto' follows the Climate mod's own unit setting when it can be discovered, otherwise Celsius. Or force 'C' / 'F'.");
		_quadrantWindowConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "QuadrantWindow", "23:30-00:30", "Time window (local) in which a quadrant fixes Latitude, on a clear night. Format HH:MM-HH:MM; windows may cross midnight; multiple windows comma-separated.");
		_chronoCompassWindowConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "ChronoCompassWindow", "11:30-12:30", "Time window (local) in which a chronocompass fixes Latitude AND Longitude, in clear weather. Widen to 06:00-18:00 for the wiki's any-daylight behavior.");
		_sextantNoonWindowConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "SextantNoonWindow", "11:30-12:30", "Sextant noon sight window (local): fixes Latitude while the sun is visible.");
		_sextantTimeSightWindowsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "SextantTimeSightWindows", "08:00-10:00,14:00-16:00", "Sextant time-sight windows (local): fix Longitude while the sun is visible, but ONLY with a chronometer also aboard.");
		_sextantPolarisWindowConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "SextantPolarisWindow", "20:00-04:00", "Sextant Polaris window (local): fixes Latitude on a clear night.");
		_sextantTwilightWindowsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "SextantTwilightWindows", "05:00-06:00,18:00-19:00", "Sextant twilight windows (local): fix Latitude AND Longitude in clear weather (stars and horizon visible together).");
		_polarisNorthOnlyConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Navigation", "PolarisNorthernHemisphereOnly", true, "The Polaris sight only works north of the equator (Polaris is below the horizon in the southern hemisphere).");
		_coordLatAxisConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "LatitudeAxis", "z", "Which component (x/y/z) of the game's GetGlobeCoords result is Latitude. Verified from the game/Climate source: z is latitude in degrees. Enable DebugMassReadout to see the raw values in the Position section.");
		_coordLonAxisConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "LongitudeAxis", "x", "Which component (x/y/z) of the game's GetGlobeCoords result is Longitude (verified: x, in degrees).");
		_coordUnitsPerDegreeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Navigation", "CoordUnitsPerDegree", 1f, "Raw GetGlobeCoords units per degree. Leave 1 if the game already reports degrees; use the Debug raw readout to calibrate otherwise (game scale: 140 nm = 1 degree).");
		_coordFlipLatConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Navigation", "CoordFlipLat", false, "Invert the latitude sign (if the HUD shows S where it should show N).");
		_coordFlipLonConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Navigation", "CoordFlipLon", false, "Invert the longitude sign (if the HUD shows W where it should show E).");
		_coordFormatConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Navigation", "CoordinateFormat", "decimal", "How Position displays coordinates. 'decimal' matches the in-game chart exactly (34.09° / -4.18°); 'degmin' is classic degrees+minutes with hemisphere (34°05' N / 004°11' W).");
		_fogBlocksSightsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Navigation", "FogBlocksSights", true, "Dense fog from the Random Encounters mod blocks all celestial sights while it is running (you cannot shoot a sight with no horizon and no sky).");
	}

	private int WeightSeverity(float fb)
	{
		if (fb >= _fbLightConfig.Value)
		{
			return 0;
		}
		if (fb >= _fbTrimConfig.Value)
		{
			return 1;
		}
		if (fb >= _fbLadenConfig.Value)
		{
			return 2;
		}
		if (fb >= _fbWeatherlyConfig.Value)
		{
			return 3;
		}
		if (fb >= _fbDeepConfig.Value)
		{
			return 4;
		}
		if (fb >= _fbOverburdenedConfig.Value)
		{
			return 5;
		}
		return 6;
	}

	private int StabilitySeverity()
	{
		int num = 0;
		if (_snapStabilityValid)
		{
			if (_snapGMoverBeam < _dangerBelowGMBeamConfig.Value)
			{
				num = 5;
			}
			else if (_snapGMoverBeam < _tenderBelowGMBeamConfig.Value)
			{
				num = 4;
			}
		}
		_snapImmersionDeg = -1f;
		_snapListRatio = -1f;
		if (_listFloodWarnConfig.Value && _freeboardInitialized && !float.IsNaN(_beamStable) && _beamStable > 0.5f)
		{
			float num2 = Mathf.Atan2(_snapFreeboard, _beamStable * 0.5f) * 57.29578f;
			if (num2 >= 1f)
			{
				_snapImmersionDeg = num2;
				float num3 = ((!(_heelSmooth >= 0f)) ? _snapHeel : _heelSmooth);
				float num4 = (_snapListRatio = num3 / num2);
				int num5 = 0;
				if (num4 >= 1f)
				{
					num5 = 6;
				}
				else if (num4 >= _listOverloadedFractionConfig.Value)
				{
					num5 = 5;
				}
				else if (num4 >= _listLoadedFractionConfig.Value)
				{
					num5 = 4;
				}
				if (num5 > num)
				{
					num = num5;
				}
			}
		}
		return num;
	}

	private int BilgeFloodSeverity()
	{
		if (!_bilgeFloodWarnConfig.Value)
		{
			return 0;
		}
		if (_snapHullDamagePct > 25f)
		{
			return 0;
		}
		float value = _bilgeFloodPctConfig.Value;
		if (!_snapBilgeRising || _snapBilgePct < value)
		{
			return 0;
		}
		return (!(_snapBilgePct >= value + 3.5f)) ? 5 : 6;
	}

	private int BuildBurden(out string label, out Color color)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: 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_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Unknown result type (might be due to invalid IL or missing references)
		if (!_freeboardInitialized || _snapHullHeight <= 0.01f)
		{
			label = "---";
			color = Color.gray;
			return -1;
		}
		float fb = ((!(_snapHullHeight > 0.01f)) ? 1f : (_snapFreeboard / _snapHullHeight));
		int num = WeightSeverity(fb);
		int num2 = (((_burdenModeConfig.Value ?? "stability").Trim().ToLowerInvariant() != "freeboard") ? StabilitySeverity() : 0);
		int num3 = BilgeFloodSeverity();
		if (num3 > num2)
		{
			num2 = num3;
		}
		int num4 = ((num < num2) ? num2 : num);
		bool flag = num2 >= num && num2 >= 4;
		string burdenPendLabel = num4 switch
		{
			6 => "Awash", 
			5 => (!flag) ? "Overburdened" : "Crank", 
			4 => (!flag) ? "Deep" : "Tender", 
			3 => "Weatherly", 
			2 => "Laden", 
			1 => "Trim", 
			_ => "Light", 
		};
		if (num4 != _burdenPendSev)
		{
			_burdenPendSev = num4;
			_burdenPendLabel = burdenPendLabel;
			_burdenPendSince = Time.time;
		}
		else
		{
			_burdenPendLabel = burdenPendLabel;
		}
		if (_burdenDispSev < -1 || Time.time - _burdenPendSince >= _burdenDebounceConfig.Value)
		{
			_burdenDispSev = _burdenPendSev;
			_burdenDispLabel = _burdenPendLabel;
		}
		label = _burdenDispLabel;
		color = ((_burdenDispSev >= 5) ? Color.red : ((_burdenDispSev != 4) ? Color.white : Color.yellow));
		return _burdenDispSev;
	}

	private static bool KeyPressed(ConfigEntry<KeyCode> entry)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return entry != null && (int)entry.Value != 0 && Input.GetKeyDown(entry.Value);
	}

	private static bool NameMatchesAny(string name, string commaList)
	{
		if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(commaList))
		{
			return false;
		}
		string[] array = commaList.Split(new char[1] { ',' });
		foreach (string text in array)
		{
			string text2 = text.Trim();
			if (text2.Length != 0 && name.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static string CompassPoint(float degrees)
	{
		degrees %= 360f;
		if (degrees < 0f)
		{
			degrees += 360f;
		}
		int num = (int)Mathf.Round(degrees / 11.25f) % 32;
		return CompassPoints[num];
	}

	private static string WindWord(float knots)
	{
		if (knots < 1f)
		{
			return "Calm (0)";
		}
		if (knots < 3f)
		{
			return "Light Air (1)";
		}
		if (knots < 6f)
		{
			return "Light Breeze (2)";
		}
		if (knots < 10f)
		{
			return "Gentle Breeze (3)";
		}
		if (knots < 16f)
		{
			return "Moderate Breeze (4)";
		}
		if (knots < 21f)
		{
			return "Fresh Breeze (5)";
		}
		if (knots < 27f)
		{
			return "Strong Breeze (6)";
		}
		if (knots < 33f)
		{
			return "High Wind (7)";
		}
		if (knots < 40f)
		{
			return "Gale (8)";
		}
		if (knots < 47f)
		{
			return "Strong Gale (9)";
		}
		if (knots < 55f)
		{
			return "Storm (10)";
		}
		if (knots < 63f)
		{
			return "Violent Storm (11)";
		}
		return "Hurricane-force (12)";
	}

	private void Update()
	{
		//IL_019a: 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_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: 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_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05be: Unknown result type (might be due to invalid IL or missing references)
		if (KeyPressed(_hudToggleKeyConfig))
		{
			_hudVisibleConfig.Value = !_hudVisibleConfig.Value;
		}
		if (KeyPressed(_instrumentsToggleKeyConfig))
		{
			_showInstrumentsConfig.Value = !_showInstrumentsConfig.Value;
		}
		if (KeyPressed(_cargoToggleKeyConfig))
		{
			_showCargoConfig.Value = !_showCargoConfig.Value;
		}
		if (KeyPressed(_soundingToggleKeyConfig))
		{
			_showSoundingConfig.Value = !_showSoundingConfig.Value;
		}
		if (KeyPressed(_statusToggleKeyConfig))
		{
			_showStatusConfig.Value = !_showStatusConfig.Value;
		}
		if (KeyPressed(_weatherToggleKeyConfig))
		{
			_showWeatherConfig.Value = !_showWeatherConfig.Value;
		}
		if (KeyPressed(_positionToggleKeyConfig))
		{
			_showPositionConfig.Value = !_showPositionConfig.Value;
		}
		_snapValid = false;
		if (!GameState.playing || GameState.justStarted || (Object)(object)GameState.lastBoat == (Object)null || (_hideWhenAshoreConfig.Value && (Object)(object)GameState.currentBoat == (Object)null))
		{
			return;
		}
		Transform lastBoat = GameState.lastBoat;
		BoatDamage component = ((Component)lastBoat).GetComponent<BoatDamage>();
		Rigidbody component2 = ((Component)lastBoat).GetComponent<Rigidbody>();
		if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
		{
			return;
		}
		Vector3 velocity = component2.velocity;
		float num = Vector3.Dot(velocity, lastBoat.forward);
		_snapSpeedKts = num * 1.94384f;
		if (Mathf.Abs(_snapSpeedKts) < 0.1f)
		{
			_snapSpeedKts = 0f;
		}
		Vector3 forward = lastBoat.forward;
		forward.y = 0f;
		if (((Vector3)(ref forward)).sqrMagnitude > 0.0001f)
		{
			float num2 = Mathf.Atan2(forward.x, forward.z) * 57.29578f;
			if (num2 < 0f)
			{
				num2 += 360f;
			}
			_snapHeadingDeg = num2;
		}
		_snapHeel = Vector3.Angle(lastBoat.up, Vector3.up);
		if (_heelSmooth < 0f)
		{
			_heelSmooth = _snapHeel;
		}
		else
		{
			_heelSmooth = Mathf.Lerp(_heelSmooth, _snapHeel, 1f - Mathf.Exp((0f - Time.deltaTime) / 3f));
		}
		_snapHeelPort = lastBoat.right.y > 0f;
		_snapHeelLimit = component.safeAngleLimit;
		Vector3 val = Wind.currentWind - component2.velocity;
		_snapWindKts = ((Vector3)(ref val)).magnitude;
		Vector3 val2 = -val;
		val2.y = 0f;
		if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
		{
			float num3 = Mathf.Atan2(val2.x, val2.z) * 57.29578f;
			if (num3 < 0f)
			{
				num3 += 360f;
			}
			_snapWindFromDeg = num3;
		}
		UpdateConditions();
		_snapHullDamagePct = component.hullDamage * 100f;
		_snapBilgePct = component.waterLevel * 100f;
		_snapSunk = component.sunk;
		_snapBoatName = ((Object)lastBoat).name;
		float num4 = Mathf.Lerp(1f, 0.66f, (component.waterLevel - 0.5f) * 2f);
		_snapBilgeEqLbs = 0f;
		if (num4 < 0.999f)
		{
			_snapBilgeEqLbs = component2.mass * (1f / num4 - 1f);
		}
		BoatMass component3 = ((Component)lastBoat).GetComponent<BoatMass>();
		float num5 = 0f;
		float snapSelfMass = 0f;
		float snapPartsMass = 0f;
		bool flag = false;
		bool flag2 = false;
		if ((Object)(object)component3 != (Object)null)
		{
			snapSelfMass = (float)SelfMassField.GetValue(component3);
			snapPartsMass = (float)PartsMassField.GetValue(component3);
			object value = ItemsOnBoatField.GetValue(component3);
			if (value is IEnumerable enumerable)
			{
				foreach (object item in enumerable)
				{
					ItemRigidbody val3 = (ItemRigidbody)((item is ItemRigidbody) ? item : null);
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Rigidbody body = val3.GetBody();
					if (!((Object)(object)body == (Object)null))
					{
						num5 += body.mass;
						string name = ((Object)val3).name;
						if (!flag && NameMatchesAny(name, _chipLogNamesConfig.Value))
						{
							flag = true;
						}
						if (!flag2 && (NameMatchesAny(name, _compassNamesConfig.Value) || NameMatchesAny(name, _chronoCompassNamesConfig.Value)))
						{
							flag2 = true;
						}
					}
				}
			}
		}
		bool flag3 = (Object)(object)GameState.currentBoat != (Object)null && (Object)(object)GameState.currentBoat.parent == (Object)(object)lastBoat;
		bool flag4 = _snapKeelY != 0f && _snapHullHeight > 0.1f;
		_snapStabilityValid = false;
		if (_snapDraft > 0.05f && !float.IsNaN(_beamStable) && _beamStable > 0.1f && flag4)
		{
			float num6 = Mathf.Clamp(component2.worldCenterOfMass.y, _snapKeelY, _snapKeelY + _snapHullHeight);
			float num7 = num6 - _snapKeelY;
			float num8 = _snapDraft * 0.5f;
			float num9 = _beamStable * _beamStable / (12f * _snapDraft);
			_snapCGaboveKeel = num7;
			_snapGM = num8 + num9 - num7;
			_snapGMoverBeam = _snapGM / _beamStable;
			_snapStabilityValid = true;
		}
		_snapDeadweightLbs = num5 + _snapBilgeEqLbs + ((!flag3) ? 0f : 160f);
		_snapSelfMass = snapSelfMass;
		_snapPartsMass = snapPartsMass;
		_hasChipLog = flag;
		_hasCompass = flag2;
		_equipScanTimer -= Time.deltaTime;
		if (_equipScanTimer <= 0f)
		{
			_equipScanTimer = 1f;
			_hasWindIndicator = ScanForWindIndicator(lastBoat);
			ScanInstruments(component3, lastBoat);
			UpdateEnvironmentReadings();
			UpdateNavigation();
			_snapBilgeRising = _snapBilgePct - _bilgePrevSample > 0.2f;
			_bilgePrevSample = _snapBilgePct;
		}
		UpdateTimeReading();
		_keelTimer -= Time.deltaTime;
		if (_keelTimer <= 0f)
		{
			_keelTimer = 0.2f;
			UpdateSounding(lastBoat, component2);
		}
		_snapValid = true;
	}

	private void UpdateConditions()
	{
		float num = 0.4f;
		float num2 = 0.1f;
		float num3 = 1f;
		WeatherStorms instance = WeatherStorms.instance;
		if ((Object)(object)instance != (Object)null)
		{
			try
			{
				if (CloudyBorderField != null)
				{
					num = (float)CloudyBorderField.GetValue(instance);
				}
				if (RainBorderField != null)
				{
					num2 = (float)RainBorderField.GetValue(instance);
				}
			}
			catch (Exception)
			{
			}
			num3 = WeatherStorms.currentStormDistance;
		}
		if (!_stormProximityInit)
		{
			_stormProximity = num3;
			_stormProximityInit = true;
		}
		else
		{
			_stormProximity = Mathf.Lerp(_stormProximity, num3, Time.deltaTime * 0.6f);
		}
		float num4 = (num + num2) * 0.5f;
		float stormProximity = _stormProximity;
		int num5 = ((!(stormProximity >= num + 0.04f)) ? ((stormProximity >= num4 + 0.04f) ? 1 : ((!(stormProximity >= num2 + 0.04f)) ? 3 : 2)) : 0);
		if (Mathf.Abs(stormProximity - num) < 0.04f || Mathf.Abs(stormProximity - num4) < 0.04f || Mathf.Abs(stormProximity - num2) < 0.04f)
		{
			num5 = _snapConditionSeverity;
		}
		if (num5 != _snapConditionSeverity)
		{
			_conditionHoldTimer += Time.deltaTime;
			if (_conditionHoldTimer >= 2f)
			{
				_snapConditionSeverity = num5;
				_conditionHoldTimer = 0f;
			}
		}
		else
		{
			_conditionHoldTimer = 0f;
		}
	}

	private bool ScanForWindIndicator(Transform boat)
	{
		string value = _windIndicatorNamesConfig.Value;
		if (ScanChildrenForName(boat, value))
		{
			return true;
		}
		BoatRefs component = ((Component)boat).GetComponent<BoatRefs>();
		if ((Object)(object)component != (Object)null && (Object)(object)component.boatModel != (Object)null && ScanChildrenForName(component.boatModel, value))
		{
			return true;
		}
		return false;
	}

	private static bool ScanChildrenForName(Transform root, string commaList)
	{
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(false);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if (NameMatchesAny(((Object)componentsInChildren[i]).name, commaList))
			{
				return true;
			}
		}
		return false;
	}

	private void InitReflection()
	{
		_sunType = AccessTools.TypeByName("Sun");
		if (_sunType != null)
		{
			_sunGlobalTimeField = AccessTools.Field(_sunType, "globalTime");
			_sunLocalTimeField = AccessTools.Field(_sunType, "localTime");
		}
		_fomType = AccessTools.TypeByName("FloatingOriginManager");
		if (_fomType != null)
		{
			_fomInstanceField = AccessTools.Field(_fomType, "instance");
			if (_fomInstanceField == null)
			{
				_fomInstanceProp = AccessTools.Property(_fomType, "instance");
			}
			_fomGetGlobeCoords = AccessTools.Method(_fomType, "GetGlobeCoords", (Type[])null, (Type[])null);
			if (_fomGetGlobeCoords != null)
			{
				_fomCoordsTakesTransform = _fomGetGlobeCoords.GetParameters().Length >= 1;
			}
		}
		_invSlotType = AccessTools.TypeByName("GPButtonInventorySlot");
		if (_invSlotType != null)
		{
			_invSlotsField = AccessTools.Field(_invSlotType, "inventorySlots");
			_invCurrentItemField = AccessTools.Field(_invSlotType, "currentItem");
		}
		_buoyancyType = AccessTools.TypeByName("Buoyancy");
		if (_buoyancyType != null)
		{
			_buoyancyBlobsField = AccessTools.Field(_buoyancyType, "blobs");
		}
	}

	private void ResolveClimateIfNeeded()
	{
		if (_climateResolved || _climateResolveAttempts >= 30)
		{
			return;
		}
		_climateResolveTimer -= 1f;
		if (_climateResolveTimer > 0f)
		{
			return;
		}
		_climateResolveTimer = 2f;
		_climateResolveAttempts++;
		Type type = AccessTools.TypeByName("Climate.WeatherService");
		if (!(type == null))
		{
			_climGetPressureMb = FindClimateMethod(type, new string[2] { "GetCurrentPressureMb", "GetPressureMb" }, out var needsCoords);
			_climPressureNeedsCoords = needsCoords;
			_climGetTempC = FindClimateMethod(type, new string[2] { "GetCurrentTemperatureC", "GetTemperatureC" }, out needsCoords);
			_climTempCNeedsCoords = needsCoords;
			_climGetTempF = FindClimateMethod(type, new string[2] { "GetCurrentTemperatureF", "GetTemperatureF" }, out needsCoords);
			_climTempFNeedsCoords = needsCoords;
			_climateResolved = _climGetPressureMb != null || _climGetTempC != null;
			if (_climateResolved)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[InstrumentDisplay] Climate mod detected - barometer/thermometer readings enabled.");
			}
		}
	}

	private static float InvokeFloat(MethodInfo method)
	{
		if (method == null || !method.IsStatic)
		{
			return float.NaN;
		}
		try
		{
			object obj = method.Invoke(null, null);
			if (obj is float result)
			{
				return result;
			}
			if (obj is double)
			{
				return (float)(double)obj;
			}
			if (obj is int)
			{
				return (int)obj;
			}
		}
		catch (Exception)
		{
		}
		return float.NaN;
	}

	private static MethodInfo FindClimateMethod(Type service, string[] names, out bool needsCoords)
	{
		needsCoords = false;
		MethodInfo[] methods;
		try
		{
			methods = service.GetMethods(BindingFlags.Static | BindingFlags.Public);
		}
		catch (Exception)
		{
			return null;
		}
		for (int i = 0; i < names.Length; i++)
		{
			for (int j = 0; j < methods.Length; j++)
			{
				if (!(methods[j].Name != names[i]))
				{
					ParameterInfo[] parameters = methods[j].GetParameters();
					if (parameters.Length == 0)
					{
						needsCoords = false;
						return methods[j];
					}
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Vector3))
					{
						needsCoords = true;
						return methods[j];
					}
				}
			}
		}
		return null;
	}

	private float InvokeClimateFloat(MethodInfo method, bool needsCoords)
	{
		if (method == null)
		{
			return float.NaN;
		}
		try
		{
			object obj;
			if (needsCoords)
			{
				if (_lastCoordsRaw == null)
				{
					return float.NaN;
				}
				obj = method.Invoke(null, new object[1] { _lastCoordsRaw });
			}
			else
			{
				obj = method.Invoke(null, null);
			}
			if (obj is float result)
			{
				return result;
			}
			if (obj is double)
			{
				return (float)(double)obj;
			}
		}
		catch (Exception)
		{
		}
		return float.NaN;
	}

	private string DiscoverClimateUnit()
	{
		if (_climateUnit != null)
		{
			return _climateUnit;
		}
		try
		{
			if (!Chainloader.PluginInfos.TryGetValue("com.raddude.climate", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return null;
			}
			ConfigFile config = value.Instance.Config;
			if (config == null)
			{
				return null;
			}
			MethodInfo method = ((object)config).GetType().GetMethod("GetConfigEntries");
			if (method == null)
			{
				return null;
			}
			if (!(method.Invoke(config, null) is IEnumerable enumerable))
			{
				return null;
			}
			foreach (object item in enumerable)
			{
				ConfigEntryBase val = (ConfigEntryBase)((item is ConfigEntryBase) ? item : null);
				if (val == null || val.Definition == (ConfigDefinition)null)
				{
					continue;
				}
				string text = val.Definition.Key ?? string.Empty;
				if (text.IndexOf("unit", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("fahrenheit", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("celsius", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					object boxedValue = val.BoxedValue;
					if (boxedValue is bool flag)
					{
						bool flag2 = text.IndexOf("fahrenheit", StringComparison.OrdinalIgnoreCase) >= 0;
						_climateUnit = ((flag2 != flag) ? "C" : "F");
						return _climateUnit;
					}
					string text2 = ((boxedValue == null) ? string.Empty : boxedValue.ToString());
					if (text2.Equals("F", StringComparison.OrdinalIgnoreCase) || text2.IndexOf("fahrenheit", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						_climateUnit = "F";
						return "F";
					}
					if (text2.Equals("C", StringComparison.OrdinalIgnoreCase) || text2.IndexOf("celsius", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						_climateUnit = "C";
						return "C";
					}
				}
			}
		}
		catch (Exception)
		{
		}
		return null;
	}

	private void ScanItemForInstruments(string itemName, Component itemComp, InstrumentFlags f)
	{
		if (!f.ChronoCompass && NameMatchesAny(itemName, _chronoCompassNamesConfig.Value))
		{
			f.ChronoCompass = true;
		}
		if (!f.Chronometer && NameMatchesAny(itemName, _chronometerNamesConfig.Value))
		{
			f.Chronometer = true;
		}
		if (!f.Quadrant && NameMatchesAny(itemName, _quadrantNamesConfig.Value))
		{
			f.Quadrant = true;
		}
		if (!f.Sextant && NameMatchesAny(itemName, _sextantNamesConfig.Value))
		{
			f.Sextant = true;
		}
		if (!f.Barometer && NameMatchesAny(itemName, _barometerNamesConfig.Value))
		{
			f.Barometer = true;
		}
		if (!f.Thermometer && NameMatchesAny(itemName, _thermometerNamesConfig.Value))
		{
			f.Thermometer = true;
		}
		if (!f.Inclinometer && NameMatchesAny(itemName, _inclinometerNamesConfig.Value))
		{
			f.Inclinometer = true;
		}
		if (!((Object)(object)itemComp != (Object)null) || (f.Barometer && f.Thermometer && f.Inclinometer))
		{
			return;
		}
		Component[] components = itemComp.GetComponents<Component>();
		for (int i = 0; i < components.Length; i++)
		{
			if (!((Object)(object)components[i] == (Object)null))
			{
				switch (((object)components[i]).GetType().Name)
				{
				case "ShipItemBarometer":
					f.Barometer = true;
					break;
				case "ShipItemThermometer":
					f.Thermometer = true;
					break;
				case "Inclinometer":
					f.Inclinometer = true;
					break;
				}
			}
		}
	}

	private void ScanInstruments(BoatMass boatMass, Transform boat)
	{
		InstrumentFlags instrumentFlags = new InstrumentFlags();
		if ((Object)(object)boatMass != (Object)null)
		{
			object value = ItemsOnBoatField.GetValue(boatMass);
			if (value is IEnumerable enumerable)
			{
				foreach (object item in enumerable)
				{
					ItemRigidbody val = (ItemRigidbody)((item is ItemRigidbody) ? item : null);
					if (!((Object)(object)val == (Object)null))
					{
						ScanItemForInstruments(((Object)val).name, (Component)(object)val, instrumentFlags);
					}
				}
			}
		}
		if (_invSlotsField != null && _invCurrentItemField != null)
		{
			try
			{
				object value2 = _invSlotsField.GetValue(null);
				if (value2 is IEnumerable enumerable2)
				{
					foreach (object item2 in enumerable2)
					{
						if (item2 != null)
						{
							object? value3 = _invCurrentItemField.GetValue(item2);
							Component val2 = (Component)((value3 is Component) ? value3 : null);
							if (!((Object)(object)val2 == (Object)null))
							{
								ScanItemForInstruments(((Object)val2).name, val2, instrumentFlags);
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
		}
		if ((Object)(object)boat != (Object)null)
		{
			Transform val3 = null;
			BoatRefs component = ((Component)boat).GetComponent<BoatRefs>();
			if ((Object)(object)component != (Object)null)
			{
				val3 = component.boatModel;
			}
			for (int i = 0; i < 2; i++)
			{
				Transform val4 = ((i != 0) ? val3 : boat);
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				if (instrumentFlags.Chronometer && instrumentFlags.ChronoCompass && instrumentFlags.Quadrant && instrumentFlags.Sextant && instrumentFlags.Barometer && instrumentFlags.Thermometer && instrumentFlags.Inclinometer)
				{
					break;
				}
				Transform[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Transform>(false);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					ScanItemForInstruments(((Object)componentsInChildren[j]).name, null, instrumentFlags);
					if (instrumentFlags.Chronometer && instrumentFlags.ChronoCompass && instrumentFlags.Quadrant && instrumentFlags.Sextant && instrumentFlags.Barometer && instrumentFlags.Thermometer && instrumentFlags.Inclinometer)
					{
						break;
					}
				}
			}
		}
		if (instrumentFlags.ChronoCompass)
		{
			instrumentFlags.Chronometer = true;
		}
		_hasChronometer = instrumentFlags.Chronometer;
		_hasChronoCompass = instrumentFlags.ChronoCompass;
		_hasQuadrant = instrumentFlags.Quadrant;
		_hasSextant = instrumentFlags.Sextant;
		_hasBarometer = instrumentFlags.Barometer;
		_hasThermometer = instrumentFlags.Thermometer;
		_hasInclinometer = instrumentFlags.Inclinometer;
	}

	private void UpdateEnvironmentReadings()
	{
		ResolveClimateIfNeeded();
		TryGetLatLonDeg(out var _, out var _);
		_snapPressureValid = false;
		if (_climateResolved)
		{
			float num = InvokeClimateFloat(_climGetPressureMb, _climPressureNeedsCoords);
			if (!float.IsNaN(num) && num > 0f)
			{
				_snapPressureMb = num;
				_snapPressureValid = true;
				if (!_pressureTrendInit)
				{
					_pressureTrendRef = num;
					_pressureTrendInit = true;
					_pressureTrendTimer = 30f;
				}
				else
				{
					_pressureTrendTimer -= 1f;
					if (_pressureTrendTimer <= 0f)
					{
						float num2 = num - _pressureTrendRef;
						if (num2 > 0.2f)
						{
							_snapPressureTrend = 1;
						}
						else if (num2 < -0.2f)
						{
							_snapPressureTrend = -1;
						}
						else
						{
							_snapPressureTrend = 0;
						}
						_pressureTrendRef = num;
						_pressureTrendTimer = 30f;
					}
				}
			}
		}
		if (_sunType != null && _sunObj == (Object)null)
		{
			_sunObj = Object.FindObjectOfType(_sunType);
		}
		if (_debugReadoutConfig.Value && _sunObj != (Object)null)
		{
			try
			{
				float num3 = ((!(_sunGlobalTimeField != null)) ? float.NaN : ((float)_sunGlobalTimeField.GetValue(_sunObj)));
				float num4 = ((!(_sunLocalTimeField != null)) ? float.NaN : ((float)_sunLocalTimeField.GetValue(_sunObj)));
				_dbgSunRaw = "g=" + num3.ToString("F4") + " l=" + num4.ToString("F4");
			}
			catch (Exception)
			{
			}
		}
		_snapTempValid = false;
		if (_climateResolved)
		{
			string text = _temperatureUnitConfig.Value ?? "auto";
			if (text != "C" && text != "F")
			{
				string text2 = DiscoverClimateUnit();
				text = ((text2 == null) ? "C" : text2);
			}
			MethodInfo method = ((!(text == "F")) ? _climGetTempC : _climGetTempF);
			bool needsCoords = ((!(text == "F")) ? _climTempCNeedsCoords : _climTempFNeedsCoords);
			float f = InvokeClimateFloat(method, needsCoords);
			if (!float.IsNaN(f))
			{
				_snapTempText = f.ToString("F0") + "°" + text;
				_snapTempValid = true;
			}
		}
		_snapFogRunning = IsDenseFogRunning();
	}

	private void UpdateTimeReading()
	{
		_snapTimeValid = false;
		if (_sunObj == (Object)null)
		{
			return;
		}
		FieldInfo fieldInfo = ((!_preferLocalTimeConfig.Value || !(_sunLocalTimeField != null)) ? _sunGlobalTimeField : _sunLocalTimeField);
		if (fieldInfo == null)
		{
			return;
		}
		try
		{
			float raw = (float)fieldInfo.GetValue(_sunObj);
			_snapTimeText = FormatGameTime(raw);
			_snapTimeValid = true;
		}
		catch (Exception)
		{
		}
	}

	private static string FormatGameTime(float raw)
	{
		float num = ((!(raw >= 0f) || !(raw <= 1.0001f)) ? (raw % 24f) : (raw * 24f));
		if (num < 0f)
		{
			num += 24f;
		}
		int num2 = (int)num;
		int num3 = (int)((num - (float)num2) * 60f);
		if (num3 >= 60)
		{
			num3 = 0;
			num2 = (num2 + 1) % 24;
		}
		if (num2 >= 24)
		{
			num2 -= 24;
		}
		return num2.ToString("00") + ":" + num3.ToString("00");
	}

	private bool TryGetLocalHours(out float hours)
	{
		hours = 0f;
		if (_sunType == null)
		{
			return false;
		}
		if (_sunObj == (Object)null)
		{
			return false;
		}
		FieldInfo fieldInfo = ((!(_sunLocalTimeField != null)) ? _sunGlobalTimeField : _sunLocalTimeField);
		if (fieldInfo == null)
		{
			return false;
		}
		try
		{
			float num = (float)fieldInfo.GetValue(_sunObj);
			if (num >= 0f && num <= 1.0001f)
			{
				hours = num * 24f;
			}
			else
			{
				hours = num % 24f;
			}
			if (hours < 0f)
			{
				hours += 24f;
			}
			return true;
		}
		catch (Exception)
		{
			return false;
		}
	}

	private bool TryGetLatLonDeg(out float latDeg, out float lonDeg)
	{
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		latDeg = 0f;
		lonDeg = 0f;
		if (_fomGetGlobeCoords == null)
		{
			return false;
		}
		object obj = null;
		if (!_fomGetGlobeCoords.IsStatic)
		{
			try
			{
				if (_fomInstanceField != null)
				{
					obj = _fomInstanceField.GetValue(null);
				}
				else if (_fomInstanceProp != null)
				{
					obj = _fomInstanceProp.GetValue(null, null);
				}
			}
			catch (Exception)
			{
			}
			if (obj == null)
			{
				return false;
			}
		}
		object[] parameters = null;
		if (_fomCoordsTakesTransform)
		{
			Transform lastBoat = GameState.lastBoat;
			if ((Object)(object)lastBoat == (Object)null)
			{
				return false;
			}
			parameters = new object[1] { lastBoat };
		}
		object obj2;
		try
		{
			obj2 = _fomGetGlobeCoords.Invoke(obj, parameters);
		}
		catch (Exception)
		{
			return false;
		}
		if (obj2 == null)
		{
			return false;
		}
		_lastCoordsRaw = obj2;
		float x = 0f;
		float y = 0f;
		float z = 0f;
		bool flag = false;
		if (obj2 is Vector2 val)
		{
			x = val.x;
			y = val.y;
			flag = true;
		}
		else if (obj2 is Vector3 val2)
		{
			x = val2.x;
			y = val2.y;
			z = val2.z;
			flag = true;
		}
		else
		{
			Type type = obj2.GetType();
			FieldInfo field = type.GetField("x");
			FieldInfo field2 = type.GetField("y");
			FieldInfo field3 = type.GetField("z");
			if (field != null && field2 != null)
			{
				x = Convert.ToSingle(field.GetValue(obj2));
				y = Convert.ToSingle(field2.GetValue(obj2));
				if (field3 != null)
				{
					z = Convert.ToSingle(field3.GetValue(obj2));
				}
				flag = true;
			}
		}
		if (!flag)
		{
			return false;
		}
		if (_debugReadoutConfig.Value)
		{
			_dbgCoordsRaw = "x=" + x.ToString("F4") + " y=" + y.ToString("F4") + " z=" + z.ToString("F4");
		}
		float num = _coordUnitsPerDegreeConfig.Value;
		if (num == 0f)
		{
			num = 1f;
		}
		latDeg = PickAxis(_coordLatAxisConfig.Value, x, y, z) / num;
		lonDeg = PickAxis(_coordLonAxisConfig.Value, x, y, z) / num;
		if (_coordFlipLatConfig.Value)
		{
			latDeg = 0f - latDeg;
		}
		if (_coordFlipLonConfig.Value)
		{
			lonDeg = 0f - lonDeg;
		}
		return true;
	}

	private static float PickAxis(string axis, float x, float y, float z)
	{
		if (axis == null)
		{
			return y;
		}
		string text = axis.Trim().ToLowerInvariant();
		if (text == "x")
		{
			return x;
		}
		if (text == "z")
		{
			return z;
		}
		return y;
	}

	private void UpdateNavigation()
	{
		_navLatFresh = false;
		_navLonFresh = false;
		if ((!_hasQuadrant && !_hasChronoCompass && !_hasSextant) || _snapConditionSeverity != 0 || (_fogBlocksSightsConfig.Value && _snapFogRunning) || !TryGetLocalHours(out var hours) || !TryGetLatLonDeg(out var latDeg, out var lonDeg))
		{
			return;
		}
		bool flag = false;
		bool flag2 = false;
		if (_hasSextant)
		{
			if (InWindows(hours, _sextantTwilightWindowsConfig.Value))
			{
				flag = true;
				flag2 = true;
			}
			else if (InWindows(hours, _sextantNoonWindowConfig.Value))
			{
				flag = true;
			}
			else if (InWindows(hours, _sextantTimeSightWindowsConfig.Value))
			{
				if (_hasChronometer)
				{
					flag2 = true;
				}
			}
			else if (InWindows(hours, _sextantPolarisWindowConfig.Value) && (!_polarisNorthOnlyConfig.Value || latDeg >= 0f))
			{
				flag = true;
			}
		}
		if (_hasChronoCompass && InWindows(hours, _chronoCompassWindowConfig.Value))
		{
			flag = true;
			flag2 = true;
		}
		if (_hasQuadrant && InWindows(hours, _quadrantWindowConfig.Value))
		{
			flag = true;
		}
		if (flag)
		{
			_navLatDeg = latDeg;
			_navLatEverFixed = true;
			_navLatFresh = true;
			if (_snapTimeValid)
			{
				_navLatFixTimeText = _snapTimeText;
			}
		}
		if (flag2)
		{
			_navLonDeg = lonDeg;
			_navLonEverFixed = true;
			_navLonFresh = true;
			if (_snapTimeValid)
			{
				_navLonFixTimeText = _snapTimeText;
			}
		}
	}

	private static bool InWindows(float hours, string spec)
	{
		if (string.IsNullOrEmpty(spec))
		{
			return false;
		}
		string[] array = spec.Split(new char[1] { ',' });
		foreach (string text in array)
		{
			string text2 = text.Trim();
			if (text2.Length == 0)
			{
				continue;
			}
			int num = text2.IndexOf('-');
			if (num <= 0 || num >= text2.Length - 1 || !TryParseHours(text2.Substring(0, num), out var hours2) || !TryParseHours(text2.Substring(num + 1), out var hours3))
			{
				continue;
			}
			if (hours2 <= hours3)
			{
				if (hours >= hours2 && hours <= hours3)
				{
					return true;
				}
			}
			else if (hours >= hours2 || hours <= hours3)
			{
				return true;
			}
		}
		return false;
	}

	private static bool TryParseHours(string s, out float hours)
	{
		hours = 0f;
		if (s == null)
		{
			return false;
		}
		s = s.Trim();
		int num = s.IndexOf(':');
		if (num > 0)
		{
			if (!int.TryParse(s.Substring(0, num), out var result))
			{
				return false;
			}
			if (!int.TryParse(s.Substring(num + 1), out var result2))
			{
				return false;
			}
			hours = (float)result + (float)result2 / 60f;
			return true;
		}
		if (!float.TryParse(s, out var result3))
		{
			return false;
		}
		hours = result3;
		return true;
	}

	private static string FormatCoord(float deg, bool isLat)
	{
		string text = (isLat ? ((!(deg >= 0f)) ? "S" : "N") : ((!(deg >= 0f)) ? "W" : "E"));
		float num = Mathf.Abs(deg);
		int num2 = (int)num;
		int num3 = (int)Mathf.Round((num - (float)num2) * 60f);
		if (num3 >= 60)
		{
			num3 = 0;
			num2++;
		}
		string text2 = ((!isLat) ? num2.ToString("000") : num2.ToString("00"));
		return text2 + "°" + num3.ToString("00") + "' " + text;
	}

	private string FormatCoordDisplay(float deg, bool isLat)
	{
		string text = _coordFormatConfig.Value ?? "decimal";
		if (text.Trim().ToLowerInvariant() == "degmin")
		{
			return FormatCoord(deg, isLat);
		}
		return deg.ToString("F2") + "°";
	}

	private string LastKnownSuffix(string fixTime)
	{
		if (string.IsNullOrEmpty(fixTime))
		{
			return "  (Last Known)";
		}
		return "  (Last Known " + fixTime + ")";
	}

	private static string PressureWord(float mb)
	{
		if (mb < 965f)
		{
			return "Stormy";
		}
		if (mb < 990f)
		{
			return "Rain";
		}
		if (mb < 1015f)
		{
			return "Change";
		}
		if (mb < 1040f)
		{
			return "Fair";
		}
		return "Very Dry";
	}

	private bool IsDenseFogRunning()
	{
		if (!_fogResolved)
		{
			if (_fogResolveAttempts >= 10)
			{
				return false;
			}
			_fogResolveAttempts++;
			Type type = AccessTools.TypeByName("RandomEncounters.DenseFog");
			if (type != null)
			{
				_fogIsRunningGetter = AccessTools.Method(type, "get_IsRunning", (Type[])null, (Type[])null);
				if (_fogIsRunningGetter != null && _fogIsRunningGetter.IsStatic)
				{
					_fogResolved = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[InstrumentDisplay] Random Encounters mod detected - dense fog will block celestial sights.");
				}
			}
			if (!_fogResolved)
			{
				return false;
			}
		}
		try
		{
			object obj = _fogIsRunningGetter.Invoke(null, null);
			return obj is bool && (bool)obj;
		}
		catch (Exception)
		{
			return false;
		}
	}

	private static bool IsNonHullName(string name)
	{
		return ContainsToken(name, NonHullTokens);
	}

	private static bool ContainsToken(string name, string[] tokens)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		for (int i = 0; i < tokens.Length; i++)
		{
			if (name.IndexOf(tokens[i], StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsRiggingName(string name)
	{
		return ContainsToken(name, RiggingTokens);
	}

	private static bool IsHullDeckName(string name)
	{
		return ContainsToken(name, HullDeckTokens);
	}

	private void UpdateBuoyancyDims(Transform boat)
	{
		//IL_014c: 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)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		if (_buoyancyType == null || _buoyancyBlobsField == null)
		{
			_buoyDbg = "no-type";
			return;
		}
		if ((Object)(object)_buoyBoat != (Object)(object)boat || _buoyComps == null)
		{
			_buoyBoat = boat;
			Transform val = ((!((Object)(object)boat.root != (Object)null)) ? boat : boat.root);
			_buoyComps = ((Component)val).GetComponentsInChildren(_buoyancyType, true);
		}
		if (_buoyComps == null || _buoyComps.Length == 0)
		{
			_buoyDbg = "no-comp";
			return;
		}
		float num = float.PositiveInfinity;
		float num2 = float.NegativeInfinity;
		float num3 = float.PositiveInfinity;
		float num4 = float.NegativeInfinity;
		int num5 = 0;
		for (int i = 0; i < _buoyComps.Length; i++)
		{
			Component val2 = _buoyComps[i];
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			object value;
			try
			{
				value = _buoyancyBlobsField.GetValue(val2);
			}
			catch (Exception)
			{
				continue;
			}
			if (!(value is IEnumerable enumerable))
			{
				continue;
			}
			Transform transform = val2.transform;
			foreach (object item in enumerable)
			{
				if (item is Vector3)
				{
					Vector3 val3 = boat.InverseTransformPoint(transform.TransformPoint((Vector3)item));
					if (val3.x < num)
					{
						num = val3.x;
					}
					if (val3.x > num2)
					{
						num2 = val3.x;
					}
					if (val3.y < num3)
					{
						num3 = val3.y;
					}
					if (val3.y > num4)
					{
						num4 = val3.y;
					}
					num5++;
				}
			}
		}
		if (num5 < 3)
		{
			TryMeshBeam(boat);
			if (!float.IsNaN(_meshBeam))
			{
				_buoyBeam = _meshBeam;
				_buoyDepth = float.NaN;
				_buoyKeelLocalUp = _meshKeel;
				_buoyDbg = "mesh b=" + _meshBeam.ToString("F1");
			}
			else
			{
				_buoyDbg = "blobs=" + num5 + ((_meshBeamTries <= 8) ? " mesh:..." : " mesh:unreadable");
				_buoyBeam = float.NaN;
			}
		}
		else
		{
			_buoyBeam = num2 - num;
			_buoyDepth = num4 - num3;
			_buoyKeelLocalUp = num3;
			_buoyDbg = "ok n=" + num5;
		}
	}

	private void TryMeshBeam(Transform boat)
	{
		//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_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: 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)
		if ((Object)(object)_meshBeamBoat != (Object)(object)boat)
		{
			_meshBeamBoat = boat;
			_meshBeam = float.NaN;
			_meshKeel = float.NaN;
			_meshBeamTries = 0;
		}
		if (!float.IsNaN(_meshBeam) || _meshBeamTries > 8)
		{
			return;
		}
		_meshBeamTries++;
		Collider[] componentsInChildren = ((Component)boat).GetComponentsInChildren<Collider>(true);
		float num = float.NaN;
		float meshKeel = float.NaN;
		float num2 = 0f;
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Collider obj = componentsInChildren[i];
			MeshCollider val = (MeshCollider)(object)((obj is MeshCollider) ? obj : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || !val.sharedMesh.isReadable || (Object)(object)((Component)componentsInChildren[i]).GetComponentInParent<ItemRigidbody>() != (Object)null || IsNonHullName(((Object)componentsInChildren[i]).name))
			{
				continue;
			}
			Vector3[] vertices = val.sharedMesh.vertices;
			if (vertices.Length < 12)
			{
				continue;
			}
			Transform transform = ((Component)val).transform;
			float num3 = float.PositiveInfinity;
			float num4 = float.NegativeInfinity;
			for (int j = 0; j < vertices.Length; j++)
			{
				float y = boat.InverseTransformPoint(transform.TransformPoint(vertices[j])).y;
				if (y < num3)
				{
					num3 = y;
				}
				if (y > num4)
				{
					num4 = y;
				}
			}
			if (num4 - num3 < 0.5f || num3 < -30f || num3 > 5f || num4 - num3 > 60f)
			{
				continue;
			}
			float num5 = num3 + (num4 - num3) * 0.45f;
			float num6 = float.PositiveInfinity;
			float num7 = float.NegativeInfinity;
			float num8 = float.PositiveInfinity;
			float num9 = float.NegativeInfinity;
			for (int k = 0; k < vertices.Length; k++)
			{
				Vector3 val2 = boat.InverseTransformPoint(transform.TransformPoint(vertices[k]));
				if (!(val2.y > num5))
				{
					if (val2.x < num6)
					{
						num6 = val2.x;
					}
					if (val2.x > num7)
					{
						num7 = val2.x;
					}
					if (val2.z < num8)
					{
						num8 = val2.z;
					}
					if (val2.z > num9)
					{
						num9 = val2.z;
					}
				}
			}
			float num10 = num7 - num6;
			if (!(num10 < 0.5f) && !(num10 > 60f))
			{
				float num11 = num10 * (num9 - num8);
				if (num11 > num2)
				{
					num2 = num11;
					num = num10;
					meshKeel = num3;
				}
			}
		}
		if (!float.IsNaN(num))
		{
			_meshBeam = num;
			_meshKeel = meshKeel;
		}
	}

	private void UpdateSounding(Transform boat, Rigidbody boatRigidbody)
	{
		//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_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: 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_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: 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_016c: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0516: Unknown result type (might be due to invalid IL or missing references)
		//IL_051b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0546: Unknown result type (might be due to invalid IL or missing references)
		//IL_053c: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_054b: Unknown result type (might be due to invalid IL or missing references)
		//IL_054e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0553: Unknown result type (might be due to invalid IL or missing references)
		//IL_0828: Unknown result type (might be due to invalid IL or missing references)
		//IL_082a: Unknown result type (might be due to invalid IL or missing references)
		//IL_057e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0574: Unknown result type (might be due to invalid IL or missing references)
		//IL_0583: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05df: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_060a: Unknown result type (might be due to invalid IL or missing references)
		//IL_060e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0613: Unknown result type (might be due to invalid IL or missing references)
		//IL_061f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0624: Unknown result type (might be due to invalid IL or missing references)
		//IL_0629: Unknown result type (might be due to invalid IL or missing references)
		//IL_0638: Unknown result type (might be due to invalid IL or missing references)
		//IL_0643: Unknown result type (might be due to invalid IL or missing references)
		//IL_0648: Unknown result type (might be due to invalid IL or missing references)
		//IL_064d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c9a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c9f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a51: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a56: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a81: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a86: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a2f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a34: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a0e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a13: Unknown result type (might be due to invalid IL or missing references)
		_snapKeelClearance = 999f;
		_snapSeaDepth = 999f;
		_snapGrounded = false;
		_snapKeelHitName = "(no hit)";
		Vector3 up = boat.up;
		Vector3 right = boat.right;
		Vector3 position = boat.position;
		float num = float.PositiveInfinity;
		float num2 = float.NegativeInfinity;
		float num3 = float.NegativeInfinity;
		float num4 = -1f;
		float num5 = 0f;
		string snapBeamSource = "(none)";
		Collider[] componentsInChildren = ((Component)boat).GetComponentsInChildren<Collider>();
		Collider[] array = componentsInChildren;
		Vector3 val2 = default(Vector3);
		foreach (Collider val in array)
		{
			if ((Object)(object)val == (Object)null || val.isTrigger || !val.enabled || (Object)(object)((Component)val).GetComponentInParent<ItemRigidbody>() != (Object)null || IsNonHullName(((Object)val).name))
			{
				continue;
			}
			Bounds bounds = val.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			float num6 = float.PositiveInfinity;
			float num7 = float.NegativeInfinity;
			float num8 = 0f;
			for (int j = -1; j <= 1; j += 2)
			{
				for (int k = -1; k <= 1; k += 2)
				{
					for (int l = -1; l <= 1; l += 2)
					{
						((Vector3)(ref val2))..ctor(center.x + (float)j * extents.x, center.y + (float)k * extents.y, center.z + (float)l * extents.z);
						Vector3 val3 = val2 - position;
						float num9 = Vector3.Dot(val3, up);
						if (num9 < num6)
						{
							num6 = num9;
						}
						if (num9 > num7)
						{
							num7 = num9;
						}
						float num10 = Mathf.Abs(Vector3.Dot(val3, right));
						if (num10 > num8)
						{
							num8 = num10;
						}
					}
				}
			}
			if (num6 < num)
			{
				num = num6;
			}
			string name = ((Object)val).name;
			if (!IsRiggingName(name))
			{
				if (IsHullDeckName(name) && num7 > num2)
				{
					num2 = num7;
				}
				float num11 = ((Bounds)(ref bounds)).size.x * ((Bounds)(ref bounds)).size.y * ((Bounds)(ref bounds)).size.z;
				if (num11 > num4)
				{
					num4 = num11;
					num3 = num7;
					num5 = num8;
					snapBeamSource = name;
				}
			}
		}
		_snapBeamSource = snapBeamSource;
		if (float.IsPositiveInfinity(num))
		{
			num = 0f;
		}
		float num12 = (float.IsNegativeInfinity(num2) ? num3 : num2);
		if ((Object)(object)_hullGeomBoat != (Object)(object)boat)
		{
			_hullGeomBoat = boat;
			_deckTopLocalStable = float.NaN;
			_keelBottomLocalStable = float.NaN;
			_beamStable = float.NaN;
			_maxFreeboardSeen = 0f;
			_buoyComps = null;
			_buoyBoat = null;
			_buoyBeam = float.NaN;
			_buoyDepth = float.NaN;
			_buoyKeelLocalUp = float.NaN;
		}
		UpdateBuoyancyDims(boat);
		float num13 = (float.IsNaN(_buoyBeam) ? (num5 * 2f) : _buoyBeam);
		if (num13 > 0.1f)
		{
			if (float.IsNaN(_beamStable))
			{
				_beamStable = num13;
			}
			else if (Mathf.Abs(num13 - _beamStable) <= _beamStable * 0.35f + 0.5f)
			{
				_beamStable = Mathf.Lerp(_beamStable, num13, 0.04f);
			}
		}
		if (!float.IsNegativeInfinity(num12))
		{
			if (float.IsNaN(_deckTopLocalStable))
			{
				_deckTopLocalStable = num12;
			}
			else if (Mathf.Abs(num12 - _deckTopLocalStable) <= Mathf.Abs(_deckTopLocalStable) * 0.35f + 0.5f)
			{
				_deckTopLocalStable = Mathf.Lerp(_deckTopLocalStable, num12, 0.04f);
			}
		}
		if (float.IsNaN(_keelBottomLocalStable))
		{
			_keelBottomLocalStable = num;
		}
		else if (Mathf.Abs(num - _keelBottomLocalStable) <= Mathf.Abs(_keelBottomLocalStable) * 0.35f + 0.5f)
		{
			_keelBottomLocalStable = Mathf.Lerp(_keelBottomLocalStable, num, 0.04f);
		}
		float num14 = ((!float.IsNaN(_deckTopLocalStable)) ? _deckTopLocalStable : num12);
		float num15 = ((!float.IsNaN(_keelBottomLocalStable)) ? _keelBottomLocalStable : num);
		float num16 = position.y + num * up.y;
		float num17 = position.y + num15 * up.y;
		float num18 = ((!float.IsNegativeInfinity(num12)) ? (position.y + num14 * up.y) : float.NegativeInfinity);
		float num19 = 0f;
		Ocean singleton = Ocean.Singleton;
		if ((Object)(object)singleton != (Object)null)
		{
			Vector3 val4 = boat.forward;
			val4.y = 0f;
			val4 = ((!(((Vector3)(ref val4)).sqrMagnitude > 0.0001f)) ? Vector3.forward : ((Vector3)(ref val4)).normalized);
			Vector3 val5 = boat.right;
			val5.y = 0f;
			val5 = ((!(((Vector3)(ref val5)).sqrMagnitude > 0.0001f)) ? Vector3.right : ((Vector3)(ref val5)).normalized);
			float num20 = Mathf.Max(2f, (num12 - num) * 1.5f);
			float num21 = Mathf.Max(1.5f, num20 * 0.4f);
			Vector3 position2 = boat.position;
			float num22 = 0f;
			int num23 = 0;
			Vector3[] array2 = (Vector3[])(object)new Vector3[5]
			{
				Vector3.zero,
				val4 * num20,
				val4 * (0f - num20),
				val5 * num21,
				val5 * (0f - num21)
			};
			for (int m = 0; m < array2.Length; m++)
			{
				Vector3 val6 = position2 + array2[m];
				num22 += singleton.GetWaterHeightAtLocation2(val6.x, val6.z);
				num23++;
			}
			num19 = num22 / (float)num23;
		}
		if (!float.IsNegativeInfinity(num18))
		{
			float num24 = (_snapHullHeight = num14 - num15);
			_snapKeelY = num17;
			float num25 = num19 - num17;
			if (num25 < 0f)
			{
				num25 = 0f;
			}
			float num26 = num18 - num19;
			if (num26 < 0f)
			{
				num26 = 0f;
			}
			if (num24 > 0f && num26 > num24)
			{
				num26 = num24;
			}
			if (!_freeboardInitialized)
			{
				_snapFreeboard = num26;
				_snapDraft = num25;
				_freeboardInitialized = true;
			}
			else
			{
				float num27 = 1f - Mathf.Exp(-1f / 35f);
				_snapFreeboard = Mathf.Lerp(_snapFreeboard, num26, num27);
				_snapDraft = Mathf.Lerp(_snapDraft, num25, num27);
			}
			if (_snapFreeboard > _maxFreeboardSeen)
			{
				_maxFreeboardSeen = _snapFreeboard;
			}
			else
			{
				_maxFreeboardSeen = Mathf.Lerp(_maxFreeboardSeen, _snapFreeboard, 0.0005f);
			}
		}
		Transform val7 = null;
		Transform val8 = null;
		BoatRefs component = ((Component)boat).GetComponent<BoatRefs>();
		if ((Object)(object)component != (Object)null)
		{
			val7 = component.walkCol;
			val8 = component.boatModel;
		}
		Vector3 val9 = default(Vector3);
		((Vector3)(ref val9))..ctor(boat.position.x, boat.position.y + 5f, boat.position.z);
		int num28 = -277;
		int num29 = LayerMask.NameToLayer("water");
		if (num29 >= 0)
		{
			num28 &= ~(1 << num29);
		}
		RaycastHit[] array3 = Physics.RaycastAll(val9, Vector3.down, 300f, num28, (QueryTriggerInteraction)1);
		bool flag = false;
		float num30 = float.NegativeInfinity;
		string snapKeelHitName = string.Empty;
		bool flag2 = false;
		float num31 = float.NegativeInfinity;
		string text = string.Empty;
		for (int n = 0; n < array3.Length; n++)
		{
			Collider collider = ((RaycastHit)(ref array3[n])).collider;
			if ((Object)(object)collider == (Object)null || (Object)(object)collider.attachedRigidbody != (Object)null)
			{
				continue;
			}
			Transform transform = ((Component)collider).transform;
			if (transform.IsChildOf(boat) || ((Object)(object)val7 != (Object)null && transform.IsChildOf(val7)) || ((Object)(object)val8 != (Object)null && transform.IsChildOf(val8)) || ((Component)collider).gameObject.tag == "WalkColBoat")
			{
				continue;
			}
			string text2 = ((!((Object)(object)transform.root != (Object)null)) ? string.Empty : ((Object)transform.root).name);
			if (!text2.StartsWith("BOAT", StringComparison.OrdinalIgnoreCase) && !text2.StartsWith("WALK", StringComparison.OrdinalIgnoreCase))
			{
				string name2 = ((Object)collider).name;
				if (!IsHullDeckName(name2) && !IsRiggingName(name2) && name2.IndexOf("player", StringComparison.OrdinalIgnoreCase) < 0 && name2.IndexOf("boat", StringComparison.OrdinalIgnoreCase) < 0 && text2.IndexOf("player", StringComparison.OrdinalIgnoreCase) < 0 && ((RaycastHit)(ref array3[n])).point.y <= num19 + 2f && (!flag2 || ((RaycastHit)(ref array3[n])).point.y > num31))
				{
					flag2 = true;
					num31 = ((RaycastHit)(ref array3[n])).point.y;
					text = ((Object)collider).name;
				}
				if (!(((RaycastHit)(ref array3[n])).point.y > num16 + 0.05f) && (!flag || ((RaycastHit)(ref array3[n])).point.y > num30))
				{
					flag = true;
					num30 = ((RaycastHit)(ref array3[n])).point.y;
					snapKeelHitName = ((Object)collider).name;
				}
			}
		}
		if (_debugReadoutConfig.Value)
		{
			_dbgGroundInfo = ((!flag2) ? "(none)" : (text + " gY=" + num31.ToString("F2"))) + "  kY=" + num16.ToString("F2") + "  wY=" + num19.ToString("F2");
		}
		bool flag3 = flag2 && num31 >= num16 - 0.02f;
		if (flag3 != _groundedLoggedState)
		{
			_groundedLoggedState = flag3;
			if (_debugReadoutConfig.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[InstrumentDisplay] Ground state -> " + ((!flag3) ? "afloat" : "GROUNDED") + "  hit='" + ((!flag2) ? "(none)" : text) + "'  groundY=" + num31.ToString("F2") + "  keelY=" + num16.ToString("F2") + "  waterY=" + num19.ToString("F2")));
			}
		}
		if (flag3)
		{
			_snapGrounded = true;
			_snapKeelClearance = 0f;
			float num32 = num19 - num31;
			if (num32 < 0f)
			{
				num32 = 0f;
			}
			_snapSeaDepth = num32;
			_snapKeelHitName = text;
		}
		else if (flag)
		{
			_snapKeelClearance = num16 - num30;
			if (_snapKeelClearance < 0f)
			{
				_snapKeelClearance = 0f;
			}
			_snapSeaDepth = boat.position.y - num30;
			_snapKeelHitName = snapKeelHitName;
		}
	}

	private Texture2D GetPanelTexture()
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		float num = Mathf.Clamp01(_panelAlphaConfig.Value);
		if ((Object)(object)_panelTexture == (Object)null || Mathf.Abs(num - _panelTextureAlpha) > 0.01f)
		{
			if ((Object)(object)_panelTexture == (Object)null)
			{
				_panelTexture = new Texture2D(1, 1, (TextureFormat)5, false);
				((Object)_panelTexture).hideFlags = (HideFlags)61;
			}
			_panelTexture.SetPixel(0, 0, new Color(0.09f, 0.07f, 0.04f, num));
			_panelTexture.Apply();
			_panelTextureAlpha = num;
		}
		return _panelTexture;
	}

	private Font GetGameFont()
	{
		string text = _fontNameConfig.Value ?? "auto";
		if (text == "default")
		{
			return null;
		}
		if (_fontSearched)
		{
			return _gameFont;
		}
		_fontSearched = true;
		Object[] array = Resources.FindObjectsOfTypeAll(typeof(Font));
		if (_debugReadoutConfig.Value)
		{
			string text2 = string.Empty;
			for (int i = 0; i < array.Length; i++)
			{
				text2 = text2 + ((i <= 0) ? string.Empty : ", ") + array[i].name;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[InstrumentDisplay] Fonts loaded by the game: " + text2));
		}
		foreach (Object obj in array)
		{
			Font val = (Font)(object)((obj is Font) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			string text3 = ((Object)val).name ?? string.Empty;
			if (text != "auto")
			{
				if (text3.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_gameFont = val;
					break;
				}
			}
			else if (text3.IndexOf("Arial", StringComparison.OrdinalIgnoreCase) < 0 && text3.Length > 0)
			{
				_gameFont = val;
				break;
			}
		}
		if ((Object)(object)_gameFont != (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[InstrumentDisplay] Using game font: " + ((Object)_gameFont).name));
		}
		return _gameFont;
	}

	private void OnGUI()
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0082: 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_0094: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_00e0: 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_0108: Expected O, but got Unknown
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Expected O, but got Unknown
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Expected O, but got Unknown
		//IL_0154: 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_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: 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_0185: 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)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: 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_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: 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_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0387: Unknown result type (might be due to invalid IL or missing references)
		//IL_038c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0393: Unknown result type (might be due to invalid IL or missing references)
		//IL_0398: Unknown result type (might be due to invalid IL or missing references)
		//IL_0540: Unknown result type (might be due to invalid IL or missing references)
		//IL_0568: Unknown result type (might be due to invalid IL or missing references)
		//IL_057d: Unknown result type (might be due to invalid IL or missing references)
		//IL_042d: Unknown result type (might be due to invalid IL or missing references)
		//IL_095a: Unknown result type (might be due to invalid IL or missing references)
		//IL_095c: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0601: Unknown result type (might be due to invalid IL or missing references)
		//IL_0629: Unknown result type (might be due to invalid IL or missing references)
		//IL_0642: Unknown result type (might be due to invalid IL or missing references)
		//IL_0adf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b07: Unknown result type (might be due to invalid IL or missing references)
		//IL_0970: Unknown result type (might be due to invalid IL or missing references)
		//IL_0975: Unknown result type (might be due to invalid IL or missing references)
		//IL_047b: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b72: Unknown result type (might be due to invalid IL or missing references)
		//IL_09af: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a49: Unknown result type (might be due to invalid IL or missing references)
		//IL_0738: Unknown result type (might be due to invalid IL or missing references)
		//IL_0751: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a72: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ca3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ca8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c90: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c95: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c7d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c82: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cdf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ee6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bf5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bfa: Unknown result type (might be due to invalid IL or missing references)
		//IL_10fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_1108: Expected O, but got Unknown
		//IL_1103: Unknown result type (might be due to invalid IL or missing references)
		//IL_1108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d22: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c11: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c16: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ddf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0815: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c2d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c32: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d90: Unknown result type (might be due to invalid IL or missing references)
		//IL_0898: Unknown result type (might be due to invalid IL or missing references)
		//IL_0885: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f87: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fa0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f5e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ed3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ecc: Unknown result type (might be due to invalid IL or missing references)
		//IL_1160: Unknown result type (might be due to invalid IL or missing references)
		//IL_116c: Unknown result type (might be due to invalid IL or missing references)
		//IL_1171: Unknown result type (might be due to invalid IL or missing references)
		//IL_1187: Unknown result type (might be due to invalid IL or missing references)
		//IL_11ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_107f: Unknown result type (might be due to invalid IL or missing references)
		//IL_1089: Expected O, but got Unknown
		//IL_1084: Unknown result type (might be due to invalid IL or missing references)
		//IL_1089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fcd: Unknown result type (might be due to invalid IL or missing references)
		//IL_10db: Unknown result type (might be due to invalid IL or missing references)
		//IL_10e5: Expected O, but got Unknown
		//IL_10e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_10e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f4b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f44: Unknown result type (might be due to invalid IL or missing references)
		//IL_11e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0931: Unknown result type (might be due to invalid IL or missing references)
		//IL_134a: Unknown result type (might be due to invalid IL or missing references)
		//IL_1337: Unknown result type (might be due to invalid IL or missing references)
		//IL_120e: Unknown result type (might be due to invalid IL or missing references)
		//IL_1213: Unknown result type (might be due to invalid IL or missing references)
		//IL_1223: Unknown result type (might be due to invalid IL or missing references)
		//IL_122a: Expected O, but got Unknown
		//IL_122c: Unknown result type (might be due to invalid IL or missing references)
		//IL_1231: Unknown result type (might be due to invalid IL or missing references)
		//IL_1242: Unknown result type (might be due to invalid IL or missing references)
		//IL_12b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_12a3: Unknown result type (might be due to invalid IL or missing references)
		if (!_snapValid || !_hudVisibleConfig.Value)
		{
			return;
		}
		float num = Mathf.Clamp01(_textAlphaConfig.Value);
		GUIStyle val = new GUIStyle();
		val.fontSize = _fontSizeConfig.Value;
		val.fontStyle = (FontStyle)0;
		Font gameFont = GetGameFont();
		if ((Object)(object)gameFont != (Object)null)
		{
			val.font = gameFont;
		}
		val.normal.textColor = new Color(0.99f, 0.97f, 0.92f, num);
		GUIStyle val2 = new GUIStyle(val);
		val2.normal.textColor = new Color(0.99f, 0.97f, 0.92f, num * 0.85f);
		GUIStyle val3 = new GUIStyle(val);
		val3.normal.textColor = new Color(0f, 0f, 0f, num * 0.8f);
		bool value = _textShadowConfig.Value;
		GUIStyle val4 = new GUIStyle(GUI.skin.button);
		val4.fontSize = 9;
		val4.padding = new RectOffset(0, 0, 0, 0);
		val4.margin = new RectOffset(0, 0, 0, 0);
		val4.alignment = (TextAnchor)4;
		Color arg = ((!(_snapHeel > _snapHeelLimit)) ? Color.white : Color.yellow);
		Color arg2 = ((_snapHullDamagePct >= 95f) ? Color.red : ((!(_snapHullDamagePct > 15f)) ? Color.white : Color.yellow));
		Color arg3 = (_snapSunk ? Color.red : ((!(_snapBilgePct > 15f)) ? Color.white : Color.yellow));
		Color arg4 = ((_snapKeelClearance <= 0.1f) ? Color.red : ((!(_snapKeelClearance < 2f)) ? Color.white : Color.yellow));
		Color arg5 = ((_snapFreeboard <= 0.15f) ? Color.red : ((!(_snapFreeboard < 0.6f)) ? Color.white : Color.yellow));
		string label;
		Color color;
		int num2 = BuildBurden(out label, out color);
		if (num2 < 0)
		{
			_burdenSevHeld = -2;
			_burdenLabelHeld = label;
			_burdenColorHeld = color;
		}
		else if (_burdenSevHeld < 0 || num2 == _burdenSevHeld)
		{
			_burdenSevHeld = num2;
			_burdenLabelHeld = label;
			_burdenColorHeld = color;
			_burdenSevCandidate = num2;
			_burdenSevTimer = 0f;
		}
		else
		{
			if (num2 == _burdenSevCandidate)
			{
				_burdenSevTimer += Time.deltaTime;
			}
			else
			{
				_burdenSevCandidate = num2;
				_burdenSevTimer = 0f;
			}
			float num3 = ((num2 <= _burdenSevHeld) ? 1.75f : 0.5f);
			if (_burdenSevTimer >= num3)
			{
				_burdenSevHeld = num2;
				_burdenLabelHeld = label;
				_burdenColorHeld = color;
				_burdenSevTimer = 0f;
			}
		}
		string burdenLabelHeld = _burdenLabelHeld;
		Color arg6 = _burdenColorHeld;
		int burdenSevHeld = _burdenSevHeld;
		if (burdenSevHeld >= 6)
		{
			float num4 = Mathf.PingPong(Time.time * 3.5f, 1f);
			arg6 = Color.Lerp(new Color(1f, 0.85f, 0.85f), Color.red, num4);
		}
		List<HudSection> sections = new List<HudSection>();
		HudSection current = null;
		Action<string, ConfigEntry<bool>> action = delegate(string name, ConfigEntry<bool> toggle)
		{
			current = new HudSection();
			current.Name = name;
			current.Toggle = toggle;
			sections.Add(current);
		};
		Action<string, Color> action2 = delegate(string text4, Color color4)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			HudLine item = new HudLine
			{
				Text = text4,
				Color = color4
			};
			current.Lines.Add(item);
		};
		Color white = Color.white;
		action("Instruments", _showInstrumentsConfig);
		if (_showInstrumentsConfig.Value)
		{
			if (_hasChipLog || !_requireChipLogConfig.Value)
			{
				action2("Speed    : " + _snapSpeedKts.ToString("F1") + " kts", white);
			}
			if (_hasCompass || !_requireCompassConfig.Value)
			{
				action2("Heading  : " + _snapHeadingDeg.ToString("000") + "° " + CompassPoint(_snapHeadingDeg), white);
			}
			if (_hasInclinometer || !_requireInclinometerForHeelConfig.Value)
			{
				string arg7 = ((!(_snapHeel < 0.05f)) ? ("Heel     : " + _snapHeel.ToString("F1") + "° " + ((!_snapHeelPort) ? "Stbd" : "Port")) : "Heel     : 0.0°");
				action2(arg7, arg);
			}
		}
		action("Cargo", _showCargoConfig);
		if (_showCargoConfig.Value)
		{
			action2("Deadweight : " + _snapDeadweightLbs.ToString("F0") + " lbs", arg6);
			action2("Freeboard  : " + _snapFreeboard.ToString("F1") + " m", arg5);
			action2("Burden     : " + burdenLabelHeld, arg6);
			if (_debugReadoutConfig.Value)
			{
				action2("Hull: " + _snapSelfMass.ToString("F0") + "  Parts: " + _snapPartsMass.ToString("F0"), white);
				action2("Total Weight