Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features.CustomStats #130

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
79 changes: 79 additions & 0 deletions EXILED/Exiled.API/Features/CustomStats/CustomHumeShieldStat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// -----------------------------------------------------------------------
// <copyright file="CustomHumeShieldStat.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Features.CustomStats
{
using Mirror;
using PlayerRoles.PlayableScps.HumeShield;
using PlayerStatsSystem;
using UnityEngine;
using Utils.Networking;

/// <summary>
/// A custom version of <see cref="HumeShieldStat"/> which allows the player's max amount of HumeShield to be changed.
/// </summary>
public class CustomHumeShieldStat : HumeShieldStat
{
/// <inheritdoc />
public override float MaxValue => CustomMaxValue == -1 ? base.MaxValue : CustomMaxValue;

/// <summary>
/// Gets or sets the multiplier for gaining HumeShield.
/// </summary>
public float ShieldRegenerationMultiplier { get; set; } = 1;

/// <summary>
/// Gets or sets the maximum amount of HumeShield the player can have.
/// </summary>
public float CustomMaxValue { get; set; } = -1;

private float ShieldRegeneration => TryGetHsModule(out HumeShieldModuleBase controller) ? controller.HsRegeneration * ShieldRegenerationMultiplier : 0;

/// <inheritdoc/>
public override void Update()
{
if (MaxValue == default)
louis1706 marked this conversation as resolved.
Show resolved Hide resolved
{
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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool be interesting to override this value

return;

float delta = ShieldRegeneration * Time.deltaTime;

if (delta > 0)
{
if (CurValue >= MaxValue)
return;

CurValue = Mathf.MoveTowards(CurValue, MaxValue, delta);
return;
}

if (CurValue <= 0)
return;

CurValue += delta;
}
}
}
56 changes: 56 additions & 0 deletions EXILED/Exiled.API/Features/CustomStats/CustomStaminaStat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// -----------------------------------------------------------------------
// <copyright file="CustomStaminaStat.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.API.Features.CustomStats
{
using Mirror;
using PlayerStatsSystem;
using UnityEngine;

/// <summary>
/// A custom version of <see cref="StaminaStat"/> which allows the player's maximum amount of Stamina to be changed.
/// </summary>
public class CustomStaminaStat : StaminaStat
{
/// <inheritdoc/>
public override float MaxValue => CustomMaxValue == default ? base.MaxValue : CustomMaxValue;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public override float MaxValue => CustomMaxValue == default ? base.MaxValue : CustomMaxValue;
public override float MaxValue => CustomMaxValue == -1 ? base.MaxValue : CustomMaxValue;


/// <summary>
/// Gets or sets the maximum amount of stamina the player will have.
/// </summary>
public float CustomMaxValue { get; set; }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public float CustomMaxValue { get; set; }
public float CustomMaxValue { get; set; } = -1;


/// <summary>
/// Clamps a float to fit the current stamina bar.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <returns>The clamped num.</returns>
public float Clamp(float value) => CustomMaxValue == default ? Mathf.Clamp01(value) : Mathf.Clamp(value, 0, MaxValue);

/// <summary>
/// Overiding NW Method to sync Player percentage of Stamina.
/// </summary>
/// <param name="writer">The writer.</param>
public override void WriteValue(NetworkWriter writer)
{
if (CustomMaxValue == default)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (CustomMaxValue == default)
if (CustomMaxValue == -1)

{
base.WriteValue(writer);
return;
}

writer.WriteByte(ToByte(CurValue / CustomMaxValue));
}

/// <summary>
/// Overriding NW Method to sync Player percentage of Stamina.
/// </summary>
/// <param name="reader">The reader.</param>
/// <returns>the float value sync to server.</returns>
public override float ReadValue(NetworkReader reader) => CustomMaxValue == default ? base.ReadValue(reader) : CurValue * CustomMaxValue;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public override float ReadValue(NetworkReader reader) => CustomMaxValue == default ? base.ReadValue(reader) : CurValue * CustomMaxValue;
public override float ReadValue(NetworkReader reader) => CustomMaxValue == -1 ? base.ReadValue(reader) : CurValue * CustomMaxValue;

}
}
36 changes: 34 additions & 2 deletions EXILED/Exiled.API/Features/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -95,7 +96,9 @@ public class Player : TypeCastObject<Player>, IEntity, IWorldSpace
private readonly HashSet<EActor> componentsInChildren = new();

private ReferenceHub referenceHub;
private CustomHumeShieldStat humeShieldStat;
private CustomHealthStat healthStat;
private CustomStaminaStat staminaStat;
private Role role;

/// <summary>
Expand Down Expand Up @@ -177,6 +180,8 @@ 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 };
value.playerStats._dictionarizedTypes[typeof(StaminaStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(StaminaStat))] = staminaStat = new CustomStaminaStat { Hub = value };
}
}

Expand Down Expand Up @@ -935,6 +940,24 @@ public float HumeShield
set => HumeShieldStat.CurValue = value;
}

/// <summary>
/// Gets or sets the players maximum Hume Shield.
/// </summary>
public float MaxHumeShield
{
get => humeShieldStat.MaxValue;
set => humeShieldStat.CustomMaxValue = value;
}

/// <summary>
/// Gets or sets the players multiplier for gaining HumeShield.
/// </summary>
public float HumeShieldRegenerationMultiplier
{
get => humeShieldStat.ShieldRegenerationMultiplier;
set => humeShieldStat.ShieldRegenerationMultiplier = value;
}

/// <summary>
/// Gets a <see cref="IEnumerable{T}"/> of all active Artificial Health processes on the player.
/// </summary>
Expand All @@ -943,7 +966,7 @@ public float HumeShield
/// <summary>
/// Gets the player's <see cref="PlayerStatsSystem.HumeShieldStat"/>.
/// </summary>
public HumeShieldStat HumeShieldStat => ReferenceHub.playerStats.GetModule<HumeShieldStat>();
public HumeShieldStat HumeShieldStat => humeShieldStat;

/// <summary>
/// Gets or sets the item in the player's hand. Value will be <see langword="null"/> if the player is not holding anything.
Expand Down Expand Up @@ -975,7 +998,7 @@ public Item CurrentItem
/// <summary>
/// Gets the <see cref="StaminaStat"/> class.
/// </summary>
public StaminaStat StaminaStat => ReferenceHub.playerStats.GetModule<StaminaStat>();
public StaminaStat StaminaStat => staminaStat;

/// <summary>
/// Gets or sets the amount of stamina the player has.
Expand All @@ -987,6 +1010,15 @@ public float Stamina
set => StaminaStat.CurValue = value;
}

/// <summary>
/// Gets or sets the players maximum stamina.
/// </summary>
public float MaxStamina
{
get => staminaStat.MaxValue;
set => staminaStat.CustomMaxValue = value;
}

/// <summary>
/// Gets a value indicating whether or not the staff bypass is enabled.
/// </summary>
Expand Down
73 changes: 73 additions & 0 deletions EXILED/Exiled.Events/Patches/Fixes/FixStaminaBar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// -----------------------------------------------------------------------
// <copyright file="FixStaminaBar.cs" company="Exiled Team">
// Copyright (c) Exiled Team. All rights reserved.
// Licensed under the CC BY-SA 3.0 license.
// </copyright>
// -----------------------------------------------------------------------

namespace Exiled.Events.Patches.Fixes
{
using Exiled.API.Features.CustomStats;
using HarmonyLib;
using Mirror;
using PlayerRoles.FirstPersonControl;
using UnityEngine;

/// <summary>
/// Fix for <see cref="CustomStaminaStat"/>.
/// </summary>
[HarmonyPatch(typeof(FpcStateProcessor), nameof(FpcStateProcessor.UpdateMovementState))]
Copy link

@louis1706 louis1706 Oct 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure there a way to not having to patch this event it's also in the wrong file

internal static class FixStaminaBar
{
#pragma warning disable SA1313
private static bool Prefix(FpcStateProcessor __instance, PlayerMovementState state, PlayerMovementState __result)
#pragma warning restore SA1313
{
if (__instance._stat is not CustomStaminaStat stat)
return true;

float height = __instance._mod.CharacterControllerSettings.Height;
float num1 = height * __instance._mod.CrouchHeightRatio;

if (__instance.UpdateCrouching(state == PlayerMovementState.Crouching, num1, height) || __instance._firstUpdate)
{
__instance._firstUpdate = false;
float num2 = Mathf.Lerp(0.0f, (float)((height - num1) / 2.0), __instance.CrouchPercent);
float num3 = Mathf.Lerp(height, num1, __instance.CrouchPercent);
float radius = __instance._mod.CharController.radius;
__instance._mod.CharController.height = num3;
__instance._mod.CharController.center = Vector3.down * num2;
__instance._camPivot.localPosition = Vector3.up * (float)((num3 / 2.0) - num2 - radius + 0.08799999952316284);
}

if (!NetworkServer.active || __instance._useRate == 0.0)
{
__result = state;
return false;
}

if (state == PlayerMovementState.Sprinting)
{
if (stat.CurValue > 0.0 && !__instance.SprintingDisabled)
{
stat.CurValue = stat.Clamp(stat.CurValue - (Time.deltaTime * __instance.ServerUseRate));
__instance._regenStopwatch.Restart();
__result = PlayerMovementState.Sprinting;
return false;
}

state = PlayerMovementState.Walking;
}

if (stat.CurValue >= stat.MaxValue)
{
__result = state;
return false;
}

stat.CurValue = stat.Clamp(__instance._stat.CurValue + (__instance.ServerRegenRate * Time.deltaTime));
__result = state;
return false;
}
}
}
Loading