Ver Fonte

Fix level-up dialog queries sent too early

Michał Zaremba há 2 meses atrás
pai
commit
ca2ef33b20

+ 1 - 0
AI/Nullkiller2/AIGateway.cpp

@@ -525,6 +525,7 @@ void AIGateway::yourTurn(QueryID queryID)
 	asyncTasks->run([this]()
 	{
 		ScopedThreadName guard("NK2AI::AIGateway::makingTurn");
+		status.waitTillFree();
 		makeTurn();
 	});
 }

+ 0 - 4
server/CGameHandler.cpp

@@ -178,9 +178,7 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
 	else if (hlu.skills.size() > 1)
 	{
 		auto levelUpQuery = std::make_shared<CHeroLevelUpDialogQuery>(this, hlu, hero);
-		hlu.queryID = levelUpQuery->queryID;
 		queries->addQuery(levelUpQuery);
-		sendAndApply(hlu);
 		//level up will be called on query reply
 	}
 }
@@ -322,9 +320,7 @@ void CGameHandler::levelUpCommander(const CCommanderInstance * c)
 	else if (skillAmount > 1) //apply and ask for secondary skill
 	{
 		auto commanderLevelUp = std::make_shared<CCommanderLevelUpDialogQuery>(this, clu, hero);
-		clu.queryID = commanderLevelUp->queryID;
 		queries->addQuery(commanderLevelUp);
-		sendAndApply(clu);
 	}
 }
 

+ 75 - 0
server/queries/MapQueries.cpp

@@ -17,6 +17,7 @@
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/MiscObjects.h"
 #include "../../lib/networkPacks/PacksForServer.h"
+#include "../server/processors/TurnOrderProcessor.h"
 
 TimerPauseQuery::TimerPauseQuery(CGameHandler * owner, PlayerColor player):
 	CQuery(owner)
@@ -217,6 +218,7 @@ CHeroLevelUpDialogQuery::CHeroLevelUpDialogQuery(CGameHandler * owner, const Her
 	CDialogQuery(owner), hero(Hero)
 {
 	hlu = Hlu;
+	hlu.queryID = queryID;
 	addPlayer(hero->tempOwner);
 }
 
@@ -227,6 +229,42 @@ void CHeroLevelUpDialogQuery::onRemoval(PlayerColor color)
 	gh->levelUpHero(hero, hlu.skills[*answer]);
 }
 
+void CHeroLevelUpDialogQuery::onExposure(QueryPtr topQuery)
+{
+	if(prompted || answer)
+	{
+		if(answer)
+			owner->popIfTop(*this);
+		return;
+	}
+
+	for(auto color : players)
+	{
+		if(owner->topQuery(color).get() == this)
+		{
+			prompted = true;
+			gh->sendAndApply(hlu);
+			break;
+		}
+	}
+}
+
+void CHeroLevelUpDialogQuery::onAdded(PlayerColor color)
+{
+	if(prompted || answer)
+		return;
+
+	if(owner->topQuery(color).get() != this)
+		return;
+
+	// Only prompt immediately during active turn processing (when map interface is ready)
+	if(!gh->turnOrder->isPlayerMakingTurn(color))
+		return;
+
+	prompted = true;
+	gh->sendAndApply(hlu);
+}
+
 void CHeroLevelUpDialogQuery::notifyObjectAboutRemoval(const CGObjectInstance * visitedObject, const CGHeroInstance * visitingHero) const
 {
 	visitedObject->heroLevelUpDone(*gh, visitingHero);
@@ -236,6 +274,7 @@ CCommanderLevelUpDialogQuery::CCommanderLevelUpDialogQuery(CGameHandler * owner,
 	CDialogQuery(owner), hero(Hero)
 {
 	clu = Clu;
+	clu.queryID = queryID;
 	addPlayer(hero->tempOwner);
 }
 
@@ -246,6 +285,42 @@ void CCommanderLevelUpDialogQuery::onRemoval(PlayerColor color)
 	gh->levelUpCommander(hero->getCommander(), clu.skills[*answer]);
 }
 
+void CCommanderLevelUpDialogQuery::onExposure(QueryPtr topQuery)
+{
+	if(prompted || answer)
+	{
+		if(answer)
+			owner->popIfTop(*this);
+		return;
+	}
+
+	for(auto color : players)
+	{
+		if(owner->topQuery(color).get() == this)
+		{
+			prompted = true;
+			gh->sendAndApply(clu);
+			break;
+		}
+	}
+}
+
+void CCommanderLevelUpDialogQuery::onAdded(PlayerColor color)
+{
+	if(prompted || answer)
+		return;
+
+	if(owner->topQuery(color).get() != this)
+		return;
+
+	// Only prompt immediately during active turn processing (when map interface is ready)
+	if(!gh->turnOrder->isPlayerMakingTurn(color))
+		return;
+
+	prompted = true;
+	gh->sendAndApply(clu);
+}
+
 void CCommanderLevelUpDialogQuery::notifyObjectAboutRemoval(const CGObjectInstance * visitedObject, const CGHeroInstance * visitingHero) const
 {
 	visitedObject->heroLevelUpDone(*gh, visitingHero);

+ 6 - 0
server/queries/MapQueries.h

@@ -96,10 +96,13 @@ public:
 	CHeroLevelUpDialogQuery(CGameHandler * owner, const HeroLevelUp &Hlu, const CGHeroInstance * Hero);
 
 	void onRemoval(PlayerColor color) override;
+	void onExposure(QueryPtr topQuery) override;
+	void onAdded(PlayerColor color) override;
 	void notifyObjectAboutRemoval(const CGObjectInstance * visitedObject, const CGHeroInstance * visitingHero) const override;
 
 	HeroLevelUp hlu;
 	const CGHeroInstance * hero;
+	bool prompted = false;
 };
 
 class CCommanderLevelUpDialogQuery : public CDialogQuery
@@ -108,8 +111,11 @@ public:
 	CCommanderLevelUpDialogQuery(CGameHandler * owner, const CommanderLevelUp &Clu, const CGHeroInstance * Hero);
 
 	void onRemoval(PlayerColor color) override;
+	void onExposure(QueryPtr topQuery) override;
+	void onAdded(PlayerColor color) override;
 	void notifyObjectAboutRemoval(const CGObjectInstance * visitedObject, const CGHeroInstance * visitingHero) const override;
 
 	CommanderLevelUp clu;
 	const CGHeroInstance * hero;
+	bool prompted = false;
 };