From 86b11151cf2e7e8be8bf22ea4ca7d086452a523b Mon Sep 17 00:00:00 2001
From: zochris <20927697+zochris@users.noreply.github.com>
Date: Sat, 2 Nov 2024 01:58:06 +0100
Subject: [PATCH] Fix items from pocket dimension spawning in tutorial room
Fix #62
+semver: minor
---
.../Patches/PocketItemManagerPatch.cs | 73 +++++++++++++++++++
docs/Testing.md | 6 +-
2 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 Spectator-Disabler/Patches/PocketItemManagerPatch.cs
diff --git a/Spectator-Disabler/Patches/PocketItemManagerPatch.cs b/Spectator-Disabler/Patches/PocketItemManagerPatch.cs
new file mode 100644
index 0000000..22be431
--- /dev/null
+++ b/Spectator-Disabler/Patches/PocketItemManagerPatch.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using System.Reflection.Emit;
+using Exiled.API.Features.Pools;
+using HarmonyLib;
+using JetBrains.Annotations;
+using PlayerRoles;
+using PlayerRoles.PlayableScps.Scp106;
+
+namespace SpectatorDisabler.Patches
+{
+ [HarmonyPatch(typeof(Scp106PocketItemManager), nameof(Scp106PocketItemManager.GetRandomValidSpawnPosition))]
+ internal static class PocketItemManagerPatch
+ {
+ ///
+ /// This transpiler replaces the following code:
+ ///
+ /// if (allHub.roleManager.CurrentRole is IFpcRole currentRole)
+ /// {
+ /// // get position to spawn item
+ /// }
+ ///
+ /// With this one:
+ ///
+ /// if (allHub.roleManager.CurrentRole is IFpcRole currentRole
+ /// && allHub.roleManager.CurrentRole.RoleTypeId != RoleTypeId.Tutorial)
+ /// {
+ /// // get position to spawn item
+ /// }
+ ///
+ ///
+ ///
+ /// The s of the original
+ /// method.
+ ///
+ ///
+ /// The new patched s of the
+ /// method.
+ ///
+ [UsedImplicitly]
+ private static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ var newInstructions = ListPool.Pool.Get(instructions);
+
+ for (var i = 0; i < newInstructions.Count; i++)
+ {
+ if (newInstructions[i].opcode == OpCodes.Isinst
+ && newInstructions[i - 1].opcode == OpCodes.Callvirt
+ && newInstructions[i - 2].opcode == OpCodes.Ldfld
+ && newInstructions[i - 3].opcode == OpCodes.Call)
+ {
+ // duplicate value of roleManager.CurrentRole on stack to use later
+ yield return new CodeInstruction(OpCodes.Dup);
+ }
+
+ if (newInstructions[i].opcode == OpCodes.Ldloc_3
+ && newInstructions[i - 1].opcode == OpCodes.Brfalse_S
+ && newInstructions[i - 2].opcode == OpCodes.Ldloc_3
+ && newInstructions[i - 3].opcode == OpCodes.Stloc_3)
+ {
+ // add check for tutorial
+ yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(PlayerRoleBase), nameof(PlayerRoleBase.RoleTypeId)));
+ yield return new CodeInstruction(OpCodes.Ldc_I4_S, 14); // RoleTypeId.Tutorial
+ yield return new CodeInstruction(OpCodes.Ceq); // currentRole.RoleTypeId == RoleTypeId.Tutorial
+ yield return new CodeInstruction(OpCodes.Brtrue_S, newInstructions[i - 1].operand); // continue
+ }
+
+ yield return newInstructions[i];
+ }
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
diff --git a/docs/Testing.md b/docs/Testing.md
index df627ff..d0d4162 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -20,4 +20,8 @@ Some test require more than one player and are marked with a remark.
- A recently killed player can be revived by SCP-049 and spawns as a zombie
- Requires 2 players
- A zombie recently killed by another player can be revived one time
- - Requires 3 players (SCP-049, human to be revived, human that kills zombie)
+ - Requires 3 players (SCP-049, zombie to be revived, human that kills zombie)
+
+## Pocket Dimension
+- Items lost in the pocket dimension spawn around players that are not in the tutorial role
+ - Requires 2 players