Add WM_DIABTWARPUP to trigger message checks so the tracker's
entrances/exits and stairs categories detect town warps from
Catacombs L1, Caves L1, Hell L1, Hive, and Crypt back to town.
Previously only regular stairs up (WM_DIABPREVLVL) were detected.
TriggerLabelForSpeech already handles WM_DIABTWARPUP and returns
"Warp up", so labeling works automatically.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove the legacy town_npc_nav tracker system which was superseded by
the unified tracker. The old tracker was still firing on PgUp/PgDown
due to hardcoded fallback logic in PressKey().
Changes:
- Remove PgUp/PgDown fallbacks in PressKey() (keep store/chat handling)
- Remove 5 keymapper registrations (ListTownNpcs, PreviousTownNpc,
NextTownNpc, SpeakSelectedTownNpc, GoToSelectedTownNpc)
- Remove UpdateAutoWalkTownNpc() and ResetAutoWalkTownNpc() calls
- Remove migration code references in options.cpp
- Delete town_npc_nav.cpp and town_npc_nav.hpp
- Update CMakeLists.txt
Town NPC tracking is now handled by the unified tracker's NPCs category.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Hold Shift when pressing the health percentage key to hear mana instead.
Extract ComputePercentage helper to deduplicate the HP/mana calculation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Port upstream tracker overhaul into the modular tracker module. Adds
Npcs, Players, DungeonEntrances, Stairs, QuestLocations, and Portals
categories with collector functions, navigation, and auto-walk support.
Replaces CycleTrackerTargetKeyPressed with TrackerPageUp/PageDown/Home
key handlers that support Ctrl for category cycling and Shift for
auto-walk. Includes review fixes: nullopt guard in auto-walk, removal
of default switch clauses in favor of app_fatal, internal linkage for
non-public functions, multi-tile object approach, and distance-sorted
town dungeon entrances.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When MyPlayer is null, the town NPC navigation functions now provide
spoken feedback instead of returning silently, matching the pattern used
in the tracker auto-walk code. RefreshTownNpcOrder also resets
SelectedTownNpc to avoid leaving stale state.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Guard against MyPlayer being nullptr in UpdateAutoWalkTownNpc() to
match the pattern used in UpdateAutoWalkTracker(). Without this,
MyPlayer could be dereferenced if CanPlayerTakeAction() changes its
null-handling behavior in the future.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Guard against MyPlayer being nullptr in IsPlayerDead(),
CycleSpellHotkeys(), RefreshTownNpcOrder(), SpeakSelectedTownNpc(), and
ListTownNpcsKeyPressed() to prevent crashes during early init or after
disconnect. Also reset AutoWalkTrackerTargetId when MyPlayer is null in
the auto-walk tracker to prevent the walk loop from retrying endlessly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The variable is only used within tracker.cpp, so remove the unnecessary
extern declaration from the header and place it in the anonymous
namespace alongside the other file-local tracker state.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix copy-paste comment errors in SpellBookKeyPressed() that referred to
"inventory" instead of "spellbook", and QuestLogKeyPressed() that said
"character quest log" instead of "quest log". Correct a misleading
FindPath comment in town NPC auto-walk, and update a stale SourceX path
reference in diablo.cpp.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move ~4,100 lines of accessibility code from diablo.cpp into 6 new
modules, reducing diablo.cpp from ~7,700 to ~3,660 lines.
New modules:
- controls/accessibility_keys: UI key handlers and guard functions
(IsPlayerDead, IsGameRunning, CanPlayerTakeAction, etc.)
- utils/walk_path_speech: BFS pathfinding, PosOk variants, walk
direction helpers, and path-to-speech formatting
- utils/accessibility_announcements: periodic announcements for low
HP warning sound, durability, boss health, monsters, doors
- controls/town_npc_nav: town NPC selection cycling and auto-walk
- utils/navigation_speech: exit/stairs/portal/unexplored speech and
keyboard walk key handlers
- controls/tracker: target category cycling, candidate finding,
pathfinding navigation, and auto-walk tracker
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove slot tracking when entering/exiting the belt. Now consistently
returns to row 4 column 1 when navigating up from the belt.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Always enter belt at slot 1 when navigating down from inventory
- Return to exact inventory position when navigating up from belt
- Keep left/right navigation within belt area only
- Track last inventory slot before entering belt with SlotBeforeBelt
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix inconsistent keyboard navigation when moving through multi-tile items
in the inventory. Previously, navigating into a large item (e.g., a 3x2 axe)
and then back out would exit from a different row than you entered from.
Changes:
- Add entry point tracking to remember which row/column you entered an item from
- Use tracked entry points when exiting items to maintain navigation consistency
- Add row and column position to accessibility speech (e.g., "Row 1, Column 3: Short Sword")
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CancelAutoWalk() now sends a walk-to-current-position command to
immediately clear the walk path buffer, instead of only preventing new
segments. Move the M key cancellation check above the CanPlayerTakeAction
guard so it works mid-walk. Add CancelAutoWalk() calls to secondary
action (D), spell action (W), and arrow-key walk so all player inputs
properly cancel an in-progress auto-walk.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix OBJ_SIGNCHEST validation mismatch (Chests case now uses
ValidateAutoWalkObjectTarget matching IsTrackedChestObject)
- Add spoken feedback for all silent early returns (bounds checks,
MyPlayer nullptr)
- M key now toggles: press again to cancel in-progress auto-walk
- A/Shift+A cancels auto-walk silently before attacking
- Auto-walk cancels when in-game menu opens
- Extract IsTrackedMonster() predicate (replaces 3 inline checks)
- Remove default: from Monsters switch cases to enable -Wswitch
exhaustiveness checking
- Add defensive re-validation in ResolveObjectTrackerTarget
- Add documentation comments
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These files had mixed CRLF/LF line endings. Normalize to CRLF to
match the .editorconfig convention for C++ source files.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixed an issue with the inventory when using a controller that was making 1x1 items clip to an invalid -1 location when picking them up if they are in the last inventory slot.
Gets rid of `orig_palette`, we now always have only 2 palettes:
1. `logical_palette`
This palette has color cycling / swapping applied but no global
effects such as brightness / fade-in.
2. `system_palette`
This palette is the actual palette used for rendering.
It is usually `logical_palette` with the global brightness setting
and fade-in/out applied.
Additionally, we now keep the k-d tree around and use it to
update single colors.
The colors that are color-cycled / swapped are never included
in the k-d tree, so the tree does not need updating on color
cycles/swaps.
The previous implementation didn't behave quite like A-* is supposed to.
After trying to figure out what's causing it and giving up,
I've reimplemented it in a straightforward manner.
Now it seems to work a lot better.
Also increases maximum player path length to 100 steps.
We still only store the first 25 steps in the save file for vanilla
compatibility.
In C++, globals initialization order accross translation units is not
defined. Accessing a global via a function ensures that it is initialized.
This will be needed for #7638, which will statically initialize change
handlers after the Options object has been initialized.