Skip to content
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
2 changes: 1 addition & 1 deletion EXILED/Exiled.API/Features/Effect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public Effect(StatusEffectBase statusEffectBase)
if (!statusEffectBase.TryGetEffectType(out EffectType effect))
Log.Error($"EffectType not found please report to Exiled BugReport : {statusEffectBase}");
Type = effect;
Duration = statusEffectBase.Duration;
Duration = statusEffectBase.TimeLeft;
Intensity = statusEffectBase.Intensity;
IsEnabled = statusEffectBase.IsEnabled;
}
Expand Down
11 changes: 3 additions & 8 deletions EXILED/Exiled.API/Features/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3433,10 +3433,7 @@ public void SyncEffect(Effect effect)
{
if (effect.IsEnabled)
{
EnableEffect(effect.Type, effect.Duration, effect.AddDurationIfActive);

if (effect.Intensity > 0)
ChangeEffectIntensity(effect.Type, effect.Intensity, effect.Duration);
EnableEffect(effect.Type, effect.Intensity, effect.Duration, effect.AddDurationIfActive);
}
}

Expand Down Expand Up @@ -3564,8 +3561,7 @@ public void ChangeEffectIntensity<T>(byte intensity, float duration = 0)
{
if (ReferenceHub.playerEffectsController.TryGetEffect(out T statusEffect))
{
statusEffect.Intensity = intensity;
statusEffect.ServerChangeDuration(duration, true);
statusEffect.ServerSetState(intensity, duration, false);
}
}

Expand All @@ -3579,8 +3575,7 @@ public void ChangeEffectIntensity(EffectType type, byte intensity, float duratio
{
if (TryGetEffect(type, out StatusEffectBase statusEffect))
{
statusEffect.Intensity = intensity;
statusEffect.ServerChangeDuration(duration, false);
statusEffect.ServerSetState(intensity, duration, false);
}
}

Expand Down
3 changes: 1 addition & 2 deletions EXILED/Exiled.API/Features/Roles/Scp049Role.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,7 @@ public void Attack(Player player)
else
{
cardiacArrest.SetAttacker(AttackAbility.Owner);
cardiacArrest.Intensity = 1;
cardiacArrest.ServerChangeDuration(AttackAbility._statusEffectDuration, false);
cardiacArrest.ServerSetState(1, AttackAbility._statusEffectDuration, false);
}

SenseAbility.OnServerHit(AttackAbility._target);
Expand Down
21 changes: 4 additions & 17 deletions EXILED/Exiled.Events/EventArgs/Player/ReceivingEffectEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ namespace Exiled.Events.EventArgs.Player
/// </summary>
public class ReceivingEffectEventArgs : IPlayerEvent, IDeniableEvent
{
private byte intensity;

/// <summary>
/// Initializes a new instance of the <see cref="ReceivingEffectEventArgs" /> class.
/// </summary>
Expand All @@ -32,9 +30,9 @@ public ReceivingEffectEventArgs(Player player, StatusEffectBase effect, byte int
{
Player = player;
Effect = effect;
this.intensity = intensity;
Intensity = intensity;
CurrentIntensity = currentIntensity;
Duration = duration;
Duration = intensity is 0 ? 0 : duration;
}

/// <summary>
Expand All @@ -53,20 +51,9 @@ public ReceivingEffectEventArgs(Player player, StatusEffectBase effect, byte int
public float Duration { get; set; } = 0;

/// <summary>
/// Gets or sets the value of the new intensity of the effect. Setting this to <c>0</c> is the same as setting IsAllowed to
/// <see langword="false" />.
/// Gets or sets the value of the new intensity of the effect.
/// </summary>
public byte Intensity
{
get => intensity;
set
{
intensity = value;

if (intensity == 0)
IsAllowed = false;
}
}
public byte Intensity { get; set; }

/// <summary>
/// Gets the value of the intensity of this effect on the player.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ namespace Exiled.Events.Patches.Events.Player

/// <summary>
/// Patches the <see cref="StatusEffectBase.Intensity"/> method.
/// Adds the <see cref="Handlers.Player.ReceivingEffect"/> event.
/// Adds the <see cref="Handlers.Player.ReceivingEffect"/> event and fix NW Duration not being correctly set to 0 when effect is Reset.
/// </summary>
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ReceivingEffect))]
// [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ReceivingEffect))]
[HarmonyPatch(typeof(StatusEffectBase), nameof(StatusEffectBase.ForceIntensity))]
internal static class ReceivingStatusEffect
{
Expand Down Expand Up @@ -74,9 +74,9 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Ldarg_0),
new(OpCodes.Ldfld, Field(typeof(StatusEffectBase), nameof(StatusEffectBase._intensity))),

// this.Duration
// this._timeLeft
new(OpCodes.Ldarg_0),
new(OpCodes.Callvirt, PropertyGetter(typeof(StatusEffectBase), nameof(StatusEffectBase.Duration))),
new(OpCodes.Ldfld, Field(typeof(StatusEffectBase), nameof(StatusEffectBase._timeLeft))),

// ReceivingEventArgs ev = new(Player, StatusEffectBase, byte, byte, float)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ReceivingEffectEventArgs))[0]),
Expand All @@ -95,11 +95,11 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new(OpCodes.Callvirt, PropertyGetter(typeof(ReceivingEffectEventArgs), nameof(ReceivingEffectEventArgs.Intensity))),
new(OpCodes.Starg_S, 1),

// this.Duration = ev.Duration
// this._timeLeft = ev.Duration
new(OpCodes.Ldarg_0),
new(OpCodes.Ldloc_S, ev.LocalIndex),
new(OpCodes.Callvirt, PropertyGetter(typeof(ReceivingEffectEventArgs), nameof(ReceivingEffectEventArgs.Duration))),
new(OpCodes.Callvirt, PropertySetter(typeof(StatusEffectBase), nameof(StatusEffectBase.Duration))),
new(OpCodes.Stfld, Field(typeof(StatusEffectBase), nameof(StatusEffectBase._timeLeft))),
});

newInstructions[newInstructions.Count - 1].WithLabels(returnLabel);
Expand Down
101 changes: 101 additions & 0 deletions EXILED/Exiled.Events/Patches/Fixes/FixEffectOrder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// -----------------------------------------------------------------------
// <copyright file="FixEffectOrder.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Fixes
{
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

using API.Features.Pools;
using CustomPlayerEffects;
using Exiled.API.Features;
using HarmonyLib;
using InventorySystem.Items.Usables.Scp330;
using PlayerRoles.PlayableScps.Scp049;

using static HarmonyLib.AccessTools;

#pragma warning disable SA1402 // File may only contain a single type

/// <summary>
/// Patches <see cref="StatusEffectBase.ServerSetState(byte, float, bool)"/>.
/// Fix than NW do not updated the EffectDuration before Intensity https://github.com/northwood-studios/LabAPI/issues/248.
/// </summary>
[HarmonyPatch(typeof(StatusEffectBase), nameof(StatusEffectBase.ServerSetState))]
internal class FixEffectOrder
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

// Find the setter call index
int offset = -2;
int intensityCallIndex = newInstructions.FindIndex(ci => ci.Calls(PropertySetter(typeof(StatusEffectBase), nameof(StatusEffectBase.Intensity)))) + offset;

// Extract: ldarg.0, ldarg.1, call set_Intensity
List<CodeInstruction> intensityBlock = newInstructions.GetRange(intensityCallIndex, 3);

// Remove it from original location
newInstructions.RemoveRange(intensityCallIndex, 3);
newInstructions[intensityCallIndex].WithLabels(intensityBlock[0].ExtractLabels());

// Find ServerChangeDuration call
int serverChangeIndex = newInstructions.FindIndex(ci => ci.Calls(Method(typeof(StatusEffectBase), nameof(StatusEffectBase.ServerChangeDuration))));

// Insert AFTER ServerChangeDuration
newInstructions.InsertRange(serverChangeIndex + 1, intensityBlock);

for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];

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

/// <summary>
/// Patches Method that should use <see cref="StatusEffectBase.ServerSetState(byte, float, bool)"/>.
/// Fix than NW do not updated the EffectDuration before Intensity https://github.com/northwood-studios/LabAPI/issues/248.
/// </summary>
[HarmonyPatch]
internal class FixEffectOrder2
{
private static IEnumerable<MethodBase> TargetMethods()
{
yield return Method(typeof(CandyYellow), nameof(CandyYellow.ServerApplyEffects));
yield return Method(typeof(Scp049AttackAbility), nameof(Scp049AttackAbility.ServerProcessCmd));
yield return Method(typeof(SugarCrave), nameof(SugarCrave.Disabled));
}

private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
List<CodeInstruction> newInstructions = ListPool<CodeInstruction>.Pool.Get(instructions);

int intensityCallIndex = newInstructions.FindIndex(ci => ci.Calls(PropertySetter(typeof(StatusEffectBase), nameof(StatusEffectBase.Intensity))));

int offset = 6;
if (newInstructions[intensityCallIndex - offset].opcode == OpCodes.Dup)
{
// specific to Yellow candy that get it's Instance from a OpCodes.Dup
newInstructions.RemoveAt(intensityCallIndex);
newInstructions.RemoveAt(intensityCallIndex - offset);
}
else
{
newInstructions.RemoveRange(intensityCallIndex, 2);
}

int serverChangeIndex = newInstructions.FindIndex(ci => ci.Calls(Method(typeof(StatusEffectBase), nameof(StatusEffectBase.ServerChangeDuration))));

newInstructions[serverChangeIndex] = new CodeInstruction(OpCodes.Callvirt, Method(typeof(StatusEffectBase), nameof(StatusEffectBase.ServerSetState)));
for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];

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