diff --git a/EXILED/Exiled.API/Features/CustomHealthStat.cs b/EXILED/Exiled.API/Features/CustomStats/CustomHealthStat.cs similarity index 95% rename from EXILED/Exiled.API/Features/CustomHealthStat.cs rename to EXILED/Exiled.API/Features/CustomStats/CustomHealthStat.cs index af351bf7ab..f0d71fc665 100644 --- a/EXILED/Exiled.API/Features/CustomHealthStat.cs +++ b/EXILED/Exiled.API/Features/CustomStats/CustomHealthStat.cs @@ -5,7 +5,7 @@ // // ----------------------------------------------------------------------- -namespace Exiled.API.Features +namespace Exiled.API.Features.CustomStats { using PlayerStatsSystem; diff --git a/EXILED/Exiled.API/Features/CustomStats/CustomHumeShieldStat.cs b/EXILED/Exiled.API/Features/CustomStats/CustomHumeShieldStat.cs new file mode 100644 index 0000000000..590c664ecf --- /dev/null +++ b/EXILED/Exiled.API/Features/CustomStats/CustomHumeShieldStat.cs @@ -0,0 +1,74 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.API.Features.CustomStats +{ + using Mirror; + using PlayerRoles.PlayableScps.HumeShield; + using PlayerStatsSystem; + using UnityEngine; + using Utils.Networking; + + /// + /// A custom version of which allows the player's max amount of HumeShield to be changed. + /// + public class CustomHumeShieldStat : HumeShieldStat + { + private const float DefaultCustomValue = -1; + + /// + public override float MaxValue => CustomMaxValue == DefaultCustomValue ? base.MaxValue : CustomMaxValue; + + /// + /// Gets or sets the multiplier for gaining HumeShield. + /// + public float ShieldRegenerationMultiplier { get; set; } = 1; + + /// + /// Gets or sets the maximum amount of HumeShield the player can have. + /// + public float CustomMaxValue { get; set; } + + private float ShieldRegeneration => TryGetHsModule(out HumeShieldModuleBase controller) ? controller.HsRegeneration * ShieldRegenerationMultiplier : 0; + + /// + public override void Update() + { + if (MaxValue == DefaultCustomValue) + { + base.Update(); + return; + } + + if (!NetworkServer.active) + return; + + if (_valueDirty) + { + new SyncedStatMessages.StatMessage() + { + Stat = this, + SyncedValue = CurValue, + }.SendToHubsConditionally(CanReceive); + _lastSent = CurValue; + _valueDirty = false; + } + + if (ShieldRegeneration == 0) + return; + + float delta = ShieldRegeneration * Time.deltaTime; + + if (delta > 0) + { + if (CurValue >= MaxValue) + return; + CurValue = Mathf.MoveTowards(CurValue, MaxValue, delta); + } + } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index 788493ca98..3012a9d39b 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -19,6 +19,7 @@ namespace Exiled.API.Features using DamageHandlers; using Enums; using Exiled.API.Features.Core.Interfaces; + using Exiled.API.Features.CustomStats; using Exiled.API.Features.Doors; using Exiled.API.Features.Hazards; using Exiled.API.Features.Items; @@ -95,6 +96,7 @@ public class Player : TypeCastObject, IEntity, IWorldSpace private ReferenceHub referenceHub; private CustomHealthStat healthStat; + private CustomHumeShieldStat humeShieldStat; private Role role; /// @@ -176,6 +178,7 @@ private set CameraTransform = value.PlayerCameraReference; value.playerStats._dictionarizedTypes[typeof(HealthStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HealthStat))] = healthStat = new CustomHealthStat { Hub = value }; + value.playerStats._dictionarizedTypes[typeof(HumeShieldStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HumeShieldStat))] = humeShieldStat = new CustomHumeShieldStat { Hub = value }; } } @@ -914,6 +917,16 @@ public float MaxArtificialHealth } } + /// + /// Gets the of the Player. + /// + public AhpStat AhpStat => ReferenceHub.playerStats.GetModule(); + + /// + /// Gets a of all active Artificial Health processes on the player. + /// + public List ActiveArtificialHealthProcesses => AhpStat._activeProcesses; + /// /// Gets or sets the player's Hume Shield. /// @@ -925,14 +938,27 @@ public float HumeShield } /// - /// Gets a of all active Artificial Health processes on the player. + /// Gets or sets the players maximum Hume Shield. /// - public IEnumerable ActiveArtificialHealthProcesses => ReferenceHub.playerStats.GetModule()._activeProcesses; + public float MaxHumeShield + { + get => HumeShieldStat.MaxValue; + set => HumeShieldStat.CustomMaxValue = value; + } + + /// + /// Gets or sets the players multiplier for gaining HumeShield. + /// + public float HumeShieldRegenerationMultiplier + { + get => HumeShieldStat.ShieldRegenerationMultiplier; + set => HumeShieldStat.ShieldRegenerationMultiplier = value; + } /// /// Gets the player's . /// - public HumeShieldStat HumeShieldStat => ReferenceHub.playerStats.GetModule(); + public CustomHumeShieldStat HumeShieldStat => humeShieldStat; /// /// Gets or sets the item in the player's hand. Value will be if the player is not holding anything. @@ -3441,10 +3467,7 @@ public void ChangeEffectIntensity(string effectName, byte intensity, float durat /// The number of seconds to delay the start of the decay. /// Whether the process is removed when the value hits 0. public void AddAhp(float amount, float limit = 75f, float decay = 1.2f, float efficacy = 0.7f, float sustain = 0f, bool persistant = false) - { - ReferenceHub.playerStats.GetModule() - .ServerAddProcess(amount, limit, decay, efficacy, sustain, persistant); - } + => AhpStat.ServerAddProcess(amount, limit, decay, efficacy, sustain, persistant); /// /// Reconnects the player to the server. Can be used to redirect them to another server on a different port but same IP. diff --git a/EXILED/Exiled.Events/Patches/Events/Player/ChangingRoleAndSpawned.cs b/EXILED/Exiled.Events/Patches/Events/Player/ChangingRoleAndSpawned.cs index ad159f736c..0e0470d928 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/ChangingRoleAndSpawned.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/ChangingRoleAndSpawned.cs @@ -179,6 +179,7 @@ private static void UpdatePlayerRole(RoleTypeId newRole, API.Features.Player pla if (newRole is RoleTypeId.Scp173) Scp173Role.TurnedPlayers.Remove(player); + player.MaxHumeShield = -1; player.MaxHealth = default; } @@ -192,10 +193,9 @@ private static void ChangeInventory(ChangingRoleEventArgs ev) } Inventory inventory = ev.Player.Inventory; - bool flag = InventoryItemProvider.KeepItemsAfterEscaping && ev.Reason == API.Enums.SpawnReason.Escaped; - if (flag) + if (InventoryItemProvider.KeepItemsAfterEscaping && ev.Reason == API.Enums.SpawnReason.Escaped) { - List list = new List(); + List list = new(); if (inventory.TryGetBodyArmor(out BodyArmor bodyArmor)) { bodyArmor.DontRemoveExcessOnDrop = true; @@ -222,8 +222,7 @@ private static void ChangeInventory(ChangingRoleEventArgs ev) HashSetPool.Pool.Return(hashSet); InventoryItemProvider.PreviousInventoryPickups[ev.Player.ReferenceHub] = list; } - - if (!flag) + else { while (inventory.UserInventory.Items.Count > 0) {