Proper fall damage prevention feature & settings refactor

* Added a proper, way more reliable fall damage removal feature
* Added an experimental 'smarter' fall damage prevention feature
* Refactored all setting labels for better readability
This commit is contained in:
Terkoiz 2024-03-02 18:40:51 +02:00
parent 796e7a6005
commit 28fd27d21d
6 changed files with 85 additions and 24 deletions

View File

@ -0,0 +1,44 @@
using System.Reflection;
using Aki.Reflection.Patching;
using EFT.HealthSystem;
using HarmonyLib;
namespace Terkoiz.Freecam
{
public class FallDamagePatch : ModulePatch
{
internal static bool HasTeleported;
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(ActiveHealthController), "HandleFall");
}
[PatchPrefix]
public static bool PatchPrefix(ActiveHealthController __instance, float height)
{
// WARNING: The 'HandleFall' method gets called every frame for every player and AI in a raid. Be very careful with logging or expensive operations in this prefix patch!
// Check if it's our own player, or if a Player property even exists
if (__instance.Player?.IsAI ?? true)
{
return true; // Run original method
}
// Global fall damage flag overrides everything
if (FreecamPlugin.GlobalDisableFallDamage.Value)
{
return false; // Prevent original method from running
}
// If smart fall damage flag is enabled, check if we've recently teleported and if the fall height value was positive
if (FreecamPlugin.SmartDisableFallDamage.Value && HasTeleported && height > 0)
{
HasTeleported = false;
return false; // Prevent original method from running
}
return true; // Run original method
}
}
}

View File

@ -21,11 +21,6 @@ namespace Terkoiz.Freecam
private Vector3? _lastPosition; private Vector3? _lastPosition;
private Quaternion? _lastRotation; private Quaternion? _lastRotation;
// TODO:
// Hide version number UI element
// Button to toggle between camera and player movement
// Independent FoV setting for Freecam mode (_mainCamera.GetComponent<Camera>().fieldOfView = ...)
[UsedImplicitly] [UsedImplicitly]
public void Start() public void Start()
{ {
@ -103,6 +98,9 @@ namespace Terkoiz.Freecam
// Move the player to the camera's current position and switch to First Person mode // Move the player to the camera's current position and switch to First Person mode
if (_freeCamScript.IsActive) if (_freeCamScript.IsActive)
{ {
// Tell the fall damage patch that we just teleported. Used for the "smart" fall damage prevention feature
FallDamagePatch.HasTeleported = true;
// We grab the camera's position, but we subtract a bit off the Y axis, because the players coordinate origin is at the feet // We grab the camera's position, but we subtract a bit off the Y axis, because the players coordinate origin is at the feet
var position = new Vector3(_mainCamera.transform.position.x, _mainCamera.transform.position.y - 1.8f, _mainCamera.transform.position.z); var position = new Vector3(_mainCamera.transform.position.x, _mainCamera.transform.position.y - 1.8f, _mainCamera.transform.position.z);
localPlayer.gameObject.transform.SetPositionAndRotation(position, Quaternion.Euler(0, _mainCamera.transform.rotation.y, 0)); localPlayer.gameObject.transform.SetPositionAndRotation(position, Quaternion.Euler(0, _mainCamera.transform.rotation.y, 0));

View File

@ -2,6 +2,7 @@ using System.Reflection;
using Aki.Reflection.Patching; using Aki.Reflection.Patching;
using Comfort.Common; using Comfort.Common;
using EFT; using EFT;
using HarmonyLib;
namespace Terkoiz.Freecam namespace Terkoiz.Freecam
{ {
@ -9,7 +10,7 @@ namespace Terkoiz.Freecam
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
{ {
return typeof(GameWorld).GetMethod("OnGameStarted", BindingFlags.Public | BindingFlags.Instance); return AccessTools.Method(typeof(GameWorld), "OnGameStarted");
} }
[PatchPostfix] [PatchPostfix]

View File

@ -7,11 +7,16 @@ using KeyboardShortcut = BepInEx.Configuration.KeyboardShortcut;
namespace Terkoiz.Freecam namespace Terkoiz.Freecam
{ {
[BepInPlugin("com.terkoiz.freecam", "Terkoiz.Freecam", "1.3.2")] [BepInPlugin("com.terkoiz.freecam", "Terkoiz.Freecam", "1.4.0")]
public class FreecamPlugin : BaseUnityPlugin public class FreecamPlugin : BaseUnityPlugin
{ {
internal new static ManualLogSource Logger { get; private set; } internal new static ManualLogSource Logger { get; private set; }
// Fall damage config entries
private const string FallDamageSectionName = "Fall Damage";
internal static ConfigEntry<bool> GlobalDisableFallDamage;
internal static ConfigEntry<bool> SmartDisableFallDamage;
// Keyboard shortcut config entries // Keyboard shortcut config entries
private const string KeybindSectionName = "Keybinds"; private const string KeybindSectionName = "Keybinds";
internal static ConfigEntry<KeyboardShortcut> ToggleFreecamMode; internal static ConfigEntry<KeyboardShortcut> ToggleFreecamMode;
@ -39,13 +44,26 @@ namespace Terkoiz.Freecam
InitConfiguration(); InitConfiguration();
new FreecamPatch().Enable(); new FreecamPatch().Enable();
new FallDamagePatch().Enable();
} }
private void InitConfiguration() private void InitConfiguration()
{ {
GlobalDisableFallDamage = Config.Bind(
FallDamageSectionName,
"Globally Disable Fall Damage",
false,
"Completely disables fall damage. This is the safest option for using freecam. Will fully override the 'Smart Fall Damage Prevention' setting.");
SmartDisableFallDamage = Config.Bind(
FallDamageSectionName,
"Smart Fall Damage Prevention",
true,
"Fall damage will only be disabled after using teleport, until your player lands. Less cheat-y way to save yourself from fall damage, but might sometimes be unreliable.");
ToggleFreecamMode = Config.Bind( ToggleFreecamMode = Config.Bind(
KeybindSectionName, KeybindSectionName,
"ToggleCamera", "Toggle Freecam",
new KeyboardShortcut(KeyCode.KeypadPlus), new KeyboardShortcut(KeyCode.KeypadPlus),
"The keyboard shortcut that toggles Freecam"); "The keyboard shortcut that toggles Freecam");
@ -57,13 +75,13 @@ namespace Terkoiz.Freecam
ToggleUi = Config.Bind( ToggleUi = Config.Bind(
KeybindSectionName, KeybindSectionName,
"ToggleUi", "Toggle UI",
new KeyboardShortcut(KeyCode.KeypadMultiply), new KeyboardShortcut(KeyCode.KeypadMultiply),
"The keyboard shortcut that toggles the game UI"); "The keyboard shortcut that toggles the game UI");
CameraMoveSpeed = Config.Bind( CameraMoveSpeed = Config.Bind(
CameraSettingsSectionName, CameraSettingsSectionName,
"CameraMoveSpeed", "Camera Speed",
10f, 10f,
new ConfigDescription( new ConfigDescription(
"The speed at which the camera will move normally", "The speed at which the camera will move normally",
@ -71,7 +89,7 @@ namespace Terkoiz.Freecam
CameraFastMoveSpeed = Config.Bind( CameraFastMoveSpeed = Config.Bind(
CameraSettingsSectionName, CameraSettingsSectionName,
"CameraFastMoveSpeed", "Camera Sprint Speed",
100f, 100f,
new ConfigDescription( new ConfigDescription(
"The speed at which the camera will move when the Shift key is held down", "The speed at which the camera will move when the Shift key is held down",
@ -79,7 +97,7 @@ namespace Terkoiz.Freecam
CameraLookSensitivity = Config.Bind( CameraLookSensitivity = Config.Bind(
CameraSettingsSectionName, CameraSettingsSectionName,
"CameraLookSensitivity", "Camera Mouse Sensitivity",
3f, 3f,
new ConfigDescription( new ConfigDescription(
"Camera free look mouse sensitivity", "Camera free look mouse sensitivity",
@ -87,7 +105,7 @@ namespace Terkoiz.Freecam
CameraZoomSpeed = Config.Bind( CameraZoomSpeed = Config.Bind(
CameraSettingsSectionName, CameraSettingsSectionName,
"CameraMousewheelZoomSpeed", "Camera Zoom Speed",
10f, 10f,
new ConfigDescription( new ConfigDescription(
"Amount to zoom the camera when using the mouse wheel", "Amount to zoom the camera when using the mouse wheel",
@ -95,7 +113,7 @@ namespace Terkoiz.Freecam
CameraFastZoomSpeed = Config.Bind( CameraFastZoomSpeed = Config.Bind(
CameraSettingsSectionName, CameraSettingsSectionName,
"CameraMousewheelFastZoomSpeed", "Camera Zoom Sprint Speed",
50f, 50f,
new ConfigDescription( new ConfigDescription(
"Amount to zoom the camera when using the mouse wheel while holding Shift", "Amount to zoom the camera when using the mouse wheel while holding Shift",
@ -116,9 +134,9 @@ namespace Terkoiz.Freecam
CameraRememberLastPosition = Config.Bind( CameraRememberLastPosition = Config.Bind(
TogglesSectionName, TogglesSectionName,
"CameraRememberLastPosition", "Remember Last Camera Position",
false, false,
"If enabled, returning to Freecam mode will put the camera to it's last position which was saved when exiting Freecam mode."); "If enabled, returning to Freecam mode will put the camera to it's last position which is saved when exiting Freecam mode.");
} }
} }
} }

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<Version>1.3.2</Version> <Version>1.4.0</Version>
<Authors>Terkoiz, Kobrakon, CWX</Authors> <Authors>Terkoiz, Kobrakon, CWX</Authors>
<RepositoryUrl>https://dev.sp-tarkov.com/Terkoiz/Freecam</RepositoryUrl> <RepositoryUrl>https://dev.sp-tarkov.com/Terkoiz/Freecam</RepositoryUrl>
<PackageLicenseExpression>NCSA</PackageLicenseExpression> <PackageLicenseExpression>NCSA</PackageLicenseExpression>
@ -20,7 +20,7 @@
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\References\Hollowed\Assembly-CSharp.dll</HintPath> <HintPath>..\References\EFT_Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Comfort"> <Reference Include="Comfort">