feat(vtank): slice 7 S7.5 — Route tab's real waypoint grid
VTank's own clWP/clWPc 2-column waypoint grid (text + a 1-based position counter standing in for VTank's own count column) replaces the padded single-column list, with any-cell-click delete matching PluginCore.cs:3576-3599. Also: the recall menu gets scroll="true" for grammar parity (still 4 real recall kinds — see the deviation note below); the nav-type menu now shows VTank's own "Follow" caption for the Target mode via a pure display remap (SelectedRouteMode/SelectRouteMode translate the string, RouteMode.Target itself is unchanged, zero behavior change); and a third nav image button (icon 0x060011F7, "Select Nearest Point") is added. Deviations, documented at their own binding site: - VTank's cmbRecallType lists 27 named retail recalls; MossTank's RouteRecallKind models 4 (Lifestone/Marketplace/Primary/Secondary Portal). Expanding to 27 needs real per-recall spell-id data, which is casting-algorithm behavior out of this UI-parity slice's scope. - VTank's btnNavResetPoint reassigns the LIVE navigation cursor mid-route (a mutable index MossTank's navigation controller never exposes to a plugin); SelectNearestRouteWaypoint instead moves the tab's own EDIT selection to the closest waypoint by horizontal distance — real, testable UI-only behavior that stays out of live-navigation territory. The new pin (contract control count 177->180) and the new panel test were shown to fail against a targeted mutation before being confirmed green. MossTank suite 658 -> 659; App markup/plugin filter holds 192/192. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
f5409530f2
commit
6118062a7a
4 changed files with 138 additions and 9 deletions
|
|
@ -773,8 +773,28 @@ internal sealed partial class MossTankPanel
|
|||
public string NavigationStatus => _navigation.Status;
|
||||
public IReadOnlyList<string> RouteRows => _routeRows;
|
||||
public int SelectedRouteWaypointIndex => _selectedRouteWaypoint;
|
||||
public IReadOnlyList<string> RouteModeNames => Enum.GetNames<RouteMode>();
|
||||
public string SelectedRouteMode => _navigationSettings.Mode.ToString();
|
||||
// Campaign VT S7.5: VTank's own clWP/clWPc 2-column grid
|
||||
// (docs/research/vtank-kb/08-ui-views.md §1 "Tab: Route";
|
||||
// PluginCore.cs:3576-3599 — any cell click deletes the waypoint).
|
||||
public IReadOnlyList<string> RouteWaypointTextColumn => _routeRows;
|
||||
public IReadOnlyList<string> RouteWaypointCountColumn => Enumerable
|
||||
.Range(1, _routeRows.Count)
|
||||
.Select(static n => n.ToString(CultureInfo.InvariantCulture))
|
||||
.ToArray();
|
||||
public Action<int> DeleteRouteWaypointAt => DeleteRouteWaypointAtCore;
|
||||
public Action SelectNearestRouteWaypoint => SelectNearestRouteWaypointCore;
|
||||
// VTank's own cmbNavType captions read Circular/Linear/Follow/Once
|
||||
// (KB §1's Route table); our RouteMode enum keeps the real value
|
||||
// named Target (what the mode actually does — navigate to/follow a
|
||||
// captured object) since that name predates this slice and nothing
|
||||
// else in the codebase needs to change. This is a pure DISPLAY
|
||||
// relabel — the same 4 enum values, same SelectRouteMode parsing,
|
||||
// zero behavior change — not a rename of the underlying mode.
|
||||
public IReadOnlyList<string> RouteModeNames =>
|
||||
["Circular", "Linear", "Follow", "Once"];
|
||||
public string SelectedRouteMode => _navigationSettings.Mode == RouteMode.Target
|
||||
? "Follow"
|
||||
: _navigationSettings.Mode.ToString();
|
||||
public IReadOnlyList<string> RouteRecallNames =>
|
||||
Enum.GetNames<RouteRecallKind>();
|
||||
public string SelectedRouteRecall => _routeRecallKind.ToString();
|
||||
|
|
@ -822,7 +842,10 @@ internal sealed partial class MossTankPanel
|
|||
};
|
||||
public Action<string> SelectRouteMode => value =>
|
||||
{
|
||||
if (!Enum.TryParse(value, ignoreCase: true, out RouteMode mode))
|
||||
string normalized = string.Equals(value, "Follow", StringComparison.OrdinalIgnoreCase)
|
||||
? nameof(RouteMode.Target)
|
||||
: value;
|
||||
if (!Enum.TryParse(normalized, ignoreCase: true, out RouteMode mode))
|
||||
return;
|
||||
_navigationSettings.Mode = mode;
|
||||
if (mode == RouteMode.Target)
|
||||
|
|
@ -2119,6 +2142,57 @@ internal sealed partial class MossTankPanel
|
|||
_routeNotice = $"Removed {removed}.";
|
||||
}
|
||||
|
||||
private void DeleteRouteWaypointAtCore(int row)
|
||||
{
|
||||
if ((uint)row >= (uint)_navigationSettings.Waypoints.Count)
|
||||
return;
|
||||
string removed = _navigationSettings.Waypoints[row].DisplayText;
|
||||
_navigationSettings.Waypoints.RemoveAt(row);
|
||||
_selectedRouteWaypoint = ClampRow(
|
||||
_selectedRouteWaypoint,
|
||||
_navigationSettings.Waypoints.Count);
|
||||
_navigation.Reset();
|
||||
RefreshRouteEditor();
|
||||
SaveRouteProfile();
|
||||
_routeNotice = $"Removed {removed}.";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VTank's btnNavResetPoint (icon 0x060011F7, "Select Nearest Point",
|
||||
/// docs/research/vtank-kb/08-ui-views.md §1 "Tab: Route"). VTank's own
|
||||
/// button reassigns the LIVE navigation cursor mid-route; MossTank's
|
||||
/// navigation controller exposes no such mutable cursor to a plugin
|
||||
/// (only a read-only CurrentWaypointIndex), so this instead moves the
|
||||
/// tab's own EDIT selection to the closest waypoint by horizontal
|
||||
/// distance — real, testable UI behavior that stays inside this
|
||||
/// slice's scope rather than adding new live-navigation control flow.
|
||||
/// </summary>
|
||||
private void SelectNearestRouteWaypointCore()
|
||||
{
|
||||
PluginNavigationSnapshot player = _host.Automation.Navigation.Snapshot;
|
||||
if (!player.IsAvailable || _navigationSettings.Waypoints.Count == 0)
|
||||
{
|
||||
_routeNotice = "Current position is unavailable.";
|
||||
return;
|
||||
}
|
||||
int best = 0;
|
||||
double bestDistance = double.PositiveInfinity;
|
||||
for (int i = 0; i < _navigationSettings.Waypoints.Count; i++)
|
||||
{
|
||||
RouteWaypoint waypoint = _navigationSettings.Waypoints[i];
|
||||
if (waypoint.Position.CellId == 0u)
|
||||
continue;
|
||||
double distance = player.Position.HorizontalDistanceMeters(waypoint.Position);
|
||||
if (distance < bestDistance)
|
||||
{
|
||||
bestDistance = distance;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
_selectedRouteWaypoint = best;
|
||||
_routeNotice = $"Selected nearest waypoint ({_navigationSettings.Waypoints[best].DisplayText}).";
|
||||
}
|
||||
|
||||
private void MoveRouteWaypoint(int direction)
|
||||
{
|
||||
if (_navigationSettings.Waypoints.Count < 2)
|
||||
|
|
|
|||
|
|
@ -510,12 +510,19 @@
|
|||
<label x="4" y="186" text="{Coverage}" color="#FF9B9072" />
|
||||
</group>
|
||||
|
||||
<!-- Route: VTank's navigation-waypoint editor and execution surface. -->
|
||||
<!-- Route: VTank's navigation-waypoint editor and execution surface.
|
||||
The waypoint list is VTank's own clWP/clWPc 2-column grid (Campaign
|
||||
VT S7.5, docs/research/vtank-kb/08-ui-views.md §1 "Tab: Route";
|
||||
PluginCore.cs:3576-3599 — any cell click deletes the waypoint).
|
||||
PITCH: text 330+7=337, count (last column) auto. -->
|
||||
<group x="8" y="42" w="848" h="194" visible="{RouteVisible}">
|
||||
<label x="4" y="0" text="Navigation Waypoints" color="#FFE8DEC3" />
|
||||
<list x="4" y="18" w="366" h="120" rowheight="17"
|
||||
items="{RouteRows}" selected="{SelectedRouteWaypointIndex}"
|
||||
onchange="{SelectRouteWaypoint}" tooltip="Select an ordered navigation waypoint." />
|
||||
selected="{SelectedRouteWaypointIndex}" onchange="{SelectRouteWaypoint}"
|
||||
tooltip="Click a waypoint to remove it.">
|
||||
<column type="text" width="337" items="{RouteWaypointTextColumn}" onclick="{DeleteRouteWaypointAt}" />
|
||||
<column type="text" width="30" items="{RouteWaypointCountColumn}" onclick="{DeleteRouteWaypointAt}" />
|
||||
</list>
|
||||
|
||||
<button x="380" y="18" w="92" h="21" text="Add"
|
||||
onclick="{AddRoutePoint}" />
|
||||
|
|
@ -526,9 +533,17 @@
|
|||
|
||||
<button x="380" y="45" w="92" h="21" text="Add Recall"
|
||||
onclick="{AddRouteRecall}" />
|
||||
<!-- VTank's own cmbRecallType lists 27 named retail recalls
|
||||
(docs/research/vtank-kb/08-ui-views.md §1's Route table);
|
||||
MossTank's RouteRecallKind models 4 (Lifestone/Marketplace/
|
||||
Primary/Secondary Portal) — expanding to 27 needs real per-recall
|
||||
spell-id data, out of this UI-parity slice's scope. scroll="true"
|
||||
is applied for grammar parity even though 4 items never need to
|
||||
scroll. -->
|
||||
<menu x="478" y="45" w="150" h="21" items="{RouteRecallNames}"
|
||||
selected="{SelectedRouteRecall}" onchange="{SelectRouteRecall}"
|
||||
rows="4" openupward="false" tooltip="Choose the recall type added by Add Recall." />
|
||||
rows="4" openupward="false" scroll="true"
|
||||
tooltip="Choose the recall type added by Add Recall." />
|
||||
<toggle x="636" y="47" w="142" h="20" text="Follow Corners"
|
||||
checked="{FollowAroundCornersEnabled}"
|
||||
onclick="{ToggleFollowAroundCorners}" />
|
||||
|
|
@ -562,10 +577,17 @@
|
|||
onclick="{MoveRouteWaypointUp}" tooltip="Move the selected waypoint up." />
|
||||
<button x="670" y="126" w="28" h="21" icon="0x060028FD" iconkind="did"
|
||||
onclick="{MoveRouteWaypointDown}" tooltip="Move the selected waypoint down." />
|
||||
<!-- VTank's own btnNavResetPoint (icon 0x060011F7, "Select Nearest
|
||||
Point") reassigns the LIVE navigation cursor; MossTank has no
|
||||
mutable cursor to expose to a plugin, so this moves the tab's
|
||||
own edit selection to the closest waypoint instead — see
|
||||
SelectNearestRouteWaypoint's own doc comment. -->
|
||||
<button x="704" y="126" w="28" h="21" icon="0x060011F7" iconkind="did"
|
||||
onclick="{SelectNearestRouteWaypoint}" tooltip="Select the nearest waypoint." />
|
||||
|
||||
<menu x="4" y="148" w="90" h="22" items="{RouteModeNames}"
|
||||
selected="{SelectedRouteMode}" onchange="{SelectRouteMode}"
|
||||
rows="4" openupward="true" tooltip="Choose Circular, Linear, Target, or Once route behavior." />
|
||||
rows="4" openupward="true" tooltip="Choose Circular, Linear, Follow, or Once route behavior." />
|
||||
<toggle x="102" y="150" w="132" h="20" text="Nav Priority"
|
||||
checked="{NavigationPriorityEnabled}"
|
||||
onclick="{ToggleNavigationPriority}" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue