A Legendary perk called "Chambered" that gives temporary bonus damage to bullets for a number of clips after a reroll. It tracks remaining clips, applies a damage bonus on reloads while clips remain, updates display text and cooldown, and resets on removal.
using System;
using Sandbox;
[Perk( Rarity.Legendary, alwaysOfferDebug: false )]
public class PerkRerollClipDmg : Perk
{
private enum Mod { BonusDmg, NumClips }
private int _clipsRemaining;
static PerkRerollClipDmg()
{
Register<PerkRerollClipDmg>(
name: "Chambered",
imagePath: "textures/icons/vector/reroll_clip_dmg.png",
description: level =>
{
int clips = (int)GetValue( level, Mod.NumClips );
string clipText = clips == 1 ? "clip" : $"{clips} clips";
return $"+{GetValue( level, Mod.BonusDmg )} bullet-icon dmg for\nyour next {clipText} on reroll\n(doesn't stack)";
},
upgradeDescription: level => $"+{GetValue( level, Mod.BonusDmg )} bullet-icon dmg for\nyour next {(int)GetValue( level - 1, Mod.NumClips )}→{(int)GetValue( level, Mod.NumClips )} clips on reroll\n(doesn't stack)"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 1f, 0.85f, 0.4f );
HighlightDuration = 0.2f;
HighlightOpacity = 1.5f;
}
public override void Refresh()
{
base.Refresh();
DisplayCooldownColor = new Color( 0.2f, 0.85f, 1f );
}
private static float GetValue( int level, Mod mod )
{
switch ( mod )
{
case Mod.BonusDmg: return 10f;
case Mod.NumClips:
default: return level;
}
}
public override void OnRerollAfter()
{
base.OnRerollAfter();
_clipsRemaining = (int)GetValue( Level, Mod.NumClips );
RefreshDisplayText();
Highlight();
}
public override void OnFinishReload()
{
base.OnFinishReload();
if ( _clipsRemaining > 0 )
{
Player.Stats[PlayerStat.ClipDamageBonus] += GetValue( Level, Mod.BonusDmg );
_clipsRemaining--;
RefreshDisplayText();
}
}
void RefreshDisplayText()
{
DisplayText = _clipsRemaining > 0 ? $"+{GetValue( Level, Mod.BonusDmg ):0.#}" : " ";
DisplayCooldown = _clipsRemaining / GetValue( Level, Mod.NumClips );
}
public override void Remove( bool restart = false )
{
base.Remove( restart );
Player.Stats[PlayerStat.ClipDamageBonus] = 0f;
_clipsRemaining = 0;
}
}