An enemy subclass MinibossRunner derived from Runner that configures stats, behavior parameters, movement/rotation tweaks, spawn visuals and damage handling for a miniboss runner enemy.
using System;
using Sandbox;
public class MinibossRunner : Runner
{
public override EnemyType EnemyType => EnemyType.MinibossRunner;
public override string GibFolder => "miniboss_runner";
public override float OverrideGibChance => 1f;
public override int ExtraDeathBloodSprayAmount => 25;
protected override float MinibossHealthScale => 1.1f;
public override float GetMaxHealth() => MinibossBaseHealth * MinibossHealthScale;
public override Vector3 SpawnScale => new Vector3( 1.4f );
public override bool ShowHealthbar => true;
public override float HealthbarOffset => 105f;
public override float HealthbarOpacity => Utils.EasePercent( SpawnProgress, EasingType.QuadIn ) * (_timeSinceHurt < 1f ? 1f : 0f);
public override float HealthbarArmorOpacity => Utils.EasePercent( SpawnProgress, EasingType.QuadIn ) * (_timeSinceHurt < 1f ? 1f : 0f);
public override bool IsBoss => true;
public override bool IsMiniboss => true;
private TimeSince _timeSinceHurt;
protected override void OnStart()
{
base.OnStart();
CoinValueMin = 10;
CoinValueMax = 18;
CoinChance = 1f;
PushStrength = 8000f;
Weight = 1.4f;
_personalSpeedScale = Game.Random.Float( 1.0f, 1.1f );
_personalSpeedFreq = Game.Random.Float( 14f, 15f );
_timeSinceHurt = 99f;
if ( IsProxy )
return;
AggroRange = 140f;
DetectTargetRange = 900f;
LoseTargetRange = 1500f;
LoseTargetTime = 9f;
MeleeDamage = Utils.Select( Manager.Instance.Difficulty, 6f, 9f, 11f );
DamageTargetDelay = 0.7f;
_personalTurnSpeed = Game.Random.Float( 5f, 8f );
Acceleration = Utils.Select( Manager.Instance.Difficulty, 90f, 105f, 108f );
AccelerationAttacking = Utils.Select( Manager.Instance.Difficulty, 105f, 118f, 122f );
Deceleration = 1.5f;
DecelerationAttacking = 1.4f;
_evadeDelayMin = 0.8f;
_evadeDelayMax = 3.4f;
_evadeDelay = Game.Random.Float( _evadeDelayMin, _evadeDelayMax );
_evadeVelocityMin = 120f;
_evadeVelocityMax = 400f;
_nextJumpDelayMin = 2f;
_nextJumpDelayMax = 9f;
_delayUntilNextJump = Game.Random.Float( _nextJumpDelayMin, _nextJumpDelayMax );
_maxJumpDist = 500f;
_retreatVelocityMin = 150f;
_retreatVelocityMax = 400f;
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( IsProxy )
return;
}
protected override void HandleRotation()
{
base.HandleRotation();
if ( _isRetreating )
WorldRotation = Rotation.Lerp( WorldRotation, Rotation.FromYaw( WorldRotation.Yaw() + Utils.FastSin( TimeSinceSpawn * 0.45f ) * 75f ), _personalTurnSpeed * Time.Delta * TimeScale );
}
protected override Vector2 GetTargetOffset()
{
if ( IsAttacking || _isRetreating )
return Vector2.Zero;
return TargetUnit.Velocity * (0.6f + Utils.FastSin( TimeSinceSpawn * 0.32f ) * 0.5f) * (TargetUnit.Position2D - Position2D).Length * 0.025f
+ new Vector2( Utils.FastSin( TimeSinceSpawn * 0.37f ), Utils.FastSin( TimeSinceSpawn * 0.39f ) ) * (100f + Utils.FastSin( TimeSinceSpawn * 0.85f ) * 250f);
}
protected override void PlayJumpSfx()
{
Manager.Instance.PlaySfxNearby( "jump_whoosh", Position2D, pitch: Game.Random.Float( 1.75f, 1.8f ), volume: 0.4f, maxDist: 320f );
}
protected override void Damage( float damage, Player player, DamageType damageType, Vector3 hitPos, Vector2 force, bool isCrit = false, bool shouldFlinch = true, DamageResultFlags damageFlags = DamageResultFlags.None )
{
base.Damage( damage, player, damageType, hitPos, force, isCrit, shouldFlinch, damageFlags );
_timeSinceHurt = 0f;
if ( IsProxy )
return;
}
protected override void OnMeleePlayer( Player player )
{
base.OnMeleePlayer( player );
FlashRpc( 0.075f, UnitFlashType.PlayerDmg );
}
}