diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 25d107140..16deb0c75 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -3371,6 +3371,45 @@ std::optional FindNearestTownPortalOnCurrentLevel() return bestPosition; } +struct QuestSetLevelEntrance { + _setlevels questLevel; + Point entrancePosition; + int distance; +}; + +std::optional FindNearestQuestSetLevelEntranceOnCurrentLevel() +{ + if (MyPlayer == nullptr || setlevel) + return std::nullopt; + + const Point playerPosition = MyPlayer->position.future; + std::optional best; + int bestDistance = 0; + + for (const Quest &quest : Quests) { + if (quest._qslvl == SL_NONE) + continue; + if (quest._qactive == QUEST_NOTAVAIL) + continue; + if (quest._qlevel != currlevel) + continue; + if (!InDungeonBounds(quest.position)) + continue; + + const int distance = playerPosition.WalkingDistance(quest.position); + if (!best || distance < bestDistance) { + best = QuestSetLevelEntrance { + .questLevel = quest._qslvl, + .entrancePosition = quest.position, + .distance = distance, + }; + bestDistance = distance; + } + } + + return best; +} + void SpeakNearestExitKeyPressed() { if (!CanPlayerTakeAction()) @@ -3384,6 +3423,28 @@ void SpeakNearestExitKeyPressed() const Point startPosition = MyPlayer->position.future; + const SDL_Keymod modState = SDL_GetModState(); + const bool seekQuestEntrance = (modState & SDL_KMOD_SHIFT) != 0; + + if (seekQuestEntrance) { + if (const std::optional entrance = FindNearestQuestSetLevelEntranceOnCurrentLevel(); entrance) { + const Point targetPosition = entrance->entrancePosition; + const std::optional> path = FindKeyboardWalkPathForSpeech(*MyPlayer, startPosition, targetPosition); + + std::string message { _(QuestLevelNames[entrance->questLevel]) }; + message.append(": "); + if (!path) + AppendDirectionalFallback(message, targetPosition - startPosition); + else + AppendKeyboardWalkPathForSpeech(message, *path); + SpeakText(message, true); + return; + } + + SpeakText(_("No quest entrances found."), true); + return; + } + if (leveltype != DTYPE_TOWN) { if (const std::optional portalPosition = FindNearestTownPortalOnCurrentLevel(); portalPosition) { const std::optional> path = FindKeyboardWalkPathForSpeech(*MyPlayer, startPosition, *portalPosition); @@ -3993,7 +4054,7 @@ void InitKeymapActions() options.Keymapper.AddAction( "SpeakNearestExit", N_("Nearest exit"), - N_("Speaks the nearest exit."), + N_("Speaks the nearest exit. Hold Shift for quest entrances."), 'E', SpeakNearestExitKeyPressed, nullptr, diff --git a/Translations/pl.po b/Translations/pl.po index 941aa8dd4..927c93ffa 100644 --- a/Translations/pl.po +++ b/Translations/pl.po @@ -12030,6 +12030,10 @@ msgstr "Najpierw zamknij mapę." msgid "No exits found." msgstr "Nie znaleziono wyjść." +#: Source/diablo.cpp +msgid "No quest entrances found." +msgstr "Nie znaleziono wejść questowych." + #: Source/diablo.cpp msgid "Not in town." msgstr "Nie jesteś w mieście." @@ -12050,6 +12054,14 @@ msgstr "Najbliższe schody w górę" msgid "Speaks directions to the nearest stairs up." msgstr "Podaje wskazówki dojścia do najbliższych schodów w górę." +#: Source/diablo.cpp +msgid "Nearest exit" +msgstr "Najbliższe wyjście" + +#: Source/diablo.cpp +msgid "Speaks the nearest exit. Hold Shift for quest entrances." +msgstr "Podaje wskazówki dojścia do najbliższego wyjścia. Przytrzymaj Shift, aby namierzyć wejścia questowe." + #: Source/diablo.cpp msgid "Nearest exit: " msgstr "Najbliższe wyjście: "