AI/ActionSystem/Actions/Guest/DisposeTrashAction.cs
using HC3.Inventory;
namespace HC3;
public sealed class DisposeTrashAction : AgentAction
{
[Sync( SyncFlags.FromHost )]
private Bin Bin { get; set; }
private Guest Guest => Agent as Guest;
public override float Score()
{
if ( !Guest.IsValid() ) return 0f;
if ( Bin.IsValid() ) return 300f;
bool hasTrash = false;
var items = Guest.Inventory.Items;
for ( int i = 0; i < items.Count; i++ )
{
if ( items[i].GetComponent<Trash>().IsValid() )
{
hasTrash = true;
break;
}
}
if ( !hasTrash ) return 0f;
// Find nearest walkable bin without LINQ allocation
Bin nearest = null;
float nearestDist = float.MaxValue;
foreach ( var b in Scene.GetAll<Bin>() )
{
float dist = b.WorldPosition.DistanceSquared( Agent.WorldPosition );
if ( dist < nearestDist && GridManager.IsWalkable( Agent.WorldPosition, b.WorldPosition ) )
{
nearestDist = dist;
nearest = b;
}
}
Bin = nearest;
return Bin.IsValid() ? 300f : 0f;
}
public override void StartAction()
{
Controller.ClearNavigation();
}
public override Status TickAction()
{
if ( !Bin.IsValid() )
return Status.Failure;
var targetPos = Bin.WorldPosition;
if ( !GridManager.IsWalkable( Agent.WorldPosition, targetPos ) )
{
Bin = null;
return Status.Failure;
}
var flags = NavFlags.Default.WithFlag( NavFlags.Owned, false );
if ( targetPos.Distance( Agent.WorldPosition ) > 64f && !Controller.Navigate( targetPos, flags ) )
return Status.Running;
Guest.Inventory.RemoveAll<Trash>();
var building = Bin.GetComponentInChildren<Building>();
if ( building.IsValid() )
{
building.Uses++;
}
Bin = null;
return Status.Success;
}
public override void StopAction()
{
Bin = null;
}
public override ActionDisplayInfo? GetDisplay()
{
if ( !Bin.IsValid() ) return null;
var dist = Agent.WorldPosition.Distance( Bin.WorldPosition );
var progress = 1f - (dist / 1500f).Clamp( 0f, 1f );
return new ActionDisplayInfo(
"delete",
$"Disposing of Trash",
progress
);
}
}