Right-click move command with unreachable feedback #81

Closed
opened 2026-09-07 20:56:31 +01:00 by liamjd · 1 comment
Owner

Part of milestone #4. Depends on #78 and #80.

Wires selection and movement together. This is the milestone's proof of navigation; the design docs are explicit that direct move orders are not a shipping feature.

Design:

  • With a pawn selected, command_move on the ground calls map.find_path() from the pawn's position to the hit position and hands the result to the view's follow().
  • An empty path means unreachable: flash the pawn red for 2 seconds (tween a material override on the capsule, then clear it) and do not move.
  • Note find_path() snaps both ends through nearest_walkable(), so clicking water walks to the shore. Unreachable therefore means a different landmass or beyond destination_snap_radius, not clicking on water. Keep that behaviour; it is what the snap radius is for.
  • A new command while moving replaces the current path.
  • The order lives in a small controller (a PawnCommandController node, or on Pawns), not in PawnView, so the view never calls find_path() itself. Milestone #5's work loop (#75) will issue the same follow() from the task system.

AC:

  • Select a pawn, right-click reachable ground: the pawn walks there and stops on the tile.
  • Right-click a separate island: the pawn flashes red for 2 seconds and stays put.
  • Right-click while moving: the pawn changes course.
  • Headed check with a screenshot of the red flash.
Part of milestone #4. Depends on #78 and #80. Wires selection and movement together. This is the milestone's proof of navigation; the design docs are explicit that direct move orders are not a shipping feature. Design: - With a pawn selected, `command_move` on the ground calls `map.find_path()` from the pawn's position to the hit position and hands the result to the view's `follow()`. - An empty path means unreachable: flash the pawn red for 2 seconds (tween a material override on the capsule, then clear it) and do not move. - Note `find_path()` snaps both ends through `nearest_walkable()`, so clicking water walks to the shore. Unreachable therefore means a different landmass or beyond `destination_snap_radius`, not clicking on water. Keep that behaviour; it is what the snap radius is for. - A new command while moving replaces the current path. - The order lives in a small controller (a `PawnCommandController` node, or on `Pawns`), not in `PawnView`, so the view never calls `find_path()` itself. Milestone #5's work loop (#75) will issue the same `follow()` from the task system. AC: - Select a pawn, right-click reachable ground: the pawn walks there and stops on the tile. - Right-click a separate island: the pawn flashes red for 2 seconds and stays put. - Right-click while moving: the pawn changes course. - Headed check with a screenshot of the red flash.
Author
Owner

Not doing this. Superseded by #95.

This issue existed to prove navigation works, not to ship a control scheme — its own body said so: "the design docs are explicit that direct move orders are not a shipping feature", and milestone #4 repeats it. Building input arbitration, a selection highlight and a red-flash tween for a mechanic that gets deleted is the wrong trade, especially when the proof can be had more cheaply.

Two things changed since it was filed:

  1. #80's probe (tools/probe_pawn_terrace.gd) settled the part that was actually in doubt. A pawn rides terraces rather than cutting through them, on the descent as well as the climb, and A* routes over a one-level riser. That was the risk; it is now evidence rather than assumption.
  2. What the probe leaves untested is above PawnView, not inside it — Pawns.move_to(), the real frame loop, generated terrain, several pawns at once. A debug scatter command (#95) covers all of that without a selection system or a fake mechanic.

Knock-on effects, recorded so they are not a surprise:

  • #82 now depends on #95 rather than this issue; it needs something to make pawns move, and scatter does that sooner.
  • #78 stays open but is no longer a navigation blocker. Its real value is pawn selection for inspection, plus extracting the raycast out of PlacementController. It can land whenever clicking a pawn to see its state becomes useful.
  • Unreachable feedback is dropped entirely. Pawns.move_to() already returns false and the empty-path branch has unit coverage; a 2-second red flash is UI for a mechanic that is not shipping. If a real need appears — most likely via #83, where a placed building cuts an in-flight path — it should be designed then, against that case rather than this one.

Milestone #4's body has been updated to match.

Not doing this. Superseded by #95. This issue existed to prove navigation works, not to ship a control scheme — its own body said so: *"the design docs are explicit that direct move orders are not a shipping feature"*, and milestone #4 repeats it. Building input arbitration, a selection highlight and a red-flash tween for a mechanic that gets deleted is the wrong trade, especially when the proof can be had more cheaply. Two things changed since it was filed: 1. **#80's probe (`tools/probe_pawn_terrace.gd`) settled the part that was actually in doubt.** A pawn rides terraces rather than cutting through them, on the descent as well as the climb, and A* routes over a one-level riser. That was the risk; it is now evidence rather than assumption. 2. **What the probe leaves untested is above `PawnView`, not inside it** — `Pawns.move_to()`, the real frame loop, generated terrain, several pawns at once. A debug scatter command (#95) covers all of that without a selection system or a fake mechanic. Knock-on effects, recorded so they are not a surprise: - **#82** now depends on #95 rather than this issue; it needs something to make pawns move, and scatter does that sooner. - **#78** stays open but is no longer a navigation blocker. Its real value is pawn selection for inspection, plus extracting the raycast out of `PlacementController`. It can land whenever clicking a pawn to see its state becomes useful. - **Unreachable feedback is dropped entirely.** `Pawns.move_to()` already returns `false` and the empty-path branch has unit coverage; a 2-second red flash is UI for a mechanic that is not shipping. If a real need appears — most likely via #83, where a placed building cuts an in-flight path — it should be designed then, against that case rather than this one. Milestone #4's body has been updated to match.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
liamjd/UntitledColonyBuilder#81
No description provided.