2
0
Эх сурвалжийг харах

Business logic of alternative actions

nordsoft 2 жил өмнө
parent
commit
87c47fff1d

+ 38 - 0
client/battle/BattleActionsController.cpp

@@ -759,7 +759,30 @@ void BattleActionsController::activateStack()
 {
 	const CStack * s = owner.stacksController->getActiveStack();
 	if(s)
+	{
 		possibleActions = getPossibleActionsForStack(s);
+		std::list<PossiblePlayerBattleAction> actionsToSelect;
+		if(!possibleActions.empty())
+		{
+			switch(possibleActions.front())
+			{
+				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());
+					break;
+			}
+		}
+		owner.controlPanel->setAlternativeActions(actionsToSelect);
+	}
 }
 
 bool BattleActionsController::spellcastingModeActive() const
@@ -773,3 +796,18 @@ SpellID BattleActionsController::selectedSpell() const
 		return SpellID::NONE;
 	return SpellID(spellToCast->actionSubtype);
 }
+
+const std::vector<PossiblePlayerBattleAction> & BattleActionsController::getPossibleActions() const
+{
+	return possibleActions;
+}
+
+void BattleActionsController::removePossibleAction(PossiblePlayerBattleAction action)
+{
+	vstd::erase(possibleActions, action);
+}
+
+void BattleActionsController::pushFrontPossibleAction(PossiblePlayerBattleAction action)
+{
+	possibleActions.insert(possibleActions.begin(), action);
+}

+ 7 - 0
client/battle/BattleActionsController.h

@@ -92,5 +92,12 @@ public:
 
 	/// returns true if UI is currently in target selection mode
 	bool spellcastingModeActive() const;
+	
+	/// methods to work with array of possible actions, needed to control special creatures abilities
+	const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;
+	void removePossibleAction(PossiblePlayerBattleAction);
+	
+	/// inserts possible action in the beggining in order to prioritize it
+	void pushFrontPossibleAction(PossiblePlayerBattleAction);
 
 };

+ 78 - 3
client/battle/BattleControlPanel.cpp

@@ -19,6 +19,7 @@
 #include "../CPlayerInterface.h"
 #include "../gui/CCursorHandler.h"
 #include "../gui/CGuiHandler.h"
+#include "../gui/CAnimation.h"
 #include "../windows/CSpellWindow.h"
 #include "../widgets/Buttons.h"
 #include "../widgets/Images.h"
@@ -43,14 +44,15 @@ BattleControlPanel::BattleControlPanel(BattleInterface & owner, const Point & po
 	bSpell = std::make_shared<CButton>      (Point(645,  5), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&BattleControlPanel::bSpellf,this), SDLK_c);
 	bWait = std::make_shared<CButton>       (Point(696,  5), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&BattleControlPanel::bWaitf,this), SDLK_w);
 	bDefence = std::make_shared<CButton>    (Point(747,  5), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&BattleControlPanel::bDefencef,this), SDLK_d);
-	bConsoleUp = std::make_shared<CButton>  (Point(624,  5), "ComSlide.def", std::make_pair("", ""),     std::bind(&BattleControlPanel::bConsoleUpf,this), SDLK_UP);
-	bConsoleDown = std::make_shared<CButton>(Point(624, 24), "ComSlide.def", std::make_pair("", ""),     std::bind(&BattleControlPanel::bConsoleDownf,this), SDLK_DOWN);
+	bSwitchAction = std::make_shared<CButton>(Point(589,  5), "icmalt00", CGI->generaltexth->zelp[387], std::bind(&BattleControlPanel::bSwitchActionf,this), SDLK_r);
+	bConsoleUp = std::make_shared<CButton>  (Point(578,  5), "ComSlide.def", std::make_pair("", ""),     std::bind(&BattleControlPanel::bConsoleUpf,this), SDLK_UP);
+	bConsoleDown = std::make_shared<CButton>(Point(578, 24), "ComSlide.def", std::make_pair("", ""),     std::bind(&BattleControlPanel::bConsoleDownf,this), SDLK_DOWN);
 
 	bDefence->assignedKeys.insert(SDLK_SPACE);
 	bConsoleUp->setImageOrder(0, 1, 0, 0);
 	bConsoleDown->setImageOrder(2, 3, 2, 2);
 
-	console = std::make_shared<BattleConsole>(Rect(211, 4, 406,38));
+	console = std::make_shared<BattleConsole>(Rect(211, 4, 350 ,38));
 	GH.statusbar = console;
 
 	if ( owner.tacticsMode )
@@ -174,6 +176,52 @@ void BattleControlPanel::reallySurrender()
 	}
 }
 
+void BattleControlPanel::showAlternativeActionIcon(PossiblePlayerBattleAction action)
+{
+	std::string iconName = "icmalt00";
+	switch(action)
+	{
+		case PossiblePlayerBattleAction::ATTACK:
+			iconName = "icmalt01";
+			break;
+			
+		case PossiblePlayerBattleAction::SHOOT:
+			iconName = "icmalt02";
+			break;
+			
+		case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
+			iconName = "icmalt03";
+			break;
+			
+		//case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
+			//iconName = "icmalt04";
+			//break;
+			
+		case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
+			iconName = "icmalt05";
+			break;
+			
+		case PossiblePlayerBattleAction::WALK_AND_ATTACK:
+			iconName = "icmalt06";
+			break;
+	}
+		
+	auto anim = std::make_shared<CAnimation>(iconName);
+	bSwitchAction->setImage(anim, false);
+}
+
+void BattleControlPanel::setAlternativeActions(const std::list<PossiblePlayerBattleAction> & actions)
+{
+	alternativeActions = actions;
+	defaultAction = PossiblePlayerBattleAction::INVALID;
+	if(alternativeActions.size() > 1)
+		defaultAction = alternativeActions.back();
+	if(!alternativeActions.empty())
+		showAlternativeActionIcon(alternativeActions.front());
+	else
+		showAlternativeActionIcon(defaultAction);
+}
+
 void BattleControlPanel::bAutofightf()
 {
 	if (owner.actionsController->spellcastingModeActive())
@@ -243,6 +291,33 @@ void BattleControlPanel::bSpellf()
 	}
 }
 
+void BattleControlPanel::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())
+	{
+		owner.actionsController->removePossibleAction(alternativeActions.front());
+		showAlternativeActionIcon(defaultAction);
+	}
+	else
+	{
+		owner.actionsController->pushFrontPossibleAction(alternativeActions.front());
+		showAlternativeActionIcon(alternativeActions.front());
+	}
+	
+	alternativeActions.push_back(alternativeActions.front());
+	alternativeActions.pop_front();
+}
+
 void BattleControlPanel::bWaitf()
 {
 	if (owner.actionsController->spellcastingModeActive())

+ 11 - 0
client/battle/BattleControlPanel.h

@@ -10,6 +10,7 @@
 #pragma once
 
 #include "../gui/CIntObject.h"
+#include "../../lib/battle/CBattleInfoCallback.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 class CStack;
@@ -31,6 +32,7 @@ class BattleControlPanel : public CIntObject
 	std::shared_ptr<CButton> bSurrender;
 	std::shared_ptr<CButton> bFlee;
 	std::shared_ptr<CButton> bAutofight;
+	std::shared_ptr<CButton> bSwitchAction;
 	std::shared_ptr<CButton> bSpell;
 	std::shared_ptr<CButton> bWait;
 	std::shared_ptr<CButton> bDefence;
@@ -46,6 +48,7 @@ class BattleControlPanel : public CIntObject
 	void bAutofightf();
 	void bSpellf();
 	void bWaitf();
+	void bSwitchActionf();
 	void bDefencef();
 	void bConsoleUpf();
 	void bConsoleDownf();
@@ -55,6 +58,11 @@ class BattleControlPanel : public CIntObject
 	/// functions for handling actions after they were confirmed by popup window
 	void reallyFlee();
 	void reallySurrender();
+	
+	/// management of alternative actions
+	std::list<PossiblePlayerBattleAction> alternativeActions;
+	PossiblePlayerBattleAction defaultAction;
+	void showAlternativeActionIcon(PossiblePlayerBattleAction);
 
 public:
 	std::shared_ptr<BattleConsole> console;
@@ -70,6 +78,9 @@ public:
 
 	/// Toggle UI to displaying battle log in place of tactics UI
 	void tacticPhaseEnded();
+	
+	/// Set possible alternative options. If more than 1 - the last will be considered as default option
+	void setAlternativeActions(const std::list<PossiblePlayerBattleAction> &);
 
 	BattleControlPanel(BattleInterface & owner, const Point & position);
 };