An enemy NPC class MinibossCharger2 that inherits from ChargerElite. It configures miniboss properties (health, scale, coin rewards), movement/charge parameters, visual healthbar settings, and overrides lifecycle hooks OnStart, OnUpdate and OnOutOfBounds to adjust charge behavior and stats.
using System;
using Sandbox;
using static Sandbox.PhysicsContact;
public class MinibossCharger2 : ChargerElite
{
public override EnemyType EnemyType => EnemyType.MinibossCharger2;
public override string GibFolder => "miniboss_charger_2";
public override float OverrideGibChance => 1f;
public override int ExtraDeathBloodSprayAmount => 25;
protected override float MinibossHealthScale => 1.2f;
public override float GetMaxHealth() => MinibossBaseHealth * MinibossHealthScale;
public override Vector3 SpawnScale => new Vector3( 1.65f );
public override bool ShowHealthbar => true;
public override float HealthbarOffset => State == ChargerState.Charge ? 70f : 110f;
public override float HealthbarOpacity => Utils.EasePercent( SpawnProgress, EasingType.QuadIn );
public override float HealthbarArmorOpacity => Utils.EasePercent( SpawnProgress, EasingType.QuadIn );
public override bool IsBoss => true;
public override bool IsMiniboss => true;
public override float ParticleYPosOverride => 0.5f;
public override float StunParticleYPosOverride => 0.75f;
protected override void OnStart()
{
base.OnStart();
CoinValueMin = 10;
CoinValueMax = 20;
CoinChance = 1f;
PushStrength = 12000f;
Weight = _baseWeight = 3f;
_chargeWeight = 5f;
_personalSpeedScale = 1f;
_personalSpeedFreq = Game.Random.Float( 9f, 11f );
if ( IsProxy )
return;
AggroRange = 70f;
DetectTargetRange = 1200f;
LoseTargetRange = 2200f;
LoseTargetTime = 15f;
MeleeDamage = Utils.Select( Manager.Instance.Difficulty, 10f, 14f, 15f );
DamageTargetDelay = 0.8f;
Acceleration = 300f;
AccelerationAttacking = 350f;
Deceleration = 1.5f;
DecelerationAttacking = 1.4f;
_personalTurnSpeed = Game.Random.Float( 5f, 7f );
_personalChargeRange = 650f;
_chargeTimeMin = 50f;
_chargeTimeMax = 60f;
_chargeDelayMin = 1f;
_chargeDelayMax = 3f;
_chargeDelayTimer = Game.Random.Float( _chargeDelayMin, _chargeDelayMax );
_chargeRotateSpeed = 9f;
_redirectDelayMin = 5f;
_redirectDelayMax = 20f;
_chargeVelMax = 250f;
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( IsProxy )
return;
}
protected override void OnOutOfBounds( Direction direction )
{
base.OnOutOfBounds( direction );
_chargeVelMax = Utils.Map( HpPercent, 1f, 0f, 250f, 350f, EasingType.QuadIn );
if ( HasTarget && !IsFearful && Game.Random.Float( 0f, 1f ) < Utils.Map( HpPercent, 1f, 0f, 0.75f, 1f ) )
{
var newDir = ((TargetUnit.Position2D + TargetUnit.Velocity * Game.Random.Float( -0.5f, 4f )) - Position2D).Normal;
_chargeVel = newDir * _chargeVel.Length * 0.4f;
_chargeDir = newDir;
}
}
}