A unique perk component named PerkCopyTwice (displayed as "Hat Trick") that duplicates the next non-curse perk the player receives. It tracks state, shows UI highlights and icons, and when the next perk is added it spawns an extra copy shortly after.
using System;
using Sandbox;
[Perk( Rarity.Unique, alwaysOfferDebug: false )]
public class PerkCopyTwice : Perk
{
private TypeDescription _type;
private bool _ready;
private bool _hasGiven;
private float _getTime;
public override float ImportanceMultiplier => 0f;
static PerkCopyTwice()
{
Register<PerkCopyTwice>(
name: "Hat Trick",
imagePath: "textures/icons/vector/copy_twice.png",
description: level => $"Duplicate the next\nperk you get twice"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 1f, 1f, 1f );
HighlightDuration = 0.4f;
HighlightOpacity = 6f;
}
public override void IncreaseLevel()
{
base.IncreaseLevel();
_ready = false;
_hasGiven = false;
DisplayText = "✌️";
ShouldUpdate = true;
DisplayCooldown = 1f;
// todo: give a random curse?
}
public override void Refresh()
{
base.Refresh();
}
public override void Update( float dt )
{
base.Update( dt );
DisplayCooldownColor = new Color( 0.3f, 0.3f, 1f, Utils.Map( Utils.FastSin( RealTime.Now * 12f ), -1f, 1f, 0f, 1f ) );
if ( _ready && Time.Now - _getTime > 0.3f )
{
Player.GivePerkItem( _type, dir: Utils.GetRandomVectorInCone(-Player.FacingDir ) );
_ready = false;
ShouldUpdate = false;
DisplayText = " ";
DisplayCooldown = 0f;
Highlight();
}
}
public override void OnAddPerkAfter( TypeDescription type )
{
base.OnAddPerkAfter( type );
if ( _hasGiven )
return;
if ( type.Equals( TypeLibrary.GetType( typeof( PerkCopyTwice ) ) ) )
return;
var attrib = type.GetAttribute<PerkAttribute>();
if ( attrib.Curse )
return;
_ready = true;
_hasGiven = true;
Player.GivePerkItem( type, dir: Utils.GetRandomVectorInCone( -Player.FacingDir ) );
_type = type;
DisplayText = "☝️";
_getTime = Time.Now;
Highlight();
// todo: chat message?
//Manager.Instance.Chat.AddLocalChatMessage( "Duplicated your next perk:", from: "", perkType: TypeLibrary.GetType( this.GetType() ), perkTypeEnd: type );
}
}