A Perk implementation that gives the player landmines on dash. It spawns a landmine prefab at the player's position when a dash starts, tracks active mines, enforces a max count by exploding the oldest, updates HUD display and modifies dash cooldown stat.
using System;
using Sandbox;
[Perk( Rarity.Rare, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.Aoe, PerkCategory.Explosion, PerkCategory.Landmine })]
public class PerkLandmine : Perk
{
private enum Mod { ExplosionDamage, DashCooldown, NumMaxMines, };
public int CurrNumLandmines { get; private set; }
private List<Landmine> _landmines = new();
static PerkLandmine()
{
Register<PerkLandmine>(
name: "Landmines",
imagePath: "textures/icons/vector/landmine.png",
description: level => $"Drop a {GetValue( level, Mod.ExplosionDamage )} dmg landmine on dash (max: {GetValue( level, Mod.NumMaxMines )})\n-{GetValue( level, Mod.DashCooldown, true )}% dash recharge speed",
upgradeDescription: level => $"Drop a {GetValue( level - 1, Mod.ExplosionDamage )}→{GetValue( level, Mod.ExplosionDamage )} dmg landmine on dash\n(max: {GetValue( level - 1, Mod.NumMaxMines )}→{GetValue( level, Mod.NumMaxMines )})\n-{GetValue( level - 1, Mod.DashCooldown, true )}%→-{GetValue( level, Mod.DashCooldown, true )}% dash recharge speed"
);
}
// todo: do we even need a max count on this? just limit it to 50 or so and explode the oldest one if you place more
public override void Start()
{
base.Start();
DisplayCooldownColor = new Color( 1f, 0.3f, 0.3f, 3f );
HighlightColor = new Color( 1f, 1f, 1f );
HighlightDuration = 0.1f;
HighlightOpacity = 0.25f;
}
public override void Refresh()
{
base.Refresh();
Player.Modify( this, PlayerStat.DashCooldown, GetValue( Level, Mod.DashCooldown ), ModifierType.Mult );
DisplayText = $"{CurrNumLandmines}/{(int)GetValue( Level, Mod.NumMaxMines )}";
}
public override void OnDashStartedEarly( Vector2 dir )
{
base.OnDashStartedEarly( dir );
if ( CurrNumLandmines >= (int)GetValue( Level, Mod.NumMaxMines ) )
{
if( _landmines.Count > 0 )
{
if( _landmines[0].IsValid() )
_landmines[0].Explode();
_landmines.RemoveAt( 0 );
}
}
var pos = Player.Position2D;
var damage = GetValue( Level, Mod.ExplosionDamage );
var landmineGo = GameObject.Clone( "prefabs/landmine.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( new Vector3( pos.x, pos.y, 0f ) ) } );
var landmine = landmineGo.Components.Get<Landmine>( true );
landmine.Damage = damage;
landmine.Shooter = Player;
landmineGo.NetworkSpawn( Player.Network.Owner );
CurrNumLandmines++;
//PlaySfx("burn", mine.Position2D, pitch: Game.Random.Float(0.95f, 1.05f));
_landmines.Add( landmine );
DisplayCooldown = Utils.Map( CurrNumLandmines, 0, (int)GetValue( Level, Mod.NumMaxMines ), 0f, 1f );
Highlight();
DisplayText = $"{CurrNumLandmines}/{(int)GetValue( Level, Mod.NumMaxMines )}";
}
public void LandmineDestroyed()
{
CurrNumLandmines = Math.Max( CurrNumLandmines - 1, 0 );
DisplayCooldown = Utils.Map( CurrNumLandmines, 0, (int)GetValue( Level, Mod.NumMaxMines ), 0f, 1f );
Highlight();
DisplayText = $"{CurrNumLandmines}/{(int)GetValue( Level, Mod.NumMaxMines )}";
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.ExplosionDamage:
default:
return 5f + 5f * level;
case Mod.NumMaxMines:
return 5 * level;
case Mod.DashCooldown:
return isPercent
? 8f + 2f * level
: 1f + (0.08f + 0.02f * level);
}
}
}