diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomGoggles.cs b/EXILED/Exiled.CustomItems/API/Features/CustomGoggles.cs new file mode 100644 index 0000000000..769f5ad936 --- /dev/null +++ b/EXILED/Exiled.CustomItems/API/Features/CustomGoggles.cs @@ -0,0 +1,215 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +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; + + /// + /// The Custom Goggles base class. + /// + public abstract class CustomGoggles : CustomItem + { + /// + /// Gets or sets the to use for these goggles. + /// This is locked to . + /// + public override ItemType Type + { + get => ItemType.SCP1344; + set => base.Type = ItemType.SCP1344; + } + + /// + /// Gets or sets the duration, in seconds, that the item has been worn. + /// + public virtual float WearingTime { get; set; } = Scp1344Item.ActivationTime; + + /// + /// Gets or sets the time, in seconds, required to remove the item. + /// + public virtual float RemovingTime { get; set; } = Scp1344Item.DeactivationTime; + + /// + /// Gets or sets a value indicating whether the default SCP-1344 effect should be removed when wearing the goggles. + /// + public virtual bool Remove1344Effect { get; set; } = true; + + /// + /// Gets or sets a value indicating whether the glasses can be safely removed without bad effects. + /// + public virtual bool CanBeRemoveSafely { get; set; } = true; + + /// + 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(); + } + + /// + 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(); + } + + /// + 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); + } + + /// + /// Called when the player equips the goggles. + /// + /// The player who equipped the goggles. + /// The item being worn. + protected virtual void OnWornGoggles(Player player, Scp1344 goggles) + { + } + + /// + /// Called when the player removes the goggles. + /// + /// The player who removed the goggles. + /// The item being removed. + 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); + } + } +} diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs index 96bcbc211e..8ff103fa53 100644 --- a/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs @@ -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; + /// /// Contains all information before deactivating. /// @@ -36,13 +39,18 @@ public DeactivatingEventArgs(Item item, bool isAllowed = true) /// /// Gets the player in owner of the item. /// - public Exiled.API.Features.Player Player { get; } + public Player Player { get; } /// /// Gets Scp1344 item. /// public Scp1344 Scp1344 { get; } + /// + /// Gets or sets the status of the SCP-1344 after the deactivation process. + /// + public Scp1344Status NewStatus { get; set; } = Scp1344Status.Active; + /// public bool IsAllowed { get; set; } } diff --git a/EXILED/Exiled.Events/Patches/Events/Scp1344/Deactivating.cs b/EXILED/Exiled.Events/Patches/Events/Scp1344/Deactivating.cs index 9cf35fe606..ca0bbe8e35 100644 --- a/EXILED/Exiled.Events/Patches/Events/Scp1344/Deactivating.cs +++ b/EXILED/Exiled.Events/Patches/Events/Scp1344/Deactivating.cs @@ -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; + /// /// Patches . /// Adds the event, @@ -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; } }