A game entity representing a landmine. It handles collision with players and enemies, computes explosion radius and damage based on the shooter stats, triggers an explosion via Manager RPCs, optionally repels players without damaging them, spawns bullets from the shooter perks/stats, and destroys itself.
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();
}
}