A game perk class 'PerkDodgeNext' that grants the player a guaranteed dodge for the next hit. It manages activation, cooldown timing, UI display colors/values, and applies/removes a player modifier for the dodge effect.
using Sandbox;
using System;
using System.Numerics;
[Perk( Rarity.Epic, locked: true, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.Dodge })]
public class PerkDodgeNext : Perk
{
private enum Mod { Cooldown };
private TimeSince _timeSinceDodge;
private bool _isActive;
static PerkDodgeNext()
{
Register<PerkDodgeNext>(
name: "Anticipate",
imagePath: "textures/icons/vector/dodge_next.png",
description: level => $"You're guaranteed to\ndodge the next hit\n(cooldown: {GetValue( level, Mod.Cooldown )}s)",
upgradeDescription: level => $"You're guaranteed to\ndodge the next hit\n(cooldown: {GetValue( level - 1, Mod.Cooldown )}→{GetValue( level, Mod.Cooldown )}s)"
);
}
public override void Start()
{
base.Start();
DisplayCooldownColor = new Color( 0.7f, 0.7f, 1f, 0.5f );
ShouldUpdate = true;
}
public override void IncreaseLevel()
{
base.IncreaseLevel();
Enable();
}
public override void Refresh()
{
base.Refresh();
}
public override void Update( float dt )
{
base.Update( dt );
if ( _isActive )
{
DisplayCooldownColor = Color.Lerp( new Color( 0.5f, 0.5f, 1f, 0.75f ), new Color( 0f, 0f, 1f, 0.75f ), 0.5f + Utils.FastSin( RealTime.Now * 24f ) * 0.5f );
DisplayCooldown = 1f;
}
else
{
var cooldown = GetValue( Level, Mod.Cooldown );
if ( _timeSinceDodge > cooldown )
{
Enable();
}
else
{
DisplayCooldown = Utils.Map( _timeSinceDodge, 0f, cooldown, 0f, 1f );
}
}
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.Cooldown:
default:
return 17 - level * 3f;
}
}
void Enable()
{
_isActive = true;
DisplayCooldownColor = new Color( 0.3f, 0.3f, 1f, 0.75f );
DisplayCooldown = 1f;
Player.Modify( this, PlayerStat.DodgeNextAttack, 1f, ModifierType.Add );
//DisplayText = "💨";
HighlightColor = new Color( 0.5f, 0.5f, 1f );
HighlightDuration = 0.3f;
HighlightOpacity = 6f;
Highlight();
}
void Disable()
{
_isActive = false;
DisplayCooldownColor = new Color( 0.7f, 0.7f, 1f, 0.5f );
DisplayCooldown = 0f;
//DisplayText = " ";
Player.StopModifying( this, PlayerStat.DodgeNextAttack );
HighlightColor = new Color( 0.55f, 0.65f, 1f );
HighlightDuration = 0.3f;
HighlightOpacity = 4f;
Highlight();
}
public override void OnDodged( float damage, DamageType damageType, Vector2 dir, Enemy enemySource )
{
base.OnDodged( damage, damageType, dir, enemySource );
if ( !_isActive )
return;
_timeSinceDodge = 0f;
Disable();
}
}