things/enemies/BarrelMystery.cs

An enemy class BarrelMystery that derives from Barrel. It sets explosion parameters on start and overrides DropLoot to spawn coins and various items with random chances and directions when the barrel is broken, sometimes targeting the player for magnetization or perk items.

Networking
using System;
using Sandbox;
using Sandbox.Diagnostics;

public class BarrelMystery : Barrel
{
	public override EnemyType EnemyType => EnemyType.BarrelMystery;
	public override EnemyType KillStatEnemyType => EnemyType.Barrel;

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

		_explosionRadius = 110f;
		_explosionDamage = 40f;
		_explodeTime = 1f;

		_debrisName = "barrel_exploding_debris";

		if ( IsProxy )
			return;

	}

	protected override void DropLoot( Player player )
	{
		var dropDir = player.IsValid() ? (player.Position2D - Position2D).Normal : Utils.GetRandomVector();

		// COINS
		int numCoins = Game.Random.Int( 1, 3 );
		for ( int i = 0; i < numCoins; i++ )
		{
			var pos = Position2D + Utils.GetRandomVectorInCone( dropDir, coneDegrees: 160f ) * Game.Random.Float( 1f, 3f );
			var dir = (pos - Position2D).Normal;

			var magnetizeChance = player.IsValid() ? player.GetSyncStat( PlayerStat.KillMagnetizeCoinChance ) : 0f;
			Player magnetizePlayer = Game.Random.Float( 0f, 1f ) < magnetizeChance ? player : null;

			Manager.Instance.SpawnCoin( pos, value: Game.Random.Int( 1, 2 ), dir, magnetizePlayer );
		}

		var healthPackChance = 0.95f;
		if ( Game.Random.Float( 0f, 1f ) < healthPackChance )
			Manager.Instance.SpawnItem( "health_pack", Position2D, Utils.GetRandomVectorInCone( dropDir, coneDegrees: 260f ) );

		// MAGNET
		var magnetChance = 0.9f;
		if ( Game.Random.Float( 0f, 1f ) < magnetChance )
		{
			var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
			Manager.Instance.SpawnItem( "magnet", pos, Utils.GetRandomVectorInCone(dropDir, coneDegrees: 260f ) );
		}

		var bombChance = 0.85f;
		if ( Game.Random.Float( 0f, 1f ) < bombChance )
		{
			var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
			Manager.Instance.SpawnItem( "bomb", Position2D, Utils.GetRandomVector() );
		}

		var rerollChance = 0.6f;
		if ( Game.Random.Float( 0f, 1f ) < rerollChance )
		{
			var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
			Manager.Instance.SpawnItem( "reroll_item", Position2D, Utils.GetRandomVectorInCone(dropDir, coneDegrees: 260f ) );
		}

		var banishChance = 0.33f;
		if ( Game.Random.Float( 0f, 1f ) < banishChance )
		{
			var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
			Manager.Instance.SpawnItem( "banish_item", Position2D, Utils.GetRandomVectorInCone(dropDir, coneDegrees: 260f ) );
		}

		var armorChance = 0.66f;
		if ( Game.Random.Float( 0f, 1f ) < armorChance )
		{
			var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
			Manager.Instance.SpawnItem( "armor_item", Position2D, Utils.GetRandomVectorInCone( dropDir, coneDegrees: 260f ) );
		}

		var numDeadPlayers = Manager.Instance.Players.Count - Manager.Instance.AlivePlayers.Count;
		if ( numDeadPlayers > 0 )
		{
			var reviveChance = 0.9f;
			if ( Game.Random.Float( 0f, 1f ) < reviveChance )
			{
				var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
				Manager.Instance.SpawnItem( "revive_soul", Position2D, Utils.GetRandomVectorInCone( dropDir, coneDegrees: 300f ) );
			}
		}

		if ( player.IsValid() )
		{
			var perkChance = 0.33f;
			if ( Game.Random.Float( 0f, 1f ) < perkChance )
			{
				var pos = Position2D + Utils.GetRandomVector() * Game.Random.Float( 1f, 5f );
				player.GiveRandomPerkItemRpc( pos, Utils.GetRandomVectorInCone( dropDir, coneDegrees: 160f ), Rarity.None );
			}
		}
	}
}