A unique perk class 'PerkDoubleDashes' that triples a player's dashes and tracks hits; after 9 hits it forces the player to die. It updates display text, plays floating text and sound effects, and modifies player dash stat while active.
using System;
using Sandbox;
[Perk( Rarity.Unique, locked: true, alwaysOfferDebug: false )]
public class PerkDoubleDashes : Perk
{
private int _numTimesHit;
static PerkDoubleDashes()
{
Register<PerkDoubleDashes>(
name: "Feline Aspect",
imagePath: "textures/icons/vector/double_dashes.png",
description: level => $"Triple your dashes\nDie after being hit 9 times"
);
}
public override void Start()
{
base.Start();
ShouldUpdate = true;
}
public override void IncreaseLevel()
{
base.IncreaseLevel();
Manager.Instance.SpawnFloaterTextRpc( Player.WorldPosition.WithZ( 65f ), $"9 LIVES LEFT", new Color( 0f, 0.7f, 0.8f ), size: 1.3f, floaterType: FloaterType.NegativeMessage );
RefreshDisplayText();
Manager.Instance.PlaySfxNearbyRpc( "cat_begin", Player.Position2D, pitch: Game.Random.Float( 0.9f, 1.1f ), volume: 2f, maxDist: 500f );
}
public override void Refresh()
{
base.Refresh();
Player.Modify( this, PlayerStat.NumDashes, 3f, ModifierType.Mult );
}
public override void OnHit( float amount, DamageType damageType, bool isSelfInflicted, Vector2 dir, float force, Enemy enemySource, EnemyType enemyType, float previousHealth )
{
base.OnHit( amount, damageType, isSelfInflicted, dir, force, enemySource, enemyType, previousHealth );
if ( Player.IsDead || damageType == DamageType.Self )
return;
_numTimesHit++;
if ( _numTimesHit >= 9 )
{
if( Player.TryDie( dir, upwardAmount: Game.Random.Float(0f, 0.2f), force, enemyType, isSelfInflicted: true, damageType: DamageType.Self, playSfx: false ) )
{
// todo: show death reason in chat
Manager.Instance.PlaySfxNearbyRpc( "cat_die_2", Player.Position2D, pitch: Game.Random.Float( 1.2f, 1.25f ), volume: 3f, maxDist: 500f );
}
RefreshDisplayText();
}
else
{
int livesLeft = 9 - _numTimesHit;
Color color = Color.Lerp( new Color( 0f, 0.7f, 0.8f ), new Color( 1f, 0.3f, 0.5f ), Utils.Map( livesLeft, 8, 1, 0f, 1f, EasingType.Linear ) );
float size = Utils.Map( livesLeft, 8, 1, 1.3f, 1.5f, EasingType.QuadIn );
var str = (livesLeft == 1) ? $"FINAL LIFE" : $"{livesLeft} LIVES LEFT";
Manager.Instance.SpawnFloaterTextRpc( Player.WorldPosition.WithZ( 65f ), str, color, size, floaterType: FloaterType.NegativeMessage );
RefreshDisplayText();
Manager.Instance.PlaySfxNearbyRpc( "cat_die", Player.Position2D, pitch: Game.Random.Float( 0.85f, 1.2f ), volume: 3.5f, maxDist: 400f );
}
}
void RefreshDisplayText()
{
var amount = 9 - _numTimesHit;
DisplayText = $"{amount}";
DisplayTextColor = Color.Lerp( new Color( 1f, 0.6f, 0.6f ), new Color( 1f, 0f, 1f ), Utils.Map( amount, 9, 1, 0f, 1f ) );
DisplayTextOpacity = Utils.Map( amount, 9, 1, 3f, 4f );
DisplayCooldown = Utils.Map( amount, 9, 0, 0f, 1f );
DisplayCooldownColor = Color.Lerp( new Color( 0.3f, 0f, 0f ), new Color( 0.5f, 0f, 0.5f ), Utils.Map( amount, 9, 0, 0f, 1f ) );
}
}