diff --git a/EXILED/Exiled.API/Enums/EffectType.cs b/EXILED/Exiled.API/Enums/EffectType.cs
index 4e7c6056d6..44c5b02301 100644
--- a/EXILED/Exiled.API/Enums/EffectType.cs
+++ b/EXILED/Exiled.API/Enums/EffectType.cs
@@ -216,7 +216,7 @@ public enum EffectType
///
/// Makes you a marshmallow guy.
///
- [Obsolete("Not functional in-game")]
+ // [Obsolete("Not functional in-game")]
Marshmallow,
///
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index 04d4b72535..89bb189c42 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -22,6 +22,7 @@ namespace Exiled.API.Features.Items
using InventorySystem.Items.Firearms.Ammo;
using InventorySystem.Items.Jailbird;
using InventorySystem.Items.Keycards;
+ using InventorySystem.Items.MarshmallowMan;
using InventorySystem.Items.MicroHID;
using InventorySystem.Items.Pickups;
using InventorySystem.Items.Radio;
@@ -260,6 +261,7 @@ public static Item Get(ItemBase itemBase)
_ => new Throwable(throwable),
},
Scp1509Item scp1509 => new Scp1509(scp1509),
+ MarshmallowItem marshmallow => new Marshmallow(marshmallow),
_ => new(itemBase),
};
}
@@ -364,6 +366,7 @@ public static T Get(ushort serial)
_ => new Throwable(type, owner),
},
Scp1509Item => new Scp1509(),
+ MarshmallowItem => new Marshmallow(type, owner),
_ => new(type),
};
diff --git a/EXILED/Exiled.API/Features/Items/Marshmallow.cs b/EXILED/Exiled.API/Features/Items/Marshmallow.cs
new file mode 100644
index 0000000000..05b8579cfe
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Marshmallow.cs
@@ -0,0 +1,102 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items
+{
+ using CustomPlayerEffects;
+ using Exiled.API.Interfaces;
+ using InventorySystem.Items.MarshmallowMan;
+ using PlayerStatsSystem;
+ using UnityEngine;
+
+ ///
+ /// A wrapper class for .
+ ///
+ public class Marshmallow : Item, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The base class.
+ public Marshmallow(MarshmallowItem itemBase)
+ : base(itemBase)
+ {
+ Base = itemBase;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the marshmallow item.
+ /// The owner of the marshmallow item. Leave for no owner.
+ internal Marshmallow(ItemType type, Player owner = null)
+ : base((MarshmallowItem)(owner ?? Server.Host).Inventory.CreateItemInstance(new(type, 0), false))
+ {
+ }
+
+ ///
+ /// Gets the that this class is encapsulating.
+ ///
+ public new MarshmallowItem Base { get; }
+
+ ///
+ /// Gets a value indicating whether this marshmallow man is evil.
+ ///
+ /// See in regards to making a marshmallow evil.
+ public bool Evil => Base.EvilMode;
+
+ ///
+ /// Gets or sets the of the marshmallow man that would be used if he was evil.
+ ///
+ public AhpStat.AhpProcess EvilAhpProcess
+ {
+ get => Base.EvilAHPProcess;
+ set
+ {
+ if (Evil && value is null)
+ return;
+
+ Base.EvilAHPProcess = value;
+ }
+ }
+
+ ///
+ /// Cackles for the owner even if they are not evil.
+ ///
+ /// How long until the player can cackle again (negative values do not affect current cooldown).
+ /// How long players near the marshmallow man get effected by .
+ public void Cackle(double cooldown = -1, float duration = 5)
+ {
+ if (cooldown >= 0)
+ Base._cackleCooldown.Trigger(cooldown);
+
+ Base.ServerSendPublicRpc(writer =>
+ {
+ writer.WriteByte(4);
+ Base._cackleCooldown.WriteCooldown(writer);
+ });
+
+ foreach (Player player in Player.List)
+ {
+ if (Vector3.Distance(player.Position, Owner.Position) <= 5F && player.CurrentItem is not Marshmallow { Evil: true })
+ player.EnableEffect(duration);
+ }
+ }
+
+ ///
+ /// Makes the owner of this marshmallow evil. You CANNOT undo this without resetting the player.
+ ///
+ /// The of the new evil player.
+ public void MakeEvil(AhpStat.AhpProcess evilProcess = null)
+ {
+ if (Evil)
+ return;
+
+ Base.ReleaseEvil(evilProcess ?? EvilAhpProcess ?? new AhpStat.AhpProcess(450F, 450F, 0F, 1F, 0F, true));
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Interfaces/IMarshmallowEvent.cs b/EXILED/Exiled.Events/EventArgs/Interfaces/IMarshmallowEvent.cs
new file mode 100644
index 0000000000..fdd41cef5b
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Interfaces/IMarshmallowEvent.cs
@@ -0,0 +1,22 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Interfaces
+{
+ using Exiled.API.Features.Items;
+
+ ///
+ /// Represents all events related to the marshmallow man.
+ ///
+ public interface IMarshmallowEvent : IItemEvent
+ {
+ ///
+ /// Gets the marshmallow item related to this event.
+ ///
+ public Marshmallow Marshmallow { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Item/CacklingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Item/CacklingEventArgs.cs
new file mode 100644
index 0000000000..69150fd226
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Item/CacklingEventArgs.cs
@@ -0,0 +1,51 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Item
+{
+ using Exiled.API.Features;
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+ using InventorySystem.Items.MarshmallowMan;
+
+ ///
+ /// Contains all information before a marshmallow man punches.
+ ///
+ public class CacklingEventArgs : IMarshmallowEvent, IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Player cackling.
+ /// The marshmallow item of the player cackling.
+ /// Whether the player is allowed to cackle.
+ public CacklingEventArgs(Player player, MarshmallowItem marshmallow, bool isAllowed = true)
+ {
+ Player = player;
+ Marshmallow = Item.Get(marshmallow);
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ /// Gets the player cackling.
+ ///
+ public Player Player { get; }
+
+ ///
+ public API.Features.Items.Item Item => Marshmallow;
+
+ ///
+ /// Gets the marshmallow item of the player cackling.
+ ///
+ public Marshmallow Marshmallow { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the player is allowed to cackle.
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Item/PunchingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Item/PunchingEventArgs.cs
new file mode 100644
index 0000000000..d616d34e93
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Item/PunchingEventArgs.cs
@@ -0,0 +1,51 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Item
+{
+ using Exiled.API.Features;
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+ using InventorySystem.Items.MarshmallowMan;
+
+ ///
+ /// Contains all information before a marshmallow man punches.
+ ///
+ public class PunchingEventArgs : IMarshmallowEvent, IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Player attacking.
+ /// The marshmallow item of the player attacking.
+ /// Whether the player is allowed to punch.
+ public PunchingEventArgs(Player player, MarshmallowItem marshmallow, bool isAllowed = true)
+ {
+ Player = player;
+ Marshmallow = Item.Get(marshmallow);
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ /// Gets the player punching.
+ ///
+ public Player Player { get; }
+
+ ///
+ public Item Item => Marshmallow;
+
+ ///
+ /// Gets the marshmallow item of the player punching.
+ ///
+ public Marshmallow Marshmallow { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the punch is allowed.
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Scp2536/FoundPositionEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp2536/FoundPositionEventArgs.cs
new file mode 100644
index 0000000000..d4935e6c92
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Scp2536/FoundPositionEventArgs.cs
@@ -0,0 +1,40 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Scp2536
+{
+ using Christmas.Scp2536;
+ using Exiled.API.Features;
+ using Exiled.Events.EventArgs.Interfaces;
+
+ ///
+ /// Contains all information after SCP-2536 chooses target for spawning.
+ ///
+ public class FoundPositionEventArgs : IPlayerEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public FoundPositionEventArgs(Player player, Scp2536Spawnpoint spawnpoint)
+ {
+ Player = player;
+ Spawnpoint = spawnpoint;
+ }
+
+ ///
+ /// Gets the player near whom SCP-2536 will spawn.
+ ///
+ public Player Player { get; }
+
+ ///
+ /// Gets or sets the spawn point where SCP will spawn.
+ ///
+ public Scp2536Spawnpoint Spawnpoint { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Handlers/Item.cs b/EXILED/Exiled.Events/Handlers/Item.cs
index 9ac83aafd3..b1ca257f09 100644
--- a/EXILED/Exiled.Events/Handlers/Item.cs
+++ b/EXILED/Exiled.Events/Handlers/Item.cs
@@ -89,6 +89,16 @@ public static class Item
///
public static Event JailbirdChangedWearState { get; set; } = new();
+ ///
+ /// Invoked before a marshmallow man punches.
+ ///
+ public static Event Punching { get; set; } = new();
+
+ ///
+ /// Invoked before a marshmallow man cackles.
+ ///
+ public static Event Cackling { get; set; } = new();
+
///
/// Called before the Jailbird's is changed.
///
@@ -173,5 +183,17 @@ public static class Item
///
/// The instance.
public static void OnInspectedItem(InspectedItemEventArgs ev) => InspectedItem.InvokeSafely(ev);
+
+ ///
+ /// Called before a marshmallow man punches.
+ ///
+ /// The instance.
+ public static void OnPunching(PunchingEventArgs ev) => Punching.InvokeSafely(ev);
+
+ ///
+ /// Called before a marshmallow man cackles.
+ ///
+ /// The instance.
+ public static void OnCackling(CacklingEventArgs ev) => Cackling.InvokeSafely(ev);
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Handlers/Scp2536.cs b/EXILED/Exiled.Events/Handlers/Scp2536.cs
index 3f7dfd1c58..8c0d272583 100644
--- a/EXILED/Exiled.Events/Handlers/Scp2536.cs
+++ b/EXILED/Exiled.Events/Handlers/Scp2536.cs
@@ -21,6 +21,11 @@ public static class Scp2536
///
public static Event FindingPosition { get; set; } = new();
+ ///
+ /// Invoked once SCP-2536 has found a spawn location.
+ ///
+ public static Event FoundPosition { get; set; } = new();
+
///
/// Invoked before SCP-2536 gives a gift to a player.
///
@@ -37,6 +42,12 @@ public static class Scp2536
/// The instance.
public static void OnFindingPosition(FindingPositionEventArgs ev) => FindingPosition.InvokeSafely(ev);
+ ///
+ /// Called after SCP-2536 chooses a target.
+ ///
+ /// The instance.
+ public static void OnFoundPosition(FoundPositionEventArgs ev) => FoundPosition.InvokeSafely(ev);
+
///
/// Called before SCP-2536 gives a gift to a player.
///
diff --git a/EXILED/Exiled.Events/Patches/Events/Item/Cackling.cs b/EXILED/Exiled.Events/Patches/Events/Item/Cackling.cs
new file mode 100644
index 0000000000..9c71dd86c6
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Item/Cackling.cs
@@ -0,0 +1,69 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Item
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features;
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Item;
+ using HarmonyLib;
+ using InventorySystem.Items.MarshmallowMan;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch the .
+ /// Adds the event.
+ ///
+ [EventPatch(typeof(Handlers.Item), nameof(Handlers.Item.Cackling))]
+ [HarmonyPatch(typeof(MarshmallowItem), nameof(MarshmallowItem.ServerProcessCackle))]
+ public class Cackling
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label retLabel = generator.DefineLabel();
+
+ int offset = 1;
+ int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ret) + offset;
+
+ newInstructions.InsertRange(index, new[]
+ {
+ // player = Player.Get(Owner);
+ new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(MarshmallowItem), nameof(MarshmallowItem.Owner))),
+
+ // item = this;
+ new(OpCodes.Ldarg_0),
+
+ // true
+ new(OpCodes.Ldc_I4_1),
+
+ // ev = new CacklingEventArgs(player, item, true);
+ new(OpCodes.Newobj, Constructor(typeof(CacklingEventArgs), new[] { typeof(Player), typeof(MarshmallowItem), typeof(bool) })),
+ new(OpCodes.Dup),
+ new(OpCodes.Call, Method(typeof(Handlers.Item), nameof(Handlers.Item.OnCackling))),
+
+ // if (!ev.IsAllowed) return
+ new(OpCodes.Callvirt, PropertyGetter(typeof(CacklingEventArgs), nameof(CacklingEventArgs.IsAllowed))),
+ new(OpCodes.Brfalse_S, retLabel),
+ });
+
+ newInstructions[newInstructions.Count - 1].WithLabels(retLabel);
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Item/Punching.cs b/EXILED/Exiled.Events/Patches/Events/Item/Punching.cs
new file mode 100644
index 0000000000..e45e0bfe76
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Item/Punching.cs
@@ -0,0 +1,69 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Item
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features;
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Item;
+ using HarmonyLib;
+ using InventorySystem.Items.MarshmallowMan;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patch the .
+ /// Adds the event.
+ ///
+ [EventPatch(typeof(Handlers.Item), nameof(Handlers.Item.Punching))]
+ [HarmonyPatch(typeof(MarshmallowItem), nameof(MarshmallowItem.ServerProcessCmd))]
+ public class Punching
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label retLabel = generator.DefineLabel();
+
+ int offset = 1;
+ int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ret) + offset;
+
+ newInstructions[^1].WithLabels(retLabel);
+
+ newInstructions.InsertRange(index, new[]
+ {
+ // player = Player.Get(Owner);
+ new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(MarshmallowItem), nameof(MarshmallowItem.Owner))),
+
+ // item = this;
+ new(OpCodes.Ldarg_0),
+
+ // true
+ new(OpCodes.Ldc_I4_1),
+
+ // ev = new PunchingEventArgs(player, item, true);
+ new(OpCodes.Newobj, Constructor(typeof(PunchingEventArgs), new[] { typeof(Player), typeof(MarshmallowItem), typeof(bool) })),
+ new(OpCodes.Dup),
+ new(OpCodes.Call, Method(typeof(Handlers.Item), nameof(Handlers.Item.OnPunching))),
+
+ // if (!ev.IsAllowed) return
+ new(OpCodes.Callvirt, PropertyGetter(typeof(PunchingEventArgs), nameof(PunchingEventArgs.IsAllowed))),
+ new(OpCodes.Brfalse_S, retLabel),
+ });
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Scp2536/FoundPosition.cs b/EXILED/Exiled.Events/Patches/Events/Scp2536/FoundPosition.cs
new file mode 100644
index 0000000000..dd942042fb
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Scp2536/FoundPosition.cs
@@ -0,0 +1,86 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Scp2536
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Christmas.Scp2536;
+ using Exiled.API.Features;
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Scp2536;
+ using HarmonyLib;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches
+ /// to add event.
+ ///
+ [EventPatch(typeof(Handlers.Scp2536), nameof(Handlers.Scp2536.FoundPosition))]
+ [HarmonyPatch(typeof(Scp2536Controller), nameof(Scp2536Controller.ServerFindTarget))]
+ public class FoundPosition
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label retLabel = generator.DefineLabel();
+
+ int index = newInstructions.Count - 1;
+
+ newInstructions[index].WithLabels(retLabel);
+
+ newInstructions.InsertRange(index, new CodeInstruction[]
+ {
+ // dupe the result (true / false if found)
+ new(OpCodes.Dup),
+
+ // return w result if failed
+ new(OpCodes.Brfalse_S, retLabel),
+ new(OpCodes.Pop),
+
+ // load ADDRESS of parameter "out Scp2536Spawnpoint spawnpoint" onto stack (so not actual value but address)
+ // this is used at end of transpiler
+ new(OpCodes.Ldarg_2),
+
+ // load address of parameter "out ReferenceHub target"
+ new(OpCodes.Ldarg_1),
+
+ // load value at address
+ new(OpCodes.Ldind_Ref),
+
+ // player = Player.Get(target);
+ new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),
+
+ // load address of parameter "out Scp2536Spawnpoint spawnpoint"
+ new(OpCodes.Ldarg_2),
+
+ // load value at address
+ new(OpCodes.Ldind_Ref),
+
+ // ev = new FoundPositionEventArgs(player, spawnpoint);
+ new(OpCodes.Newobj, Constructor(typeof(FoundPositionEventArgs), new[] { typeof(Player), typeof(Scp2536Spawnpoint) })),
+ new(OpCodes.Dup),
+ new(OpCodes.Call, Method(typeof(Handlers.Scp2536), nameof(Handlers.Scp2536.OnFoundPosition))),
+
+ // spawnpoint = ev.Spawnpoint;
+ new(OpCodes.Callvirt, PropertyGetter(typeof(FoundPositionEventArgs), nameof(FoundPositionEventArgs.Spawnpoint))),
+
+ // this uses the address already on stack (see 3rd comment) with the value from the event args
+ new(OpCodes.Stind_Ref),
+ });
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Fixes/FixMarshmallowManFF.cs b/EXILED/Exiled.Events/Patches/Fixes/FixMarshmallowManFF.cs
index d91c2d0398..bdfc2e5f0d 100644
--- a/EXILED/Exiled.Events/Patches/Fixes/FixMarshmallowManFF.cs
+++ b/EXILED/Exiled.Events/Patches/Fixes/FixMarshmallowManFF.cs
@@ -35,7 +35,7 @@ internal class FixMarshmallowManFF : AttackerDamageHandler
#pragma warning disable SA1600 // Elements should be documented
public FixMarshmallowManFF(MarshmallowItem marshmallowItem)
{
- Attacker = new(marshmallowItem.Owner);
+ Attacker = new Footprint(marshmallowItem.Owner);
Damage = marshmallowItem._attackDamage;
AllowSelfDamage = false;
ServerLogsText = "MarshmallowManFF Fix";
@@ -47,53 +47,36 @@ public FixMarshmallowManFF(MarshmallowItem marshmallowItem)
public override float Damage { get; set; }
- public override string RagdollInspectText { get; }
+ public override string RagdollInspectText { get; } = DeathTranslations.MarshmallowMan.RagdollTranslation;
- public override CassieAnnouncement CassieDeathAnnouncement
+ public override CassieAnnouncement CassieDeathAnnouncement { get; } = new()
{
- get
- {
- return new CassieAnnouncement()
- {
- Announcement = "TERMINATED BY MARSHMALLOW MAN",
- SubtitleParts = new SubtitlePart[]
- {
- new SubtitlePart(SubtitleType.TerminatedByMarshmallowMan, null),
- },
- };
- }
- }
+ Announcement = "TERMINATED BY MARSHMALLOW MAN",
+ SubtitleParts =
+ [
+ new SubtitlePart(SubtitleType.TerminatedByMarshmallowMan, null),
+ ],
+ };
- public override string DeathScreenText { get; }
+ public override string DeathScreenText { get; } = DeathTranslations.MarshmallowMan.DeathscreenTranslation;
public override string ServerLogsText { get; }
#pragma warning restore SA1600 // Elements should be documented
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
- private static bool Prefix(MarshmallowItem __instance, ReferenceHub syncTarget)
+ private static IEnumerable Transpiler(IEnumerable instructions)
{
- foreach (IDestructible destructible in __instance.DetectDestructibles())
- {
- HitboxIdentity hitboxIdentity = destructible as HitboxIdentity;
- if ((hitboxIdentity == null || (!(hitboxIdentity.TargetHub != syncTarget) && (__instance.EvilMode || HitboxIdentity.IsDamageable(__instance.Owner, hitboxIdentity.TargetHub)))) && destructible.Damage(__instance._attackDamage, new FixMarshmallowManFF(__instance), destructible.CenterOfMass))
- {
- HitboxIdentity hitboxIdentity2 = destructible as HitboxIdentity;
- if (hitboxIdentity2 != null && !hitboxIdentity2.TargetHub.IsAlive())
- __instance.Owner.playerEffectsController.GetEffect().OnKill();
-
- if (__instance.EvilMode)
- __instance.EvilAHPProcess.CurrentAmount += 100f;
-
- Hitmarker.SendHitmarkerDirectly(__instance.Owner, 1f, true);
- __instance.ServerSendPublicRpc(writer =>
- {
- writer.WriteByte(1);
- });
- break;
- }
- }
-
- return false;
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ int index = newInstructions.FindIndex(instruction => instruction.Calls(PropertyGetter(typeof(MarshmallowItem), nameof(MarshmallowItem.NewDamageHandler))));
+
+ // replace the getter for NewDamageHandler with ctor of FixMarshmallowManFF
+ newInstructions[index] = new CodeInstruction(OpCodes.Newobj, Constructor(typeof(FixMarshmallowManFF), new[] { typeof(MarshmallowItem) }));
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
}
}
}