A unique curse perk named Indecision that automatically rerolls the player's level-up reward after a fixed time. It tracks a countdown while the player is choosing a reward, updates visual cooldown/highlight values, and triggers Player.UseReroll() when the timer exceeds the time limit.
using System;
using Sandbox;
[Perk( Rarity.Unique, curse: true, alwaysOfferDebug: false )]
public class CurseRerollAuto : Perk
{
private enum Mod { TimeLimit };
private RealTimeSince _timeSinceTrigger;
public float TimerProgress { get; private set; }
static CurseRerollAuto()
{
Register<CurseRerollAuto>(
name: "Indecision",
imagePath: "textures/icons/vector/curse_reroll_auto.png",
description: level => $"You automatically reroll after {(int)GetValue( level, Mod.TimeLimit )}s"
);
}
public override void Start()
{
base.Start();
ShouldUpdate = true;
_timeSinceTrigger = 0f;
TimerProgress = 0f;
HighlightColor = new Color( 0.7f, 0.3f, 1f );
HighlightDuration = 0.3f;
HighlightOpacity = 4f;
DisplayCooldownColor = new Color( 0.6f, 0.25f, 0.9f, 0.65f );
}
public override void Refresh()
{
base.Refresh();
}
public override void Update( float dt )
{
base.Update( dt );
if ( Player.IsChoosingLevelUpReward && Player.CanReroll() )
{
TimerProgress = Utils.Map( _timeSinceTrigger, 0f, GetValue( Level, Mod.TimeLimit ), 0f, 1f );
DisplayCooldown = TimerProgress;
DisplayCooldownColor = Color.Lerp(
new Color( 0.5f, 0.2f, 0.85f, 0.6f ),
new Color( 1f, 0.2f, 0.9f, 0.85f ),
TimerProgress
);
if ( _timeSinceTrigger > GetValue( Level, Mod.TimeLimit ) )
{
Player.UseReroll();
_timeSinceTrigger = 0f;
TimerProgress = 0f;
DisplayCooldown = 0f;
Highlight();
IconScale = Game.Random.Float( 1.1f, 1.2f );
IconAngleOffset = Game.Random.Float( 5f, 15f ) * (Game.Random.Int( 0, 1 ) == 0 ? -1f : 1f);
}
}
else
{
TimerProgress = 0f;
DisplayCooldown = 0f;
if ( Player.IsChoosingLevelUpReward )
_timeSinceTrigger = 0f;
}
}
public override void OnChoosePerk( TypeDescription type )
{
base.OnChoosePerk( type );
_timeSinceTrigger = 0f;
}
public override void OnRerollAfter()
{
base.OnRerollAfter();
_timeSinceTrigger = 0f;
}
public override void OnPlayerLevelUp()
{
base.OnPlayerLevelUp();
if ( Player.NumPerkPointsAvailable <= 1 )
_timeSinceTrigger = 0f;
}
public override void OnRevive()
{
base.OnRevive();
_timeSinceTrigger = 0f;
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.TimeLimit:
default:
return 3f;
}
}
}