Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimAviation v0.1.2
BepInEx/plugins/ValheimAviation/ValheimAviation.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; using Valheim.SettingsGui; using ValheimAviation.BlackBox; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ValheimAviation")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+e1098061b82d04e59fc3547043f576c649761335")] [assembly: AssemblyProduct("ValheimAviation")] [assembly: AssemblyTitle("ValheimAviation")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimAviation { internal static class AviationAircraftFactory { internal static AviationController Assemble(GameObject instance, string persistentId) { instance.AddComponent<AviationWaterEffects>(); instance.AddComponent<AviationDamagePresentation>(); instance.AddComponent<AviationGroundContactPresentation>(); if (AviationConfig.NoiseEnabled) { AviationNoiseStaticTarget aviationNoiseStaticTarget = instance.AddComponent<AviationNoiseStaticTarget>(); ((StaticTarget)aviationNoiseStaticTarget).m_primaryTarget = false; ((StaticTarget)aviationNoiseStaticTarget).m_randomTarget = false; } AviationController aviationController = instance.AddComponent<AviationController>(); aviationController.PersistentId = persistentId; instance.AddComponent<AviationEnginePresentation>(); AviationEngineInteractable.Attach(aviationController); if (AviationConfig.FuelEnabled) { AviationFuelInteractable.Attach(aviationController); } return aviationController; } internal static void AttachCollisionForwarder(GameObject instance) { if ((Object)(object)instance.GetComponent<CollisionForwarder>() == (Object)null) { instance.AddComponent<CollisionForwarder>(); } } } internal static class AviationBreakup { private sealed class Chunk { public GameObject Go; public Rigidbody Body; public Collider[] Colliders; public float DieAt; public string Group; public int Serial; } internal const int MaxChunksPerAircraft = 10; internal const int MaxActiveChunks = 48; internal const int MaxBreakupsPerFrame = 3; internal const float MinLifetimeSeconds = 15f; internal const float MaxLifetimeSeconds = 20f; internal const float VelocityGraceSeconds = 0.5f; internal const float MaxSeparationSpeed = 2.2f; internal const float MaxExtraSpeed = 6f; internal const float MaxTumbleRadPerSec = 2f; internal const float NearbyAircraftRadius = 80f; internal const float NearbyCharacterRadius = 40f; internal const int MaxNearbyAircraft = 8; internal const int MaxNearbyCharacters = 24; internal const string ChunkNamePrefix = "AVIATION_BREAKUP_CHUNK_"; internal static readonly string[] GroupNames = new string[9] { "UpperWing", "LowerWing", "Frame", "Gear", "WheelL", "WheelR", "Tail", "Engine", "Propeller" }; private static readonly List<Chunk> s_chunks = new List<Chunk>(); private static bool s_unloaded; private static int s_frame = -1; private static int s_spawnsThisFrame; private static int s_serial; private static bool s_layerNoted; internal static bool AllowInEditMode; internal static Func<float> DebugNow; internal static Func<int> DebugFrame; internal static int DebugSpawnCount; internal static int DebugSkippedByFrameBudget; internal static int DebugEvictions; internal static int DebugIgnoredPairs; internal static int DebugLastChunkCount; internal static string DebugLastReport = ""; internal static int ActiveChunkCount { get { Prune(); return s_chunks.Count; } } internal static IEnumerable<GameObject> DebugActiveChunks => from c in s_chunks where (Object)(object)c.Go != (Object)null select c.Go; private static float Now() { if (DebugNow == null) { return Time.time; } return DebugNow(); } private static int Frame() { if (DebugFrame == null) { return Time.frameCount; } return DebugFrame(); } internal static string GroupOf(string rendererName, string parentName) { if (rendererName == "WheelVisual") { if (parentName == null || !parentName.EndsWith("_L", StringComparison.Ordinal)) { if (parentName == null || !parentName.EndsWith("_R", StringComparison.Ordinal)) { return "Gear"; } return "WheelR"; } return "WheelL"; } if (rendererName.StartsWith("Propeller_", StringComparison.Ordinal)) { return "Propeller"; } if (rendererName.StartsWith("Engine_", StringComparison.Ordinal) || rendererName.StartsWith("Frame_EngineCradle", StringComparison.Ordinal)) { return "Engine"; } if (rendererName.StartsWith("Wing_Upper_", StringComparison.Ordinal) || rendererName.StartsWith("Wing_Cabane", StringComparison.Ordinal) || rendererName.StartsWith("Wing_Interplane", StringComparison.Ordinal) || rendererName.StartsWith("Rigging_Wing", StringComparison.Ordinal)) { return "UpperWing"; } if (rendererName.StartsWith("Wing_Lower_", StringComparison.Ordinal)) { return "LowerWing"; } if (rendererName.StartsWith("Tail_", StringComparison.Ordinal) || rendererName.StartsWith("Gear_TailSkid", StringComparison.Ordinal) || rendererName.StartsWith("Rigging_Tail", StringComparison.Ordinal) || rendererName.StartsWith("Rigging_Boom", StringComparison.Ordinal) || rendererName.StartsWith("Frame_Boom", StringComparison.Ordinal)) { return "Tail"; } if (rendererName.StartsWith("Gear_", StringComparison.Ordinal)) { return "Gear"; } return "Frame"; } private static int Layer() { int num = LayerMask.NameToLayer("effect"); if (num >= 0) { return num; } if (!s_layerNoted) { s_layerNoted = true; Debug.Log((object)"AVIATION_BREAKUP: the native 'effect' layer is not available here (Editor): debris uses the Default layer with explicit per-collider ignore pairs only."); } return 0; } private static void Prune() { for (int num = s_chunks.Count - 1; num >= 0; num--) { if ((Object)(object)s_chunks[num].Go == (Object)null) { s_chunks.RemoveAt(num); } } } private static void Kill(Chunk c) { if (!((Object)(object)c.Go == (Object)null)) { if (Application.isPlaying) { Object.Destroy((Object)(object)c.Go); } else { Object.DestroyImmediate((Object)(object)c.Go); } c.Go = null; } } internal static void Tick() { if (s_chunks.Count == 0) { return; } float num = Now(); for (int num2 = s_chunks.Count - 1; num2 >= 0; num2--) { Chunk chunk = s_chunks[num2]; if ((Object)(object)chunk.Go == (Object)null) { s_chunks.RemoveAt(num2); } else if (num >= chunk.DieAt) { Kill(chunk); s_chunks.RemoveAt(num2); } } } internal static void DestroyAll(bool permanent) { foreach (Chunk s_chunk in s_chunks) { Kill(s_chunk); } s_chunks.Clear(); if (permanent) { s_unloaded = true; } } internal static void DebugReset() { DestroyAll(permanent: false); s_unloaded = false; AllowInEditMode = false; s_frame = -1; s_spawnsThisFrame = 0; s_serial = 0; s_layerNoted = false; DebugNow = null; DebugFrame = null; DebugSpawnCount = (DebugSkippedByFrameBudget = (DebugEvictions = (DebugIgnoredPairs = (DebugLastChunkCount = 0)))); DebugLastReport = ""; } internal static int Spawn(Transform hullRoot, Vector3 com, Vector3 linearVelocity, Vector3 angularVelocity, float velocityAgeSeconds, string label) { //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if (s_unloaded || (Object)(object)hullRoot == (Object)null) { return 0; } if (!Application.isPlaying && !AllowInEditMode) { return 0; } Prune(); Tick(); int num = Frame(); if (num != s_frame) { s_frame = num; s_spawnsThisFrame = 0; } if (s_spawnsThisFrame >= 3) { DebugSkippedByFrameBudget++; return 0; } Dictionary<string, List<MeshRenderer>> dictionary = new Dictionary<string, List<MeshRenderer>>(); MeshRenderer[] componentsInChildren = ((Component)hullRoot).GetComponentsInChildren<MeshRenderer>(false); foreach (MeshRenderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || !((Renderer)val).enabled || !((Component)val).gameObject.activeInHierarchy || ((Object)val).name.StartsWith("AVIATION_BREAKUP_CHUNK_", StringComparison.Ordinal)) { continue; } MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null)) { string key = GroupOf(((Object)val).name, ((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Object)((Component)val).transform.parent).name : null); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List<MeshRenderer>()); } value.Add(val); } } if (dictionary.Count == 0) { return 0; } int num2 = Math.Min(dictionary.Count, 10); while (s_chunks.Count + num2 > 48 && s_chunks.Count > 0) { Kill(s_chunks[0]); s_chunks.RemoveAt(0); DebugEvictions++; } if (s_chunks.Count + num2 > 48) { return 0; } int num3 = Layer(); float num4 = ((velocityAgeSeconds <= 0.5f) ? 1f : Mathf.Clamp01(1f - (velocityAgeSeconds - 0.5f) / 1f)); Vector3 baseVelocity = linearVelocity * num4; Vector3 baseAngular = angularVelocity * num4; float now = Now(); List<Chunk> list2 = new List<Chunk>(); foreach (string item in GroupNames.Where(dictionary.ContainsKey).Concat(dictionary.Keys.Where((string k) => !GroupNames.Contains(k))).Take(10)) { try { Chunk chunk = BuildChunk(item, dictionary[item], hullRoot.rotation, com, baseVelocity, baseAngular, num3, now); if (chunk != null) { list2.Add(chunk); } } catch (Exception ex) { Debug.LogWarning((object)("AVIATION_BREAKUP: chunk '" + item + "' skipped (" + ex.Message + ")")); } } if (list2.Count == 0) { return 0; } ApplyIgnorePairs(list2, hullRoot); s_chunks.AddRange(list2); s_spawnsThisFrame++; DebugSpawnCount++; DebugLastChunkCount = list2.Count; DebugLastReport = string.Format("AVIATION_BREAKUP: '{0}' broke into {1} chunks [{2}] layer={3}, active debris {4}/{5}, lifetime {6:F0}-{7:F0} s, inherited velocity x{8:F2}.", label, list2.Count, string.Join(", ", list2.Select((Chunk c) => c.Group)), (num3 == 0) ? "Default(fallback)" : LayerMask.LayerToName(num3), s_chunks.Count, 48, 15f, 20f, num4); Debug.Log((object)DebugLastReport); return list2.Count; } private static Chunk BuildChunk(string group, List<MeshRenderer> sources, Quaternion hullRotation, Vector3 com, Vector3 baseVelocity, Vector3 baseAngular, int layer, float now) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0338: 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_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = ((Renderer)sources[0]).bounds; foreach (MeshRenderer source in sources) { ((Bounds)(ref bounds)).Encapsulate(((Renderer)source).bounds); } GameObject val = new GameObject("AVIATION_BREAKUP_CHUNK_" + group) { layer = layer }; try { val.transform.SetPositionAndRotation(((Bounds)(ref bounds)).center, hullRotation); foreach (MeshRenderer source2 in sources) { MeshFilter component = ((Component)source2).GetComponent<MeshFilter>(); GameObject val2 = new GameObject(((Object)source2).name) { layer = layer }; val2.transform.SetParent(val.transform, false); val2.transform.SetPositionAndRotation(((Component)source2).transform.position, ((Component)source2).transform.rotation); val2.transform.localScale = ((Component)source2).transform.lossyScale; val2.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh; MeshRenderer obj = val2.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterials = ((Renderer)source2).sharedMaterials; ((Renderer)obj).shadowCastingMode = ((Renderer)source2).shadowCastingMode; ((Renderer)obj).receiveShadows = ((Renderer)source2).receiveShadows; } Bounds val3 = default(Bounds); ((Bounds)(ref val3))..ctor(val.transform.InverseTransformPoint(((Bounds)(ref bounds)).center), Vector3.zero); bool flag = true; foreach (MeshRenderer source3 in sources) { Bounds bounds2 = ((Component)source3).GetComponent<MeshFilter>().sharedMesh.bounds; float[] array = new float[2] { -1f, 1f }; foreach (float num in array) { float[] array2 = new float[2] { -1f, 1f }; foreach (float num2 in array2) { float[] array3 = new float[2] { -1f, 1f }; foreach (float num3 in array3) { Vector3 val4 = val.transform.InverseTransformPoint(((Component)source3).transform.TransformPoint(((Bounds)(ref bounds2)).center + Vector3.Scale(((Bounds)(ref bounds2)).extents, new Vector3(num, num2, num3)))); if (flag) { val3 = new Bounds(val4, Vector3.zero); flag = false; } else { ((Bounds)(ref val3)).Encapsulate(val4); } } } } } BoxCollider val5 = val.AddComponent<BoxCollider>(); val5.center = ((Bounds)(ref val3)).center; val5.size = new Vector3(Mathf.Max(0.12f, ((Bounds)(ref val3)).size.x), Mathf.Max(0.12f, ((Bounds)(ref val3)).size.y), Mathf.Max(0.12f, ((Bounds)(ref val3)).size.z)); Rigidbody val6 = val.AddComponent<Rigidbody>(); val6.mass = Mathf.Clamp(5f + val5.size.x * val5.size.y * val5.size.z * 40f, 5f, 40f); val6.linearDamping = 0.05f; val6.angularDamping = 0.25f; val6.maxAngularVelocity = 8f; val6.interpolation = (RigidbodyInterpolation)0; Vector3 val7 = ((Bounds)(ref bounds)).center - com; Vector3 val8 = baseVelocity + Vector3.Cross(baseAngular, val7); Vector3 val9 = ((((Vector3)(ref val7)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val7)).normalized : Random.onUnitSphere) * Random.Range(0.8f, 2.2f) + Vector3.up * Random.Range(0.5f, 1.5f); float num4 = ((Vector3)(ref baseVelocity)).magnitude + 6f; Vector3 linearVelocity = val8 + val9; if (((Vector3)(ref linearVelocity)).magnitude > num4) { linearVelocity = ((Vector3)(ref linearVelocity)).normalized * num4; } val6.linearVelocity = linearVelocity; val6.angularVelocity = baseAngular + Random.onUnitSphere * Random.Range(0.5f, 2f); val6.collisionDetectionMode = (CollisionDetectionMode)((((Vector3)(ref linearVelocity)).magnitude > 8f) ? 2 : 0); Chunk chunk = new Chunk(); chunk.Go = val; chunk.Body = val6; chunk.Colliders = (Collider[])(object)new Collider[1] { (Collider)val5 }; chunk.DieAt = now + Random.Range(15f, 20f); chunk.Group = group; chunk.Serial = ++s_serial; return chunk; } catch { val.SetActive(false); if (Application.isPlaying) { Object.Destroy((Object)(object)val); } else { Object.DestroyImmediate((Object)(object)val); } throw; } } private static void ApplyIgnorePairs(List<Chunk> fresh, Transform hullRoot) { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) List<Collider> list = (from c in fresh.SelectMany((Chunk c) => c.Colliders) where (Object)(object)c != (Object)null select c).ToList(); for (int num = 0; num < list.Count; num++) { for (int num2 = num + 1; num2 < list.Count; num2++) { Ignore(list[num], list[num2]); } } foreach (Chunk s_chunk in s_chunks) { if (!((Object)(object)s_chunk.Go != (Object)null)) { continue; } Collider[] colliders = s_chunk.Colliders; foreach (Collider b in colliders) { foreach (Collider item in list) { Ignore(item, b); } } } Vector3 position = hullRoot.position; int num4 = 0; Vector3 val; foreach (AviationController liveInstance in AviationController.LiveInstances) { if ((Object)(object)liveInstance == (Object)null || (Object)(object)((Component)liveInstance).transform == (Object)(object)hullRoot) { continue; } val = ((Component)liveInstance).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude > 6400f) { continue; } if (num4++ >= 8) { break; } Collider[] colliders = ((Component)liveInstance).GetComponentsInChildren<Collider>(true); foreach (Collider b2 in colliders) { foreach (Collider item2 in list) { Ignore(item2, b2); } } } try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Collider[] colliders = ((Component)localPlayer).GetComponentsInChildren<Collider>(true); foreach (Collider b3 in colliders) { foreach (Collider item3 in list) { Ignore(item3, b3); } } } int num5 = 0; List<Character> allCharacters = Character.GetAllCharacters(); if (allCharacters == null) { return; } foreach (Character item4 in allCharacters) { if ((Object)(object)item4 == (Object)null) { continue; } val = ((Component)item4).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude > 1600f) { continue; } if (num5++ >= 24) { break; } Collider[] colliders = ((Component)item4).GetComponentsInChildren<Collider>(true); foreach (Collider b4 in colliders) { foreach (Collider item5 in list) { Ignore(item5, b4); } } } } catch (Exception) { } static void Ignore(Collider a, Collider val2) { if ((Object)(object)a != (Object)null && (Object)(object)val2 != (Object)null && (Object)(object)a != (Object)(object)val2) { Physics.IgnoreCollision(a, val2, true); DebugIgnoredPairs++; } } } } internal static class AviationConfig { private static ConfigEntry<float> _throttleRampPercentPerSecond; private static ConfigEntry<float> _maxThrustNewtons; private static ConfigEntry<float> _thrustFalloffSpeedMps; private static ConfigEntry<float> _lowSpeedThrustEfficiencyFloor; private static ConfigEntry<float> _lowSpeedThrustEfficiencyDipStartSpeedMps; private static ConfigEntry<float> _lowSpeedThrustEfficiencyDipEndSpeedMps; private static ConfigEntry<float> _steerTorqueNewtonMeters; private static ConfigEntry<float> _steerRampSpeedMps; private static ConfigEntry<float> _rollingResistanceCoefficient; private static ConfigEntry<float> _rollingResistanceRampSpeedMps; private static ConfigEntry<float> _groundThrustBonusNewtons; private static ConfigEntry<float> _groundThrustBonusFadeSpeedMps; private static ConfigEntry<float> _groundThrustBonusRampInSpeedMps; private static ConfigEntry<float> _groundDragBonusFraction; private static ConfigEntry<float> _groundElevatorTorqueBonusNewtonMeters; private static ConfigEntry<float> _groundElevatorTorqueBonusRampInSpeedMps; private static ConfigEntry<float> _groundThrustAlignmentExponent; private static ConfigEntry<float> _brakeForceNewtons; private static ConfigEntry<float> _brakeStaticThresholdMps; private static ConfigEntry<float> _dismountHoldSeconds; private static ConfigEntry<float> _safeDismountSpeedMps; private static ConfigEntry<float> _safeDismountAngularSpeedRadPerSec; private static ConfigEntry<float> _groundedRayLengthMeters; private static ConfigEntry<float> _controlSurfaceEaseDegPerSecond; private static ConfigEntry<float> _propellerMaxDegPerSecond; private static ConfigEntry<float> _cameraDistanceMeters; private static ConfigEntry<float> _cameraMaxDistanceMeters; private static ConfigEntry<float> _cameraPullbackRateMetersPerSecond; private static ConfigEntry<float> _cameraPullbackWindowSeconds; private static ConfigEntry<float> _wingAreaSquareMeters; private static ConfigEntry<float> _airDensityKgPerCubicMeter; private static ConfigEntry<float> _stallAngleDeg; private static ConfigEntry<float> _liftSlopePerRadian; private static ConfigEntry<float> _zeroLiftDragCoefficient; private static ConfigEntry<float> _inducedDragFactor; private static ConfigEntry<float> _elevatorControlAuthority; private static ConfigEntry<float> _aileronControlAuthority; private static ConfigEntry<float> _rudderControlAuthority; private static ConfigEntry<float> _pitchTrimAoaDeg; private static ConfigEntry<float> _pitchStabilityCoefficient; private static ConfigEntry<float> _yawStabilityCoefficient; private static ConfigEntry<float> _rollStabilityCoefficient; private static ConfigEntry<float> _pitchDampingCoefficient; private static ConfigEntry<float> _rollDampingCoefficient; private static ConfigEntry<float> _yawDampingCoefficient; private static ConfigEntry<bool> _windEnabled; private static ConfigEntry<float> _windSpeedScaleMetersPerSecond; private static ConfigEntry<bool> _stormExtrasEnabled; private static ConfigEntry<float> _stormHighIntensityWindBonusMps; private static ConfigEntry<float> _stormGustPeakVerticalMps; private static ConfigEntry<float> _stormGustPeakLateralMps; private static ConfigEntry<float> _waterReferenceDepthMeters; private static ConfigEntry<float> _waterBuoyancyCapacityMultiplier; private static ConfigEntry<float> _waterDragCoefficient; private static ConfigEntry<float> _waterAngularDragCoefficient; private static ConfigEntry<float> _waterFloodRatePerSecondAtFullImmersion; private static ConfigEntry<float> _waterEngineSubmergeMarginMeters; private static ConfigEntry<float> _waterGearContactCapacityFraction; private static ConfigEntry<bool> _waterEffectsEnabled; private static ConfigEntry<float> _waterEffectsSkimImmersionMax; private static ConfigEntry<float> _waterEffectsSkimMinSpeedMps; private static ConfigEntry<float> _waterEffectsEntryImmersionThreshold; private static ConfigEntry<float> _waterEffectsEntryMinSpeedMps; private static ConfigEntry<float> _waterEffectsPerPointCooldownSeconds; private static ConfigEntry<int> _waterEffectsMaxConcurrentInstances; private static ConfigEntry<float> _waterEffectsMaxAudioDistanceMeters; private static ConfigEntry<float> _waterEffectsSkimEffectScale; private static ConfigEntry<float> _waterEffectsEntryEffectScale; private static ConfigEntry<bool> _groundDustEnabled; private static ConfigEntry<bool> _propWashEnabled; private static ConfigEntry<KeyCode> _rudderLeftKey; private static ConfigEntry<KeyCode> _rudderRightKey; private static bool _bound; private static ConfigEntry<float> _engineRundownSeconds; public static float? DebugThrottleRampPercentPerSecondOverride; public static float? DebugLowSpeedThrustEfficiencyFloorOverride; public static float? DebugLowSpeedThrustEfficiencyDipStartSpeedMpsOverride; public static float? DebugLowSpeedThrustEfficiencyDipEndSpeedMpsOverride; public static float? DebugRollingResistanceCoefficientOverride; public static float? DebugRollingResistanceRampSpeedMpsOverride; public static float? DebugGroundThrustBonusNewtonsOverride; public static float? DebugGroundThrustBonusFadeSpeedMpsOverride; public static float? DebugGroundThrustBonusRampInSpeedMpsOverride; public static float? DebugGroundDragBonusFractionOverride; public static float? DebugGroundElevatorTorqueBonusNewtonMetersOverride; public static float? DebugGroundElevatorTorqueBonusRampInSpeedMpsOverride; public static float? DebugPropellerMaxDegPerSecondOverride; public static bool? DebugGroundDustEnabledOverride; public static bool? DebugPropWashEnabledOverride; public static float? DebugElevatorControlAuthorityOverride; public static float? DebugWindSpeedScaleOverride; public static bool? DebugStormExtrasEnabledOverride; public static float? DebugStormHighIntensityWindBonusMpsOverride; private static ConfigEntry<bool> _fuelEnabled; private static ConfigEntry<float> _fuelCapacityUnits; private static ConfigEntry<float> _fuelUnitsPerItem; private static ConfigEntry<float> _refuelSeconds; private static ConfigEntry<float> _fuelConsumptionFullPerMinute; private static ConfigEntry<float> _fuelConsumptionIdlePerMinute; public static bool? DebugFuelEnabledOverride; public static float? DebugFuelUnitsPerItemOverride; public static float? DebugRefuelSecondsOverride; private static ConfigEntry<bool> _damageEnabled; private static ConfigEntry<float> _maxHealth; private static ConfigEntry<float> _impactDamageThresholdMps; private static ConfigEntry<float> _impactDamagePerMpsAboveThreshold; private static ConfigEntry<float> _spawnDamageGraceSeconds; public static bool? DebugDamageEnabledOverride; private static ConfigEntry<bool> _propellerContactEnabled; public static bool? DebugPropellerContactEnabledOverride; private static ConfigEntry<bool> _wreckDecayEnabled; private static ConfigEntry<float> _wreckDecayGraceDays; private static ConfigEntry<float> _wreckDecayDurationDays; public static bool? DebugWreckDecayEnabledOverride; private static ConfigEntry<bool> _wreckPartialEnabled; private static ConfigEntry<float> _wreckPartialLossFraction; public static bool? DebugWreckPartialEnabledOverride; private static ConfigEntry<bool> _wreckRainEnabled; private static ConfigEntry<float> _wreckRainLossFraction; public static bool? DebugWreckRainEnabledOverride; private static ConfigEntry<bool> _noiseEnabled; private static ConfigEntry<float> _noiseIdleRangeMeters; private static ConfigEntry<float> _noiseFullRangeMeters; private static ConfigEntry<float> _noisePulseIntervalSeconds; private static ConfigEntry<float> _noiseListenerExpirySeconds; public static bool? DebugNoiseEnabledOverride; private static ConfigEntry<bool> _flightRecorderEnabled; private static ConfigEntry<float> _flightRecorderSampleHz; private static ConfigEntry<float> _flightRecorderTerrainPollHz; private static ConfigEntry<float> _flightRecorderFlushIntervalSeconds; private static ConfigEntry<long> _flightRecorderMaxBytesPerFlight; private static ConfigEntry<long> _flightRecorderMaxTotalBytes; private static ConfigEntry<bool> _showPilotDiagnostics; internal static KeyCode RudderLeftKey => (KeyCode)(((??)_rudderLeftKey?.Value) ?? 113); internal static KeyCode RudderRightKey => (KeyCode)(((??)_rudderRightKey?.Value) ?? 101); internal static float EngineRundownSeconds => _engineRundownSeconds?.Value ?? 9f; internal static float ThrottleRampPercentPerSecond => DebugThrottleRampPercentPerSecondOverride ?? _throttleRampPercentPerSecond?.Value ?? 12.5f; internal static float MaxThrustNewtons => _maxThrustNewtons?.Value ?? 3000f; internal static float ThrustFalloffSpeedMps => _thrustFalloffSpeedMps?.Value ?? 11.4f; internal static float LowSpeedThrustEfficiencyFloor => DebugLowSpeedThrustEfficiencyFloorOverride ?? _lowSpeedThrustEfficiencyFloor?.Value ?? 1f; internal static float LowSpeedThrustEfficiencyDipStartSpeedMps => DebugLowSpeedThrustEfficiencyDipStartSpeedMpsOverride ?? _lowSpeedThrustEfficiencyDipStartSpeedMps?.Value ?? 0f; internal static float LowSpeedThrustEfficiencyDipEndSpeedMps => DebugLowSpeedThrustEfficiencyDipEndSpeedMpsOverride ?? _lowSpeedThrustEfficiencyDipEndSpeedMps?.Value ?? 0f; internal static float SteerTorqueNewtonMeters => _steerTorqueNewtonMeters?.Value ?? 4500f; internal static float SteerRampSpeedMps => _steerRampSpeedMps?.Value ?? 1.5f; internal static float RollingResistanceCoefficient => DebugRollingResistanceCoefficientOverride ?? _rollingResistanceCoefficient?.Value ?? 0.19f; internal static float RollingResistanceRampSpeedMps => DebugRollingResistanceRampSpeedMpsOverride ?? _rollingResistanceRampSpeedMps?.Value ?? 5f; internal static float GroundThrustBonusNewtons => DebugGroundThrustBonusNewtonsOverride ?? _groundThrustBonusNewtons?.Value ?? 1100f; internal static float GroundThrustBonusFadeSpeedMps => DebugGroundThrustBonusFadeSpeedMpsOverride ?? _groundThrustBonusFadeSpeedMps?.Value ?? 9f; internal static float GroundThrustBonusRampInSpeedMps => DebugGroundThrustBonusRampInSpeedMpsOverride ?? _groundThrustBonusRampInSpeedMps?.Value ?? 2f; internal static float GroundDragBonusFraction => DebugGroundDragBonusFractionOverride ?? _groundDragBonusFraction?.Value ?? 1.4f; internal static float GroundElevatorTorqueBonusNewtonMeters => DebugGroundElevatorTorqueBonusNewtonMetersOverride ?? _groundElevatorTorqueBonusNewtonMeters?.Value ?? 2200f; internal static float GroundElevatorTorqueBonusRampInSpeedMps => DebugGroundElevatorTorqueBonusRampInSpeedMpsOverride ?? _groundElevatorTorqueBonusRampInSpeedMps?.Value ?? 6.5f; internal static float GroundThrustAlignmentExponent => _groundThrustAlignmentExponent?.Value ?? 0.35f; internal static float BrakeForceNewtons => _brakeForceNewtons?.Value ?? 4000f; internal static float BrakeStaticThresholdMps => _brakeStaticThresholdMps?.Value ?? 0.15f; internal static float DismountHoldSeconds => _dismountHoldSeconds?.Value ?? 1f; internal static float SafeDismountSpeedMps => _safeDismountSpeedMps?.Value ?? 0.5f; internal static float SafeDismountAngularSpeedRadPerSec => _safeDismountAngularSpeedRadPerSec?.Value ?? 0.3f; internal static float GroundedRayLengthMeters => _groundedRayLengthMeters?.Value ?? 0.45f; internal static float ControlSurfaceEaseDegPerSecond => _controlSurfaceEaseDegPerSecond?.Value ?? 60f; internal static float PropellerMaxDegPerSecond => DebugPropellerMaxDegPerSecondOverride ?? _propellerMaxDegPerSecond?.Value ?? 3600f; internal static float CameraDistanceMeters => _cameraDistanceMeters?.Value ?? 14f; internal static float CameraMaxDistanceMeters => _cameraMaxDistanceMeters?.Value ?? 22f; internal static float CameraPullbackRateMetersPerSecond => _cameraPullbackRateMetersPerSecond?.Value ?? 8f; internal static float CameraPullbackWindowSeconds => _cameraPullbackWindowSeconds?.Value ?? 3f; internal static float WaterReferenceDepthMeters => _waterReferenceDepthMeters?.Value ?? 0.6f; internal static float WaterBuoyancyCapacityMultiplier => _waterBuoyancyCapacityMultiplier?.Value ?? 1.8f; internal static float WaterDragCoefficient => _waterDragCoefficient?.Value ?? 35000f; internal static float WaterAngularDragCoefficient => _waterAngularDragCoefficient?.Value ?? 8f; internal static float WaterFloodRatePerSecondAtFullImmersion => _waterFloodRatePerSecondAtFullImmersion?.Value ?? 0.07f; internal static float WaterEngineSubmergeMarginMeters => _waterEngineSubmergeMarginMeters?.Value ?? 0.05f; internal static float WaterGearContactCapacityFraction => _waterGearContactCapacityFraction?.Value ?? 0.014f; internal static bool WaterEffectsEnabled => _waterEffectsEnabled?.Value ?? true; internal static float WaterEffectsSkimImmersionMax => _waterEffectsSkimImmersionMax?.Value ?? 0.35f; internal static float WaterEffectsSkimMinSpeedMps => _waterEffectsSkimMinSpeedMps?.Value ?? 0.5f; internal static float WaterEffectsEntryImmersionThreshold => _waterEffectsEntryImmersionThreshold?.Value ?? 0.2f; internal static float WaterEffectsEntryMinSpeedMps => _waterEffectsEntryMinSpeedMps?.Value ?? 2f; internal static float WaterEffectsPerPointCooldownSeconds => _waterEffectsPerPointCooldownSeconds?.Value ?? 0.2f; internal static int WaterEffectsMaxConcurrentInstances => _waterEffectsMaxConcurrentInstances?.Value ?? 8; internal static float WaterEffectsMaxAudioDistanceMeters => _waterEffectsMaxAudioDistanceMeters?.Value ?? 40f; internal static float WaterEffectsSkimEffectScale => _waterEffectsSkimEffectScale?.Value ?? 0.35f; internal static float WaterEffectsEntryEffectScale => _waterEffectsEntryEffectScale?.Value ?? 1.2f; internal static bool GroundDustEnabled => DebugGroundDustEnabledOverride ?? _groundDustEnabled?.Value ?? true; internal static bool PropWashEnabled => DebugPropWashEnabledOverride ?? _propWashEnabled?.Value ?? true; internal static float WingAreaSquareMeters => _wingAreaSquareMeters?.Value ?? 45f; internal static float AirDensityKgPerCubicMeter => _airDensityKgPerCubicMeter?.Value ?? 1.2f; internal static float StallAngleDeg => _stallAngleDeg?.Value ?? 16f; internal static float LiftSlopePerRadian => _liftSlopePerRadian?.Value ?? 6f; internal static float ZeroLiftDragCoefficient => _zeroLiftDragCoefficient?.Value ?? 0.15f; internal static float InducedDragFactor => _inducedDragFactor?.Value ?? 0.05f; internal static float ElevatorControlAuthority => DebugElevatorControlAuthorityOverride ?? _elevatorControlAuthority?.Value ?? 5f; internal static float AileronControlAuthority => _aileronControlAuthority?.Value ?? 70f; internal static float RudderControlAuthority => _rudderControlAuthority?.Value ?? 60f; internal static float PitchTrimAoaDeg => _pitchTrimAoaDeg?.Value ?? 8.25f; internal static float PitchStabilityCoefficient => _pitchStabilityCoefficient?.Value ?? 17f; internal static float YawStabilityCoefficient => _yawStabilityCoefficient?.Value ?? 25f; internal static float RollStabilityCoefficient => _rollStabilityCoefficient?.Value ?? 20f; internal static float PitchDampingCoefficient => _pitchDampingCoefficient?.Value ?? 30f; internal static float RollDampingCoefficient => _rollDampingCoefficient?.Value ?? 60f; internal static float YawDampingCoefficient => _yawDampingCoefficient?.Value ?? 86f; internal static bool WindEnabled => _windEnabled?.Value ?? false; internal static float WindSpeedScaleMetersPerSecond => DebugWindSpeedScaleOverride ?? _windSpeedScaleMetersPerSecond?.Value ?? 10f; internal static bool StormExtrasEnabled => DebugStormExtrasEnabledOverride ?? _stormExtrasEnabled?.Value ?? false; internal static float StormHighIntensityWindBonusMps => DebugStormHighIntensityWindBonusMpsOverride ?? _stormHighIntensityWindBonusMps?.Value ?? 0f; internal static float StormGustPeakVerticalMps => _stormGustPeakVerticalMps?.Value ?? 0.75f; internal static float StormGustPeakLateralMps => _stormGustPeakLateralMps?.Value ?? 0.5f; internal static bool FuelEnabled => DebugFuelEnabledOverride ?? _fuelEnabled?.Value ?? false; internal static float FuelCapacityUnits => _fuelCapacityUnits?.Value ?? 10f; internal static float FuelUnitsPerItem => DebugFuelUnitsPerItemOverride ?? _fuelUnitsPerItem?.Value ?? 2.5f; internal static float RefuelSeconds => AviationMath.SanitizeRefuelSeconds(DebugRefuelSecondsOverride ?? _refuelSeconds?.Value ?? 3f); internal static float FuelConsumptionFullPerMinute => _fuelConsumptionFullPerMinute?.Value ?? 1f; internal static float FuelConsumptionIdlePerMinute => _fuelConsumptionIdlePerMinute?.Value ?? 0.625f; internal static bool DamageEnabled => DebugDamageEnabledOverride ?? _damageEnabled?.Value ?? false; internal static float MaxHealth => _maxHealth?.Value ?? 100f; internal static bool PropellerContactEnabled => DebugPropellerContactEnabledOverride ?? _propellerContactEnabled?.Value ?? true; internal static float ImpactDamageThresholdMps => _impactDamageThresholdMps?.Value ?? 4f; internal static float ImpactDamagePerMpsAboveThreshold => _impactDamagePerMpsAboveThreshold?.Value ?? 15f; internal static float SpawnDamageGraceSeconds => _spawnDamageGraceSeconds?.Value ?? 3f; internal static bool WreckDecayEnabled => DebugWreckDecayEnabledOverride ?? _wreckDecayEnabled?.Value ?? true; internal static float WreckDecayGraceDays => _wreckDecayGraceDays?.Value ?? 1f; internal static float WreckDecayDurationDays => _wreckDecayDurationDays?.Value ?? 3f; internal static bool WreckPartialWeatheringEnabled => DebugWreckPartialEnabledOverride ?? _wreckPartialEnabled?.Value ?? true; internal static float WreckPartialLossFraction => _wreckPartialLossFraction?.Value ?? 0.5f; internal static bool WreckRainWeatheringEnabled => DebugWreckRainEnabledOverride ?? _wreckRainEnabled?.Value ?? true; internal static float WreckRainLossFraction => _wreckRainLossFraction?.Value ?? 0.5f; internal static bool NoiseEnabled => DebugNoiseEnabledOverride ?? _noiseEnabled?.Value ?? false; internal static float NoiseIdleRangeMeters => _noiseIdleRangeMeters?.Value ?? 20f; internal static float NoiseFullRangeMeters => _noiseFullRangeMeters?.Value ?? 40f; internal static float NoisePulseIntervalSeconds => _noisePulseIntervalSeconds?.Value ?? 1f; internal static float NoiseListenerExpirySeconds => _noiseListenerExpirySeconds?.Value ?? 3f; internal static bool FlightRecorderEnabled => _flightRecorderEnabled?.Value ?? true; internal static float FlightRecorderSampleHz => _flightRecorderSampleHz?.Value ?? 10f; internal static float FlightRecorderTerrainPollHz => _flightRecorderTerrainPollHz?.Value ?? 2f; internal static float FlightRecorderFlushIntervalSeconds => _flightRecorderFlushIntervalSeconds?.Value ?? 1f; internal static long FlightRecorderMaxBytesPerFlight => _flightRecorderMaxBytesPerFlight?.Value ?? 134217728; internal static long FlightRecorderMaxTotalBytes => _flightRecorderMaxTotalBytes?.Value ?? 1073741824; internal static bool ShowPilotDiagnostics => _showPilotDiagnostics?.Value ?? false; internal static void Bind(ConfigFile config) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Expected O, but got Unknown //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Expected O, but got Unknown //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Expected O, but got Unknown //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Expected O, but got Unknown //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Expected O, but got Unknown //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Expected O, but got Unknown //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Expected O, but got Unknown //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Expected O, but got Unknown //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Expected O, but got Unknown //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Expected O, but got Unknown //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04a1: Expected O, but got Unknown //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Expected O, but got Unknown //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_0511: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Expected O, but got Unknown //IL_0577: Unknown result type (might be due to invalid IL or missing references) //IL_0581: Expected O, but got Unknown //IL_05af: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Expected O, but got Unknown //IL_05e7: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Expected O, but got Unknown //IL_061f: Unknown result type (might be due to invalid IL or missing references) //IL_0629: Expected O, but got Unknown //IL_0657: Unknown result type (might be due to invalid IL or missing references) //IL_0661: Expected O, but got Unknown //IL_068f: Unknown result type (might be due to invalid IL or missing references) //IL_0699: Expected O, but got Unknown //IL_06c7: Unknown result type (might be due to invalid IL or missing references) //IL_06d1: Expected O, but got Unknown //IL_06ff: Unknown result type (might be due to invalid IL or missing references) //IL_0709: Expected O, but got Unknown //IL_0737: Unknown result type (might be due to invalid IL or missing references) //IL_0741: Expected O, but got Unknown //IL_076f: Unknown result type (might be due to invalid IL or missing references) //IL_0779: Expected O, but got Unknown //IL_07a7: Unknown result type (might be due to invalid IL or missing references) //IL_07b1: Expected O, but got Unknown //IL_07df: Unknown result type (might be due to invalid IL or missing references) //IL_07e9: Expected O, but got Unknown //IL_0817: Unknown result type (might be due to invalid IL or missing references) //IL_0821: Expected O, but got Unknown //IL_084f: Unknown result type (might be due to invalid IL or missing references) //IL_0859: Expected O, but got Unknown //IL_0887: Unknown result type (might be due to invalid IL or missing references) //IL_0891: Expected O, but got Unknown //IL_08bf: Unknown result type (might be due to invalid IL or missing references) //IL_08c9: Expected O, but got Unknown //IL_08f7: Unknown result type (might be due to invalid IL or missing references) //IL_0901: Expected O, but got Unknown //IL_092f: Unknown result type (might be due to invalid IL or missing references) //IL_0939: Expected O, but got Unknown //IL_0967: Unknown result type (might be due to invalid IL or missing references) //IL_0971: Expected O, but got Unknown //IL_099f: Unknown result type (might be due to invalid IL or missing references) //IL_09a9: Expected O, but got Unknown //IL_09d7: Unknown result type (might be due to invalid IL or missing references) //IL_09e1: Expected O, but got Unknown //IL_0a0f: Unknown result type (might be due to invalid IL or missing references) //IL_0a19: Expected O, but got Unknown //IL_0a47: Unknown result type (might be due to invalid IL or missing references) //IL_0a51: Expected O, but got Unknown //IL_0a9e: Unknown result type (might be due to invalid IL or missing references) //IL_0aa8: Expected O, but got Unknown //IL_0af5: Unknown result type (might be due to invalid IL or missing references) //IL_0aff: Expected O, but got Unknown //IL_0b2d: Unknown result type (might be due to invalid IL or missing references) //IL_0b37: Expected O, but got Unknown //IL_0b65: Unknown result type (might be due to invalid IL or missing references) //IL_0b6f: Expected O, but got Unknown //IL_0bd7: Unknown result type (might be due to invalid IL or missing references) //IL_0be1: Expected O, but got Unknown //IL_0c0f: Unknown result type (might be due to invalid IL or missing references) //IL_0c19: Expected O, but got Unknown //IL_0c47: Unknown result type (might be due to invalid IL or missing references) //IL_0c51: Expected O, but got Unknown //IL_0c7f: Unknown result type (might be due to invalid IL or missing references) //IL_0c89: Expected O, but got Unknown //IL_0cb7: Unknown result type (might be due to invalid IL or missing references) //IL_0cc1: Expected O, but got Unknown //IL_0d2d: Unknown result type (might be due to invalid IL or missing references) //IL_0d37: Expected O, but got Unknown //IL_0d65: Unknown result type (might be due to invalid IL or missing references) //IL_0d6f: Expected O, but got Unknown //IL_0d9d: Unknown result type (might be due to invalid IL or missing references) //IL_0da7: Expected O, but got Unknown //IL_0e13: Unknown result type (might be due to invalid IL or missing references) //IL_0e1d: Expected O, but got Unknown //IL_0e6a: Unknown result type (might be due to invalid IL or missing references) //IL_0e74: Expected O, but got Unknown //IL_0ea2: Unknown result type (might be due to invalid IL or missing references) //IL_0eac: Expected O, but got Unknown //IL_0eda: Unknown result type (might be due to invalid IL or missing references) //IL_0ee4: Expected O, but got Unknown //IL_0f12: Unknown result type (might be due to invalid IL or missing references) //IL_0f1c: Expected O, but got Unknown //IL_0f69: Unknown result type (might be due to invalid IL or missing references) //IL_0f73: Expected O, but got Unknown //IL_0fa1: Unknown result type (might be due to invalid IL or missing references) //IL_0fab: Expected O, but got Unknown //IL_0fd9: Unknown result type (might be due to invalid IL or missing references) //IL_0fe3: Expected O, but got Unknown //IL_1011: Unknown result type (might be due to invalid IL or missing references) //IL_101b: Expected O, but got Unknown //IL_1068: Unknown result type (might be due to invalid IL or missing references) //IL_1072: Expected O, but got Unknown //IL_10a0: Unknown result type (might be due to invalid IL or missing references) //IL_10aa: Expected O, but got Unknown //IL_10d8: Unknown result type (might be due to invalid IL or missing references) //IL_10e2: Expected O, but got Unknown //IL_114e: Unknown result type (might be due to invalid IL or missing references) //IL_1158: Expected O, but got Unknown //IL_1186: Unknown result type (might be due to invalid IL or missing references) //IL_1190: Expected O, but got Unknown //IL_11be: Unknown result type (might be due to invalid IL or missing references) //IL_11c8: Expected O, but got Unknown //IL_11f6: Unknown result type (might be due to invalid IL or missing references) //IL_1200: Expected O, but got Unknown //IL_122e: Unknown result type (might be due to invalid IL or missing references) //IL_1238: Expected O, but got Unknown //IL_1266: Unknown result type (might be due to invalid IL or missing references) //IL_1270: Expected O, but got Unknown //IL_129e: Unknown result type (might be due to invalid IL or missing references) //IL_12a8: Expected O, but got Unknown //IL_12f5: Unknown result type (might be due to invalid IL or missing references) //IL_12ff: Expected O, but got Unknown //IL_132d: Unknown result type (might be due to invalid IL or missing references) //IL_1337: Expected O, but got Unknown //IL_1365: Unknown result type (might be due to invalid IL or missing references) //IL_136f: Expected O, but got Unknown //IL_139d: Unknown result type (might be due to invalid IL or missing references) //IL_13a7: Expected O, but got Unknown //IL_13d5: Unknown result type (might be due to invalid IL or missing references) //IL_13df: Expected O, but got Unknown //IL_1406: Unknown result type (might be due to invalid IL or missing references) //IL_1410: Expected O, but got Unknown //IL_143e: Unknown result type (might be due to invalid IL or missing references) //IL_1448: Expected O, but got Unknown //IL_1476: Unknown result type (might be due to invalid IL or missing references) //IL_1480: Expected O, but got Unknown //IL_14ae: Unknown result type (might be due to invalid IL or missing references) //IL_14b8: Expected O, but got Unknown if (!_bound) { _bound = true; _rudderLeftKey = config.Bind<KeyCode>("Controls", "RudderLeft", (KeyCode)113, "Legacy initial rudder key. After first launch, rebind Aircraft controls in Valheim Settings > Controls."); _rudderRightKey = config.Bind<KeyCode>("Controls", "RudderRight", (KeyCode)101, "Legacy initial rudder key. After first launch, rebind Aircraft controls in Valheim Settings > Controls."); _engineRundownSeconds = config.Bind<float>("Taxi", "EngineRundownSeconds", 9f, new ConfigDescription("Seconds to spool from full power to zero after releasing gas; does not brake aircraft motion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>())); _throttleRampPercentPerSecond = config.Bind<float>("Taxi", "ThrottleRampPercentPerSecond", ThrottleRampPercentPerSecond, new ConfigDescription("Throttle ramp rate while Shift/Ctrl is held, in %/s (0-100% in 100/this seconds).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>())); _maxThrustNewtons = config.Bind<float>("Taxi", "MaxThrustNewtons", MaxThrustNewtons, new ConfigDescription("Engine thrust at 100% throttle and zero airspeed, in newtons - applies on the ground AND in the air alike, tapering off with airspeed (see ThrustFalloffSpeedMps) like a real propeller.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(200f, 20000f), Array.Empty<object>())); _thrustFalloffSpeedMps = config.Bind<float>("Taxi", "ThrustFalloffSpeedMps", ThrustFalloffSpeedMps, new ConfigDescription("Forward airspeed (m/s) at which available thrust has linearly tapered to zero - a simplified real-propeller advance-ratio effect, not an arbitrary cap; the SAME curve applies whether grounded or airborne.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>())); _lowSpeedThrustEfficiencyFloor = config.Bind<float>("Taxi", "LowSpeedThrustEfficiencyFloor", LowSpeedThrustEfficiencyFloor, new ConfigDescription("Fraction of available thrust delivered at the DIP'S OWN MIDPOINT speed (1.0 = no reduction, disabled) - full (1.0) thrust at and below LowSpeedThrustEfficiencyDipStartSpeedMps and at and above LowSpeedThrustEfficiencyDipEndSpeedMps, dipping to this floor at the midpoint between them. Applies whether grounded or airborne, like the thrust curve it modifies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>())); _lowSpeedThrustEfficiencyDipStartSpeedMps = config.Bind<float>("Taxi", "LowSpeedThrustEfficiencyDipStartSpeedMps", LowSpeedThrustEfficiencyDipStartSpeedMps, new ConfigDescription("Airspeed (m/s) below which LowSpeedThrustEfficiencyFloor's dip applies NO reduction at all - kept above breakaway/walking taxi speed so that thin low-throttle thrust margin is untouched.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _lowSpeedThrustEfficiencyDipEndSpeedMps = config.Bind<float>("Taxi", "LowSpeedThrustEfficiencyDipEndSpeedMps", LowSpeedThrustEfficiencyDipEndSpeedMps, new ConfigDescription("Airspeed (m/s) above which LowSpeedThrustEfficiencyFloor's dip applies NO reduction at all - 0 (or at/below DipStartSpeedMps) disables the dip entirely. Kept below the measured climb/cruise operating range so that range is unaffected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 12f), Array.Empty<object>())); _steerTorqueNewtonMeters = config.Bind<float>("Taxi", "SteerTorqueNewtonMeters", SteerTorqueNewtonMeters, new ConfigDescription("Ground steering yaw torque (about world up) at full A/D input and full steer availability, in newton-metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(200f, 40000f), Array.Empty<object>())); _steerRampSpeedMps = config.Bind<float>("Taxi", "SteerRampSpeedMps", SteerRampSpeedMps, new ConfigDescription("Forward speed (m/s) at which full steering torque becomes available - 0 at a dead stop (a stationary taildragger cannot pivot on the spot).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); _rollingResistanceCoefficient = config.Bind<float>("Taxi", "RollingResistanceCoefficient", RollingResistanceCoefficient, new ConfigDescription("Wheel/tailskid rolling resistance opposing ground-relative forward motion, scaled by remaining gear load, ground proximity and the speed ramp. Lower values allow a longer unbraked rollout. This is a game-balance coefficient, not a measured tyre-on-grass friction value. The 30-40m takeoff target is validated separately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.6f), Array.Empty<object>())); _rollingResistanceRampSpeedMps = config.Bind<float>("Taxi", "RollingResistanceRampSpeedMps", RollingResistanceRampSpeedMps, new ConfigDescription("Ground speed (m/s) over which rolling resistance ramps in from zero - keeps low-throttle breakaway/walking-speed taxi from being blocked by a constant resistance while still applying full resistance for the great majority of a takeoff ground roll.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); _groundThrustBonusNewtons = config.Bind<float>("Taxi", "GroundThrustBonusNewtons", GroundThrustBonusNewtons, new ConfigDescription("Additional engine thrust, in newtons at full throttle and zero ground speed, applied ONLY while grounded (scaled by the same continuous ground-contact fraction and throttle-power curve as the base thrust, and faded out by ground speed - see GroundThrustBonusFadeSpeedMps) - a simplified stand-in for extra low-speed slipstream/ground-effect propulsive efficiency this model previously omitted, giving a second, independent lever alongside RollingResistanceCoefficient so a modest uphill launch and the 30-40m flat/calm ground-roll target can both be met at once. Exactly zero once airborne by construction, so it cannot affect cruise/climb/glide.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3000f), Array.Empty<object>())); _groundThrustBonusFadeSpeedMps = config.Bind<float>("Taxi", "GroundThrustBonusFadeSpeedMps", GroundThrustBonusFadeSpeedMps, new ConfigDescription("Ground speed (m/s) above GroundThrustBonusRampInSpeedMps over which GroundThrustBonusNewtons linearly fades OUT to zero (full bonus at RampInSpeedMps, none at or above this speed) - 0 disables fading out (bonus stays at full magnitude once ramped in). Keeps the bonus targeted at the mid-speed regime where a slope's own equilibrium plateau sits, well under this aircraft's own flat-ground liftoff speed, so flat's own final approach to liftoff stays governed by RollingResistanceCoefficient.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); _groundThrustBonusRampInSpeedMps = config.Bind<float>("Taxi", "GroundThrustBonusRampInSpeedMps", GroundThrustBonusRampInSpeedMps, new ConfigDescription("Ground speed (m/s) over which GroundThrustBonusNewtons ramps IN from zero (zero at a dead stop, full magnitude at this speed) - 0 disables ramp-in (bonus is at full magnitude from v=0). Keeps the bonus exactly zero at a dead stop, so a taxi brake test holding throttle while braking sees identical behaviour to before this lever existed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _groundDragBonusFraction = config.Bind<float>("Taxi", "GroundDragBonusFraction", GroundDragBonusFraction, new ConfigDescription("Extra aerodynamic drag while fully grounded, as a fraction of the drag this model already computes every step (e.g. 1.0 doubles drag at groundFraction=1) - scaled by the same continuous ground-contact fraction every other ground-only term uses, so it is exactly zero once airborne by construction and cannot affect cruise/climb/glide/stall. A second, independent lever from RollingResistanceCoefficient specifically for lengthening the flat-ground reference roll without touching resistance (and so without touching the uphill/taxi margins resistance itself governs).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); _groundElevatorTorqueBonusNewtonMeters = config.Bind<float>("Taxi", "GroundElevatorTorqueBonusNewtonMeters", GroundElevatorTorqueBonusNewtonMeters, new ConfigDescription("Additional elevator pitch torque (newton-metres at full pitch input, full throttle, full ground contact, at/above GroundElevatorTorqueBonusRampInSpeedMps and while the tailskid is itself still down) - a bounded GAMEPLAY ASSIST/approximation, not a general physical propwash model, standing in for real propeller-slipstream authority over the tailplane while genuinely grounded (distinct from the free-stream-airspeed-only elevatorControlAuthority term) - see this value's own docstring for the measured ~5500Nm rest-attitude weight moment about the main-wheel line the existing dynamic-pressure-only torque could not begin to overcome. Scales with EnginePowerFraction(throttle), a ground-speed ramp-in (see GroundElevatorTorqueBonusRampInSpeedMps), the same continuous ground-contact RAY-PROXIMITY fraction every other ground-only term uses (this is a proximity weight, not a literal touching boolean - it can still act during near-ground flight within GroundedRayLengthMeters of terrain, not only while physically touching, though normal cruise/climb/glide/stall-recovery flight stays well clear of that band), the pilot's own forward (W) pitch command ONLY (zero at neutral or S, never an automatic/uncommanded torque and never applied for S - a symmetric version measurably pressed the already-grounded tailskid harder into the ground under held S, adding unintended contact-friction drag), and - self-limiting - the tailskid's OWN independent ground-contact weight (fades out as the tail itself genuinely clears, instead of continuing to push at full strength long after its own job is done; a corrected, tightly-measured test exposed a CONSTANT-strength version's razor-thin, unstable margin between too-weak and permanently-stuck).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 6000f), Array.Empty<object>())); _groundElevatorTorqueBonusRampInSpeedMps = config.Bind<float>("Taxi", "GroundElevatorTorqueBonusRampInSpeedMps", GroundElevatorTorqueBonusRampInSpeedMps, new ConfigDescription("Ground speed (m/s) over which GroundElevatorTorqueBonusNewtonMeters ramps IN from zero (zero at a dead stop, full magnitude at this speed) - see that value's own docstring for the measured slope-comparison regression this fixes (a purely throttle/time-based bonus reached full strength at different elapsed times depending on how fast a scenario accelerates, inverting the expected uphill/downhill ordering). 0 disables ramp-in (bonus depends only on throttle/pitch/groundFraction).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _groundThrustAlignmentExponent = config.Bind<float>("Taxi", "GroundThrustAlignmentExponent", GroundThrustAlignmentExponent, new ConfigDescription("Exponent (<1) applied to groundFraction before blending thrust direction from ground-aligned toward the tilted-up body-forward axis - keeps thrust ground-aligned until substantially (not merely starting to be) unweighted, addressing a hypothesised self-reinforcing early-liftoff cascade a taildragger's own near-stall rest attitude may otherwise produce (measured to contribute under 1m of ground-roll distance on its own - a small, real effect, not confirmed as the dominant cause). 1.0 reproduces the old linear blend exactly. groundFraction is a bounded ray-proximity weight, not a measured wheel load, and is only exactly 0 once every gear probe is out of ray range - ordinary cruise/climb/glide well clear of terrain is unaffected, but low-altitude/transitional flight near terrain can still see a nonzero value here too.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); _brakeForceNewtons = config.Bind<float>("Taxi", "BrakeForceNewtons", BrakeForceNewtons, new ConfigDescription("Constant wheel-brake force while Space is held (or automatically while parked/unpiloted), in newtons - a Coulomb/dry-friction model, not a speed-proportional one. See docs/DEVELOPMENT_HANDOVER.md for the stopping-distance/grade-holding derivation.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 10000f), Array.Empty<object>())); _brakeStaticThresholdMps = config.Bind<float>("Taxi", "BrakeStaticThresholdMps", BrakeStaticThresholdMps, new ConfigDescription("Speed (m/s) below which the brake switches from kinetic (opposing motion) to static (holding position against e.g. a slope) behaviour.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 2f), Array.Empty<object>())); _controlSurfaceEaseDegPerSecond = config.Bind<float>("Taxi", "ControlSurfaceEaseDegPerSecond", ControlSurfaceEaseDegPerSecond, new ConfigDescription("Visual return-to-neutral rate for the ailerons/elevator/rudder/stick, in degrees/second of the full deflection range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 500f), Array.Empty<object>())); _propellerMaxDegPerSecond = config.Bind<float>("Taxi", "PropellerMaxDegPerSecond", PropellerMaxDegPerSecond, new ConfigDescription("Visual-only baseline propeller spin rate in degrees/second. Legacy scale: 3600 gives beta rotor 1500 RPM idle / 2600 RPM full; other values scale both proportionally.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5000f), Array.Empty<object>())); _dismountHoldSeconds = config.Bind<float>("Dismount", "DismountHoldSeconds", DismountHoldSeconds, new ConfigDescription("Seconds to hold the Sit-bound key to exit the seat.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>())); _safeDismountSpeedMps = config.Bind<float>("Dismount", "SafeDismountSpeedMps", SafeDismountSpeedMps, new ConfigDescription("Maximum linear speed (m/s) the aircraft may be moving for a dismount (hold-exit or aviation_remove) to be allowed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), Array.Empty<object>())); _safeDismountAngularSpeedRadPerSec = config.Bind<float>("Dismount", "SafeDismountAngularSpeedRadPerSec", SafeDismountAngularSpeedRadPerSec, new ConfigDescription("Maximum angular speed (rad/s) the aircraft may be rotating for a dismount to be allowed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 3f), Array.Empty<object>())); _groundedRayLengthMeters = config.Bind<float>("Dismount", "GroundedRayLengthMeters", GroundedRayLengthMeters, new ConfigDescription("Downward ground-contact probe length (m) from each wheel/skid sample point.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>())); _cameraDistanceMeters = config.Bind<float>("Camera", "CameraDistanceMeters", CameraDistanceMeters, new ConfigDescription("Default third-person camera distance while piloting, in metres - wide enough for the 11 m wingspan and ground ahead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 40f), Array.Empty<object>())); _cameraMaxDistanceMeters = config.Bind<float>("Camera", "CameraMaxDistanceMeters", CameraMaxDistanceMeters, new ConfigDescription("Scroll-zoom-out ceiling while piloting, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 60f), Array.Empty<object>())); _cameraPullbackRateMetersPerSecond = config.Bind<float>("Camera", "CameraPullbackRateMetersPerSecond", CameraPullbackRateMetersPerSecond, new ConfigDescription("How fast the camera glides toward CameraDistanceMeters on entry, in m/s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 60f), Array.Empty<object>())); _cameraPullbackWindowSeconds = config.Bind<float>("Camera", "CameraPullbackWindowSeconds", CameraPullbackWindowSeconds, new ConfigDescription("How long after entering the seat the camera actively glides toward CameraDistanceMeters, in seconds, before handing control back to the player's own scroll zoom.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 20f), Array.Empty<object>())); _wingAreaSquareMeters = config.Bind<float>("Aerodynamics", "WingAreaSquareMeters", WingAreaSquareMeters, new ConfigDescription("Combined effective lift/drag area (m^2) used by the simplified single-coefficient wing model - a tuning value, not the wing's real geometric area. Sized together with LiftSlopePerRadian/PitchTrimAoaDeg so the wing can actually generate lift = weight (220 kg) at the cruise target without exceeding StallAngleDeg.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 80f), Array.Empty<object>())); _airDensityKgPerCubicMeter = config.Bind<float>("Aerodynamics", "AirDensityKgPerCubicMeter", AirDensityKgPerCubicMeter, new ConfigDescription("Air density (kg/m^3) used for dynamic pressure - a fixed simplified value, no altitude falloff modelled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); _stallAngleDeg = config.Bind<float>("Aerodynamics", "StallAngleDeg", StallAngleDeg, new ConfigDescription("Angle of attack (degrees) beyond which lift coefficient falls off instead of rising.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 30f), Array.Empty<object>())); _liftSlopePerRadian = config.Bind<float>("Aerodynamics", "LiftSlopePerRadian", LiftSlopePerRadian, new ConfigDescription("Lift coefficient slope per radian of angle of attack, pre-stall (thin-airfoil theory's own 2*pi is deliberately not used - tuned down for a controllable prototype).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6.5f), Array.Empty<object>())); _zeroLiftDragCoefficient = config.Bind<float>("Aerodynamics", "ZeroLiftDragCoefficient", ZeroLiftDragCoefficient, new ConfigDescription("Parasite (zero-lift) drag coefficient - a strut-braced grey-box biplane is draggy, so this is deliberately higher than a clean monoplane.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.3f), Array.Empty<object>())); _inducedDragFactor = config.Bind<float>("Aerodynamics", "InducedDragFactor", InducedDragFactor, new ConfigDescription("Induced-drag factor (k in CD = CD0 + k*CL^2) - drag added as lift is generated.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.005f, 0.3f), Array.Empty<object>())); _elevatorControlAuthority = config.Bind<float>("Aerodynamics", "ElevatorControlAuthority", ElevatorControlAuthority, new ConfigDescription("Elevator pitch-control torque authority (torque = dynamic pressure * input * this) - W/S, tail elevators only, no wing-surface pitch mixing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 2000f), Array.Empty<object>())); _aileronControlAuthority = config.Bind<float>("Aerodynamics", "AileronControlAuthority", AileronControlAuthority, new ConfigDescription("Aileron roll-control torque authority (torque = dynamic pressure * input * this) - A/D, opposing wing ailerons only.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 2000f), Array.Empty<object>())); _rudderControlAuthority = config.Bind<float>("Aerodynamics", "RudderControlAuthority", RudderControlAuthority, new ConfigDescription("Rudder yaw-control torque authority in the air (torque = dynamic pressure * input * this) - Q/E; ground taxi yaw uses the separate SteerTorqueNewtonMeters instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 2000f), Array.Empty<object>())); _pitchTrimAoaDeg = config.Bind<float>("Aerodynamics", "PitchTrimAoaDeg", PitchTrimAoaDeg, new ConfigDescription("Angle of attack (degrees) the weathervane pitch stability restores TOWARD, not zero - the aircraft's rigging/incidence angle, tuned so the wing still generates lift = weight in level cruise. See PitchTrimAoaDeg's own docstring for why zero would starve the aircraft of lift entirely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 25f), Array.Empty<object>())); _pitchStabilityCoefficient = config.Bind<float>("Aerodynamics", "PitchStabilityCoefficient", PitchStabilityCoefficient, new ConfigDescription("Weathervane pitch-restoring torque authority (torque = -dynamic pressure * (angle of attack - PitchTrimAoaDeg) * this) - the tailplane's own natural stability, independent of pilot input. Pitch/stall response task: lowered from 45 to 17 so continuously holding S can over-pull into a real, recoverable aerodynamic stall instead of asymptotically approaching a safe margin below it forever - see this property's own docstring for the worked equilibrium math and the migration note for already-generated config files.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _yawStabilityCoefficient = config.Bind<float>("Aerodynamics", "YawStabilityCoefficient", YawStabilityCoefficient, new ConfigDescription("Weathervane yaw-restoring torque authority (torque = -dynamic pressure * sideslip angle * this) - the fin's own natural stability, independent of pilot input.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _rollStabilityCoefficient = config.Bind<float>("Aerodynamics", "RollStabilityCoefficient", RollStabilityCoefficient, new ConfigDescription("Dihedral-effect roll-restoring torque authority (torque = dynamic pressure * sideslip angle * this) - converts sideslip into a wings-levelling roll moment, independent of pilot input.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _pitchDampingCoefficient = config.Bind<float>("Aerodynamics", "PitchDampingCoefficient", PitchDampingCoefficient, new ConfigDescription("Aerodynamic pitch-rate damping (torque = -dynamic pressure * pitch angular velocity * this) - lets pitch stability converge instead of oscillating, and bounds full-elevator steady-state pitch rate to ElevatorControlAuthority/this radians/sec (default free pitch-rate ratio ~7.6 deg/s; restoring torque also affects response).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _rollDampingCoefficient = config.Bind<float>("Aerodynamics", "RollDampingCoefficient", RollDampingCoefficient, new ConfigDescription("Aerodynamic roll-rate damping (torque = -dynamic pressure * roll angular velocity * this) - resists an unchecked roll rate from building up, and bounds full-aileron steady-state roll rate to AileronControlAuthority/this radians/sec (default ~90 deg/s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _yawDampingCoefficient = config.Bind<float>("Aerodynamics", "YawDampingCoefficient", YawDampingCoefficient, new ConfigDescription("Aerodynamic yaw-rate damping (torque = -dynamic pressure * yaw angular velocity * this) - lets yaw stability converge instead of oscillating, and bounds full-rudder steady-state yaw rate to RudderControlAuthority/this radians/sec (default ~40 deg/s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); _windEnabled = config.Bind<bool>("Wind", "WindEnabled", WindEnabled, "Sample the game's own EnvMan wind for air-relative velocity. OFF by default - the exact wind-intensity-to-m/s conversion is not independently verified (see AviationConfig's own class docstring for the full investigation); enable only after calibrating WindSpeedScaleMetersPerSecond against observed behaviour."); _windSpeedScaleMetersPerSecond = config.Bind<float>("Wind", "WindSpeedScaleMetersPerSecond", WindSpeedScaleMetersPerSecond, new ConfigDescription("Unverified conversion factor from EnvMan's 0..1-ish wind intensity to metres/second - only used while WindEnabled is true.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); _stormExtrasEnabled = config.Bind<bool>("Wind", "StormExtrasEnabled", StormExtrasEnabled, "Storm gusts task: enables BOTH the high-intensity mean-wind addition and the turbulence gust field below, ramped in only above raw wind intensity 0.35. OFF by default - with this false, wind response is byte-identical to the pre-storm-task behaviour regardless of the other storm values."); _stormHighIntensityWindBonusMps = config.Bind<float>("Wind", "StormHighIntensityWindBonusMps", StormHighIntensityWindBonusMps, new ConfigDescription("Extra mean-wind magnitude (m/s), added along the existing wind direction, fully ramped in by raw intensity 1 - only applied while StormExtrasEnabled is true. Default 0 (no change) until reviewed; the task's own initial candidate is 1 (peak wind 2+1=3 m/s at the installed WindSpeedScaleMetersPerSecond=2).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _stormGustPeakVerticalMps = config.Bind<float>("Wind", "StormGustPeakVerticalMps", StormGustPeakVerticalMps, new ConfigDescription("Peak vertical (updraft/downdraft) turbulence gust velocity (m/s) at raw wind intensity 1, per wing/tail point - only applied while StormExtrasEnabled is true and the aircraft is airborne and dry.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); _stormGustPeakLateralMps = config.Bind<float>("Wind", "StormGustPeakLateralMps", StormGustPeakLateralMps, new ConfigDescription("Peak lateral (crosswind) turbulence gust velocity (m/s) at raw wind intensity 1, per wing/tail point - only applied while StormExtrasEnabled is true and the aircraft is airborne and dry.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); _showPilotDiagnostics = config.Bind<bool>("Development", "ShowPilotDiagnostics", false, "Show development-only throttle and stall readouts while piloting. Disabled for normal play."); _fuelEnabled = config.Bind<bool>("Fuel", "FuelEnabled", FuelEnabled, "Enables finite fuel: a fresh aircraft starts empty, the engine refuses to start without fuel, and a running engine consumes fuel and shuts down when depleted. OFF by default - with this false every fuel code path is skipped and engine/flight behaviour is byte-identical to before this task."); _fuelCapacityUnits = config.Bind<float>("Fuel", "FuelCapacityUnits", FuelCapacityUnits, new ConfigDescription("Tank capacity in fuel units - a provisional test-balance value, not final progression.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>())); _fuelUnitsPerItem = config.Bind<float>("Fuel", "FuelUnitsPerItem", FuelUnitsPerItem, new ConfigDescription("Fuel units added per Strong Spirits item consumed at the tank. Review fix: must be positive - RequestRefuel also rejects a <= 0 value at runtime regardless of this bound (e.g. an already-out-of-range value on disk), since accepting an item for zero fuel would otherwise be possible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 100f), Array.Empty<object>())); _refuelSeconds = config.Bind<float>("Fuel", "RefuelSeconds", 3f, new ConfigDescription("Seconds one bottle of Strong Spirits takes to pour into the tank after a single E press (cancellable; the item and the fuel are only taken when the pour completes).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>())); _fuelConsumptionFullPerMinute = config.Bind<float>("Fuel", "FuelConsumptionFullPerMinute", FuelConsumptionFullPerMinute, new ConfigDescription("Fuel units/minute burned at full running power (engine rpm01=1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); _fuelConsumptionIdlePerMinute = config.Bind<float>("Fuel", "FuelConsumptionIdlePerMinute", FuelConsumptionIdlePerMinute, new ConfigDescription("Fuel units/minute burned at idle running power (engine rpm01=EngineIdleRpm01) - burn rate interpolates smoothly between this and FuelConsumptionFullPerMinute with actual engine rpm.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); _damageEnabled = config.Bind<bool>("Damage", "DamageEnabled", DamageEnabled, "Enables structural health: native weapon/creature attacks and hard physical impacts reduce health, and the engine shuts down and refuses to (re)start at zero health until repaired. OFF by default - with this false every damage code path is skipped and behaviour is byte-identical to before this task."); _propellerContactEnabled = config.Bind<bool>("Damage", "PropellerContactEnabled", PropellerContactEnabled, "A turning propeller strikes creatures, players and destructibles in its swept blade path (native damage, armour and resistances apply; a stopped or slow-coasting rotor is harmless and idle is forgiving), and a solid obstacle (rock, terrain, tree, structure) stops the rotor, shuts the engine down and costs airframe health; the engine then needs a manual restart once the blockage is clear. Requires DamageEnabled."); _maxHealth = config.Bind<float>("Damage", "MaxHealth", MaxHealth, new ConfigDescription("Maximum/starting structural health, in the same units HitData/impact damage is measured in - a provisional test-balance value, not final progression.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10000f), Array.Empty<object>())); _impactDamageThresholdMps = config.Bind<float>("Damage", "ImpactDamageThresholdMps", ImpactDamageThresholdMps, new ConfigDescription("Forgiving threshold, in m/s of RELATIVE CLOSING speed along the actual contact normal (not total forward speed - see AviationController.RegisterImpactCandidate) - at/below this, an impact causes zero damage. Chosen above this aircraft's own measured settle-touchdown and taxi-bump normal speeds (see docs/DEVELOPMENT_HANDOVER.md for the exact measured values) so gentle landings/bumps stay undamaged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); _impactDamagePerMpsAboveThreshold = config.Bind<float>("Damage", "ImpactDamagePerMpsAboveThreshold", ImpactDamagePerMpsAboveThreshold, new ConfigDescription("Damage per m/s of closing speed ABOVE ImpactDamageThresholdMps - a plain linear (monotonic) excess curve, the smallest defensible shape for this first bounded pass.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>())); _wreckDecayEnabled = config.Bind<bool>("WreckDecay", "Enabled", WreckDecayEnabled, "Abandoned wrecks that sit substantially submerged (most of the airframe under water, confirmed for 10 world seconds, with hysteresis) slowly lose structural health and are removed when it reaches zero. Time is the world's own game time (day length from the game), so it only advances while the world runs and it also counts world time while the wreck's area is unloaded. Requires Damage.DamageEnabled=true (with damage off nothing decays). Brief water contact, skimming, rain and a floating airframe never count."); _wreckPartialEnabled = config.Bind<bool>("WreckDecay", "PartialWeatheringEnabled", WreckPartialWeatheringEnabled, "Sustained PARTIAL immersion (a floating or half-sunk airframe: capacity-weighted immersion of at least 0.30, confirmed for 30 world seconds; a wheel skim or splash never counts) slowly wears the airframe: after GraceDays, PartialLossFraction of maximum health is lost over DecayDays of partially submerged world time, but never below the floor (maximum health x (1 - PartialLossFraction)), never healing and never destroying. Full submersion keeps the destructive Enabled/GraceDays/DecayDays rule; the two never charge the same interval. Requires WreckDecay.Enabled and Damage.DamageEnabled."); _wreckPartialLossFraction = config.Bind<float>("WreckDecay", "PartialLossFraction", WreckPartialLossFraction, new ConfigDescription("Share of maximum health that partial-submersion weathering can remove (default 0.5 = 50%); the health floor is maximum health x (1 - this value), never below 1 HP.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>())); _wreckRainEnabled = config.Bind<bool>("WreckDecay", "RainWeatheringEnabled", WreckRainWeatheringEnabled, "Exposed PARKED aircraft (ground-supported, practically stationary, unpiloted for 30 world seconds) slowly weather while it rains at their location: after GraceDays of accumulated rain exposure, RainLossFraction of maximum health is lost over DecayDays of rainy exposure, never below the floor (maximum health x (1 - RainLossFraction)), never healing and never destroying. An adequate roof over the airframe (static geometry above the fuselage, the whole wing span and the tailplane - walls alone do nothing, a roof without walls works, the aircraft's own upper wing does not) pauses it; a partial roof scales the exposure. Water weathering takes precedence and rain is never charged for unloaded time. Requires WreckDecay.Enabled and Damage.DamageEnabled."); _wreckRainLossFraction = config.Bind<float>("WreckDecay", "RainLossFraction", WreckRainLossFraction, new ConfigDescription("Share of maximum health that rain weathering can remove (default 0.5 = 50%); the health floor is maximum health x (1 - this value), never below 1 HP.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>())); _wreckDecayGraceDays = config.Bind<float>("WreckDecay", "GraceDays", WreckDecayGraceDays, new ConfigDescription("World days of confirmed submersion before any decay damage starts (fractions allowed). Exposure only accumulates while submerged and is never reset by lifting the aircraft out or by repairs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 365f), Array.Empty<object>())); _wreckDecayDurationDays = config.Bind<float>("WreckDecay", "DecayDays", WreckDecayDurationDays, new ConfigDescription("Further submerged world days over which ONE maximum-health airframe worth of damage accrues after the grace period (full-health wreck expires after GraceDays + DecayDays; a damaged one sooner). For a quick manual test in a throwaway world use e.g. GraceDays 0.02 and DecayDays 0.03 (about 24 s + 36 s on a 1200 s day), then restore the defaults.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 365f), Array.Empty<object>())); _spawnDamageGraceSeconds = config.Bind<float>("Damage", "SpawnDamageGraceSeconds", SpawnDamageGraceSeconds, new ConfigDescription("Fixed, one-time, NEVER-renewed window (seconds of accumulated physics time) from spawn during which impact damage is suppressed - covers exactly the initial gravity-settle touchdown, not a general collision immunity (native attacks are NOT covered by this grace at all).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); _noiseEnabled = config.Bind<bool>("EngineNoise", "NoiseEnabled", NoiseEnabled, "Enables engine-noise creature attraction: a bounded periodic pulse alerts nearby eligible hostile creatures (native BaseAI.Alert()) while the engine is running, idle/full-throttle range interpolated. OFF by default - with this false the pulse never runs and behaviour is byte-identical to before this task."); _noiseIdleRangeMeters = config.Bind<float>("EngineNoise", "NoiseIdleRangeMeters", NoiseIdleRangeMeters, new ConfigDescription("Pulse radius in metres at idle rpm (and throughout Starting) - a provisional test value, not claimed final balance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>())); _noiseFullRangeMeters = config.Bind<float>("EngineNoise", "NoiseFullRangeMeters", NoiseFullRangeMeters, new ConfigDescription("Pulse radius in metres at full running rpm - interpolates smoothly from NoiseIdleRangeMeters with actual engine rpm.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>())); _noisePulseIntervalSeconds = config.Bind<float>("EngineNoise", "NoisePulseIntervalSeconds", NoisePulseIntervalSeconds, new ConfigDescription("Seconds between bounded eligibility scans/pulses - not a per-frame search.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); _noiseListenerExpirySeconds = config.Bind<float>("EngineNoise", "NoiseListenerExpirySeconds", NoiseListenerExpirySeconds, new ConfigDescription("Final noise target-discovery gate: how long a creature that passed this aircraft's own eligibility check remains a valid native-discovery listener afterward - should stay comfortably longer than NoisePulseIntervalSeconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>())); _flightRecorderEnabled = config.Bind<bool>("FlightRecorder", "Enabled", FlightRecorderEnabled, "Record a local, structured flight log (docs/BLACK_BOX.md) for the aircraft while the local player is piloting it. Purely diagnostic - never affects flight physics."); _flightRecorderSampleHz = config.Bind<float>("FlightRecorder", "SampleHz", FlightRecorderSampleHz, new ConfigDescription("Regular sample rate in Hz. Short-lived input/event changes are still captured at actual physics-step timing regardless of this rate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 50f), Array.Empty<object>())); _flightRecorderTerrainPollHz = config.Bind<float>("FlightRecorder", "TerrainPollHz", FlightRecorderTerrainPollHz, new ConfigDescription("Rate in Hz at which terrain/water/biome queries are refreshed (these are comparatively expensive and do not need per-sample freshness).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); _flightRecorderFlushIntervalSeconds = config.Bind<float>("FlightRecorder", "FlushIntervalSeconds", FlightRecorderFlushIntervalSeconds, new ConfigDescription("How often buffered records are flushed to disk. A hard process kill can still lose the last unflushed buffer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>())); _flightRecorderMaxBytesPerFlight = config.Bind<long>("FlightRecorder", "MaxBytesPerFlight", FlightRecorderMaxBytesPerFlight, "Per-flight byte budget. Once reached, a truncation marker is written and that flight's recorder stops (gameplay is never affected)."); _flightRecorderMaxTotalBytes = config.Bind<long>("FlightRecorder", "MaxTotalBytes", FlightRecorderMaxTotalBytes, "Total on-disk byte budget across all stored flights. Past flights are never auto-deleted; once this is reached, new flights are not recorded and a single warning is logged."); _waterReferenceDepthMeters = config.Bind<float>("Water", "ReferenceDepthMeters", WaterReferenceDepthMeters, new ConfigDescription("Depth (m) at which one hull sample point's own buoyancy ramp saturates to full - a smaller value makes buoyancy respond more sharply right at the waterline.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 3f), Array.Empty<object>())); _waterBuoyancyCapacityMultiplier = config.Bind<float>("Water", "BuoyancyCapacityMultiplier", WaterBuoyancyCapacityMultiplier, new ConfigDescription("How many times the aircraft's own weight (mass * current Physics.gravity, not a hardcoded Earth value) the fully-submerged hull's own buoyant capacity could support - lets it float mostly at the surface rather than needing to be fully underwater just to stay neutrally buoyant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); _waterDragCoefficient = config.Bind<float>("Water", "DragCoefficient", WaterDragCoefficient, new ConfigDescription("Quadratic water-drag coefficient for the whole body's own linear (COM) velocity - opposes relative motion through water, scaled by overall immersion, exactly zero when dry. Large by design (a real terminal SINK speed of only ~0.2-0.5m/s once fully flooded requires a big coefficient, since drag only grows with speed-SQUARED), but protected against overshoot/energy-injection at ANY magnitude by AviationMath.MomentumSafeDragMagnitude's own momentum-safe clamp, not a fixed force cap.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200000f), Array.Empty<object>())); _waterAngularDragCoefficient = config.Bind<float>("Water", "AngularDragCoefficient", WaterAngularDragCoefficient, new ConfigDescription("Quadratic water-drag coefficient for the whole body's own angular velocity (spin) while immersed - real water resists tumbling far more than air. Also protected by the same momentum-safe clamp as the linear coefficient above.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>())); _waterFloodRatePerSecondAtFullImmersion = config.Bind<float>("Water", "FloodRatePerSecondAtFullImmersion", WaterFloodRatePerSecondAtFullImmersion, new ConfigDescription("How fast the flooded fraction fills per second at full immersion (scaled down by lower immersion) - tuned toward a roughly 10-20s survivable float window before net buoyancy drops below weight and gradual sinking begins. Flooding never drains on its own once accumulated (no bailout/repair mechanic in this prototype).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 1f), Array.Empty<object>())); _waterEngineSubmergeMarginMeters = config.Bind<float>("Water", "EngineSubmergeMarginMeters", WaterEngineSubmergeMarginMeters, new ConfigDescription("The engine (propeller assembly) counts as submerged, permanently shutting off thrust for this aircraft instance until respawn, once the sampled water level exceeds the engine's own position by this margin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); _waterGearContactCapacityFraction = config.Bind<float>("Water", "GearContactCapacityFraction", WaterGearContactCapacityFraction, new ConfigDescription("Total share (0..1) of buoyancy capacity/drag effective-mass attributed to gear/skid contact points combined (split evenly among however many exist) rather than the broad hull structure points - keeps a brief wheel/skid touch mild and proportionate instead of engaging full wing/body-strength water resistance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())); _waterEffectsEnabled = config.Bind<bool>("WaterEffects", "Enabled", WaterEffectsEnabled, "Cosmetic splash/spray and spatial water sound on skim/entry contact. Purely presentational - disabling this never changes water physics forces or trajectory."); _waterEffectsSkimImmersionMax = config.Bind<float>("WaterEffects", "SkimImmersionMax", WaterEffectsSkimImmersionMax, new ConfigDescription("A sample point's own immersion01 at/below this counts as a light skim touch (spray), not a substantial/deep contact.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>())); _waterEffectsSkimMinSpeedMps = config.Bind<float>("WaterEffects", "SkimMinSpeedMps", WaterEffectsSkimMinSpeedMps, new ConfigDescription("Minimum relative speed (m/s) for a skim spray to fire at all - keeps a stationary or near-stationary bobbing aircraft silent/effect-free.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); _waterEffectsEntryImmersionThreshold = config.Bind<float>("WaterEffects", "EntryImmersionThreshold", WaterEffectsEntryImmersionThreshold, new ConfigDescription("Overall (capacity-weighted) immersion01 crossing this on a rising edge counts as a substantial water entry - fires the larger one-shot splash/sound exactly once per entry.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); _waterEffectsEntryMinSpeedMps = config.Bind<float>("WaterEffects", "EntryMinSpeedMps", WaterEffectsEntryMinSpeedMps, new ConfigDescription("Minimum aircraft speed (m/s) at the moment of a substantial water entry for the larger one-shot effect to fire - a slow settle does not re-trigger it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); _waterEffectsPerPointCooldownSeconds = config.Bind<float>("WaterEffects", "PerPointCooldownSeconds", WaterEffectsPerPointCooldownSeconds, new ConfigDescription("Minimum real time between successive skim-spray dispatches from the same sample point on the same aircraft - also the bounded interval for a sustained moving skim's own intermittent bursts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 5f), Array.Empty<object>())); _waterEffectsMaxConcurrentInstances = config.Bind<int>("WaterEffects", "MaxConcurrentInstances", WaterEffectsMaxConcurrentInstances, new ConfigDescription("Maximum REAL concurren