Skip to content

Commit 877469e

Browse files
committed
Scp3114FriendlyFireFix
1 parent fcf3987 commit 877469e

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// -----------------------------------------------------------------------
2+
// <copyright file="Scp3114FriendlyFireFix.cs" company="Exiled Team">
3+
// Copyright (c) Exiled Team. All rights reserved.
4+
// Licensed under the CC BY-SA 3.0 license.
5+
// </copyright>
6+
// -----------------------------------------------------------------------
7+
8+
namespace Exiled.Events.Patches.Fixes
9+
{
10+
#pragma warning disable SA1402 // File may only contain a single type
11+
using System.Collections.Generic;
12+
using System.Reflection.Emit;
13+
14+
using API.Features.Pools;
15+
using Footprinting;
16+
using HarmonyLib;
17+
using InventorySystem.Items.Pickups;
18+
using InventorySystem.Items.ThrowableProjectiles;
19+
using PlayerRoles;
20+
using PlayerStatsSystem;
21+
22+
using static HarmonyLib.AccessTools;
23+
24+
/// <summary>
25+
/// Patches the <see cref="Scp2176Projectile.ServerShatter()"/> delegate.
26+
/// Fix Throwing a ghostlight with Scp in the room stun 079.
27+
/// Bug reported to NW (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/55).
28+
/// </summary>
29+
[HarmonyPatch(typeof(Scp2176Projectile), nameof(Scp2176Projectile.ServerShatter))]
30+
internal class Scp3114FriendlyFireFix
31+
{
32+
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
33+
{
34+
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);
35+
36+
int offset = 0;
37+
int index = newInstructions.FindIndex(x => x.operand == (object)Field(typeof(Scp2176Projectile), nameof(Scp2176Projectile.OnServerShattered))) + offset;
38+
39+
Label skip = (Label)newInstructions[index].operand;
40+
41+
newInstructions.InsertRange(index, new[]
42+
{
43+
// if (this.PreviousOwner.Role.GetTeam() is Team.SCPs)
44+
new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]),
45+
new(OpCodes.Ldfld, Field(typeof(Scp2176Projectile), nameof(Scp2176Projectile.PreviousOwner))),
46+
new(OpCodes.Ldfld, Field(typeof(Footprint), nameof(Footprint.Role))),
47+
new(OpCodes.Call, Method(typeof(PlayerRolesUtils), nameof(PlayerRolesUtils.GetTeam))),
48+
new(OpCodes.Ldc_I4_0),
49+
new(OpCodes.Ceq),
50+
new CodeInstruction(OpCodes.Brtrue_S, skip),
51+
});
52+
53+
offset = 0;
54+
index = newInstructions.FindIndex(x => x.operand == (object)Field(typeof(RoomLightController), nameof(RoomLightController.Instances))) + offset;
55+
56+
newInstructions[index].labels.Add(skip);
57+
58+
for (int z = 0; z < newInstructions.Count; z++)
59+
yield return newInstructions[z];
60+
61+
ListPool<CodeInstruction>.Pool.Return(newInstructions);
62+
}
63+
}
64+
65+
/// <summary>
66+
/// Patches the <see cref="CollisionDetectionPickup.ProcessCollision(UnityEngine.Collision)"/> delegate.
67+
/// Fix Throwing a ghostlight with Scp in the room stun 079.
68+
/// Bug reported to NW (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/55).
69+
/// </summary>
70+
[HarmonyPatch(typeof(CollisionDetectionPickup), nameof(CollisionDetectionPickup.ProcessCollision))]
71+
internal class Scp3114FriendlyFireFix2 : AttackerDamageHandler
72+
{
73+
#pragma warning disable SA1600 // Elements should be documented
74+
public Scp3114FriendlyFireFix2(Footprint attacker, float damage)
75+
{
76+
Attacker = attacker;
77+
Damage = damage;
78+
AllowSelfDamage = false;
79+
ServerLogsText = "Scp3114 Fix";
80+
}
81+
82+
public override Footprint Attacker { get; set; }
83+
84+
public override bool AllowSelfDamage { get; }
85+
86+
public override float Damage { get; set; }
87+
88+
public override string ServerLogsText { get; }
89+
#pragma warning restore SA1600 // Elements should be documented
90+
91+
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
92+
{
93+
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);
94+
95+
int offset = 0;
96+
int index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldnull) + offset;
97+
98+
// replace null with new Scp3114FriendlyFireFix2(this.PreviousOwner, num2)
99+
newInstructions.RemoveAt(index);
100+
newInstructions.InsertRange(index, new CodeInstruction[]
101+
{
102+
// new Scp3114FriendlyFireFix2(this.PreviousOwner, num2)
103+
new(OpCodes.Ldarg_0),
104+
new(OpCodes.Ldfld, Field(typeof(CollisionDetectionPickup), nameof(CollisionDetectionPickup.PreviousOwner))),
105+
new(OpCodes.Ldloc_3),
106+
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(Scp3114FriendlyFireFix2))[0]),
107+
});
108+
109+
for (int z = 0; z < newInstructions.Count; z++)
110+
yield return newInstructions[z];
111+
112+
ListPool<CodeInstruction>.Pool.Return(newInstructions);
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)