A unique curse perk called "Obsessive" that penalizes the player when they pick a perk they already have. It subtracts max HP, tracks total max HP lost, shows a floating negative text, and briefly highlights the player.
using System;
using Sandbox;
[Perk( Rarity.Unique, curse: true, alwaysOfferDebug: false )]
public class CurseChooseSamePerk : Perk
{
private enum Mod { MaxHpLost };
private float _totalMaxHpLost;
static CurseChooseSamePerk()
{
Register<CurseChooseSamePerk>(
name: "Obsessive",
imagePath: "textures/icons/vector/curse_choose_same_perk.png",
description: level => $"-{(int)GetValue( level, Mod.MaxHpLost )} max hp when you get\n a perk you already have"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 1f, 0f, 0f );
HighlightDuration = 0.4f;
HighlightOpacity = 3f;
}
public override void Refresh()
{
base.Refresh();
}
public override void OnAddPerkBefore( TypeDescription type )
{
base.OnAddPerkBefore( type );
var typeIdentity = type.Identity;
if ( !Player.Perks.ContainsKey( typeIdentity ) )
return;
var attrib = type.GetAttribute<PerkAttribute>();
bool isCurse = attrib.Curse;
if ( isCurse )
return;
int maxHpToLose = (int)GetValue(Level, Mod.MaxHpLost );
_totalMaxHpLost += maxHpToLose;
Player.Modify( this, PlayerStat.MaxHp, -_totalMaxHpLost, ModifierType.Add );
Manager.Instance.SpawnFloaterTextRpc( Player.WorldPosition.WithZ( 65f ), $"-{maxHpToLose} MAX HP", new Color( 0.8f, 0.1f, 0.5f ), size: 1.1f, floaterType: FloaterType.NegativeMessage );
Highlight();
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.MaxHpLost:
default:
return 2;
}
}
}