target single-building transfers by hovering, not by footprint coincidence
Coincidence required the ghost's anchor to land exactly on the target's anchor, so on a 2x2 assembler three of its four tiles read as an ordinary overlap and went red: you had to find the top-left tile before the copy gesture would fire. A single-building blueprint now finds its target by hit-testing the cursor instead -- any body tile, any facing -- and its ghost snaps onto the target so it shows what the click will act on. A constellation is unchanged: it is placed as a layout, so its ghosts stay where the blueprint puts them and still need coincidence plus a matching rotation. The old "single-building blueprints ignore target rotation" carve-out is gone, subsumed by hovering. blueprintHoldsOneBuilding becomes std::optional<QPoint> hoverTile, which carries both facts in one parameter: set means "single-building blueprint, cursor here". BlueprintGhostResolved gains ghostAnchor/ghostRotation so the snap comes out of the classifier both callers already share, rather than the renderer working it out separately. Note the shipyard, which I had cited as the motivating case, is not one: its mask needs A cells on asteroid and S cells in space, and the asteroid edge is vertical, so a rotated shipyard can never be placed at all. Rotation was never the real problem here; alignment was. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
@@ -79,14 +79,24 @@ struct BlueprintGhostResolved
|
||||
{
|
||||
BlueprintGhostAction action;
|
||||
std::optional<BuildingId> targetId; // set for CompatibleOverlap and Transfer
|
||||
// Where the ghost belongs on screen. The queried anchor and rotation, except at a
|
||||
// hovered transfer target, where the ghost snaps onto the target so it shows what the
|
||||
// click will act on (REQ-UI-BLUEPRINT-TRANSFER).
|
||||
QPoint ghostAnchor;
|
||||
Rotation ghostRotation;
|
||||
};
|
||||
|
||||
// Classifies one ghost of a blueprint against the current factory state
|
||||
// (REQ-UI-BLUEPRINT-OVERLAP, REQ-UI-BLUEPRINT-TRANSFER). `blueprintHoldsOneBuilding`
|
||||
// only widens the transfer rule to differently-facing targets; a same-facing target
|
||||
// transfers whatever the blueprint's size. It is the blueprint's stored size, counted
|
||||
// before locked types are dropped, so the gesture does not change behavior as the player
|
||||
// unlocks things.
|
||||
// (REQ-UI-BLUEPRINT-OVERLAP, REQ-UI-BLUEPRINT-TRANSFER).
|
||||
//
|
||||
// `hoverTile` is set only for a blueprint holding exactly one building, and is then the
|
||||
// tile under the cursor. That gesture is a copying tool rather than a layout, so it finds
|
||||
// its transfer target by hit-testing the cursor instead of by footprint coincidence --
|
||||
// without which a Shipyard could never be targeted at a different facing, its 4x2
|
||||
// footprint covering entirely different tiles once rotated. Pass nullopt for a
|
||||
// constellation, whose ghosts are judged purely by where the blueprint puts them. The
|
||||
// size is read from the blueprint as stored, before locked types are dropped, so the
|
||||
// gesture does not change behavior as the player unlocks things.
|
||||
//
|
||||
// Shared by the ghost coloring and the click path so a preview cannot disagree with what
|
||||
// the click then does -- the same reason resolveBeltDragPath is shared.
|
||||
@@ -94,7 +104,7 @@ BlueprintGhostResolved resolveBlueprintGhost(const FactoryState& state,
|
||||
const GameConfig& config,
|
||||
BuildingType type, QPoint anchor,
|
||||
Rotation rotation,
|
||||
bool blueprintHoldsOneBuilding);
|
||||
std::optional<QPoint> hoverTile);
|
||||
|
||||
// What a belt drag would do to one tile of its path (REQ-BLD-BELT-DRAG).
|
||||
enum class BeltTileAction
|
||||
|
||||
Reference in New Issue
Block a user