From 84d56b88a03054d35b84dc1ecbd7ad4614f8ac86 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Tue, 24 Jun 2014 22:49:20 +0300
Subject: Add new action for select closest monster without filters and
 sorting.

By default unassigned.
---
 src/actionmanager.cpp     | 21 +++++++++++++--------
 src/actionmanager.h       |  1 +
 src/actormanager.cpp      | 29 +++++++++++++++++++++--------
 src/actormanager.h        | 19 ++++++++++---------
 src/commands.cpp          |  6 +++---
 src/gui/setupactiondata.h |  6 ++++++
 src/gui/viewport.cpp      |  2 +-
 src/input/inputaction.h   |  1 +
 src/input/keyboarddata.h  | 10 +++++++++-
 9 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp
index 5c0bf85fd..876c04700 100644
--- a/src/actionmanager.cpp
+++ b/src/actionmanager.cpp
@@ -402,7 +402,7 @@ impHandler0(heal)
             if (!target || target->getType() != ActorType::PLAYER)
             {
                 target = actorManager->findNearestLivingBeing(
-                    player_node, 10, ActorType::PLAYER);
+                    player_node, 10, ActorType::PLAYER, true);
                 if (target)
                     player_node->setTarget(target);
             }
@@ -1020,7 +1020,7 @@ impHandler0(talk)
         if (!target && actorManager)
         {
             target = actorManager->findNearestLivingBeing(
-                player_node, 1, ActorType::NPC);
+                player_node, 1, ActorType::NPC, true);
             // ignore closest target if distance in each direction more than 1
             if (target)
             {
@@ -1091,7 +1091,7 @@ impHandler0(targetAttack)
         {
             // Only auto target Monsters
             target = actorManager->findNearestLivingBeing(
-                player_node, 90, ActorType::MONSTER);
+                player_node, 90, ActorType::MONSTER, true);
         }
         else
         {
@@ -1104,12 +1104,12 @@ impHandler0(targetAttack)
     return false;
 }
 
-static bool setTarget(const ActorType::Type type)
+static bool setTarget(const ActorType::Type type, const bool allowSort)
 {
     if (actorManager && player_node)
     {
         Being *const target = actorManager->findNearestLivingBeing(
-            player_node, 20, type);
+            player_node, 20, type, allowSort);
 
         if (target && target != player_node->getTarget())
             player_node->setTarget(target);
@@ -1121,17 +1121,22 @@ static bool setTarget(const ActorType::Type type)
 
 impHandler0(targetPlayer)
 {
-    return setTarget(ActorType::PLAYER);
+    return setTarget(ActorType::PLAYER, true);
 }
 
 impHandler0(targetMonster)
 {
-    return setTarget(ActorType::MONSTER);
+    return setTarget(ActorType::MONSTER, true);
+}
+
+impHandler0(targetClosestMonster)
+{
+    return setTarget(ActorType::MONSTER, false);
 }
 
 impHandler0(targetNPC)
 {
-    return setTarget(ActorType::NPC);
+    return setTarget(ActorType::NPC, true);
 }
 
 impHandler0(safeVideoMode)
diff --git a/src/actionmanager.h b/src/actionmanager.h
index 8e11697fc..0286ba3cf 100644
--- a/src/actionmanager.h
+++ b/src/actionmanager.h
@@ -89,6 +89,7 @@ namespace ActionManager
     decHandler(targetAttack);
     decHandler(targetPlayer);
     decHandler(targetMonster);
+    decHandler(targetClosestMonster);
     decHandler(targetNPC);
     decHandler(safeVideoMode);
     decHandler(stopSit);
diff --git a/src/actormanager.cpp b/src/actormanager.cpp
index 36fdf7c93..4e4cf0655 100644
--- a/src/actormanager.cpp
+++ b/src/actormanager.cpp
@@ -833,25 +833,36 @@ Being *ActorManager::findNearestLivingBeing(const int x, const int y,
 {
     const int maxDist = maxTileDist * mapTileSize;
 
-    return findNearestLivingBeing(nullptr, maxDist, type, x, y, excluded);
+    return findNearestLivingBeing(nullptr, maxDist,
+        type,
+        x, y,
+        excluded,
+        true);
 }
 
 Being *ActorManager::findNearestLivingBeing(const Being *const aroundBeing,
                                             const int maxDist,
-                                            const ActorType::Type type) const
+                                            const ActorType::Type type,
+                                            const bool allowSort) const
 {
     if (!aroundBeing)
         return nullptr;
 
-    return findNearestLivingBeing(aroundBeing, maxDist, type,
-        aroundBeing->getTileX(), aroundBeing->getTileY(), aroundBeing);
+    return findNearestLivingBeing(aroundBeing,
+        maxDist,
+        type,
+        aroundBeing->getTileX(),
+        aroundBeing->getTileY(),
+        aroundBeing,
+        allowSort);
 }
 
 Being *ActorManager::findNearestLivingBeing(const Being *const aroundBeing,
                                             int maxDist,
                                             const ActorType::Type &type,
                                             const int x, const int y,
-                                            const Being *const excluded) const
+                                            const Being *const excluded,
+                                            const bool allowSort) const
 {
     if (!aroundBeing || !player_node)
         return nullptr;
@@ -874,11 +885,13 @@ Being *ActorManager::findNearestLivingBeing(const Being *const aroundBeing,
 
     maxDist = maxDist * maxDist;
 
-    const bool cycleSelect = (mCyclePlayers && type == ActorType::PLAYER)
+    const bool cycleSelect = allowSort
+        && ((mCyclePlayers && type == ActorType::PLAYER)
         || (mCycleMonsters && type == ActorType::MONSTER)
-        || (mCycleNPC && type == ActorType::NPC);
+        || (mCycleNPC && type == ActorType::NPC));
 
-    const bool filtered = config.getBoolValue("enableAttackFilter")
+    const bool filtered = allowSort
+        && config.getBoolValue("enableAttackFilter")
         && type == ActorType::MONSTER;
     const bool modActive = inputManager.isActionActive(
         InputAction::STOP_ATTACK);
diff --git a/src/actormanager.h b/src/actormanager.h
index 5c089b377..e30a7011b 100644
--- a/src/actormanager.h
+++ b/src/actormanager.h
@@ -134,10 +134,9 @@ class ActorManager final: public ConfigListener
          */
         Being *findNearestLivingBeing(const int x, const int y,
                                       int maxTileDist,
-                                      const ActorType::Type
-                                      type = ActorType::UNKNOWN,
-                                      const Being *const
-                                      excluded = nullptr) const A_WARN_UNUSED;
+                                      const ActorType::Type type,
+                                      const Being *const excluded)
+                                      const A_WARN_UNUSED;
 
         /**
          * Returns a being nearest to another being.
@@ -149,8 +148,8 @@ class ActorManager final: public ConfigListener
          */
         Being *findNearestLivingBeing(const Being *const aroundBeing,
                                       const int maxTileDist,
-                                      const ActorType::Type
-                                      type = ActorType::UNKNOWN)
+                                      const ActorType::Type type,
+                                      const bool allowSort)
                                       const A_WARN_UNUSED;
 
         /**
@@ -158,7 +157,8 @@ class ActorManager final: public ConfigListener
          */
         Being *findBeingByName(const std::string &name,
                                const ActorType::Type
-                               type = ActorType::UNKNOWN) const A_WARN_UNUSED;
+                               type = ActorType::UNKNOWN)
+                               const A_WARN_UNUSED;
 
        /**
         * Finds a nearest being by name and (optionally) by type.
@@ -320,8 +320,9 @@ class ActorManager final: public ConfigListener
                                       const int maxdist,
                                       const ActorType::Type &type,
                                       const int x, const int y,
-                                      const Being *const
-                                      excluded = nullptr) const A_WARN_UNUSED;
+                                      const Being *const excluded,
+                                      const bool allowSort)
+                                      const A_WARN_UNUSED;
 
         void loadAttackList();
 
diff --git a/src/commands.cpp b/src/commands.cpp
index 6be14ee16..94781aef5 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -677,7 +677,7 @@ impHandler0(attackHuman)
         return;
 
     Being *const target = actorManager->findNearestLivingBeing(
-        player_node, 10, ActorType::PLAYER);
+        player_node, 10, ActorType::PLAYER, true);
     if (target)
     {
         if (player_node->checAttackPermissions(target))
@@ -1523,7 +1523,7 @@ void replaceVars(std::string &str)
         if (!target || target->getType() != ActorType::PLAYER)
         {
             target = actorManager->findNearestLivingBeing(
-                player_node, 20, ActorType::PLAYER);
+                player_node, 20, ActorType::PLAYER, true);
         }
         if (target)
             replaceAll(str, "<PLAYER>", target->getName());
@@ -1536,7 +1536,7 @@ void replaceVars(std::string &str)
         if (!target || target->getType() != ActorType::MONSTER)
         {
             target = actorManager->findNearestLivingBeing(
-                player_node, 20, ActorType::MONSTER);
+                player_node, 20, ActorType::MONSTER, true);
         }
         if (target)
             replaceAll(str, "<MONSTER>", target->getName());
diff --git a/src/gui/setupactiondata.h b/src/gui/setupactiondata.h
index 25d315b49..41fa6e3d9 100644
--- a/src/gui/setupactiondata.h
+++ b/src/gui/setupactiondata.h
@@ -125,6 +125,12 @@ static SetupActionData setupActionData0[] =
         InputAction::TARGET_MONSTER,
         "",
     },
+    {
+        // TRANSLATORS: input action name
+        N_("Target closest monster (without filters)"),
+        InputAction::TARGET_CLOSEST_MONSTER,
+        "",
+    },
     {
         // TRANSLATORS: input action name
         N_("Target NPC"),
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index af199c42e..225b88f30 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -543,7 +543,7 @@ void Viewport::mousePressed(MouseEvent &event)
         if (actorManager)
         {
             Being *const target = actorManager->findNearestLivingBeing(
-                pixelX, pixelY, 20, ActorType::MONSTER);
+                pixelX, pixelY, 20, ActorType::MONSTER, nullptr);
 
             if (target)
                 player_node->setTarget(target);
diff --git a/src/input/inputaction.h b/src/input/inputaction.h
index 68b0b8a1a..2231a89dd 100644
--- a/src/input/inputaction.h
+++ b/src/input/inputaction.h
@@ -340,6 +340,7 @@ namespace InputAction
         GUI_F12,
         WINDOW_ABOUT,
         WINDOW_UPDATER,
+        TARGET_CLOSEST_MONSTER,
         TOTAL
     };
 }  // namespace InputAction
diff --git a/src/input/keyboarddata.h b/src/input/keyboarddata.h
index 779fcd2ac..fb810a683 100644
--- a/src/input/keyboarddata.h
+++ b/src/input/keyboarddata.h
@@ -2208,7 +2208,15 @@ static const KeyData keyData[InputAction::TOTAL] = {
         Input::GRP_DEFAULT | Input::GRP_GUI,
         &ActionManager::updaterWindowShow,
         InputAction::NO_VALUE, 50,
-        InputCondition::GAME}
+        InputCondition::GAME},
+    {"keyTargetClosestMonster",
+        InputType::UNKNOWN, InputAction::NO_VALUE,
+        InputType::UNKNOWN, InputAction::NO_VALUE,
+        Input::GRP_DEFAULT | Input::GRP_REPEAT,
+        &ActionManager::targetClosestMonster,
+        InputAction::NO_VALUE, 50,
+        InputCondition::GAME | InputCondition::NOTARGET
+            | InputCondition::VALIDSPEED}
 };
 
 #endif  // INPUT_KEYBOARDDATA_H
-- 
cgit v1.2.3-70-g09d2