Selaa lähdekoodia

Add query for dwellings dialog

Ivan Savenko 2 vuotta sitten
vanhempi
sitoutus
39a92cdde3

+ 4 - 1
AI/Nullkiller/AIGateway.cpp

@@ -324,10 +324,13 @@ void AIGateway::heroPrimarySkillChanged(const CGHeroInstance * hero, PrimarySkil
 	NET_EVENT_HANDLER;
 }
 
-void AIGateway::showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level)
+void AIGateway::showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level, QueryID queryID)
 {
 	LOG_TRACE_PARAMS(logAi, "level '%i'", level);
 	NET_EVENT_HANDLER;
+
+	status.addQuery(queryID, "RecruitmentDialog");
+	requestActionASAP([=](){ answerQuery(queryID, 0); });
 }
 
 void AIGateway::heroMovePointsChanged(const CGHeroInstance * hero)

+ 1 - 1
AI/Nullkiller/AIGateway.h

@@ -145,7 +145,7 @@ public:
 	void tileRevealed(const std::unordered_set<int3> & pos) override;
 	void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, PrimarySkill which, si64 val) override;
-	void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) override;
+	void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level, QueryID queryID) override;
 	void heroMovePointsChanged(const CGHeroInstance * hero) override;
 	void garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override;
 	void newObject(const CGObjectInstance * obj) override;

+ 4 - 1
AI/VCAI/VCAI.cpp

@@ -360,10 +360,13 @@ void VCAI::heroPrimarySkillChanged(const CGHeroInstance * hero, PrimarySkill whi
 	NET_EVENT_HANDLER;
 }
 
-void VCAI::showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level)
+void VCAI::showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level, QueryID queryID)
 {
 	LOG_TRACE_PARAMS(logAi, "level '%i'", level);
 	NET_EVENT_HANDLER;
+
+	status.addQuery(queryID, "RecruitmentDialog");
+	requestActionASAP([=](){ answerQuery(queryID, 0); });
 }
 
 void VCAI::heroMovePointsChanged(const CGHeroInstance * hero)

+ 1 - 1
AI/VCAI/VCAI.h

@@ -178,7 +178,7 @@ public:
 	void tileRevealed(const std::unordered_set<int3> & pos) override;
 	void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
 	void heroPrimarySkillChanged(const CGHeroInstance * hero, PrimarySkill which, si64 val) override;
-	void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) override;
+	void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level, QueryID queryID) override;
 	void heroMovePointsChanged(const CGHeroInstance * hero) override;
 	void garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override;
 	void newObject(const CGObjectInstance * obj) override;

+ 7 - 3
client/CPlayerInterface.cpp

@@ -1318,15 +1318,19 @@ void CPlayerInterface::initializeHeroTownList()
 		adventureInt->onHeroChanged(nullptr);
 }
 
-void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level)
+void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level, QueryID queryID)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	waitWhileDialog();
 	auto recruitCb = [=](CreatureID id, int count)
 	{
-		LOCPLINT->cb->recruitCreatures(dwelling, dst, id, count, -1);
+		cb->recruitCreatures(dwelling, dst, id, count, -1);
 	};
-	GH.windows().createAndPushWindow<CRecruitmentWindow>(dwelling, level, dst, recruitCb);
+	auto closeCb = [=]()
+	{
+		cb->selectionMade(0, queryID);
+	};
+	GH.windows().createAndPushWindow<CRecruitmentWindow>(dwelling, level, dst, recruitCb, closeCb);
 }
 
 void CPlayerInterface::waitWhileDialog()

+ 1 - 1
client/CPlayerInterface.h

@@ -117,7 +117,7 @@ protected: // Call-ins from server, should not be called directly, but only via
 	void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
 	void receivedResource() override;
 	void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID) override;
-	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
+	void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level, QueryID queryID) override;
 	void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
 	void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
 	void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;

+ 1 - 2
client/NetPacksClient.cpp

@@ -936,10 +936,9 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
 	case EOpenWindowMode::RECRUITMENT_FIRST:
 	case EOpenWindowMode::RECRUITMENT_ALL:
 		{
-			assert(pack.queryID == QueryID::NONE);
 			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl.getObj(ObjectInstanceID(pack.object)));
 			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl.getObj(ObjectInstanceID(pack.visitor)));
-			callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, pack.window == EOpenWindowMode::RECRUITMENT_FIRST ? 0 : -1);
+			callInterfaceIfPresent(cl, dst->tempOwner, &IGameEventsReceiver::showRecruitmentDialog, dw, dst, pack.window == EOpenWindowMode::RECRUITMENT_FIRST ? 0 : -1, pack.queryID);
 		}
 		break;
 	case EOpenWindowMode::SHIPYARD_WINDOW:

+ 2 - 2
client/windows/CCastleInterface.cpp

@@ -864,7 +864,7 @@ void CCastleBuildings::enterDwelling(int level)
 	{
 		LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level);
 	};
-	GH.windows().createAndPushWindow<CRecruitmentWindow>(town, level, town, recruitCb, -87);
+	GH.windows().createAndPushWindow<CRecruitmentWindow>(town, level, town, recruitCb, nullptr, -87);
 }
 
 void CCastleBuildings::enterToTheQuickRecruitmentWindow()
@@ -1073,7 +1073,7 @@ void CCreaInfo::clickPressed(const Point & cursorPosition)
 	{
 		LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level);
 	};
-	GH.windows().createAndPushWindow<CRecruitmentWindow>(town, level, town, recruitCb, offset);
+	GH.windows().createAndPushWindow<CRecruitmentWindow>(town, level, town, recruitCb, nullptr, offset);
 }
 
 std::string CCreaInfo::genGrowthText()

+ 9 - 1
client/windows/GUIClasses.cpp

@@ -135,6 +135,13 @@ void CRecruitmentWindow::select(std::shared_ptr<CCreatureCard> card)
 	}
 }
 
+void CRecruitmentWindow::close()
+{
+	if (onClose)
+		onClose();
+	CStatusbarWindow::close();
+}
+
 void CRecruitmentWindow::buy()
 {
 	CreatureID crid =  selected->creature->getId();
@@ -192,9 +199,10 @@ void CRecruitmentWindow::showAll(Canvas & to)
 	to.drawBorder(Rect(289, 312, 66, 34) + pos.topLeft(), Colors::METALLIC_GOLD);
 }
 
-CRecruitmentWindow::CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, int y_offset):
+CRecruitmentWindow::CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, const std::function<void()> & onClose, int y_offset):
 	CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPRCRT")),
 	onRecruit(Recruit),
+	onClose(onClose),
 	level(Level),
 	dst(Dst),
 	selected(nullptr),

+ 3 - 1
client/windows/GUIClasses.h

@@ -61,6 +61,7 @@ class CRecruitmentWindow : public CStatusbarWindow
 	};
 
 	std::function<void(CreatureID,int)> onRecruit; //void (int ID, int amount) <-- call to recruit creatures
+	std::function<void()> onClose;
 
 	int level;
 	const CArmedInstance * dst;
@@ -87,8 +88,9 @@ class CRecruitmentWindow : public CStatusbarWindow
 	void showAll(Canvas & to) override;
 public:
 	const CGDwelling * const dwelling;
-	CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, int y_offset = 0);
+	CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function<void(CreatureID,int)> & Recruit, const std::function<void()> & onClose, int y_offset = 0);
 	void availableCreaturesChanged();
+	void close();
 };
 
 /// Split window where creatures can be split up into two single unit stacks

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -105,7 +105,7 @@ public:
 	virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
 	virtual void receivedResource(){};
 	virtual void showInfoDialog(EInfoWindowMode type, const std::string & text, const std::vector<Component> & components, int soundID){};
-	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
+	virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level, QueryID queryID){}
 	virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
 
 	virtual void showPuzzleMap(){};

+ 1 - 1
lib/mapObjects/CGDwelling.cpp

@@ -394,7 +394,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
 		}
 
 		auto windowMode = (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::REFUGEE_CAMP) ? EOpenWindowMode::RECRUITMENT_FIRST : EOpenWindowMode::RECRUITMENT_ALL;
-		cb->showObjectWindow(this, windowMode, h, false);
+		cb->showObjectWindow(this, windowMode, h, true);
 	}
 }
 

+ 10 - 0
server/queries/MapQueries.cpp

@@ -171,6 +171,16 @@ void OpenWindowQuery::onExposure(QueryPtr topQuery)
 
 bool OpenWindowQuery::blocksPack(const CPack *pack) const
 {
+	if (mode == EOpenWindowMode::RECRUITMENT_FIRST || mode == EOpenWindowMode::RECRUITMENT_ALL)
+	{
+		if(dynamic_ptr_cast<RecruitCreatures>(pack) != nullptr)
+			return false;
+
+		// If hero has no free slots, he might get some stacks merged automatically
+		if(dynamic_ptr_cast<ArrangeStacks>(pack) != nullptr)
+			return false;
+	}
+
 	if (mode == EOpenWindowMode::TAVERN_WINDOW)
 	{
 		if(dynamic_ptr_cast<HireHero>(pack) != nullptr)