Utils/IPlacementObject.cs
using System.Collections;
namespace HC3;
/// <summary>
/// Describes a grouping for a placeable object. It's done in a way that it's more like a tree.
/// </summary>
/// <param name="Groups"></param>
public record struct Group( params string[] Groups ) : IEnumerable<string>
{
public IEnumerator<string> GetEnumerator() => ((IEnumerable<string>)Groups).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public string MainGroup => Groups.FirstOrDefault();
public string SecondaryGroup => Groups.ElementAtOrDefault( 1 );
}
/// <summary>
/// Describes a placeable object, like a building, a decoration
/// </summary>
public interface IPlacementObject : IValid
{
/// <inheritdoc cref="Sandbox.GameObject"/>
GameObject GameObject { get; }
/// <inheritdoc cref="GameObject.WorldPosition"/>
Vector3 WorldPosition { get; set; }
/// <inheritdoc cref="GameObject.WorldRotation"/>
Rotation WorldRotation { get; set; }
/// <summary>
/// Has this item been placed - this seems useless to have in the interface?
/// </summary>
bool IsPlaced { get; set; }
/// <summary>
/// How much does this item cost to purchase?
/// </summary>
public int Cost { get; }
/// <summary>
/// A nice title for the object
/// </summary>
public string Title { get; }
/// <summary>
/// Optional prefab source
/// </summary>
public string PrefabSource { get; }
/// <summary>
/// A thumbnail image
/// </summary>
[Property, ImageAssetPath]
public string Thumbnail { get; }
/// <summary>
/// A grouping for the item
/// </summary>
[Property, InlineEditor]
public Group Group { get; }
/// <summary>
/// We can define tags on items to show up on the top
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetTags() => null;
/// <summary>
/// Sort order
/// </summary>
/// <returns></returns>
int GetOrder() => 0;
/// <summary>
/// Accessor to grab tint component from the object's <see cref="GameObject"/>
/// </summary>
/// <returns></returns>
public TintMaskComponent GetTintComponent()
{
return GameObject
.GetComponentsInChildren<TintMaskComponent>()
.FirstOrDefault();
}
public static IEnumerable<IPlacementObject> GetAllPrefabs()
{
return ResourceLibrary.GetAll<PrefabFile>()
.Where( x => !string.IsNullOrEmpty( x.GetMetadata( "Type", "" ) ) )
.Select( x => GameObject.GetPrefab( x.ResourcePath ) )
.ToList()
.Where( x => x.GetComponent<IPlacementObject>().IsValid() )
.Select( x => x.GetComponent<IPlacementObject>() );
}
public static IEnumerable<IPlacementObject> GetAllPrefabs( string groupName )
{
return GetAllPrefabs()
.Where( x => x.Group.MainGroup.Equals( groupName ) );
}
public static bool CanPurchase( IPlacementObject item )
{
// Can't afford it
if ( ParkManager.Instance?.Money < item.Cost )
return false;
// Needs to be unlocked via goals
if ( item is Building building )
{
var goal = Goal.GetRequiredForBuilding( building );
if ( goal.IsValid() && !goal.IsUnlocked() )
return false;
}
return true;
}
public static string GetPurchaseFailedReason( IPlacementObject item )
{
if ( item is Building building )
{
var goal = Goal.GetRequiredForBuilding( building );
if ( goal.IsValid() && !goal.IsUnlocked() )
return $"You need to complete the goal '{goal.GoalName}' to unlock {item.Title}";
}
if ( ParkManager.Instance?.Money < item.Cost )
return $"You can't afford {item.Title} ({item.Cost} money)";
return null;
}
}