An Epic rarity perk called "Parting Shot" that can spawn an arc-traveling bullet from a killed enemy. It hooks OnKill, rolls chance based on perk level, spawns and configures a bullet (position, direction, arc, velocity, lifetime) and sets some visual highlight/icon tweaks.
using System;
using Sandbox;
[Perk( Rarity.Epic, locked: true, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.ArcBullets })]
public class PerkKillArcBullet : Perk
{
private enum Mod { Chance, };
static PerkKillArcBullet()
{
Register<PerkKillArcBullet>(
name: "Parting Shot",
imagePath: "textures/icons/vector/kill_arc_bullet.png",
description: level => $"[+]{GetValue( level, Mod.Chance, true )}%[/+] chance to lob a\nbullet-icon from enemies you kill",
upgradeDescription: level => $"{GetValue( level - 1, Mod.Chance, true )}→{GetValue( level, Mod.Chance, true )}% chance to lob a\nbullet-icon from enemies you kill"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 1f, 0.7f, 0.4f );
HighlightDuration = 0.15f;
HighlightOpacity = 0.85f;
}
public override void OnKill( Enemy enemy, DamageType damageType, bool countsAsKill )
{
base.OnKill( enemy, damageType, countsAsKill );
if ( !countsAsKill ) return;
if ( Game.Random.Float( 0f, 1f ) < GetValue( Level, Mod.Chance ) )
{
var spawnOffset = 10f;
var towardEnemy = (enemy.Position2D - Player.Position2D).Normal;
var dir = Utils.GetRandomVectorInCone( towardEnemy, 200f );
var pos = enemy.Position2D + dir * spawnOffset * Player.Stats[PlayerStat.Scale];
var damage = Player.GetBulletDamage( isFromClip: false, isLastAmmo: false );
var bullet = Player.SpawnBullet( pos, dir, damage, isFromClip: false );
bullet.SetupArc( arcHeight: Game.Random.Float( 220f, 280f ), Player.Stats[PlayerStat.ArcBulletBounces] );
bullet.Velocity *= Game.Random.Float( 0.05f, 0.25f );
bullet.Stats[BulletStat.Lifetime] *= Game.Random.Float( 1.5f, 1.8f );
Highlight();
IconScale = Game.Random.Float( 1.075f, 1.1f );
IconAngleOffset = Game.Random.Float( 5f, 9f ) * (Game.Random.Int( 0, 1 ) == 0 ? -1f : 1f);
//Manager.Instance.PlaySfxNearbyRpc( "flick2", pos, pitch: Game.Random.Float(0.85f, 0.9f), volume: 0.9f, maxDist: 300f );
}
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.Chance:
default:
return isPercent
? 25f * level
: 0.25f * level;
}
}
}