Items/Coffin.cs

An inventory pickup component named Coffin. It holds items and ammo counts, auto-destroys after 30 seconds, transfers contained items and ammo to a PlayerInventory when a player enters its trigger, plays a pickup sound via a broadcast RPC, and then destroys itself.

NetworkingFile Access
/// <summary>
/// It's not the coughing you're coughin', it's the coffin they carry you off in
/// </summary>
public sealed class Coffin : BaseInventoryComponent, Component.ITriggerListener
{
	/// <summary>
	/// Sound to play when this coffin is picked up
	/// </summary>
	[Property] public SoundEvent PickupSound { get; set; }

	/// <summary>
	/// How much ammo are we holding on this coffin?
	/// </summary>
	[Sync] public Dictionary<BaseAmmoResource, int> AmmoCounts { get; set; }

	TimeUntil timeUntilDestroy;

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

		timeUntilDestroy = 30;
	}

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

		if ( IsProxy ) return;
		if ( timeUntilDestroy > 0 ) return;

		DestroyGameObject();
	}

	/// <summary>
	/// Called when a gameobject enters the trigger.
	/// </summary>
	void ITriggerListener.OnTriggerEnter( GameObject other )
	{
		if ( IsProxy ) return;
		if ( GameObject.IsDestroyed ) return;

		var player = other.GetComponent<Player>();
		if ( !player.IsValid() )
			return;

		PlayPickupEffects();

		if ( player.Components.TryGet<PlayerInventory>( out var inventory ) )
		{
			foreach ( var item in Items.ToArray() )
			{
				Transfer( item, inventory );
			}

			// A coffin placed in a map by hand never gets its counts filled in.
			foreach ( var pair in AmmoCounts ?? [] )
			{
				if ( pair.Key.IsValid() )
					inventory.GiveAmmo( pair.Key, pair.Value, true );
			}
		}

		DestroyGameObject();
	}

	/// <summary>
	/// Broadcasts a pickup effect for everyone.
	/// </summary>
	[Rpc.Broadcast]
	public void PlayPickupEffects()
	{
		if ( Application.IsDedicatedServer ) return;

		Sound.Play( PickupSound, WorldPosition );
	}
}