Skip to content

Commit

Permalink
Buncha fixes for v1.2.1
Browse files Browse the repository at this point in the history
- Fixed a benign warning when loading input bindings
- Reduced impact of playerspace spoofing hacks
- Fixed an issue where somehow getting the camera out of water would prevent drowning
- Fixed Diversity custom pass warping rendering when DynRes is enabled
  • Loading branch information
DaXcess committed Mar 25, 2024
1 parent 8c316df commit 933474d
Show file tree
Hide file tree
Showing 16 changed files with 625 additions and 547 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 1.2.1

**Bug fixes:**

- Fixed corrupt/improper OpenXR setup causing the settings menu to not load
- Fixed a benign warning when loading input bindings
- Reduced impact of playerspace spoofing hacks
- Fixed an issue where somehow getting the camera out of water would prevent drowning
- Fixed Diversity custom pass warping rendering when DynRes is enabled

# 1.2.0

## Settings Menu
Expand Down
1 change: 1 addition & 0 deletions LCVR.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<ItemGroup>
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all" />
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="Diversity" Version="2.0.3" />
<PackageReference Include="LCVRDeps" Version="1.49.0" />
<PackageReference Include="Mimics" Version="2.4.1" />
<PackageReference Include="MoreCompany" Version="1.8.1" />
Expand Down
1 change: 1 addition & 0 deletions Source/Compat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class Compat
[
new("MoreCompany", "me.swipez.melonloader.morecompany"),
new("Mimics", "x753.Mimics"),
new("Diversity", "Chaos.Diversity"),
];

private static readonly List<string> DetectedMods = [];
Expand Down
29 changes: 29 additions & 0 deletions Source/Compatibility/Diversity/Patches.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Diversity.Misc;
using HarmonyLib;
using LCVR.Patches;

namespace LCVR.Compatibility.Diversity;

[LCVRPatch(dependency: "Diversity")]
[HarmonyPatch]
internal static class DiversityPatches
{
[HarmonyPatch(typeof(HUDManagerRevamp), nameof(HUDManagerRevamp.Start))]
[HarmonyPostfix]
private static void OnHUDManagerRevampStart()
{
DisableGlitchCustomPass();
}

[HarmonyPatch(typeof(HUDManagerRevamp), nameof(HUDManagerRevamp.Cpp_OnLoad))]
[HarmonyPostfix]
private static void OnLoadCustomPostProcess()
{
DisableGlitchCustomPass();
}

private static void DisableGlitchCustomPass()
{
HUDManagerRevamp.Instance.fullscreenPass2.enabled = false;
}
}
2 changes: 1 addition & 1 deletion Source/Compatibility/Mimics/Patches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using Mimics;
using UnityEngine;

namespace LCVR.Compatibility;
namespace LCVR.Compatibility.Mimics;

[LCVRPatch(dependency: "Mimics")]
[HarmonyPatch]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using UnityEngine;

namespace LCVR.Compatibility;
namespace LCVR.Compatibility.MoreCompany;

internal static class MoreCompany
internal static class MoreCompanyCompatibility
{
public static void SetupMoreCompanyUI()
{
Expand Down
4 changes: 2 additions & 2 deletions Source/Compatibility/MoreCompany/Patches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
using LCVR.Patches;
using MoreCompany.Behaviors;
using MoreCompany.Cosmetics;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine;

namespace LCVR.Compatibility;
namespace LCVR.Compatibility.MoreCompany;

[LCVRPatch(dependency: "MoreCompany")]
[HarmonyPatch]
Expand Down
19 changes: 11 additions & 8 deletions Source/Input/Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Actions
{ "hp_reverb", AssetManager.Input("HPReverbInputs") },
};

public static Actions Instance { get; private set; } = new Actions();
public static Actions Instance { get; private set; } = new();

private InputActionAsset allActions;

Expand Down Expand Up @@ -61,6 +61,9 @@ public void Reload()
{
InputSystem.onDeviceChange += InputSystem_onDeviceChange;

if (string.IsNullOrEmpty(Plugin.Config.LastInternalControllerProfile.Value))
Plugin.Config.LastInternalControllerProfile.Value = "default";

profile = Plugin.Config.LastInternalControllerProfile.Value;
}

Expand All @@ -77,15 +80,15 @@ public void Reload()

private void InputSystem_onDeviceChange(InputDevice _1, InputDeviceChange _2)
{
if (DetectControllerProfile(out var profile))
{
InputSystem.onDeviceChange -= InputSystem_onDeviceChange;
if (!DetectControllerProfile(out var profile))
return;

Plugin.Config.LastInternalControllerProfile.Value = profile;
InputSystem.onDeviceChange -= InputSystem_onDeviceChange;

allActions = GetProfile(profile);
allActions.Enable();
}
Plugin.Config.LastInternalControllerProfile.Value = profile;

allActions = GetProfile(profile);
allActions.Enable();
}

/// <summary>
Expand Down
24 changes: 24 additions & 0 deletions Source/Patches/PlayerControllerPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,30 @@ private static void SwitchedToItemSlot(PlayerControllerB __instance)
component.enabled = true;
}
}

/// <summary>
/// Fix for water suffocation to be calculated from a predetermined offset instead of the camera position,
/// which fixes an exploit where being too tall prevents drowning
/// </summary>
// TODO: Remove debug
[HarmonyPatch(typeof(PlayerControllerB), nameof(PlayerControllerB.SetFaceUnderwaterFilters))]
[HarmonyTranspiler]
[HarmonyDebug]
private static IEnumerable<CodeInstruction> UnderwaterExploitFix(IEnumerable<CodeInstruction> instructions)
{
return new CodeMatcher(instructions)
.MatchForward(false, [new CodeMatch(OpCodes.Call, Method(typeof(Bounds), nameof(Bounds.Contains), [typeof(Vector3)]))])
.Advance(-3)
.RemoveInstructions(3)
.InsertAndAdvance(new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(Component), nameof(Component.transform))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(Transform), nameof(Transform.position))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_R4, 0f))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_R4, 2.3f))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldc_R4, 0f))
.InsertAndAdvance(new CodeInstruction(OpCodes.Newobj, Constructor(typeof(Vector3), [typeof(float), typeof(float), typeof(float)])))
.InsertAndAdvance(new CodeInstruction(OpCodes.Call, Method(typeof(Vector3), "op_Addition", [typeof(Vector3), typeof(Vector3)])))
.InstructionEnumeration();
}
}

[LCVRPatch(LCVRPatchTarget.Universal)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,112 +1,112 @@
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using GameNetcodeStuff;
using HarmonyLib;
using LCVR.Patches;
using UnityEngine;

using static HarmonyLib.AccessTools;

namespace LCVR.Player.Spectating;

/// <summary>
/// Generic AI patches for the free roam spectator functionality
/// </summary>
[LCVRPatch]
[HarmonyPatch]
internal static class SpectatorAIPatches
{
/// <summary>
/// Prevent dead player from notifying enemies that they are being looked at
/// </summary>
[HarmonyPatch(typeof(PlayerControllerB), nameof(PlayerControllerB.HasLineOfSightToPosition))]
[HarmonyPrefix]
private static bool CanCheckLineOfSight(PlayerControllerB __instance, ref bool __result)
{
if (!__instance.IsOwner || !__instance.isPlayerControlled || !__instance.isPlayerDead)
return true;

__result = false;
return false;
}

/// <summary>
/// Prevent dead player from making audible noises for enemies to hear
/// </summary>
[HarmonyPatch(typeof(RoundManager), nameof(RoundManager.PlayAudibleNoise))]
[HarmonyPrefix]
private static bool CanBeHeard()
{
return !StartOfRound.Instance.localPlayerController.isPlayerDead;
}

/// <summary>
/// Prevent player line of sight detection for dead players
/// </summary>
[HarmonyPatch(typeof(EnemyAI), nameof(EnemyAI.CheckLineOfSightForPlayer))]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> LineOfSightPlayerIgnoreDeadPlayer(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
return new CodeMatcher(instructions, generator)
.MatchForward(false, new CodeMatch(i => i.opcode == OpCodes.Ldfld && (FieldInfo)i.operand == Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.Advance(-1)
.Insert(new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(StartOfRound), nameof(StartOfRound.Instance))))
.CreateLabel(out var label)
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_1))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldelem_Ref))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(PlayerControllerB), nameof(PlayerControllerB.isPlayerDead))))
.InsertBranchAndAdvance(OpCodes.Brtrue, 77)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.Advance(1)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.SetOperandAndAdvance(label)
.InstructionEnumeration();
}

/// <summary>
/// Prevent closest player line of sight detection for dead players
/// </summary>
[HarmonyPatch(typeof(EnemyAI), nameof(EnemyAI.CheckLineOfSightForClosestPlayer))]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> LineOfSightClosestPlayerIgnoreDeadPlayer(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
return new CodeMatcher(instructions, generator)
.MatchForward(false, new CodeMatch(i => i.opcode == OpCodes.Ldfld && (FieldInfo)i.operand == Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.Advance(-1)
.Insert(new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(StartOfRound), nameof(StartOfRound.Instance))))
.CreateLabel(out var label)
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 4))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldelem_Ref))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(PlayerControllerB), nameof(PlayerControllerB.isPlayerDead))))
.InsertBranchAndAdvance(OpCodes.Brtrue, 79)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.Advance(1)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.SetOperandAndAdvance(label)
.InstructionEnumeration();
}

/// <summary>
/// Prevent collision detection on dead players
/// </summary>
[HarmonyPatch(typeof(EnemyAICollisionDetect), "OnTriggerStay")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> OnCollidePlayerTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
return new CodeMatcher(instructions, generator)
.MatchForward(false, new CodeMatch(OpCodes.Brfalse))
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_1))
.InsertAndAdvance(new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(Component), nameof(Component.gameObject))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Callvirt, Method(typeof(GameObject), nameof(GameObject.GetComponent)).MakeGenericMethod([typeof(PlayerControllerB)])))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(PlayerControllerB), nameof(PlayerControllerB.isPlayerDead))))
.InsertBranchAndAdvance(OpCodes.Brfalse_S, 8)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ret))
.InstructionEnumeration();
}
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using GameNetcodeStuff;
using HarmonyLib;
using LCVR.Patches;
using UnityEngine;

using static HarmonyLib.AccessTools;

namespace LCVR.Player.Spectating;

/// <summary>
/// Generic AI patches for the free roam spectator functionality
/// </summary>
[LCVRPatch]
[HarmonyPatch]
internal static class SpectatorAIPatches
{
/// <summary>
/// Prevent dead player from notifying enemies that they are being looked at
/// </summary>
[HarmonyPatch(typeof(PlayerControllerB), nameof(PlayerControllerB.HasLineOfSightToPosition))]
[HarmonyPrefix]
private static bool CanCheckLineOfSight(PlayerControllerB __instance, ref bool __result)
{
if (!__instance.IsOwner || !__instance.isPlayerControlled || !__instance.isPlayerDead)
return true;

__result = false;
return false;
}

/// <summary>
/// Prevent dead player from making audible noises for enemies to hear
/// </summary>
[HarmonyPatch(typeof(RoundManager), nameof(RoundManager.PlayAudibleNoise))]
[HarmonyPrefix]
private static bool CanBeHeard()
{
return !StartOfRound.Instance.localPlayerController.isPlayerDead;
}

/// <summary>
/// Prevent player line of sight detection for dead players
/// </summary>
[HarmonyPatch(typeof(EnemyAI), nameof(EnemyAI.CheckLineOfSightForPlayer))]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> LineOfSightPlayerIgnoreDeadPlayer(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
return new CodeMatcher(instructions, generator)
.MatchForward(false, new CodeMatch(i => i.opcode == OpCodes.Ldfld && (FieldInfo)i.operand == Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.Advance(-1)
.Insert(new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(StartOfRound), nameof(StartOfRound.Instance))))
.CreateLabel(out var label)
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_1))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldelem_Ref))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(PlayerControllerB), nameof(PlayerControllerB.isPlayerDead))))
.InsertBranchAndAdvance(OpCodes.Brtrue, 77)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.Advance(1)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.SetOperandAndAdvance(label)
.InstructionEnumeration();
}

/// <summary>
/// Prevent closest player line of sight detection for dead players
/// </summary>
[HarmonyPatch(typeof(EnemyAI), nameof(EnemyAI.CheckLineOfSightForClosestPlayer))]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> LineOfSightClosestPlayerIgnoreDeadPlayer(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
return new CodeMatcher(instructions, generator)
.MatchForward(false, new CodeMatch(i => i.opcode == OpCodes.Ldfld && (FieldInfo)i.operand == Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.Advance(-1)
.Insert(new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(StartOfRound), nameof(StartOfRound.Instance))))
.CreateLabel(out var label)
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(StartOfRound), nameof(StartOfRound.allPlayerScripts))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldloc_S, 4))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldelem_Ref))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(PlayerControllerB), nameof(PlayerControllerB.isPlayerDead))))
.InsertBranchAndAdvance(OpCodes.Brtrue, 79)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.Advance(1)
.MatchForward(false, new CodeMatch(OpCodes.Blt))
.SetOperandAndAdvance(label)
.InstructionEnumeration();
}

/// <summary>
/// Prevent collision detection on dead players
/// </summary>
[HarmonyPatch(typeof(EnemyAICollisionDetect), "OnTriggerStay")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> OnCollidePlayerTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
return new CodeMatcher(instructions, generator)
.MatchForward(false, new CodeMatch(OpCodes.Brfalse))
.Advance(1)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_1))
.InsertAndAdvance(new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(Component), nameof(Component.gameObject))))
.InsertAndAdvance(new CodeInstruction(OpCodes.Callvirt, Method(typeof(GameObject), nameof(GameObject.GetComponent)).MakeGenericMethod([typeof(PlayerControllerB)])))
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, Field(typeof(PlayerControllerB), nameof(PlayerControllerB.isPlayerDead))))
.InsertBranchAndAdvance(OpCodes.Brfalse_S, 8)
.InsertAndAdvance(new CodeInstruction(OpCodes.Ret))
.InstructionEnumeration();
}
}

0 comments on commit 933474d

Please sign in to comment.