Browse Source

access: speak monster type

pull/8474/head
mojsior 1 month ago
parent
commit
62be784242
  1. 52
      Source/controls/tracker.cpp
  2. 58
      Source/utils/accessibility_announcements.cpp
  3. 26
      Source/utils/accessibility_announcements.hpp

52
Source/controls/tracker.cpp

@ -557,10 +557,10 @@ template <typename Predicate>
return CollectNearbyObjectTrackerCandidates(playerPosition, maxDistance, IsTrackedMiscInteractableObject);
}
[[nodiscard]] std::vector<TrackerCandidate> CollectNearbyMonsterTrackerCandidates(Point playerPosition, int maxDistance)
{
std::vector<TrackerCandidate> result;
result.reserve(ActiveMonsterCount);
[[nodiscard]] std::vector<TrackerCandidate> CollectNearbyMonsterTrackerCandidates(Point playerPosition, int maxDistance)
{
std::vector<TrackerCandidate> result;
result.reserve(ActiveMonsterCount);
for (size_t i = 0; i < ActiveMonsterCount; ++i) {
const int monsterId = static_cast<int>(ActiveMonsters[i]);
@ -571,15 +571,15 @@ template <typename Predicate>
const int distance = playerPosition.ApproxDistance(monster.position.future);
if (distance > maxDistance)
continue;
result.push_back(TrackerCandidate {
.id = monsterId,
.distance = distance,
.name = monster.name(),
});
}
std::sort(result.begin(), result.end(), IsBetterTrackerCandidate);
result.push_back(TrackerCandidate {
.id = monsterId,
.distance = distance,
.name = MonsterLabelForSpeech(monster),
});
}
std::sort(result.begin(), result.end(), IsBetterTrackerCandidate);
return result;
}
@ -1896,10 +1896,10 @@ void NavigateToTrackerTargetKeyPressed()
}
break;
}
case TrackerTargetCategory::Monsters: {
const std::vector<TrackerCandidate> nearbyCandidates = CollectNearbyMonsterTrackerCandidates(playerPosition, TrackerCycleDistanceTiles);
if (cycleTarget) {
targetId = FindNextTrackerCandidateId(nearbyCandidates, lockedTargetId);
case TrackerTargetCategory::Monsters: {
const std::vector<TrackerCandidate> nearbyCandidates = CollectNearbyMonsterTrackerCandidates(playerPosition, TrackerCycleDistanceTiles);
if (cycleTarget) {
targetId = FindNextTrackerCandidateId(nearbyCandidates, lockedTargetId);
if (!targetId) {
if (nearbyCandidates.empty())
SpeakText(_("No monsters found."), true);
@ -1926,15 +1926,15 @@ void NavigateToTrackerTargetKeyPressed()
return;
}
}
lockedTargetId = *targetId;
const Monster &tracked = Monsters[*targetId];
targetName = tracked.name();
DecorateTrackerTargetNameWithOrdinalIfNeeded(*targetId, targetName, nearbyCandidates);
if (!cycleTarget) {
targetPosition = tracked.position.tile;
}
lockedTargetId = *targetId;
const Monster &tracked = Monsters[*targetId];
targetName = MonsterLabelForSpeech(tracked);
DecorateTrackerTargetNameWithOrdinalIfNeeded(*targetId, targetName, nearbyCandidates);
if (!cycleTarget) {
targetPosition = tracked.position.tile;
}
break;
}
case TrackerTargetCategory::DeadBodies: {

58
Source/utils/accessibility_announcements.cpp

@ -306,11 +306,11 @@ void UpdateBossHealthAnnouncements()
}
}
void UpdateAttackableMonsterAnnouncements()
{
static std::optional<int> LastAttackableMonsterId;
if (MyPlayer == nullptr) {
void UpdateAttackableMonsterAnnouncements()
{
static std::optional<int> LastAttackableMonsterId;
if (MyPlayer == nullptr) {
LastAttackableMonsterId = std::nullopt;
return;
}
@ -372,18 +372,42 @@ void UpdateAttackableMonsterAnnouncements()
if (LastAttackableMonsterId && *LastAttackableMonsterId == *bestId)
return;
LastAttackableMonsterId = *bestId;
const std::string_view name = Monsters[*bestId].name();
if (!name.empty())
SpeakText(name, /*force=*/true);
}
StringOrView DoorLabelForSpeech(const Object &door)
{
if (!door.isDoor())
return door.name();
LastAttackableMonsterId = *bestId;
const StringOrView label = MonsterLabelForSpeech(Monsters[*bestId]);
if (!label.empty())
SpeakText(label.str(), /*force=*/true);
}
StringOrView MonsterLabelForSpeech(const Monster &monster)
{
const std::string_view name = monster.name();
if (name.empty())
return name;
std::string_view type;
switch (monster.data().monsterClass) {
case MonsterClass::Animal:
type = _("Animal");
break;
case MonsterClass::Demon:
type = _("Demon");
break;
case MonsterClass::Undead:
type = _("Undead");
break;
}
if (type.empty())
return name;
return StrCat(name, ", ", type);
}
StringOrView DoorLabelForSpeech(const Object &door)
{
if (!door.isDoor())
return door.name();
// Catacombs doors are grates, so differentiate them for the screen reader / tracker.
if (IsAnyOf(door._otype, _object_id::OBJ_L2LDOOR, _object_id::OBJ_L2RDOOR)) {

26
Source/utils/accessibility_announcements.hpp

@ -8,15 +8,17 @@
#include "utils/string_or_view.hpp"
namespace devilution {
struct Object;
void UpdatePlayerLowHpWarningSound();
void UpdateLowDurabilityWarnings();
void UpdateBossHealthAnnouncements();
void UpdateAttackableMonsterAnnouncements();
StringOrView DoorLabelForSpeech(const Object &door);
void UpdateInteractableDoorAnnouncements();
} // namespace devilution
namespace devilution {
struct Monster;
struct Object;
void UpdatePlayerLowHpWarningSound();
void UpdateLowDurabilityWarnings();
void UpdateBossHealthAnnouncements();
void UpdateAttackableMonsterAnnouncements();
StringOrView MonsterLabelForSpeech(const Monster &monster);
StringOrView DoorLabelForSpeech(const Object &door);
void UpdateInteractableDoorAnnouncements();
} // namespace devilution

Loading…
Cancel
Save