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 FreeFlight v1.1.0
plugins/FreeFlight.dll
Decompiled a week agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("FreeFlight")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+47387fc1dd9268975412a4fec193f5bfd45a3264")] [assembly: AssemblyProduct("FreeFlight")] [assembly: AssemblyTitle("FreeFlight")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [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 Oddhatter.FreeFlight { internal static class Flight { private static bool _safeLanding; internal static bool Active { get; private set; } internal static bool IsLocalFlyer(Character character) { if (Active && (Object)(object)character != (Object)null) { return (Object)(object)character == (Object)(object)Player.m_localPlayer; } return false; } internal static void UpdateToggle() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Active = false; _safeLanding = false; return; } bool flag = ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsAttached() || ((Character)localPlayer).IsAttachedToShip(); if (Active && (!FreeFlightPlugin.Enabled.Value || flag)) { SetActive(localPlayer, on: false); } else if (FreeFlightPlugin.Enabled.Value && !flag && ((Character)localPlayer).TakeInput() && (ZInput.GetKeyDown(FreeFlightPlugin.ToggleKey.Value, false) || (FreeFlightPlugin.GamepadToggle.Value && BothSticksPressed()))) { SetActive(localPlayer, !Active); } } private static bool BothSticksPressed() { if (!ZInput.GetButtonDown("JoyLStick") || !ZInput.GetButton("JoyRStick")) { if (ZInput.GetButtonDown("JoyRStick")) { return ZInput.GetButton("JoyLStick"); } return false; } return true; } private static void SetActive(Player player, bool on) { Active = on; if (!on) { _safeLanding = true; ((Character)player).m_lastGroundTouch = 1f; } ((Character)player).Message((MessageType)1, on ? "Flight on" : "Flight off", 0, (Sprite)null, false); } internal static bool UpdateMotion(Player player, float dt) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (Active && !((Character)player).IsDead() && !((Character)player).IsTeleporting()) { Move(player, dt); return true; } if (_safeLanding) { if (((Character)player).IsDead() || ((Character)player).InLiquidSwimDepth() || ((Character)player).m_lastGroundTouch < 0.1f) { _safeLanding = false; } else { if (player.m_crouchToggled) { ((Character)player).SetCrouch(false); } ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; } } return false; } private static void Move(Player player, float dt) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) ((Character)player).UpdateBodyFriction(); ((Character)player).m_sliding = false; ((Character)player).m_wallRunning = false; ((Character)player).m_running = false; ((Character)player).m_walking = false; if (player.m_crouchToggled) { ((Character)player).SetCrouch(false); } float num = FreeFlightPlugin.FlySpeed.Value * (((Character)player).m_run ? FreeFlightPlugin.SprintMultiplier.Value : 1f); Vector3 val = ((Character)player).m_moveDir * num; if (((Character)player).TakeInput()) { if ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) && !Hud.IsPieceSelectionVisible()) { val.y = num; } else if (ZInput.GetButton("Crouch") || ZInput.GetButtonPressedTimer("JoyCrouch") > 0.33f) { val.y = 0f - num; } } Rigidbody body = ((Character)player).m_body; ((Character)player).m_currentVel = Vector3.Lerp(((Character)player).m_currentVel, val, 0.5f); body.linearVelocity = ((Character)player).m_currentVel; body.useGravity = false; body.rotation = Quaternion.RotateTowards(((Component)player).transform.rotation, ((Character)player).m_lookYaw, ((Character)player).m_turnSpeed * dt); body.angularVelocity = Vector3.zero; ((Character)player).m_lastGroundTouch = 0f; ((Character)player).m_maxAirAltitude = ((Component)player).transform.position.y; ((Character)player).m_fallTimer = 0f; ((Character)player).m_zanim.SetBool(Character.s_animatorFalling, false); ((Character)player).UpdateEyeRotation(); } } [BepInPlugin("com.oddhatter.freeflight", "FreeFlight", "1.1.0")] [BepInProcess("valheim.exe")] public sealed class FreeFlightPlugin : BaseUnityPlugin { public const string Guid = "com.oddhatter.freeflight"; public const string Name = "FreeFlight"; public const string Version = "1.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyCode> ToggleKey; internal static ConfigEntry<bool> GamepadToggle; internal static ConfigEntry<float> FlySpeed; internal static ConfigEntry<float> SprintMultiplier; internal static ConfigEntry<bool> DragHarpooned; internal static ConfigEntry<float> RopeLength; private const float ConfigReloadDelay = 0.5f; private Harmony _harmony; private FileSystemWatcher _configWatcher; private volatile bool _configFileChanged; private float _configReloadAt = -1f; private bool _configLockedLogged; private void Awake() { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. When false, flight is unavailable and the harpoon works as in vanilla."); ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)104, "Key that turns flying on and off. While flying: Jump (Space) climbs, Crouch (Ctrl) descends, Run (Shift) is faster."); GamepadToggle = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "GamepadToggle", true, "Controller: press both thumbsticks in together (L3 + R3) to turn flying on and off."); FlySpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Speed", "FlySpeed", 20f, new ConfigDescription("Flying speed in meters per second (normal running is about 7).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); SprintMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Speed", "SprintMultiplier", 2.5f, new ConfigDescription("Speed multiplier while holding Run. Flying never costs stamina.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>())); DragHarpooned = ((BaseUnityPlugin)this).Config.Bind<bool>("Harpoon", "DragHarpooned", true, "true: an enemy you harpoon is towed through the air while you fly (the line doesn't snap and costs no stamina). Release it the vanilla way, by attacking or blocking. false: vanilla harpoon."); RopeLength = ((BaseUnityPlugin)this).Config.Bind<float>("Harpoon", "RopeLength", 5f, new ConfigDescription("How far below/behind you a towed enemy hangs, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>())); _harmony = new Harmony("com.oddhatter.freeflight"); _harmony.PatchAll(typeof(FreeFlightPlugin).Assembly); foreach (MethodBase patchedMethod in _harmony.GetPatchedMethods()) { Log.LogInfo((object)("Patched " + patchedMethod.DeclaringType?.Name + "." + patchedMethod.Name)); } WatchConfigFile(); Log.LogInfo((object)"FreeFlight 1.1.0 loaded."); } private void Update() { Flight.UpdateToggle(); if (_configFileChanged) { _configFileChanged = false; _configReloadAt = Time.realtimeSinceStartup + 0.5f; } if (_configReloadAt >= 0f && Time.realtimeSinceStartup >= _configReloadAt) { _configReloadAt = -1f; ReloadConfigFromDisk(); } } private void OnDestroy() { _configWatcher?.Dispose(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void WatchConfigFile() { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; _configWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath)) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), IncludeSubdirectories = false }; _configWatcher.Changed += OnConfigFileEvent; _configWatcher.Created += OnConfigFileEvent; _configWatcher.Renamed += OnConfigFileEvent; _configWatcher.EnableRaisingEvents = true; } private void OnConfigFileEvent(object sender, FileSystemEventArgs e) { _configFileChanged = true; } private void ReloadConfigFromDisk() { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return; } bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; try { ((BaseUnityPlugin)this).Config.Reload(); _configLockedLogged = false; Log.LogInfo((object)"Configuration reloaded from disk."); } catch (IOException ex) { if (!_configLockedLogged) { _configLockedLogged = true; Log.LogWarning((object)("Config file busy, will retry: " + ex.Message)); } _configReloadAt = Time.realtimeSinceStartup + 0.5f; } catch (Exception ex2) { Log.LogError((object)("Failed to reload configuration: " + ex2.Message)); } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } } [HarmonyPatch(typeof(Character), "UpdateMotion")] internal static class Character_UpdateMotion_Patch { private static bool Prefix(Character __instance, float dt) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } return !Flight.UpdateMotion((Player)__instance, dt); } } [HarmonyPatch(typeof(Character), "Jump")] internal static class Character_Jump_Patch { private static bool Prefix(Character __instance) { return !Flight.IsLocalFlyer(__instance); } } [HarmonyPatch(typeof(Player), "IsEncumbered")] internal static class Player_IsEncumbered_Patch { private static void Postfix(Player __instance, ref bool __result) { if (__result && Flight.IsLocalFlyer((Character)(object)__instance)) { __result = false; } } } [HarmonyPatch(typeof(Character), "Damage")] internal static class Character_Damage_Patch { private static void Prefix(Character __instance, HitData hit) { if (hit == null || hit.m_statusEffectHash == 0 || !FreeFlightPlugin.Enabled.Value || !FreeFlightPlugin.DragHarpooned.Value) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !__instance.IsPlayer() && !__instance.IsBoss()) { ZNetView nview = __instance.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && !nview.IsOwner() && !((Object)(object)hit.GetAttacker() != (Object)(object)localPlayer) && !((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.GetStatusEffect(hit.m_statusEffectHash) is SE_Harpooned) { nview.ClaimOwnership(); } } } } [HarmonyPatch(typeof(SE_Harpooned), "UpdateStatusEffect")] internal static class SE_Harpooned_UpdateStatusEffect_Patch { private const float Stiffness = 5f; private const float MaxCatchUpSpeed = 50f; private const float SnapDistance = 40f; private static bool Prefix(SE_Harpooned __instance, float dt) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (!FreeFlightPlugin.Enabled.Value || !FreeFlightPlugin.DragHarpooned.Value || !Flight.Active) { return true; } Character attacker = __instance.m_attacker; Character character = ((StatusEffect)__instance).m_character; if ((Object)(object)attacker == (Object)null || (Object)(object)attacker != (Object)(object)Player.m_localPlayer || (Object)(object)character == (Object)null || (Object)(object)character.m_body == (Object)null) { return true; } BaseUpdate((StatusEffect)(object)__instance, dt); Rigidbody body = character.m_body; float value = FreeFlightPlugin.RopeLength.Value; Vector3 val = ((Component)attacker).transform.position - body.position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude > value) { Vector3 val2 = val / magnitude; float num = magnitude - value; if (num > 40f) { body.position = ((Component)attacker).transform.position - val2 * value; body.linearVelocity = attacker.m_body.linearVelocity; } else { body.linearVelocity = attacker.m_body.linearVelocity + val2 * Mathf.Min(num * 5f, 50f); } } __instance.m_baseDistance = value; if ((Object)(object)__instance.m_line != (Object)null) { __instance.m_line.SetSlack((1f - Utils.LerpStep(value / 2f, value, magnitude)) * __instance.m_maxLineSlack); } return false; } private static void BaseUpdate(StatusEffect se, float dt) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) se.m_time += dt; if (se.m_repeatInterval > 0f && !string.IsNullOrEmpty(se.m_repeatMessage)) { se.m_msgTimer += dt; if (se.m_msgTimer > se.m_repeatInterval) { se.m_msgTimer = 0f; se.m_character.Message(se.m_repeatMessageType, se.m_repeatMessage, 0, (Sprite)null, false); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }