things/enemies/MinibossCharger2.cs

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.

Networking
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;
		}
	}

}