A perk class PerkPunch that replaces the player gun with a melee "punch" mechanic. It registers the perk with metadata, adjusts player stats (punch damage percent, punch bullets flag, attack speed multiplier), hides the gun while active, and restores visibility on removal. It also exposes static value calculations for damage and attack speed per level.
using System;
using Sandbox;
[Perk( Rarity.Rare, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.Punch })]
public class PerkPunch : Perk
{
private enum Mod { DamagePercent, AttackSpeed };
public const float PUNCH_LIFETIME = 0.04f;
public const float PUNCH_SPEED = 1320f;
public override float ImportanceMultiplier => 1.4f;
static PerkPunch()
{
Register<PerkPunch>(
name: "Puncher",
imagePath: "textures/icons/vector/punch.png",
description: level => $"You no longer shoot bullets\nPunch for {(int)GetValue( level, Mod.DamagePercent, true )}% bullet dmg\n-{GetValue( level, Mod.AttackSpeed, true )}% attack speed",
upgradeDescription: level => $"You no longer shoot bullets\nPunch for {(int)GetValue( level - 1, Mod.DamagePercent, true )}%→{(int)GetValue( level, Mod.DamagePercent, true )}% bullet dmg\n-{GetValue( level - 1, Mod.AttackSpeed, true )}%→-{GetValue( level, Mod.AttackSpeed, true )}% attack speed"
);
}
public override void Start()
{
base.Start();
}
public override void Refresh()
{
base.Refresh();
// todo: add to stats screen - Punch Damage
Player.Modify( this, PlayerStat.PunchDamagePercent, GetValue( Level, Mod.DamagePercent ), ModifierType.Add );
Player.Modify( this, PlayerStat.PunchBullets, 1f, ModifierType.Add );
Player.Modify( this, PlayerStat.AttackSpeed, GetValue( Level, Mod.AttackSpeed ), ModifierType.Mult );
Player.SetGunVisible( false );
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.DamagePercent:
default:
return isPercent
? 150f + 20f * level + (level == 5 ? 10f : 0f)
: 1.50f + 0.20f * level + (level == 5 ? 0.10f : 0f);
case Mod.AttackSpeed:
return isPercent
? 30f + 5f * level
: 1f - (0.30f + 0.05f * level);
}
}
public override void Remove( bool restart = false )
{
Player.SetGunVisible( true );
}
}