A Thing subclass representing a landmine entity. It initializes collision tags, detects collisions with enemies or players after a short spawn delay, and triggers an explosion that applies damage, repel effects, optional player-safe behavior, perk callbacks, and spawns bullets based on shooter stats.
using System;
using Sandbox;
using Sandbox.Diagnostics;
using Sandbox.UI;
public class Landmine : Thing
{
[Property] public ModelRenderer ModelRenderer { get; set; }
public Player Shooter { get; set; }
public float Damage { get; set; }
private const float EXPLOSION_RADIUS = 80f;
protected override void OnStart()
{
base.OnStart();
if ( IsProxy )
return;
CollideWithTags.Add( "enemy" );
CollideWithTags.Add( "player" );
}
protected override void OnUpdate()
{
base.OnUpdate();
}
public override void Colliding( Thing other, float percent, float dt )
{
base.Colliding( other, percent, dt );
if ( TimeSinceSpawn < 0.5f )
return;
if ( other is Enemy enemy && !enemy.IsInTheAir )
{
Explode();
}
else if ( other is Player player && !player.IsDead && !player.IsInTheAir )
{
Explode();
}
}
public void Explode()
{
Assert.True( !IsProxy );
float radius = EXPLOSION_RADIUS * (Shooter.IsValid() ? Shooter.Stats[PlayerStat.RadiusMultiplier] * Shooter.Stats[PlayerStat.ExplosionSizeMultiplier] : 1f);
float damage = Damage * (Shooter.IsValid() ? Shooter.Stats[PlayerStat.ExplosionDamageMultiplier] : 1f);
var dontHurtPlayers = Shooter.IsValid() && Shooter.GetSyncStat( PlayerStat.LandmineRepelPlayerAmount ) > 0f;
RepelOptions options = RepelOptions.RepelPlayers | RepelOptions.DamagePlayers | RepelOptions.DamageEnemies | RepelOptions.RepelEnemies | RepelOptions.RepelItems;
if( dontHurtPlayers )
options &= ~RepelOptions.DamagePlayers;
var color = dontHurtPlayers ? new Color( 0.7f, 0f, 1f ) : Color.Red;
var force = damage * 20f;
Manager.Instance.CreateExplosionRpc( Position2D, radius, damage, repelRadius: radius * 1.15f, repelForce: force, playerSource: Shooter, enemySource: null, enemyType: EnemyType.None, color, options );
if( dontHurtPlayers )
{
var repelPlayerAmount = force * Shooter.GetSyncStat( PlayerStat.LandmineRepelPlayerAmount );
Manager.Instance.AffectInRadiusHost( Position2D, radius, damage: 0f, repelRadius: radius * 1.15f, repelForce: repelPlayerAmount, playerSource: Shooter, enemySource: null, enemyType: EnemyType.None, DamageType.Aoe, options: RepelOptions.RepelPlayers );
}
if ( Shooter.IsValid() )
{
var perkType = TypeLibrary.GetType( typeof( PerkLandmine ) );
if ( Shooter.HasPerk( perkType ) )
{
var landminePerk = Shooter.GetPerk( perkType ) as PerkLandmine;
if ( landminePerk != null )
landminePerk.LandmineDestroyed();
}
if ( Shooter.Stats[PlayerStat.NumLandmineBulletsPerAmmo] > 0f )
{
int numBullets = (int)Shooter.Stats[PlayerStat.NumLandmineBulletsPerAmmo] * (int)Shooter.Stats[PlayerStat.MaxAmmoCount];
var bullets = Shooter.SpawnBulletRing( Position2D, numBullets, Utils.GetRandomVector(), isFromClip: false, spawnOffset: 10f );
foreach ( var bullet in bullets )
{
bullet.SetupArc( arcHeight: Game.Random.Float( 150f, 200f ), Shooter.Stats[PlayerStat.ArcBulletBounces] );
bullet.Velocity *= Game.Random.Float( 0.3f, 0.55f );
bullet.Stats[BulletStat.Lifetime] *= Game.Random.Float( 1f, 1.4f );
}
}
}
GameObject.Destroy();
}
}