perks/PerkPunchBullets.cs

Perk class that spawns arc bullets when the player kills an enemy with a punch. It registers a perk called "Backblast", computes number of bullets, spread and damage, then spawns and randomizes arc bullets around the enemy position on punch kills.

NetworkingFile Access
using System;
using Sandbox;

[Perk( Rarity.Common, includedAtStart: false, locked: true, minUnlocksReq: 2, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.NumProjectiles, PerkCategory.ArcBullets })]
public class PerkPunchBullets : Perk
{
	private enum Mod { NumBullets, SpreadModifier };


	static PerkPunchBullets()
	{
		Register<PerkPunchBullets>(
			name: "Backblast",
			imagePath: "textures/icons/vector/punch_bullets.png",
			description: level => $"Lob {(int)GetValue( level, Mod.NumBullets )} bullet-icon from enemies\nyou kill with punches",
			upgradeDescription: level => $"Lob {(int)GetValue( level - 1, Mod.NumBullets )}→{(int)GetValue( level, Mod.NumBullets )} bullet-icon from enemies\nyou kill with punches"
		);
	}

	public override void Start()
	{
		base.Start();
	}

	public override void Refresh()
	{
		base.Refresh();

	}

	public override void OnKill( Enemy enemy, DamageType damageType, bool countsAsKill )
	{
		base.OnKill( enemy, damageType, countsAsKill );
		if ( !countsAsKill ) return;

		if ( damageType != DamageType.Punch )
			return;

		int numBullets = (int)GetValue( Level, Mod.NumBullets );
		float damage = Player.GetBulletDamage( isFromClip: false, isLastAmmo: false );
		float spread = Player.Stats[PlayerStat.BulletSpread] * GetValue( Level, Mod.SpreadModifier );
		var dir = Player.FacingDir;

		float currAngleOffset = numBullets == 1 ? 0f : -spread * 0.5f;
		float increment = numBullets == 1 ? 0f : spread / (float)(numBullets - 1);

		for ( int i = 0; i < numBullets; i++ )
		{
			var spawnOffset = 10f;
			var currDir = Utils.RotateVector( dir, currAngleOffset + increment * i );
			var pos = enemy.Position2D + currDir * spawnOffset * Player.Stats[PlayerStat.Scale];
			var bullet = Player.SpawnBullet( pos, currDir, damage, isFromClip: false );
			bullet.SetupArc( arcHeight: Game.Random.Float( 120f, 160f ), Player.Stats[PlayerStat.ArcBulletBounces] );
			bullet.Velocity *= Game.Random.Float( 0.05f, 0.45f );
			bullet.Stats[BulletStat.Lifetime] *= Game.Random.Float( 1f, 1.4f );
		}
	}

	private static float GetValue( int level, Mod mod, bool isPercent = false )
	{
		switch ( mod )
		{
			case Mod.NumBullets:
			default:
				switch(level)
				{
					case 1: default: return 2;
					case 2: return 3;
					case 3: return 4;
					case 4: return 5;
					case 5: return 6;
					case 6: return 7;
					case 7: return 8;
				}
			case Mod.SpreadModifier:
				return 1.3f + 0.55f * level;
		}
	}
}