1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Added Query to track visit duration for Taverns and Markets

This commit is contained in:
Ivan Savenko 2023-09-28 01:17:05 +03:00
parent e322d0a084
commit 898733eed7
27 changed files with 230 additions and 113 deletions

View File

@ -154,10 +154,13 @@ void AIGateway::artifactAssembled(const ArtifactLocation & al)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void AIGateway::showTavernWindow(const CGObjectInstance * townOrTavern) void AIGateway::showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.addQuery(queryID, "TavernWindow");
requestActionASAP([=](){ answerQuery(queryID, 0); });
} }
void AIGateway::showThievesGuildWindow(const CGObjectInstance * obj) void AIGateway::showThievesGuildWindow(const CGObjectInstance * obj)
@ -425,10 +428,13 @@ void AIGateway::receivedResource()
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void AIGateway::showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) void AIGateway::showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.addQuery(queryID, "UniversityWindow");
requestActionASAP([=](){ answerQuery(queryID, 0); });
} }
void AIGateway::heroManaPointsChanged(const CGHeroInstance * hero) void AIGateway::heroManaPointsChanged(const CGHeroInstance * hero)
@ -498,10 +504,13 @@ void AIGateway::heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonu
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void AIGateway::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) void AIGateway::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.addQuery(queryID, "MarketWindow");
requestActionASAP([=](){ answerQuery(queryID, 0); });
} }
void AIGateway::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) void AIGateway::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain)

View File

@ -130,7 +130,7 @@ public:
void tileHidden(const std::unordered_set<int3> & pos) override; void tileHidden(const std::unordered_set<int3> & pos) override;
void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override; void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override;
void artifactAssembled(const ArtifactLocation & al) override; void artifactAssembled(const ArtifactLocation & al) override;
void showTavernWindow(const CGObjectInstance * townOrTavern) override; void showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID) override;
void showThievesGuildWindow(const CGObjectInstance * obj) override; void showThievesGuildWindow(const CGObjectInstance * obj) override;
void playerBlocked(int reason, bool start) override; void playerBlocked(int reason, bool start) override;
void showPuzzleMap() override; void showPuzzleMap() override;
@ -157,7 +157,7 @@ public:
void requestRealized(PackageApplied * pa) override; void requestRealized(PackageApplied * pa) override;
void receivedResource() override; void receivedResource() override;
void objectRemoved(const CGObjectInstance * obj, const PlayerColor & initiator) override; void objectRemoved(const CGObjectInstance * obj, const PlayerColor & initiator) override;
void showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) override; void showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
void heroManaPointsChanged(const CGHeroInstance * hero) override; void heroManaPointsChanged(const CGHeroInstance * hero) override;
void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override; void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
void battleResultsApplied() override; void battleResultsApplied() override;
@ -165,7 +165,7 @@ public:
void objectPropertyChanged(const SetObjectProperty * sop) override; void objectPropertyChanged(const SetObjectProperty * sop) override;
void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override; void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override; void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override; void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override; void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override; std::optional<BattleAction> makeSurrenderRetreatDecision(const BattleID & battleID, const BattleStateInfoForRetreat & battleState) override;

View File

@ -165,10 +165,13 @@ void VCAI::artifactAssembled(const ArtifactLocation & al)
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void VCAI::showTavernWindow(const CGObjectInstance * townOrTavern) void VCAI::showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.addQuery(queryID, "TavernWindow");
requestActionASAP([=](){ answerQuery(queryID, 0); });
} }
void VCAI::showThievesGuildWindow(const CGObjectInstance * obj) void VCAI::showThievesGuildWindow(const CGObjectInstance * obj)
@ -512,10 +515,13 @@ void VCAI::receivedResource()
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void VCAI::showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) void VCAI::showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.addQuery(queryID, "UniversityWindow");
requestActionASAP([=](){ answerQuery(queryID, 0); });
} }
void VCAI::heroManaPointsChanged(const CGHeroInstance * hero) void VCAI::heroManaPointsChanged(const CGHeroInstance * hero)
@ -577,10 +583,13 @@ void VCAI::heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bo
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
} }
void VCAI::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) void VCAI::showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
status.addQuery(queryID, "MarketWindow");
requestActionASAP([=](){ answerQuery(queryID, 0); });
} }
void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain)

View File

@ -163,7 +163,7 @@ public:
void tileHidden(const std::unordered_set<int3> & pos) override; void tileHidden(const std::unordered_set<int3> & pos) override;
void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override; void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override;
void artifactAssembled(const ArtifactLocation & al) override; void artifactAssembled(const ArtifactLocation & al) override;
void showTavernWindow(const CGObjectInstance * townOrTavern) override; void showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID) override;
void showThievesGuildWindow(const CGObjectInstance * obj) override; void showThievesGuildWindow(const CGObjectInstance * obj) override;
void playerBlocked(int reason, bool start) override; void playerBlocked(int reason, bool start) override;
void showPuzzleMap() override; void showPuzzleMap() override;
@ -190,7 +190,7 @@ public:
void requestRealized(PackageApplied * pa) override; void requestRealized(PackageApplied * pa) override;
void receivedResource() override; void receivedResource() override;
void objectRemoved(const CGObjectInstance * obj, const PlayerColor & initiator) override; void objectRemoved(const CGObjectInstance * obj, const PlayerColor & initiator) override;
void showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) override; void showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
void heroManaPointsChanged(const CGHeroInstance * hero) override; void heroManaPointsChanged(const CGHeroInstance * hero) override;
void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override; void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
void battleResultsApplied() override; void battleResultsApplied() override;
@ -198,7 +198,7 @@ public:
void objectPropertyChanged(const SetObjectProperty * sop) override; void objectPropertyChanged(const SetObjectProperty * sop) override;
void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override; void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override; void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override; void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor, QueryID queryID) override;
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override; void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain) override;
void battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override; void battleStart(const BattleID & battleID, const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side, bool replayAllowed) override;

View File

@ -1621,24 +1621,30 @@ void CPlayerInterface::battleNewRoundFirst(const BattleID & battleID)
battleInt->newRoundFirst(); battleInt->newRoundFirst();
} }
void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) void CPlayerInterface::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
auto onWindowClosed = [this, queryID](){
cb->selectionMade(0, queryID);
};
if(market->allowsTrade(EMarketMode::ARTIFACT_EXP) && visitor->getAlignment() != EAlignment::EVIL) if(market->allowsTrade(EMarketMode::ARTIFACT_EXP) && visitor->getAlignment() != EAlignment::EVIL)
GH.windows().createAndPushWindow<CAltarWindow>(market, visitor, EMarketMode::ARTIFACT_EXP); GH.windows().createAndPushWindow<CAltarWindow>(market, visitor, onWindowClosed, EMarketMode::ARTIFACT_EXP);
else if(market->allowsTrade(EMarketMode::CREATURE_EXP) && visitor->getAlignment() != EAlignment::GOOD) else if(market->allowsTrade(EMarketMode::CREATURE_EXP) && visitor->getAlignment() != EAlignment::GOOD)
GH.windows().createAndPushWindow<CAltarWindow>(market, visitor, EMarketMode::CREATURE_EXP); GH.windows().createAndPushWindow<CAltarWindow>(market, visitor, onWindowClosed, EMarketMode::CREATURE_EXP);
else if(market->allowsTrade(EMarketMode::CREATURE_UNDEAD)) else if(market->allowsTrade(EMarketMode::CREATURE_UNDEAD))
GH.windows().createAndPushWindow<CTransformerWindow>(market, visitor); GH.windows().createAndPushWindow<CTransformerWindow>(market, visitor, onWindowClosed);
else if(!market->availableModes().empty()) else if(!market->availableModes().empty())
GH.windows().createAndPushWindow<CMarketplaceWindow>(market, visitor, market->availableModes().front()); GH.windows().createAndPushWindow<CMarketplaceWindow>(market, visitor, onWindowClosed, market->availableModes().front());
} }
void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
GH.windows().createAndPushWindow<CUniversityWindow>(visitor, market); auto onWindowClosed = [this, queryID](){
cb->selectionMade(0, queryID);
};
GH.windows().createAndPushWindow<CUniversityWindow>(visitor, market, onWindowClosed);
} }
void CPlayerInterface::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) void CPlayerInterface::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor)
@ -1654,10 +1660,13 @@ void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket * bm)
cmw->artifactsChanged(false); cmw->artifactsChanged(false);
} }
void CPlayerInterface::showTavernWindow(const CGObjectInstance *townOrTavern) void CPlayerInterface::showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
GH.windows().createAndPushWindow<CTavernWindow>(townOrTavern); auto onWindowClosed = [this, queryID](){
cb->selectionMade(0, queryID);
};
GH.windows().createAndPushWindow<CTavernWindow>(object, onWindowClosed);
} }
void CPlayerInterface::showThievesGuildWindow (const CGObjectInstance * obj) void CPlayerInterface::showThievesGuildWindow (const CGObjectInstance * obj)

View File

@ -122,8 +122,8 @@ protected: // Call-ins from server, should not be called directly, but only via
void showTeleportDialog(const CGHeroInstance * hero, TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override; 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; void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override; void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override; void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID) override;
void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override; void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID) override;
void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override; void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override; //called when a hero casts a spell void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID) override; //called when a hero casts a spell
void tileHidden(const std::unordered_set<int3> &pos) override; //called when given tiles become hidden under fog of war void tileHidden(const std::unordered_set<int3> &pos) override; //called when given tiles become hidden under fog of war
@ -179,7 +179,7 @@ public: // public interface for use by client via LOCPLINT access
void viewWorldMap() override; void viewWorldMap() override;
void showQuestLog() override; void showQuestLog() override;
void showThievesGuildWindow (const CGObjectInstance * obj) override; void showThievesGuildWindow (const CGObjectInstance * obj) override;
void showTavernWindow(const CGObjectInstance *townOrTavern) override; void showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID) override;
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard; void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2); void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2);

View File

@ -170,7 +170,7 @@ public:
void showBlockingDialog(BlockingDialog * iw) override {}; void showBlockingDialog(BlockingDialog * iw) override {};
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {}; void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override {};
void showTeleportDialog(TeleportDialog * iw) override {}; void showTeleportDialog(TeleportDialog * iw) override {};
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) override {}; void showObjectWindow(const CGObjectInstance * object, EOpenWindowMode window, const CGHeroInstance * visitor, bool addQuery) override {};
void giveResource(PlayerColor player, GameResID which, int val) override {}; void giveResource(PlayerColor player, GameResID which, int val) override {};
virtual void giveResources(PlayerColor player, TResources resources) override {}; virtual void giveResources(PlayerColor player, TResources resources) override {};

View File

@ -936,58 +936,67 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
case EOpenWindowMode::RECRUITMENT_FIRST: case EOpenWindowMode::RECRUITMENT_FIRST:
case EOpenWindowMode::RECRUITMENT_ALL: case EOpenWindowMode::RECRUITMENT_ALL:
{ {
const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl.getObj(ObjectInstanceID(pack.id1))); assert(pack.queryID == QueryID::NONE);
const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl.getObj(ObjectInstanceID(pack.id2))); 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);
} }
break; break;
case EOpenWindowMode::SHIPYARD_WINDOW: case EOpenWindowMode::SHIPYARD_WINDOW:
{ {
const IShipyard *sy = IShipyard::castFrom(cl.getObj(ObjectInstanceID(pack.id1))); assert(pack.queryID == QueryID::NONE);
const IShipyard *sy = IShipyard::castFrom(cl.getObj(ObjectInstanceID(pack.object)));
callInterfaceIfPresent(cl, sy->getObject()->getOwner(), &IGameEventsReceiver::showShipyardDialog, sy); callInterfaceIfPresent(cl, sy->getObject()->getOwner(), &IGameEventsReceiver::showShipyardDialog, sy);
} }
break; break;
case EOpenWindowMode::THIEVES_GUILD: case EOpenWindowMode::THIEVES_GUILD:
{ {
assert(pack.queryID == QueryID::NONE);
//displays Thieves' Guild window (when hero enters Den of Thieves) //displays Thieves' Guild window (when hero enters Den of Thieves)
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id2)); const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
callInterfaceIfPresent(cl, PlayerColor(pack.id1), &IGameEventsReceiver::showThievesGuildWindow, obj); const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
callInterfaceIfPresent(cl, hero->getOwner(), &IGameEventsReceiver::showThievesGuildWindow, obj);
} }
break; break;
case EOpenWindowMode::UNIVERSITY_WINDOW: case EOpenWindowMode::UNIVERSITY_WINDOW:
{ {
//displays University window (when hero enters University on adventure map) //displays University window (when hero enters University on adventure map)
const IMarket *market = IMarket::castFrom(cl.getObj(ObjectInstanceID(pack.id1))); const IMarket *market = IMarket::castFrom(cl.getObj(ObjectInstanceID(pack.object)));
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.id2)); const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero); callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showUniversityWindow, market, hero, pack.queryID);
} }
break; break;
case EOpenWindowMode::MARKET_WINDOW: case EOpenWindowMode::MARKET_WINDOW:
{ {
//displays Thieves' Guild window (when hero enters Den of Thieves) //displays Thieves' Guild window (when hero enters Den of Thieves)
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id1)); const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.id2)); const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
const IMarket *market = IMarket::castFrom(obj); const IMarket *market = IMarket::castFrom(obj);
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero); callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showMarketWindow, market, hero, pack.queryID);
} }
break; break;
case EOpenWindowMode::HILL_FORT_WINDOW: case EOpenWindowMode::HILL_FORT_WINDOW:
{ {
assert(pack.queryID == QueryID::NONE);
//displays Hill fort window //displays Hill fort window
const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.id1)); const CGObjectInstance *obj = cl.getObj(ObjectInstanceID(pack.object));
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.id2)); const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showHillFortWindow, obj, hero); callInterfaceIfPresent(cl, cl.getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::showHillFortWindow, obj, hero);
} }
break; break;
case EOpenWindowMode::PUZZLE_MAP: case EOpenWindowMode::PUZZLE_MAP:
{ {
callInterfaceIfPresent(cl, PlayerColor(pack.id1), &IGameEventsReceiver::showPuzzleMap); assert(pack.queryID == QueryID::NONE);
const CGHeroInstance *hero = cl.getHero(ObjectInstanceID(pack.visitor));
callInterfaceIfPresent(cl, hero->getOwner(), &IGameEventsReceiver::showPuzzleMap);
} }
break; break;
case EOpenWindowMode::TAVERN_WINDOW: case EOpenWindowMode::TAVERN_WINDOW:
const CGObjectInstance *obj1 = cl.getObj(ObjectInstanceID(pack.id1)), {
*obj2 = cl.getObj(ObjectInstanceID(pack.id2)); const CGObjectInstance *obj1 = cl.getObj(ObjectInstanceID(pack.object));
callInterfaceIfPresent(cl, obj1->tempOwner, &IGameEventsReceiver::showTavernWindow, obj2); const CGHeroInstance * hero = cl.getHero(ObjectInstanceID(pack.visitor));
callInterfaceIfPresent(cl, hero->tempOwner, &IGameEventsReceiver::showTavernWindow, obj1, hero, pack.queryID);
}
break; break;
} }
} }

View File

@ -342,7 +342,7 @@ void AdventureMapShortcuts::showMarketplace()
} }
if(townWithMarket) //if any town has marketplace, open window if(townWithMarket) //if any town has marketplace, open window
GH.windows().createAndPushWindow<CMarketplaceWindow>(townWithMarket); GH.windows().createAndPushWindow<CMarketplaceWindow>(townWithMarket, nullptr, nullptr, EMarketMode::RESOURCE_RESOURCE);
else //if not - complain else //if not - complain
LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket")); LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithMarket"));
} }

View File

@ -674,7 +674,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
break; break;
case BuildingID::TAVERN: case BuildingID::TAVERN:
LOCPLINT->showTavernWindow(town); LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
break; break;
case BuildingID::SHIPYARD: case BuildingID::SHIPYARD:
@ -700,7 +700,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
case BuildingID::MARKETPLACE: case BuildingID::MARKETPLACE:
// can't use allied marketplace // can't use allied marketplace
if (town->getOwner() == LOCPLINT->playerID) if (town->getOwner() == LOCPLINT->playerID)
GH.windows().createAndPushWindow<CMarketplaceWindow>(town, town->visitingHero); GH.windows().createAndPushWindow<CMarketplaceWindow>(town, town->visitingHero, nullptr, EMarketMode::RESOURCE_RESOURCE);
else else
enterBuilding(building); enterBuilding(building);
break; break;
@ -728,7 +728,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
case BuildingSubID::ARTIFACT_MERCHANT: case BuildingSubID::ARTIFACT_MERCHANT:
if(town->visitingHero) if(town->visitingHero)
GH.windows().createAndPushWindow<CMarketplaceWindow>(town, town->visitingHero, EMarketMode::RESOURCE_ARTIFACT); GH.windows().createAndPushWindow<CMarketplaceWindow>(town, town->visitingHero, nullptr, EMarketMode::RESOURCE_ARTIFACT);
else else
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->getNameTranslated())); //Only visiting heroes may use the %s. LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->getNameTranslated())); //Only visiting heroes may use the %s.
break; break;
@ -739,21 +739,21 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
case BuildingSubID::FREELANCERS_GUILD: case BuildingSubID::FREELANCERS_GUILD:
if(getHero()) if(getHero())
GH.windows().createAndPushWindow<CMarketplaceWindow>(town, getHero(), EMarketMode::CREATURE_RESOURCE); GH.windows().createAndPushWindow<CMarketplaceWindow>(town, getHero(), nullptr, EMarketMode::CREATURE_RESOURCE);
else else
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->getNameTranslated())); //Only visiting heroes may use the %s. LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % b->getNameTranslated())); //Only visiting heroes may use the %s.
break; break;
case BuildingSubID::MAGIC_UNIVERSITY: case BuildingSubID::MAGIC_UNIVERSITY:
if (getHero()) if (getHero())
GH.windows().createAndPushWindow<CUniversityWindow>(getHero(), town); GH.windows().createAndPushWindow<CUniversityWindow>(getHero(), town, nullptr);
else else
enterBuilding(building); enterBuilding(building);
break; break;
case BuildingSubID::BROTHERHOOD_OF_SWORD: case BuildingSubID::BROTHERHOOD_OF_SWORD:
if(upgrades == BuildingID::TAVERN) if(upgrades == BuildingID::TAVERN)
LOCPLINT->showTavernWindow(town); LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
else else
enterBuilding(building); enterBuilding(building);
break; break;
@ -763,7 +763,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
break; break;
case BuildingSubID::CREATURE_TRANSFORMER: //Skeleton Transformer case BuildingSubID::CREATURE_TRANSFORMER: //Skeleton Transformer
GH.windows().createAndPushWindow<CTransformerWindow>(town, getHero()); GH.windows().createAndPushWindow<CTransformerWindow>(town, getHero(), nullptr);
break; break;
case BuildingSubID::PORTAL_OF_SUMMONING: case BuildingSubID::PORTAL_OF_SUMMONING:
@ -1319,7 +1319,7 @@ void CCastleInterface::keyPressed(EShortcut key)
break; break;
case EShortcut::TOWN_OPEN_TAVERN: case EShortcut::TOWN_OPEN_TAVERN:
if(town->hasBuilt(BuildingID::TAVERN)) if(town->hasBuilt(BuildingID::TAVERN))
LOCPLINT->showTavernWindow(town); LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE);
break; break;
default: default:
break; break;

View File

@ -317,9 +317,10 @@ void CTradeWindow::CTradeableItem::setArtInstance(const CArtifactInstance *art)
setID(-1); setID(-1);
} }
CTradeWindow::CTradeWindow(const ImagePath & bgName, const IMarket *Market, const CGHeroInstance *Hero, EMarketMode Mode): CTradeWindow::CTradeWindow(const ImagePath & bgName, const IMarket *Market, const CGHeroInstance *Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode):
CWindowObject(PLAYER_COLORED, bgName), CWindowObject(PLAYER_COLORED, bgName),
market(Market), market(Market),
onWindowClosed(onWindowClosed),
hero(Hero), hero(Hero),
readyToTrade(false) readyToTrade(false)
{ {
@ -561,6 +562,14 @@ void CTradeWindow::showAll(Canvas & to)
} }
} }
void CTradeWindow::close()
{
if (onWindowClosed)
onWindowClosed();
CWindowObject::close();
}
void CTradeWindow::removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove) void CTradeWindow::removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove)
{ {
for(auto item : toRemove) for(auto item : toRemove)
@ -589,17 +598,19 @@ void CTradeWindow::setMode(EMarketMode Mode)
{ {
const IMarket *m = market; const IMarket *m = market;
const CGHeroInstance *h = hero; const CGHeroInstance *h = hero;
const auto functor = onWindowClosed;
onWindowClosed = nullptr; // don't call on closing of this window - pass it to next window
close(); close();
switch(Mode) switch(Mode)
{ {
case EMarketMode::CREATURE_EXP: case EMarketMode::CREATURE_EXP:
case EMarketMode::ARTIFACT_EXP: case EMarketMode::ARTIFACT_EXP:
GH.windows().createAndPushWindow<CAltarWindow>(m, h, Mode); GH.windows().createAndPushWindow<CAltarWindow>(m, h, functor, Mode);
break; break;
default: default:
GH.windows().createAndPushWindow<CMarketplaceWindow>(m, h, Mode); GH.windows().createAndPushWindow<CMarketplaceWindow>(m, h, functor, Mode);
break; break;
} }
} }
@ -635,8 +646,8 @@ ImagePath CMarketplaceWindow::getBackgroundForMode(EMarketMode mode)
return {}; return {};
} }
CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode Mode) CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode)
: CTradeWindow(getBackgroundForMode(Mode), Market, Hero, Mode) : CTradeWindow(getBackgroundForMode(Mode), Market, Hero, onWindowClosed, Mode)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -1093,8 +1104,8 @@ void CMarketplaceWindow::updateTraderText()
traderText->setText(CGI->generaltexth->allTexts[gnrtxtnr]); traderText->setText(CGI->generaltexth->allTexts[gnrtxtnr]);
} }
CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode Mode) CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode)
: CTradeWindow(ImagePath::builtin(Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, Mode) : CTradeWindow(ImagePath::builtin(Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, onWindowClosed, Mode)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);

View File

@ -83,9 +83,10 @@ public:
std::shared_ptr<CSlider> slider; //for choosing amount to be exchanged std::shared_ptr<CSlider> slider; //for choosing amount to be exchanged
bool readyToTrade; bool readyToTrade;
CTradeWindow(const ImagePath & bgName, const IMarket * Market, const CGHeroInstance * Hero, EMarketMode Mode); //c CTradeWindow(const ImagePath & bgName, const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode); //c
void showAll(Canvas & to) override; void showAll(Canvas & to) override;
void close();
void initSubs(bool Left); void initSubs(bool Left);
void initTypes(); void initTypes();
@ -106,6 +107,7 @@ public:
virtual void garrisonChanged() = 0; virtual void garrisonChanged() = 0;
virtual void artifactsChanged(bool left) = 0; virtual void artifactsChanged(bool left) = 0;
protected: protected:
std::function<void()> onWindowClosed;
std::shared_ptr<CGStatusBar> statusBar; std::shared_ptr<CGStatusBar> statusBar;
std::vector<std::shared_ptr<CLabel>> labels; std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CPicture>> images; std::vector<std::shared_ptr<CPicture>> images;
@ -130,7 +132,7 @@ public:
void sliderMoved(int to); void sliderMoved(int to);
void makeDeal(); void makeDeal();
void selectionChanged(bool side) override; //true == left void selectionChanged(bool side) override; //true == left
CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero = nullptr, EMarketMode Mode = EMarketMode::RESOURCE_RESOURCE); CMarketplaceWindow(const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode);
~CMarketplaceWindow(); ~CMarketplaceWindow();
Point selectionOffset(bool Left) const override; Point selectionOffset(bool Left) const override;
@ -157,7 +159,7 @@ public:
std::shared_ptr<CLabel> expOnAltar; std::shared_ptr<CLabel> expOnAltar;
std::shared_ptr<CArtifactsOfHeroAltar> arts; std::shared_ptr<CArtifactsOfHeroAltar> arts;
CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode Mode); CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode);
~CAltarWindow(); ~CAltarWindow();
void getExpValues(); void getExpValues();

View File

@ -430,8 +430,9 @@ CLevelWindow::~CLevelWindow()
LOCPLINT->showingDialog->setn(false); LOCPLINT->showingDialog->setn(false);
} }
CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj) CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed)
: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPTAVERN")), : CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("TPTAVERN")),
onWindowClosed(onWindowClosed),
tavernObj(TavernObj) tavernObj(TavernObj)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -500,8 +501,9 @@ void CTavernWindow::recruitb()
{ {
const CGHeroInstance *toBuy = (selected ? h2 : h1)->h; const CGHeroInstance *toBuy = (selected ? h2 : h1)->h;
const CGObjectInstance *obj = tavernObj; const CGObjectInstance *obj = tavernObj;
close();
LOCPLINT->cb->recruitHero(obj, toBuy); LOCPLINT->cb->recruitHero(obj, toBuy);
close();
} }
void CTavernWindow::thievesguildb() void CTavernWindow::thievesguildb()
@ -509,6 +511,14 @@ void CTavernWindow::thievesguildb()
GH.windows().createAndPushWindow<CThievesGuildWindow>(tavernObj); GH.windows().createAndPushWindow<CThievesGuildWindow>(tavernObj);
} }
void CTavernWindow::close()
{
if (onWindowClosed)
onWindowClosed();
CStatusbarWindow::close();
}
CTavernWindow::~CTavernWindow() CTavernWindow::~CTavernWindow()
{ {
CCS->videoh->close(); CCS->videoh->close();
@ -993,9 +1003,10 @@ void CTransformerWindow::updateGarrisons()
item->update(); item->update();
} }
CTransformerWindow::CTransformerWindow(const IMarket * _market, const CGHeroInstance * _hero) CTransformerWindow::CTransformerWindow(const IMarket * _market, const CGHeroInstance * _hero, const std::function<void()> & onWindowClosed)
: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("SKTRNBK")), : CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("SKTRNBK")),
hero(_hero), hero(_hero),
onWindowClosed(onWindowClosed),
market(_market) market(_market)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -1024,6 +1035,14 @@ CTransformerWindow::CTransformerWindow(const IMarket * _market, const CGHeroInst
helpRight = std::make_shared<CTextBox>(CGI->generaltexth->allTexts[488], Rect(320, 56, 255, 40), 0, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW);//creatures here will become skeletons helpRight = std::make_shared<CTextBox>(CGI->generaltexth->allTexts[488], Rect(320, 56, 255, 40), 0, FONT_MEDIUM, ETextAlignment::CENTER, Colors::YELLOW);//creatures here will become skeletons
} }
void CTransformerWindow::close()
{
if (onWindowClosed)
onWindowClosed();
CStatusbarWindow::close();
}
CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int Y) CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int Y)
: CIntObject(LCLICK | SHOW_POPUP | HOVER), : CIntObject(LCLICK | SHOW_POPUP | HOVER),
ID(_ID), ID(_ID),
@ -1083,9 +1102,10 @@ void CUniversityWindow::CItem::showAll(Canvas & to)
CIntObject::showAll(to); CIntObject::showAll(to);
} }
CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market) CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market, const std::function<void()> & onWindowClosed)
: CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("UNIVERS1")), : CStatusbarWindow(PLAYER_COLORED, ImagePath::builtin("UNIVERS1")),
hero(_hero), hero(_hero),
onWindowClosed(onWindowClosed),
market(_market) market(_market)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -1130,6 +1150,14 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket
statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26)); statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
} }
void CUniversityWindow::close()
{
if (onWindowClosed)
onWindowClosed();
CStatusbarWindow::close();
}
void CUniversityWindow::makeDeal(int skill) void CUniversityWindow::makeDeal(int skill)
{ {
LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_SKILL, 6, skill, 1, hero); LOCPLINT->cb->trade(market, EMarketMode::RESOURCE_SKILL, 6, skill, 1, hero);

View File

@ -193,6 +193,8 @@ public:
class CTavernWindow : public CStatusbarWindow class CTavernWindow : public CStatusbarWindow
{ {
std::function<void()> onWindowClosed;
public: public:
class HeroPortrait : public CIntObject class HeroPortrait : public CIntObject
{ {
@ -233,9 +235,10 @@ public:
std::shared_ptr<CTextBox> rumor; std::shared_ptr<CTextBox> rumor;
CTavernWindow(const CGObjectInstance * TavernObj); CTavernWindow(const CGObjectInstance * TavernObj, const std::function<void()> & onWindowClosed);
~CTavernWindow(); ~CTavernWindow();
void close();
void recruitb(); void recruitb();
void thievesguildb(); void thievesguildb();
void show(Canvas & to) override; void show(Canvas & to) override;
@ -349,12 +352,15 @@ class CTransformerWindow : public CStatusbarWindow, public IGarrisonHolder
std::shared_ptr<CButton> all; std::shared_ptr<CButton> all;
std::shared_ptr<CButton> convert; std::shared_ptr<CButton> convert;
std::shared_ptr<CButton> cancel; std::shared_ptr<CButton> cancel;
std::function<void()> onWindowClosed;
public: public:
void makeDeal(); void makeDeal();
void addAll(); void addAll();
void close();
void updateGarrisons() override; void updateGarrisons() override;
CTransformerWindow(const IMarket * _market, const CGHeroInstance * _hero); CTransformerWindow(const IMarket * _market, const CGHeroInstance * _hero, const std::function<void()> & onWindowClosed);
}; };
class CUniversityWindow : public CStatusbarWindow class CUniversityWindow : public CStatusbarWindow
@ -390,10 +396,13 @@ class CUniversityWindow : public CStatusbarWindow
std::shared_ptr<CLabel> title; std::shared_ptr<CLabel> title;
std::shared_ptr<CTextBox> clerkSpeech; std::shared_ptr<CTextBox> clerkSpeech;
std::function<void()> onWindowClosed;
public: public:
CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market); CUniversityWindow(const CGHeroInstance * _hero, const IMarket * _market, const std::function<void()> & onWindowClosed);
void makeDeal(int skill); void makeDeal(int skill);
void close();
}; };
/// Confirmation window for University /// Confirmation window for University

View File

@ -25,6 +25,7 @@ struct ArtifactLocation;
class CCreatureSet; class CCreatureSet;
class CStackBasicDescriptor; class CStackBasicDescriptor;
class CGCreature; class CGCreature;
enum class EOpenWindowMode : uint8_t;
namespace spells namespace spells
{ {
@ -96,7 +97,7 @@ public:
virtual void showBlockingDialog(BlockingDialog *iw) =0; virtual void showBlockingDialog(BlockingDialog *iw) =0;
virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window virtual void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) =0; //cb will be called when player closes garrison window
virtual void showTeleportDialog(TeleportDialog *iw) =0; virtual void showTeleportDialog(TeleportDialog *iw) =0;
virtual void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) =0; virtual void showObjectWindow(const CGObjectInstance * object, EOpenWindowMode window, const CGHeroInstance * visitor, bool addQuery) = 0;
virtual void giveResource(PlayerColor player, GameResID which, int val)=0; virtual void giveResource(PlayerColor player, GameResID which, int val)=0;
virtual void giveResources(PlayerColor player, TResources resources)=0; virtual void giveResources(PlayerColor player, TResources resources)=0;

View File

@ -110,11 +110,11 @@ public:
virtual void showPuzzleMap(){}; virtual void showPuzzleMap(){};
virtual void viewWorldMap(){}; virtual void viewWorldMap(){};
virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor){}; virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID){};
virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor){}; virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor, QueryID queryID){};
virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){}; virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){};
virtual void showTavernWindow(const CGObjectInstance *townOrTavern){};
virtual void showThievesGuildWindow (const CGObjectInstance * obj){}; virtual void showThievesGuildWindow (const CGObjectInstance * obj){};
virtual void showTavernWindow(const CGObjectInstance * object, const CGHeroInstance * visitor, QueryID queryID) {};
virtual void showQuestLog(){}; virtual void showQuestLog(){};
virtual void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID){}; //called when a hero casts a spell virtual void advmapSpellCast(const CGHeroInstance * caster, SpellID spellID){}; //called when a hero casts a spell
virtual void tileHidden(const std::unordered_set<int3> &pos){}; virtual void tileHidden(const std::unordered_set<int3> &pos){};

View File

@ -786,19 +786,20 @@ struct DLL_LINKAGE GiveHero : public CPackForClient
} }
}; };
struct DLL_LINKAGE OpenWindow : public CPackForClient struct DLL_LINKAGE OpenWindow : public Query
{ {
EOpenWindowMode window; EOpenWindowMode window;
si32 id1 = -1; ObjectInstanceID object;
si32 id2 = -1; ObjectInstanceID visitor;
virtual void visitTyped(ICPackVisitor & visitor) override; virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h, const int version) template <typename Handler> void serialize(Handler & h, const int version)
{ {
h & queryID;
h & window; h & window;
h & id1; h & object;
h & id2; h & visitor;
} }
}; };

View File

@ -393,13 +393,8 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h) const
cb->sendAndApply(&sac); cb->sendAndApply(&sac);
} }
OpenWindow ow; auto windowMode = (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::REFUGEE_CAMP) ? EOpenWindowMode::RECRUITMENT_FIRST : EOpenWindowMode::RECRUITMENT_ALL;
ow.id1 = id.getNum(); cb->showObjectWindow(this, windowMode, h, false);
ow.id2 = h->id.getNum();
ow.window = (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::REFUGEE_CAMP)
? EOpenWindowMode::RECRUITMENT_FIRST
: EOpenWindowMode::RECRUITMENT_ALL;
cb->sendAndApply(&ow);
} }
} }

View File

@ -30,7 +30,7 @@ void CGMarket::initObj(CRandomGenerator & rand)
void CGMarket::onHeroVisit(const CGHeroInstance * h) const void CGMarket::onHeroVisit(const CGHeroInstance * h) const
{ {
openWindow(EOpenWindowMode::MARKET_WINDOW, id.getNum(), h->id.getNum()); cb->showObjectWindow(this, EOpenWindowMode::MARKET_WINDOW, h, true);
} }
int CGMarket::getMarketEfficiency() const int CGMarket::getMarketEfficiency() const
@ -124,7 +124,7 @@ std::vector<int> CGUniversity::availableItemsIds(EMarketMode mode) const
void CGUniversity::onHeroVisit(const CGHeroInstance * h) const void CGUniversity::onHeroVisit(const CGHeroInstance * h) const
{ {
openWindow(EOpenWindowMode::UNIVERSITY_WINDOW,id.getNum(),h->id.getNum()); cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -283,7 +283,7 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const
break; break;
case Obj::TAVERN: case Obj::TAVERN:
{ {
openWindow(EOpenWindowMode::TAVERN_WINDOW,h->id.getNum(),id.getNum()); cb->showObjectWindow(this, EOpenWindowMode::TAVERN_WINDOW, h, true);
} }
break; break;
} }

View File

@ -22,16 +22,6 @@ VCMI_LIB_NAMESPACE_BEGIN
IGameCallback * IObjectInterface::cb = nullptr; IGameCallback * IObjectInterface::cb = nullptr;
///helpers
void IObjectInterface::openWindow(const EOpenWindowMode type, const int id1, const int id2)
{
OpenWindow ow;
ow.window = type;
ow.id1 = id1;
ow.id2 = id2;
IObjectInterface::cb->sendAndApply(&ow);
}
void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const
{ {
InfoWindow iw; InfoWindow iw;

View File

@ -52,9 +52,6 @@ public:
//unified helper to show info dialog for object owner //unified helper to show info dialog for object owner
virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const; virtual void showInfoDialog(const ui32 txtID, const ui16 soundID = 0, EInfoWindowMode mode = EInfoWindowMode::AUTO) const;
//unified helper to show a specific window
static void openWindow(const EOpenWindowMode type, const int id1, const int id2 = -1);
//unified interface, AI helpers //unified interface, AI helpers
virtual bool wasVisited (PlayerColor player) const; virtual bool wasVisited (PlayerColor player) const;
virtual bool wasVisited (const CGHeroInstance * h) const; virtual bool wasVisited (const CGHeroInstance * h) const;

View File

@ -1399,7 +1399,7 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
} }
else else
{ {
openWindow(EOpenWindowMode::SHIPYARD_WINDOW,id.getNum(),h->id.getNum()); cb->showObjectWindow(this, EOpenWindowMode::SHIPYARD_WINDOW, h, false);
} }
} }
@ -1488,7 +1488,7 @@ void CCartographer::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answ
void CGDenOfthieves::onHeroVisit (const CGHeroInstance * h) const void CGDenOfthieves::onHeroVisit (const CGHeroInstance * h) const
{ {
cb->showThievesGuildWindow(h->tempOwner, id); cb->showObjectWindow(this, EOpenWindowMode::THIEVES_GUILD, h, false);
} }
void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
@ -1507,8 +1507,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
// increment general visited obelisks counter // increment general visited obelisks counter
cb->setObjProperty(id, CGObelisk::OBJPROP_INC, team.getNum()); cb->setObjProperty(id, CGObelisk::OBJPROP_INC, team.getNum());
cb->showObjectWindow(this, EOpenWindowMode::PUZZLE_MAP, h, false);
openWindow(EOpenWindowMode::PUZZLE_MAP, h->tempOwner.getNum());
// mark that particular obelisk as visited for all players in the team // mark that particular obelisk as visited for all players in the team
for(const auto & color : ts->players) for(const auto & color : ts->players)
@ -1619,7 +1618,7 @@ void CGLighthouse::serializeJsonOptions(JsonSerializeFormat& handler)
void HillFort::onHeroVisit(const CGHeroInstance * h) const void HillFort::onHeroVisit(const CGHeroInstance * h) const
{ {
openWindow(EOpenWindowMode::HILL_FORT_WINDOW,id.getNum(),h->id.getNum()); cb->showObjectWindow(this, EOpenWindowMode::HILL_FORT_WINDOW, h, false);
} }
void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const

View File

@ -3364,13 +3364,20 @@ void CGameHandler::showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID h
sendAndApply(&gd); sendAndApply(&gd);
} }
void CGameHandler::showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) void CGameHandler::showObjectWindow(const CGObjectInstance * object, EOpenWindowMode window, const CGHeroInstance * visitor, bool addQuery)
{ {
OpenWindow ow; OpenWindow pack;
ow.window = EOpenWindowMode::THIEVES_GUILD; pack.window = window;
ow.id1 = player.getNum(); pack.object = object->id;
ow.id2 = requestingObjId.getNum(); pack.visitor = visitor->id;
sendAndApply(&ow);
if (addQuery)
{
auto windowQuery = std::make_shared<OpenWindowQuery>(this, visitor, window);
pack.queryID = windowQuery->queryID;
queries->addQuery(windowQuery);
}
sendAndApply(&pack);
} }
bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2) bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)

View File

@ -109,7 +109,7 @@ public:
void showBlockingDialog(BlockingDialog *iw) override; void showBlockingDialog(BlockingDialog *iw) override;
void showTeleportDialog(TeleportDialog *iw) override; void showTeleportDialog(TeleportDialog *iw) override;
void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override; void showGarrisonDialog(ObjectInstanceID upobj, ObjectInstanceID hid, bool removableUnits) override;
void showThievesGuildWindow(PlayerColor player, ObjectInstanceID requestingObjId) override; void showObjectWindow(const CGObjectInstance * object, EOpenWindowMode window, const CGHeroInstance * visitor, bool addQuery) override;
void giveResource(PlayerColor player, GameResID which, int val) override; void giveResource(PlayerColor player, GameResID which, int val) override;
void giveResources(PlayerColor player, TResources resources) override; void giveResources(PlayerColor player, TResources resources) override;

View File

@ -157,6 +157,39 @@ CBlockingDialogQuery::CBlockingDialogQuery(CGameHandler * owner, const BlockingD
addPlayer(bd.player); addPlayer(bd.player);
} }
OpenWindowQuery::OpenWindowQuery(CGameHandler * owner, const CGHeroInstance *hero, EOpenWindowMode mode):
CDialogQuery(owner),
mode(mode)
{
addPlayer(hero->getOwner());
}
bool OpenWindowQuery::blocksPack(const CPack *pack) const
{
if (mode == EOpenWindowMode::TAVERN_WINDOW)
{
if(dynamic_ptr_cast<HireHero>(pack) != nullptr)
return false;
}
if (mode == EOpenWindowMode::MARKET_WINDOW)
{
if(dynamic_ptr_cast<ExchangeArtifacts>(pack) != nullptr)
return false;
if(dynamic_ptr_cast<AssembleArtifacts>(pack))
return false;
if(dynamic_ptr_cast<EraseArtifactByClient>(pack))
return false;
if(dynamic_ptr_cast<TradeOnMarketplace>(pack) != nullptr)
return false;
}
return CDialogQuery::blocksPack(pack);
}
void CTeleportDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery & objectVisit) const void CTeleportDialogQuery::notifyObjectAboutRemoval(const CObjectVisitQuery & objectVisit) const
{ {
// do not change to dynamic_ptr_cast - SIGSEGV! // do not change to dynamic_ptr_cast - SIGSEGV!

View File

@ -61,7 +61,6 @@ public:
virtual void onRemoval(PlayerColor color) override; virtual void onRemoval(PlayerColor color) override;
}; };
class CGarrisonDialogQuery : public CDialogQuery //used also for hero exchange dialogs class CGarrisonDialogQuery : public CDialogQuery //used also for hero exchange dialogs
{ {
public: public:
@ -83,6 +82,15 @@ public:
virtual void notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const override; virtual void notifyObjectAboutRemoval(const CObjectVisitQuery &objectVisit) const override;
}; };
class OpenWindowQuery : public CDialogQuery
{
EOpenWindowMode mode;
public:
OpenWindowQuery(CGameHandler * owner, const CGHeroInstance *hero, EOpenWindowMode mode);
virtual bool blocksPack(const CPack *pack) const override;
};
class CTeleportDialogQuery : public CDialogQuery class CTeleportDialogQuery : public CDialogQuery
{ {
public: public: