diff --git a/client/battle/BattleActionsController.cpp b/client/battle/BattleActionsController.cpp index 0228334ec..bd1f3fb99 100644 --- a/client/battle/BattleActionsController.cpp +++ b/client/battle/BattleActionsController.cpp @@ -985,26 +985,23 @@ void BattleActionsController::activateStack() std::list actionsToSelect; if(!possibleActions.empty()) { - switch(possibleActions.front().get()) + auto primaryAction = possibleActions.front().get(); + + if(primaryAction == PossiblePlayerBattleAction::SHOOT || primaryAction == PossiblePlayerBattleAction::AIMED_SPELL_CREATURE + || primaryAction == PossiblePlayerBattleAction::ANY_LOCATION || primaryAction == PossiblePlayerBattleAction::ATTACK_AND_RETURN) { - case PossiblePlayerBattleAction::SHOOT: - actionsToSelect.push_back(possibleActions.front()); - actionsToSelect.push_back(PossiblePlayerBattleAction::ATTACK); - break; - - case PossiblePlayerBattleAction::ATTACK_AND_RETURN: - actionsToSelect.push_back(possibleActions.front()); - actionsToSelect.push_back(PossiblePlayerBattleAction::WALK_AND_ATTACK); - break; - - case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE: - actionsToSelect.push_back(possibleActions.front()); - actionsToSelect.push_back(PossiblePlayerBattleAction::ATTACK); - break; - case PossiblePlayerBattleAction::ANY_LOCATION: - actionsToSelect.push_back(possibleActions.front()); - actionsToSelect.push_back(PossiblePlayerBattleAction::ATTACK); - break; + actionsToSelect.push_back(possibleActions.front()); + + auto shootActionPredicate = [](const PossiblePlayerBattleAction& action) + { + return action.get() == PossiblePlayerBattleAction::SHOOT; + }; + bool hasShootSecondaryAction = std::any_of(possibleActions.begin() + 1, possibleActions.end(), shootActionPredicate); + + if(hasShootSecondaryAction) + actionsToSelect.emplace_back(PossiblePlayerBattleAction::SHOOT); + + actionsToSelect.emplace_back(PossiblePlayerBattleAction::ATTACK); //always allow melee attack as last option } } owner.windowObject->setAlternativeActions(actionsToSelect); @@ -1071,3 +1068,8 @@ void BattleActionsController::pushFrontPossibleAction(PossiblePlayerBattleAction { possibleActions.insert(possibleActions.begin(), action); } + +void BattleActionsController::resetCurrentStackPossibleActions() +{ + possibleActions = getPossibleActionsForStack(owner.stacksController->getActiveStack()); +} diff --git a/client/battle/BattleActionsController.h b/client/battle/BattleActionsController.h index 3c9b35660..a22f86251 100644 --- a/client/battle/BattleActionsController.h +++ b/client/battle/BattleActionsController.h @@ -122,4 +122,7 @@ public: /// inserts possible action in the beggining in order to prioritize it void pushFrontPossibleAction(PossiblePlayerBattleAction); + + /// resets possible actions to original state + void resetCurrentStackPossibleActions(); }; diff --git a/client/battle/BattleWindow.cpp b/client/battle/BattleWindow.cpp index 9f874f59e..5b228d82f 100644 --- a/client/battle/BattleWindow.cpp +++ b/client/battle/BattleWindow.cpp @@ -48,7 +48,7 @@ BattleWindow::BattleWindow(BattleInterface & owner): owner(owner), - defaultAction(PossiblePlayerBattleAction::INVALID) + lastAlternativeAction(PossiblePlayerBattleAction::INVALID) { OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; pos.w = 800; @@ -568,14 +568,18 @@ void BattleWindow::showAlternativeActionIcon(PossiblePlayerBattleAction action) void BattleWindow::setAlternativeActions(const std::list & actions) { + assert(actions.size() != 1); + alternativeActions = actions; - defaultAction = PossiblePlayerBattleAction::INVALID; + lastAlternativeAction = PossiblePlayerBattleAction::INVALID; + if(alternativeActions.size() > 1) - defaultAction = alternativeActions.back(); - if(!alternativeActions.empty()) + { + lastAlternativeAction = alternativeActions.back(); showAlternativeActionIcon(alternativeActions.front()); + } else - showAlternativeActionIcon(defaultAction); + showAlternativeActionIcon(PossiblePlayerBattleAction::INVALID); } void BattleWindow::bAutofightf() @@ -670,23 +674,18 @@ void BattleWindow::bSwitchActionf() { if(alternativeActions.empty()) return; - - if(alternativeActions.front() == defaultAction) - { - alternativeActions.push_back(alternativeActions.front()); - alternativeActions.pop_front(); - } - + auto actions = owner.actionsController->getPossibleActions(); - if(!actions.empty() && actions.front() == alternativeActions.front()) + + if(!actions.empty() && actions.front() != lastAlternativeAction) { owner.actionsController->removePossibleAction(alternativeActions.front()); - showAlternativeActionIcon(defaultAction); + showAlternativeActionIcon(*std::next(alternativeActions.begin())); } else { - owner.actionsController->pushFrontPossibleAction(alternativeActions.front()); - showAlternativeActionIcon(alternativeActions.front()); + owner.actionsController->resetCurrentStackPossibleActions(); + showAlternativeActionIcon(owner.actionsController->getPossibleActions().front()); } alternativeActions.push_back(alternativeActions.front()); diff --git a/client/battle/BattleWindow.h b/client/battle/BattleWindow.h index 5369cca9d..8b6b4f30d 100644 --- a/client/battle/BattleWindow.h +++ b/client/battle/BattleWindow.h @@ -65,7 +65,7 @@ class BattleWindow : public InterfaceObjectConfigurable /// management of alternative actions std::list alternativeActions; - PossiblePlayerBattleAction defaultAction; + PossiblePlayerBattleAction lastAlternativeAction; void showAlternativeActionIcon(PossiblePlayerBattleAction); /// flip battle queue visibility to opposite diff --git a/lib/battle/PossiblePlayerBattleAction.h b/lib/battle/PossiblePlayerBattleAction.h index 401c18d00..402980ded 100644 --- a/lib/battle/PossiblePlayerBattleAction.h +++ b/lib/battle/PossiblePlayerBattleAction.h @@ -74,6 +74,11 @@ public: { return action == other.action && spellToCast == other.spellToCast; } + + bool operator != (const PossiblePlayerBattleAction & other) const + { + return action != other.action || spellToCast != other.spellToCast; + } }; VCMI_LIB_NAMESPACE_END