A unique curse perk that obscures the player screen when the player is hit. It enables an overlay vignette, animates intensity (fade in, hold, fade out) over 5 seconds, updates UI cooldown and display text, and clears the effect on death or removal.
using System;
using Sandbox;
[Perk( Rarity.Unique, curse: true, alwaysOfferDebug: false )]
public class CurseObscureScreen : Perk
{
private const float TOTAL_TIME = 5f;
private const float FADE_IN_TIME = 0.2f;
private const float FADE_OUT_START = 4.5f;
private const float MAX_INTENSITY = 2f;
private TimeSince _timeSinceHurt;
private bool _isActive;
private float _fadeInStartIntensity;
static CurseObscureScreen()
{
Register<CurseObscureScreen>(
name: "Blindness",
imagePath: "textures/icons/vector/curse_obscure_screen.png",
description: level => $"Reduce vision for {TOTAL_TIME}s when hit"
);
}
public override void Start()
{
base.Start();
}
public override void Update( float dt )
{
base.Update( dt );
if ( !_isActive )
return;
var obscure = Manager.Instance.OverlayEffects[OverlayEffectsType.Obscure];
var vignette = obscure.GetComponent<Vignette>();
if ( _timeSinceHurt > TOTAL_TIME )
{
obscure.Enabled = false;
_isActive = false;
ShouldUpdate = false;
DisplayText = " ";
DisplayCooldown = 0f;
}
else
{
float intensity;
if ( _timeSinceHurt < FADE_IN_TIME )
intensity = Utils.Map( _timeSinceHurt, 0f, FADE_IN_TIME, _fadeInStartIntensity, MAX_INTENSITY, EasingType.SineOut );
else if ( _timeSinceHurt < FADE_OUT_START )
intensity = MAX_INTENSITY;
else
intensity = Utils.Map( _timeSinceHurt, FADE_OUT_START, TOTAL_TIME, MAX_INTENSITY, 0f, EasingType.SineIn );
vignette.Intensity = intensity;
DisplayText = $"{MathX.CeilToInt( TOTAL_TIME - _timeSinceHurt )}";
DisplayCooldown = Utils.Map( _timeSinceHurt, 0f, TOTAL_TIME, 1f, 0f );
}
}
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 ( damageType == DamageType.Self )
return;
var obscure = Manager.Instance.OverlayEffects[OverlayEffectsType.Obscure];
var vignette = obscure.GetComponent<Vignette>();
_fadeInStartIntensity = _isActive ? vignette.Intensity : 0f;
obscure.Enabled = true;
_timeSinceHurt = 0f;
_isActive = true;
ShouldUpdate = true;
DisplayCooldown = 1f;
HighlightColor = new Color( 1f, 0f, 0.5f );
HighlightDuration = 0.4f;
HighlightOpacity = 2.5f;
Highlight();
IconScale = Game.Random.Float( 1.1f, 1.2f );
IconAngleOffset = Game.Random.Float( 8f, 12f ) * (Game.Random.Int( 0, 1 ) == 0 ? -1f : 1f);
}
void DisableEffect()
{
Manager.Instance.OverlayEffects[OverlayEffectsType.Obscure].Enabled = false;
_isActive = false;
ShouldUpdate = false;
}
public override void OnDie()
{
base.OnDie();
DisableEffect();
}
public override void Remove( bool restart = false )
{
base.Remove( restart );
DisableEffect();
}
}