things/enemies/RunnerElite.cs

Enemy subclass RunnerElite. It configures health, scale, movement and combat parameters, randomizes some behavior variables, and overrides rotation, targeting offset and jump sound effects.

using System;
using Sandbox;

public class RunnerElite : Runner
{
	public override EnemyType EnemyType => EnemyType.RunnerElite;
	public override float GetMaxHealth()
	{
		switch ( Manager.Instance.Difficulty )
		{
			case 0: default: return 105f;
			case 1: return 120f;
			case 2: return 125f;
		}
	}

	public override Vector3 SpawnScale => new Vector3( 1.4f );

	public override int ExtraDeathBloodSprayAmount => 20;

	protected override void OnStart()
	{
		base.OnStart();

		CoinValueMin = 3;
		CoinValueMax = 4;
		CoinChance = 1f;

		PushStrength = 7000f;
		Weight = 1.4f;

		_personalSpeedScale = Game.Random.Float( 1.0f, 1.1f );
		_personalSpeedFreq = Game.Random.Float( 14f, 15f );

		if ( IsProxy )
			return;

		AggroRange = 140f;
		DetectTargetRange = 700f;
		LoseTargetRange = 1000f;
		LoseTargetTime = 7f;
		MeleeDamage = Utils.Select( Manager.Instance.Difficulty, 7f, 8f, 9f );
		DamageTargetDelay = 0.5f;
		_personalTurnSpeed = Game.Random.Float( 7f, 9f );
		Acceleration = 130f * Utils.Select(Manager.Instance.Difficulty, 0.9f, 1f, 1.13f);
		AccelerationAttacking = 145f * Utils.Select(Manager.Instance.Difficulty, 0.9f, 1f, 1.13f);
		Deceleration = 1.6f;
		DecelerationAttacking = 1.45f;

		_evadeDelayMin = 0.8f;
		_evadeDelayMax = 3.6f;
		_evadeDelay = Game.Random.Float( _evadeDelayMin, _evadeDelayMax );
		_evadeVelocityMin = 120f;
		_evadeVelocityMax = 250f;

		_nextJumpDelayMin = 1f;
		_nextJumpDelayMax = 8f;
		_delayUntilNextJump = Game.Random.Float( _nextJumpDelayMin, _nextJumpDelayMax );
		_maxJumpDist = 450f;

		_retreatVelocityMin = 150f;
		_retreatVelocityMax = 350f;
	}

	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.29f ) * 0.5f) * (TargetUnit.Position2D - Position2D).Length * 0.02f
			+ new Vector2( Utils.FastSin( TimeSinceSpawn * 0.33f ), Utils.FastSin( TimeSinceSpawn * 0.38f ) ) * (100f + Utils.FastSin( TimeSinceSpawn * 0.77f ) * 250f);
	}

	protected override void PlayJumpSfx()
	{
		Manager.Instance.PlaySfxNearby( "jump_whoosh", Position2D, pitch: Game.Random.Float( 1.65f, 1.7f ), volume: 0.4f, maxDist: 300f );
	}
}