Skip to content
Open
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
215 changes: 215 additions & 0 deletions EXILED/Exiled.CustomItems/API/Features/CustomGoggles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// -----------------------------------------------------------------------
// <copyright file="CustomGoggles.cs" company="ExMod Team">
// Copyright (c) ExMod Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.CustomItems.API.Features
{
using EventArgs;
using Exiled.API.Enums;
using Exiled.API.Features;
using Exiled.API.Features.Items;
using Exiled.Events.EventArgs.Player;
using Exiled.Events.EventArgs.Scp1344;

using InventorySystem.Items.Usables.Scp1344;

using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers.Wearables;

/// <summary>
/// The Custom Goggles base class.
/// </summary>
public abstract class CustomGoggles : CustomItem
{
/// <summary>
/// Gets or sets the <see cref="ItemType"/> to use for these goggles.
/// This is locked to <see cref="ItemType.SCP1344"/>.
/// </summary>
public override ItemType Type
{
get => ItemType.SCP1344;
set => base.Type = ItemType.SCP1344;
}

/// <summary>
/// Gets or sets the duration, in seconds, that the item has been worn.
/// </summary>
public virtual float WearingTime { get; set; } = Scp1344Item.ActivationTime;

/// <summary>
/// Gets or sets the time, in seconds, required to remove the item.
/// </summary>
public virtual float RemovingTime { get; set; } = Scp1344Item.DeactivationTime;

/// <summary>
/// Gets or sets a value indicating whether the default SCP-1344 effect should be removed when wearing the goggles.
/// </summary>
public virtual bool Remove1344Effect { get; set; } = true;

/// <summary>
/// Gets or sets a value indicating whether the glasses can be safely removed without bad effects.
/// </summary>
public virtual bool CanBeRemoveSafely { get; set; } = true;

/// <inheritdoc/>
protected override void SubscribeEvents()
{
Exiled.Events.Handlers.Player.UsingItem += OnInternalUsingItem;
Exiled.Events.Handlers.Player.ItemRemoved += OnInternalItemRemoved;
Exiled.Events.Handlers.Scp1344.Deactivating += OnInternalDeactivating;
Exiled.Events.Handlers.Scp1344.ChangedStatus += OnInternalChangedStatus;
Exiled.Events.Handlers.Scp1344.ChangingStatus += OnInternalChangingStatus;
base.SubscribeEvents();
}

/// <inheritdoc/>
protected override void UnsubscribeEvents()
{
Exiled.Events.Handlers.Player.UsingItem -= OnInternalUsingItem;
Exiled.Events.Handlers.Player.ItemRemoved -= OnInternalItemRemoved;
Exiled.Events.Handlers.Scp1344.Deactivating -= OnInternalDeactivating;
Exiled.Events.Handlers.Scp1344.ChangedStatus -= OnInternalChangedStatus;
Exiled.Events.Handlers.Scp1344.ChangingStatus -= OnInternalChangingStatus;
base.UnsubscribeEvents();
}

/// <inheritdoc/>
protected override void OnOwnerChangingRole(OwnerChangingRoleEventArgs ev)
{
if (!ev.IsAllowed)
return;

if (Item.Get(ev.Item) is not Scp1344 { IsWorn: true } scp1344)
return;

InternalRemove(ev.Player, scp1344);
}

/// <summary>
/// Called when the player equips the goggles.
/// </summary>
/// <param name="player">The player who equipped the goggles.</param>
/// <param name="goggles">The <see cref="Scp1344"/> item being worn.</param>
protected virtual void OnWornGoggles(Player player, Scp1344 goggles)
{
}

/// <summary>
/// Called when the player removes the goggles.
/// </summary>
/// <param name="player">The player who removed the goggles.</param>
/// <param name="goggles">The <see cref="Scp1344"/> item being removed.</param>
protected virtual void OnRemovedGoggles(Player player, Scp1344 goggles)
{
}

private void OnInternalUsingItem(UsingItemEventArgs ev)
{
if (!ev.IsAllowed)
return;

if (ev.Item.Type != ItemType.SCP1344)
return;

foreach (Item item in ev.Player.Items)
{
if (item.Type != ItemType.SCP1344)
continue;

if (item is not Scp1344 { IsWorn: true })
continue;

ev.IsAllowed = false;
break;
}
}

private void OnInternalDeactivating(DeactivatingEventArgs ev)
{
if (!ev.IsAllowed)
return;

if (!Check(ev.Item))
return;

if (!CanBeRemoveSafely)
return;

ev.NewStatus = Scp1344Status.Idle;
ev.IsAllowed = false;
}

private void OnInternalChangedStatus(ChangedStatusEventArgs ev)
{
if (!Check(ev.Item))
return;

switch (ev.Scp1344Status)
{
case Scp1344Status.Deactivating:
ev.Scp1344.Base._useTime = Scp1344Item.DeactivationTime - RemovingTime;
break;

case Scp1344Status.Activating:
ev.Scp1344.Base._useTime = Scp1344Item.ActivationTime - WearingTime;
break;

case Scp1344Status.Active:
InternalEquip(ev.Player, ev.Scp1344);
break;
}
}

private void InternalEquip(Player player, Scp1344 goggles)
{
if (Remove1344Effect)
{
player.DisableEffect(EffectType.Scp1344);
player.ReferenceHub.EnableWearables(WearableElements.Scp1344Goggles);
}

OnWornGoggles(player, goggles);
}

private void InternalRemove(Player player, Scp1344 goggles)
{
if (!Remove1344Effect)
player.DisableEffect(EffectType.Scp1344);

if (CanBeRemoveSafely)
{
player.DisableEffect(EffectType.Blinded);
player.ReferenceHub?.DisableWearables(WearableElements.Scp1344Goggles);
}

OnRemovedGoggles(player, goggles);
}

private void OnInternalItemRemoved(ItemRemovedEventArgs ev)
{
if (!Check(ev.Item))
return;

if (ev.Item is not Scp1344 { IsWorn: true } scp1344)
return;

InternalRemove(ev.Player, scp1344);
}

private void OnInternalChangingStatus(ChangingStatusEventArgs ev)
{
if (!ev.IsAllowed)
return;

if (!Check(ev.Item))
return;

if (ev.Scp1344StatusOld != Scp1344Status.Deactivating || ev.Scp1344StatusNew != Scp1344Status.Idle)
return;

InternalRemove(ev.Player, ev.Scp1344);
}
}
}
10 changes: 9 additions & 1 deletion EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

namespace Exiled.Events.EventArgs.Scp1344
{
using Exiled.API.Features;
using Exiled.API.Features.Items;
using Exiled.Events.EventArgs.Interfaces;

using InventorySystem.Items.Usables.Scp1344;

/// <summary>
/// Contains all information before deactivating.
/// </summary>
Expand All @@ -36,13 +39,18 @@ public DeactivatingEventArgs(Item item, bool isAllowed = true)
/// <summary>
/// Gets the player in owner of the item.
/// </summary>
public Exiled.API.Features.Player Player { get; }
public Player Player { get; }

/// <summary>
/// Gets Scp1344 item.
/// </summary>
public Scp1344 Scp1344 { get; }

/// <summary>
/// Gets or sets the status of the SCP-1344 after the deactivation process.
/// </summary>
public Scp1344Status NewStatus { get; set; } = Scp1344Status.Active;

/// <inheritdoc/>
public bool IsAllowed { get; set; }
}
Expand Down
32 changes: 23 additions & 9 deletions EXILED/Exiled.Events/Patches/Events/Scp1344/Deactivating.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ namespace Exiled.Events.Patches.Events.Scp1344
using Exiled.API.Features.Items;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Scp1344;

using HarmonyLib;

using InventorySystem.Items.Usables.Scp1344;
using InventorySystem.Items.Usables.Scp244;

using UnityEngine;

using static PlayerList;

/// <summary>
/// Patches <see cref="Scp1344Item.ServerUpdateDeactivating"/>.
/// Adds the <see cref="Handlers.Scp1344.TryingDeactivating" /> event,
Expand All @@ -34,39 +39,48 @@ private static bool Prefix(ref Scp1344Item __instance)
if (__instance._useTime == 0)
{
TryingDeactivatingEventArgs ev = new(Item.Get(__instance));
Exiled.Events.Handlers.Scp1344.OnTryingDeactivating(ev);
Handlers.Scp1344.OnTryingDeactivating(ev);

if (!ev.IsAllowed)
{
return StopDeactivation(__instance);
return StopDeactivation(__instance, Scp1344Status.Active);
}
}

if (__instance._useTime + Time.deltaTime >= 5.1f)
if (__instance._useTime + Time.deltaTime >= Scp1344Item.DeactivationTime)
{
DeactivatingEventArgs deactivating = new(Item.Get(__instance));
Exiled.Events.Handlers.Scp1344.OnDeactivating(deactivating);
Handlers.Scp1344.OnDeactivating(deactivating);

if (!deactivating.IsAllowed)
{
return StopDeactivation(__instance);
return StopDeactivation(__instance, deactivating.NewStatus);
}

__instance.ActivateFinalEffects();
__instance.ServerDropItem(__instance);

DeactivatedEventArgs ev = new(Item.Get(__instance));
Exiled.Events.Handlers.Scp1344.OnDeactivated(ev);
Handlers.Scp1344.OnDeactivated(ev);
return false;
}

return true;
}

private static bool StopDeactivation(Scp1344Item instance)
private static bool StopDeactivation(Scp1344Item instance, Scp1344Status newStatus)
{
instance.Status = Scp1344Status.Active;
instance.ServerSetStatus(Scp1344Status.Active);
instance.Status = newStatus;
instance.ServerSetStatus(newStatus);

if (newStatus == Scp1344Status.Idle)
{
instance._useTime = 0f;
instance._savedIntensity = 0;
instance._cancelationTime = 0f;
instance.OwnerInventory?.ServerSelectItem(0);
}

return false;
}
}
Expand Down
Loading