A mythic perk class 'PerkFearArmor' that grants a temporary melee-damage reduction and scares melee attackers. It tracks activation/cooldown, updates UI display values, applies player stat modifiers while active, and triggers an enemy Fear effect when hit by melee, then starts cooldown.
using System;
using Sandbox;
[Perk( Rarity.Mythic, locked: true, alwaysOfferDebug: false, IncludedCategories = new[] { PerkCategory.Fear })]
public class PerkFearArmor : Perk
{
private enum Mod { Cooldown };
public bool IsActive { get; private set; }
private TimeSince _timeSinceActivate;
// todo: particle to show when it's active
static PerkFearArmor()
{
Register<PerkFearArmor>(
name: "Scary Shield",
imagePath: "textures/icons/vector/fear_armor.png",
description: level => $"[+]-50%[/+] melee dmg taken\nand scare the enemy\n(cooldown: {GetValue( level, Mod.Cooldown ).ToString("0.#")}s)",
upgradeDescription: level => $"[+]-50%[/+] melee dmg taken\nand scare the enemy\n(cooldown: {GetValue( level - 1, Mod.Cooldown ).ToString("0.#")}→{GetValue( level, Mod.Cooldown ).ToString("0.#")}s)"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 0f, 0f, 0f );
HighlightDuration = 0.2f;
HighlightOpacity = 3f;
}
public override void IncreaseLevel()
{
base.IncreaseLevel();
IsActive = true;
}
public override void Refresh()
{
base.Refresh();
Player.Modify( this, PlayerStat.FearOnMeleeCooldownDisplay, GetValue( Level, Mod.Cooldown ), ModifierType.Add );
Player.Modify( this, PlayerStat.FearArmorActive, 1f, ModifierType.Add );
}
public override void Update( float dt )
{
base.Update( dt );
float cooldown = GetValue( Level, Mod.Cooldown );
if ( _timeSinceActivate > cooldown )
{
IsActive = true;
Player.Modify( this, PlayerStat.FearArmorActive, 1f, ModifierType.Add );
ShouldUpdate = false;
DisplayText = " ";
DisplayCooldown = 0f;
}
else
{
DisplayCooldown = Utils.Map( _timeSinceActivate, 0f, cooldown, 1f, 0f );
}
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.Cooldown:
default:
return 5f - 1f * level;
}
}
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 ( !IsActive )
return;
if ( Player.IsDamageTypeMelee( damageType ) && enemySource.IsValid() && !enemySource.IsDying )
{
enemySource.Fear( Player, enemySource: null, lifetime: Player.Stats[PlayerStat.FearLifetime] );
_timeSinceActivate = 0f;
IsActive = false;
Player.StopModifying( this, PlayerStat.FearArmorActive );
ShouldUpdate = true;
DisplayText = "❌";
Highlight();
}
}
}