Enemy subclass for a Mushroom enemy. It configures stats, movement-disabled behavior, proximity-triggered explosion logic, visuals and death effects.
using System;
using System.Numerics;
using Sandbox;
public class Mushroom : Enemy
{
public override EnemyType EnemyType => EnemyType.Mushroom;
public override float GetMaxHealth()
{
return 250f;
}
[Property] public Material MushroomExplodeFlashMaterial { get; set; }
public override Vector3 SpawnScale => new Vector3( 4f, 4f, 5f );
public override bool CanHaveTarget => false;
public override bool CanAttack => false;
public override bool CanTurn => false;
public override bool CanBeBackstabbed => false;
public override bool CountsAsKill => false;
public override bool CanMove => false;
public override bool CanBeTargeted => false;
private float _explodeRange;
protected override void OnStart()
{
base.OnStart();
CoinValueMin = 1;
CoinValueMax = 2;
CoinChance = 0.75f;
PushStrength = 16000f;
Weight = 6f;
ExplodeFlashMaterial = MushroomExplodeFlashMaterial;
if ( IsProxy )
return;
Deceleration = 4.5f;
_explodeRange = Game.Random.Float( 60f, 150f );
}
protected override void OnUpdate()
{
base.OnUpdate();
//Gizmo.Draw.Color = Color.White;
//Gizmo.Draw.Text( $"IsExploding: {IsExploding}", new global::Transform( WorldPosition ) );
if ( IsProxy || IsDying || IsSpawning )
return;
Velocity *= Math.Max( 1f - Time.Delta * Deceleration * Manager.Instance.GlobalFrictionModifier, 0f );
WorldPosition += (Vector3)Velocity * Time.Delta;
if( !IsExploding )
{
foreach ( var player in Manager.Instance.AlivePlayers )
{
var dist_sqr = (Position2D - player.Position2D).LengthSquared;
var req_dist_sqr = MathF.Pow( _explodeRange, 2f );
if ( dist_sqr < req_dist_sqr )
{
if( player.IsValid() )
player.OnDisturbMushroom();
// todo: sfx
StartExplodingRpc(
time: Game.Random.Float( 0.5f, 2f),
radius: Game.Random.Float(130f, 200f),
damage: 0f,
player: null
);
break;
}
}
}
}
public override void Explode()
{
Manager.Instance.SpawnRingRpc( Position2D, _explosionRadius, new Color( 0.6f, 0.1f, 1f, 0.8f ), lifetime: Game.Random.Float( 0.2f, 0.3f ), path: "ring_mushroom" );
Manager.Instance.PlaySfxNearbyRpc( "enemy.explode", Position2D, pitch: Game.Random.Float( 2.2f, 2.5f ), volume: 0.8f, maxDist: 750f );
Manager.Instance.AffectInRadius( Position2D, _explosionRadius, damage: 0f, repelRadius: _explosionRadius, repelForce: Game.Random.Float( 750f, 1100f ), options: RepelOptions.RepelPlayers | RepelOptions.RepelEnemies | RepelOptions.RepelItems );
DieRpc( dir: Vector2.Zero, force: 4f, player: _playerWhoKilledUs, damageType: DamageType.Explosion );
}
public override void Flinch( float time, Vector2 dir )
{
base.Flinch( time, dir );
ModelRenderer.LocalRotation = new Angles(Game.Random.Float(-6f, 6f), 0f, Game.Random.Float(-6f, 6f));
}
public override void StopFlinching()
{
base.StopFlinching();
ModelRenderer.LocalRotation = new Angles(0f, 0f, 0f);
}
public override void SetAnim( string name, bool forceRestart = false )
{
return;
}
//protected override void ResetMaterial()
//{
// ModelRenderer.ClearMaterialOverrides();
// ModelRenderer.RenderType = Sandbox.ModelRenderer.ShadowRenderType.On;
//}
protected override void SpawnGibs( Vector2 dir, float force, DamageType damageType )
{
}
}