A game perk component named PerkCopyNext that duplicates the next non-curse perk the player receives. It tracks a deferred count, increments when level increases, applies the copy in OnAddPerkBefore, updates a player stat each frame, and manages UI highlight and display values.
using System;
using Sandbox;
[Perk( Rarity.Rare, alwaysOfferDebug: false )]
public class PerkCopyNext : Perk
{
private float _deferredAmount;
public override float ImportanceMultiplier => 0f;
static PerkCopyNext()
{
Register<PerkCopyNext>(
name: "Two For One",
imagePath: "textures/icons/vector/copy_next.png",
description: level => $"Duplicate the next perk you get",
upgradeDescription: level => $"Duplicate the next perk you get"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 1f, 1f, 0.5f );
HighlightDuration = 0.4f;
HighlightOpacity = 6f;
}
public override void IncreaseLevel()
{
base.IncreaseLevel();
_deferredAmount += 1f;
ShouldUpdate = true;
DisplayText = "➕";
DisplayCooldown = 1f;
}
public override void Refresh()
{
base.Refresh();
}
public override void Update( float dt )
{
base.Update( dt );
Player.Stats[PlayerStat.CopyNextPerk] += _deferredAmount;
_deferredAmount = 0f;
DisplayCooldownColor = new Color( 0.3f, 0.3f, 1f, Utils.Map( Utils.FastSin( RealTime.Now * 12f ), -1f, 1f, 0f, 1f ) );
}
public override void OnAddPerkBefore( TypeDescription type )
{
base.OnAddPerkBefore( type );
var attrib = type.GetAttribute<PerkAttribute>();
if ( attrib.Curse )
return;
if ( Player.Stats[PlayerStat.CopyNextPerk] > 0f )
{
Player.GivePerkItem( type, dir: Utils.GetRandomVectorInCone(-Player.FacingDir ) );
Player.Stats[PlayerStat.CopyNextPerk] -= 1f;
if ( !(Player.Stats[PlayerStat.CopyNextPerk] > 0f) && _deferredAmount == 0 )
{
DisplayText = " ";
DisplayCooldown = 0f;
ShouldUpdate = false;
}
Highlight();
}
}
public override void Remove( bool restart = false )
{
base.Remove( restart );
Player.Stats[PlayerStat.CopyNextPerk] = 0f;
}
}