Park/Buildings/Building.Slots.cs
using System;
namespace HC3;
public partial class Building : ISceneMetadata
{
private SlotMarker[] _cachedSlots;
IReadOnlyList<SlotMarker> AllSlots
{
get
{
_cachedSlots ??= GameObject.GetComponentsInChildren<SlotMarker>().ToArray();
return _cachedSlots;
}
}
/// <summary>
/// Invalidate cached slot list (call when slots change)
/// </summary>
public void InvalidateSlotCache() => _cachedSlots = null;
public virtual void OnLoadedIn( Guest guest ) { }
public virtual void OnUnloaded( Guest guest ) { }
/// <summary>
/// Load in a Guest to the building
/// </summary>
public bool LoadIn( Guest guest )
{
SlotMarker slot = GetFreeSlot();
if ( !slot.IsValid() ) return false;
slot.LoadIn( guest );
OnLoadedIn( guest );
guest.Building = this;
IBuildingEvents.PostToGameObject( GameObject, x => x.OnGuestEnter( guest ) );
return true;
}
/// <summary>
/// Unload a GameObject from this building
/// </summary>
public bool Unload( Guest guest )
{
SlotMarker found = null;
foreach ( var s in AllSlots )
{
if ( s.Contents == guest )
{
found = s;
break;
}
}
if ( !found.IsValid() ) return false;
found.LoadIn( null );
OnUnloaded( guest );
guest.Building = null;
IBuildingEvents.PostToGameObject( GameObject, x => x.OnGuestLeave( guest ) );
return true;
}
/// <summary>
/// Unload everyone
/// </summary>
public void UnloadAll( bool useCompleted )
{
foreach ( var slot in AllSlots )
{
if ( !slot.Contents.IsValid() )
continue;
if ( useCompleted )
{
OnUse( slot.Contents );
}
Unload( slot.Contents );
}
}
/// <summary>
/// Do we have any slots for this building
/// </summary>
public bool HasSlots() => AllSlots.Count != 0;
/// <summary>
/// Do we have any free slots for this building
/// </summary>
public bool HasFreeSlot()
{
if ( AllSlots.Count == 0 ) return true;
foreach ( var s in GetLoadableSlots() )
{
if ( s.IsFree() ) return true;
}
return false;
}
/// <summary>
/// How many slots are occupied in this whole building
/// </summary>
public int GetTotalOccupiedSlots()
{
int count = 0;
foreach ( var s in AllSlots )
{
if ( !s.IsFree() ) count++;
}
return count;
}
/// <summary>
/// How many slots are occupied of the currently loadable
/// </summary>
public int GetOccupiedSlots()
{
int count = 0;
foreach ( var s in GetLoadableSlots() )
{
if ( !s.IsFree() ) count++;
}
return count;
}
/// <summary>
/// Get all guests in this building (NOT the queue)
/// </summary>
public IEnumerable<Guest> GetGuests()
{
foreach ( var s in GetLoadableSlots() )
{
if ( !s.IsFree() )
yield return s.Contents;
}
}
/// <summary>
/// Fetches a free slot
/// </summary>
private SlotMarker GetFreeSlot()
{
// Pick a random free slot without LINQ allocation
SlotMarker pick = null;
int count = 0;
foreach ( var s in GetLoadableSlots() )
{
if ( !s.IsFree() ) continue;
count++;
if ( Random.Shared.Next( count ) == 0 )
pick = s;
}
return pick;
}
/// <summary>
/// Current slots (incl occupied) for loading
/// </summary>
protected virtual IEnumerable<SlotMarker> GetLoadableSlots()
{
return AllSlots;
}
}