A rare perk component that heals the player for a percentage of missing HP every 3 seconds. It computes the heal amount based on perk level, updates a regen display modifier each frame, heals on a timer, and shows a highlight and cooldown display.
using System;
using Sandbox;
[Perk( Rarity.Rare, alwaysOfferDebug: false )]
public class PerkRegenMissingHp : Perk
{
private enum Mod { MissingHpPercent };
public bool IsShielded { get; private set; }
private float _timer;
private const float DELAY = 3f;
static PerkRegenMissingHp()
{
Register<PerkRegenMissingHp>(
name: "IV Drip",
imagePath: "textures/icons/vector/regen_missing_hp.png",
description: level => $"Heal {string.Format( "{0:0}", GetValue( level, Mod.MissingHpPercent, true ) )}% of your\nmissing hp every {DELAY}s",
upgradeDescription: level => $"Heal {string.Format( "{0:0}", GetValue( level - 1, Mod.MissingHpPercent, true ) )}%→{string.Format( "{0:0}", GetValue( level, Mod.MissingHpPercent, true ) )}% of your\nmissing hp every {DELAY}s"
);
}
public override void Start()
{
base.Start();
ShouldUpdate = true;
HighlightColor = new Color( 0.4f, 1f, 0.4f );
HighlightDuration = 0.25f;
HighlightOpacity = 0.75f;
}
public override void Refresh()
{
base.Refresh();
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.MissingHpPercent:
default:
switch ( level )
{
case 1: default: return isPercent ? 4f : 0.04f;
case 2: return isPercent ? 5.5f : 0.055f;
case 3: return isPercent ? 7f : 0.07f;
case 4: return isPercent ? 8f : 0.08f;
case 5: return isPercent ? 9f : 0.09f;
}
}
}
public override void Update( float dt )
{
base.Update( dt );
float amount = Player.Health < Player.Stats[PlayerStat.MaxHp] ? (Player.Stats[PlayerStat.MaxHp] - Player.Health) * GetValue( Level, Mod.MissingHpPercent ) : 0f;
float amountPerSecond = amount / DELAY;
float displayAmount = amountPerSecond > 0f ? MathF.Max( amountPerSecond, 0.1f ) : 0f;
Player.Modify( this, PlayerStat.HpRegenDisplay, displayAmount, ModifierType.Add );
_timer += dt;
if ( _timer > DELAY )
{
if ( Player.Health < Player.Stats[PlayerStat.MaxHp] )
{
Player.Heal( amount );
Highlight();
}
_timer = 0f;
}
DisplayCooldown = Utils.Map( _timer, 0f, DELAY, 0f, 1f );
}
}