Editor/Platform/ArchPlatformDeck.cs
using System;
using System.Collections.Generic;
using Sandbox;
namespace Sunless.Architecture;
public readonly record struct ArchPlatformHit( ArchBuilding On, ArchPlatformPart Platform, Vector3 World, float Seat );
// Poured on grade, not in building space — compare raw and a column seated on a podium lands a foundation too high.
public static class ArchPlatformDeck {
// Raked or level, in the platform's OWN grade space - which is also world, because nothing lifts it.
public static float Seat( ArchPlatformPart platform, Vector2 at ) => ArchRamp.Deck( platform ).At( at );
// The same surface in the BUILDING's space, for anything that has to weigh it against a floor or a beam.
public static float Seated( ArchPlan plan, ArchBuilding building, ArchKit kit, ArchPlatformPart platform, Vector2 at ) {
return Seat( platform, at ) - ArchAsks.Lift( plan, building, kit );
}
// Nearest deck a downward ray meets — grade correction only on the way out (Seated).
public static bool Struck( ArchPlan plan, ArchKit kit, int level, Ray ray, out ArchPlatformHit hit ) {
hit = default;
if ( plan is null || ray.Forward.z >= -0.001f ) {
return false;
}
var answers = ArchAnswers.Load();
var nearest = float.MaxValue;
foreach ( var building in plan.Buildings ) {
foreach ( var platform in ArchLayerGate.Enabled( building.Platforms ) ) {
if ( platform.Level != level
|| !ArchRamp.Deck( platform ).Crosses( ray, out var reach, out var struck )
|| reach >= nearest
|| !ArchFootprint.Contains( platform.Outline(), new Vector2( struck.x, struck.y ) ) ) {
continue;
}
nearest = reach;
hit = new ArchPlatformHit( building, platform, struck,
struck.z - answers.Lift( plan, building, kit ) );
}
}
return hit.Platform is not null;
}
}