Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scp330 interacting fix #184

Merged
merged 6 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions EXILED/Exiled.API/Features/Items/Scp330.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,6 @@ internal Scp330()
/// </summary>
public CandyKindID ExposedType { get; set; } = CandyKindID.None;

/// <summary>
/// Gets or sets the candy that will be added to the bag. Used for events.
/// </summary>
internal CandyKindID CandyToAdd { get; set; } = CandyKindID.None;

/// <summary>
/// Adds a specific candy to the bag.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,13 @@ public InteractingScp330EventArgs(Player player, int usage)
Scp330.RemoveAllCandy();
player.AddItem(Scp330);
}

Scp330.CandyToAdd = Scp330Candies.GetRandom();
}

/// <summary>
/// Gets a value indicating how many times this player has interacted with SCP-330.
/// </summary>
public int UsageCount { get; }

/// <summary>
/// Gets or sets a value indicating the type of candy that will be received from this interaction.
/// </summary>
public CandyKindID Candy
{
get => Scp330.CandyToAdd;
set => Scp330.CandyToAdd = value;
}

/// <summary>
/// Gets or sets a value indicating whether the player's hands should get severed.
/// </summary>
Expand All @@ -75,6 +64,11 @@ public CandyKindID Candy
/// <remarks>It won't work if <see cref="IsAllowed"/> = <see langword="false"/>.</remarks>
public bool ShouldPlaySound { get; set; }

/// <summary>
/// Gets or sets a value indicating the type of candy that will be received from this interaction.
/// </summary>
public CandyKindID Candy { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the player is allowed to interact with SCP-330.
/// </summary>
Expand Down
60 changes: 43 additions & 17 deletions EXILED/Exiled.Events/Patches/Events/Scp330/InteractingScp330.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Exiled.Events.Patches.Events.Scp330
{
#pragma warning disable SA1402
#pragma warning disable SA1313

using System.Collections.Generic;
using System.Reflection.Emit;

Expand All @@ -18,6 +19,7 @@ namespace Exiled.Events.Patches.Events.Scp330
using Exiled.Events.EventArgs.Scp330;
using HarmonyLib;
using Interactables.Interobjects;
using InventorySystem;
using InventorySystem.Items.Usables.Scp330;
using PluginAPI.Events;

Expand Down Expand Up @@ -73,29 +75,46 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
// return;
new(OpCodes.Callvirt, PropertyGetter(typeof(InteractingScp330EventArgs), nameof(InteractingScp330EventArgs.IsAllowed))),
new(OpCodes.Brfalse, returnLabel),

// ldarg.1 to player
new(OpCodes.Ldarg_1),

// ev.Candy
new(OpCodes.Ldloc, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(InteractingScp330EventArgs), nameof(InteractingScp330EventArgs.Candy))),

// bag
new(OpCodes.Ldloca_S, 3),

// ServerProcessPickup(ReferenceHub, CandyKindID, Scp330Bag)
new CodeInstruction(OpCodes.Call, Method(typeof(InteractingScp330), nameof(ServerProcessPickup), new[] { typeof(ReferenceHub), typeof(CandyKindID), typeof(Scp330Bag).MakeByRefType() })),
});

int remove_offset = -3;
int remove_index = newInstructions.FindLastIndex(
instruction => instruction.Calls(Method(typeof(Scp330Bag), nameof(Scp330Bag.ServerProcessPickup)))) + remove_offset;

// Remove original add candy logic
newInstructions.RemoveRange(remove_index, 4);

/* next code will used to override sound rpc check by EXILED
* old:
* if (args.PlaySound)
* new:
* if (args.PlaySound && ev.PlaySound)
* if (args.PlaySound | ev.PlaySound)
*/

offset = 1;
index = newInstructions.FindLastIndex(
instruction => instruction.Calls(PropertyGetter(typeof(PlayerInteractScp330Event), nameof(PlayerInteractScp330Event.PlaySound)))) + offset;

newInstructions.InsertRange(
index,
new[]
{
// load ev.ShouldPlaySound and or operation with nw property.
new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(InteractingScp330EventArgs), nameof(InteractingScp330EventArgs.ShouldPlaySound))),
new(OpCodes.And),
new(OpCodes.Or),
});

/* next code will used to override Sever check by EXILED
* old:
* if (args.AllowPunishment && uses >= 2)
Expand Down Expand Up @@ -135,21 +154,28 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi

ListPool<CodeInstruction>.Pool.Return(newInstructions);
}
}

/// <summary>
/// Replaces <see cref="Scp330Candies.GetRandom"/> with <see cref="InteractingScp330EventArgs.Candy"/>.
/// </summary>
[EventPatch(typeof(Handlers.Scp330), nameof(Handlers.Scp330.InteractingScp330))]
[HarmonyPatch(typeof(Scp330Bag), nameof(Scp330Bag.TryAddSpecific))]
internal static class ReplaceCandy
{
private static void Prefix(Scp330Bag __instance, ref CandyKindID kind)
private static bool ServerProcessPickup(ReferenceHub player, CandyKindID candy, out Scp330Bag bag)
{
Scp330 scp330 = Item.Get<Scp330>(__instance);
if (!Scp330Bag.TryGetBag(player, out bag))
{
player.inventory.ServerAddItem(ItemType.SCP330);

if (!Scp330Bag.TryGetBag(player, out bag))
return false;

bag.Candies = new List<CandyKindID> { candy };
bag.ServerRefreshBag();

return true;
}

bool result = bag.TryAddSpecific(candy);

if (bag.AcquisitionAlreadyReceived)
bag.ServerRefreshBag();

if (scp330.CandyToAdd != CandyKindID.None)
kind = scp330.CandyToAdd;
return result;
}
}
}