mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge pull request #2005 from IvanSavenko/advmap_refactor
Refactoring of adventure map interface
This commit is contained in:
commit
48abf46824
@ -256,7 +256,7 @@ void AIGateway::heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void AIGateway::tileHidden(const std::unordered_set<int3, ShashInt3> & pos)
|
||||
void AIGateway::tileHidden(const std::unordered_set<int3> & pos)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
@ -264,7 +264,7 @@ void AIGateway::tileHidden(const std::unordered_set<int3, ShashInt3> & pos)
|
||||
nullkiller->memory->removeInvisibleObjects(myCb.get());
|
||||
}
|
||||
|
||||
void AIGateway::tileRevealed(const std::unordered_set<int3, ShashInt3> & pos)
|
||||
void AIGateway::tileRevealed(const std::unordered_set<int3> & pos)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
|
@ -127,7 +127,7 @@ public:
|
||||
void heroMoved(const TryMoveHero & details, bool verbose = true) override;
|
||||
void heroInGarrisonChange(const CGTownInstance * town) override;
|
||||
void centerView(int3 pos, int focusTime) override;
|
||||
void tileHidden(const std::unordered_set<int3, ShashInt3> & pos) override;
|
||||
void tileHidden(const std::unordered_set<int3> & pos) override;
|
||||
void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override;
|
||||
void artifactAssembled(const ArtifactLocation & al) override;
|
||||
void showTavernWindow(const CGObjectInstance * townOrTavern) override;
|
||||
@ -142,7 +142,7 @@ public:
|
||||
void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override;
|
||||
void availableArtifactsChanged(const CGBlackMarket * bm = nullptr) override;
|
||||
void heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * town) override;
|
||||
void tileRevealed(const std::unordered_set<int3, ShashInt3> & pos) override;
|
||||
void tileRevealed(const std::unordered_set<int3> & pos) override;
|
||||
void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
|
||||
void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) override;
|
||||
void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) override;
|
||||
|
@ -268,7 +268,7 @@ void VCAI::heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * to
|
||||
//moveCreaturesToHero(town);
|
||||
}
|
||||
|
||||
void VCAI::tileHidden(const std::unordered_set<int3, ShashInt3> & pos)
|
||||
void VCAI::tileHidden(const std::unordered_set<int3> & pos)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
@ -277,7 +277,7 @@ void VCAI::tileHidden(const std::unordered_set<int3, ShashInt3> & pos)
|
||||
clearPathsInfo();
|
||||
}
|
||||
|
||||
void VCAI::tileRevealed(const std::unordered_set<int3, ShashInt3> & pos)
|
||||
void VCAI::tileRevealed(const std::unordered_set<int3> & pos)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
|
@ -160,7 +160,7 @@ public:
|
||||
void heroMoved(const TryMoveHero & details, bool verbose = true) override;
|
||||
void heroInGarrisonChange(const CGTownInstance * town) override;
|
||||
void centerView(int3 pos, int focusTime) override;
|
||||
void tileHidden(const std::unordered_set<int3, ShashInt3> & pos) override;
|
||||
void tileHidden(const std::unordered_set<int3> & pos) override;
|
||||
void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override;
|
||||
void artifactAssembled(const ArtifactLocation & al) override;
|
||||
void showTavernWindow(const CGObjectInstance * townOrTavern) override;
|
||||
@ -175,7 +175,7 @@ public:
|
||||
void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override;
|
||||
void availableArtifactsChanged(const CGBlackMarket * bm = nullptr) override;
|
||||
void heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * town) override;
|
||||
void tileRevealed(const std::unordered_set<int3, ShashInt3> & pos) override;
|
||||
void tileRevealed(const std::unordered_set<int3> & pos) override;
|
||||
void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
|
||||
void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) override;
|
||||
void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) override;
|
||||
|
@ -3,7 +3,7 @@ set(client_SRCS
|
||||
../CCallback.cpp
|
||||
|
||||
adventureMap/CAdvMapPanel.cpp
|
||||
adventureMap/CAdvMapInt.cpp
|
||||
adventureMap/CAdventureMapInterface.cpp
|
||||
adventureMap/CAdventureOptions.cpp
|
||||
adventureMap/CInGameConsole.cpp
|
||||
adventureMap/CInfoBar.cpp
|
||||
@ -110,6 +110,7 @@ set(client_SRCS
|
||||
CMT.cpp
|
||||
CMusicHandler.cpp
|
||||
CPlayerInterface.cpp
|
||||
PlayerLocalState.cpp
|
||||
CServerHandler.cpp
|
||||
CVideoHandler.cpp
|
||||
Client.cpp
|
||||
@ -122,7 +123,7 @@ set(client_HEADERS
|
||||
StdInc.h
|
||||
|
||||
adventureMap/CAdvMapPanel.h
|
||||
adventureMap/CAdvMapInt.h
|
||||
adventureMap/CAdventureMapInterface.h
|
||||
adventureMap/CAdventureOptions.h
|
||||
adventureMap/CInGameConsole.h
|
||||
adventureMap/CInfoBar.h
|
||||
@ -238,6 +239,7 @@ set(client_HEADERS
|
||||
CMT.h
|
||||
CMusicHandler.h
|
||||
CPlayerInterface.h
|
||||
PlayerLocalState.h
|
||||
CServerHandler.h
|
||||
CVideoHandler.h
|
||||
Client.h
|
||||
|
@ -8,14 +8,14 @@
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CPlayerInterface.h"
|
||||
|
||||
#include <vcmi/Artifact.h>
|
||||
|
||||
#include "adventureMap/CAdvMapInt.h"
|
||||
#include "adventureMap/CAdventureMapInterface.h"
|
||||
#include "mapView/mapHandler.h"
|
||||
#include "adventureMap/CList.h"
|
||||
#include "adventureMap/CInfoBar.h"
|
||||
#include "adventureMap/CMinimap.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
#include "battle/BattleEffectsController.h"
|
||||
#include "battle/BattleFieldController.h"
|
||||
@ -26,12 +26,12 @@
|
||||
#include "gui/CursorHandler.h"
|
||||
#include "windows/CKingdomInterface.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "PlayerLocalState.h"
|
||||
#include "CMT.h"
|
||||
#include "windows/CHeroWindow.h"
|
||||
#include "windows/CCreatureWindow.h"
|
||||
#include "windows/CQuestLog.h"
|
||||
#include "windows/CPuzzleWindow.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "widgets/CComponent.h"
|
||||
#include "widgets/Buttons.h"
|
||||
#include "windows/CTradeWindow.h"
|
||||
@ -115,97 +115,8 @@ struct HeroObjectRetriever
|
||||
}
|
||||
};
|
||||
|
||||
HeroPathStorage::HeroPathStorage(CPlayerInterface & owner):
|
||||
owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
void HeroPathStorage::setPath(const CGHeroInstance *h, const CGPath & path)
|
||||
{
|
||||
paths[h] = path;
|
||||
}
|
||||
|
||||
const CGPath & HeroPathStorage::getPath(const CGHeroInstance *h) const
|
||||
{
|
||||
assert(hasPath(h));
|
||||
return paths.at(h);
|
||||
}
|
||||
|
||||
bool HeroPathStorage::hasPath(const CGHeroInstance *h) const
|
||||
{
|
||||
return paths.count(h) > 0;
|
||||
}
|
||||
|
||||
bool HeroPathStorage::setPath(const CGHeroInstance *h, const int3 & destination)
|
||||
{
|
||||
CGPath path;
|
||||
if (!owner.cb->getPathsInfo(h)->getPath(path, destination))
|
||||
return false;
|
||||
|
||||
setPath(h, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HeroPathStorage::removeLastNode(const CGHeroInstance *h)
|
||||
{
|
||||
assert(hasPath(h));
|
||||
if (!hasPath(h))
|
||||
return;
|
||||
|
||||
auto & path = paths[h];
|
||||
path.nodes.pop_back();
|
||||
if (path.nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
|
||||
erasePath(h);
|
||||
}
|
||||
|
||||
void HeroPathStorage::erasePath(const CGHeroInstance *h)
|
||||
{
|
||||
paths.erase(h);
|
||||
adventureInt->updateMoveHero(h, false);
|
||||
|
||||
}
|
||||
|
||||
void HeroPathStorage::verifyPath(const CGHeroInstance *h)
|
||||
{
|
||||
if (!hasPath(h))
|
||||
return;
|
||||
setPath(h, getPath(h).endPos());
|
||||
}
|
||||
|
||||
template<typename Handler>
|
||||
void HeroPathStorage::serialize(Handler & h, int version)
|
||||
{
|
||||
std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
|
||||
if (h.saving)
|
||||
{
|
||||
for (auto &p : paths)
|
||||
{
|
||||
if (p.second.nodes.size())
|
||||
pathsMap[p.first] = p.second.endPos();
|
||||
else
|
||||
logGlobal->debug("%s has assigned an empty path! Ignoring it...", p.first->getNameTranslated());
|
||||
}
|
||||
h & pathsMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
h & pathsMap;
|
||||
|
||||
if (owner.cb)
|
||||
{
|
||||
for (auto &p : pathsMap)
|
||||
{
|
||||
CGPath path;
|
||||
owner.cb->getPathsInfo(p.first)->getPath(path, p.second);
|
||||
paths[p.first] = path;
|
||||
logGlobal->trace("Restored path for hero %s leading to %s with %d nodes", p.first->nodeName(), p.second.toString(), path.nodes.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||
paths(*this)
|
||||
localState(std::make_unique<PlayerLocalState>(*this))
|
||||
{
|
||||
logGlobal->trace("\tHuman player interface for player %s being constructed", Player.getStr());
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
@ -248,8 +159,53 @@ void CPlayerInterface::initGameInterface(std::shared_ptr<Environment> ENV, std::
|
||||
initializeHeroTownList();
|
||||
|
||||
// always recreate advmap interface to avoid possible memory-corruption bugs
|
||||
adventureInt.reset(new CAdvMapInt());
|
||||
adventureInt.reset(new CAdventureMapInterface());
|
||||
}
|
||||
|
||||
void CPlayerInterface::playerStartsTurn(PlayerColor player)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
if (!vstd::contains (GH.listInt, adventureInt))
|
||||
{
|
||||
// after map load - remove all active windows and replace them with adventure map
|
||||
GH.popInts ((int)GH.listInt.size());
|
||||
GH.pushInt (adventureInt);
|
||||
}
|
||||
|
||||
// remove all dialogs that do not expect query answer
|
||||
while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.listInt.front().get()))
|
||||
GH.popInts(1);
|
||||
|
||||
if (player != playerID && LOCPLINT == this)
|
||||
{
|
||||
waitWhileDialog();
|
||||
adventureInt->onEnemyTurnStarted(player);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::performAutosave()
|
||||
{
|
||||
std::string prefix = settings["session"]["saveprefix"].String();
|
||||
int frequency = static_cast<int>(settings["general"]["saveFrequency"].Integer());
|
||||
if(firstCall)
|
||||
{
|
||||
autosaveCount = getLastIndex(prefix + "Autosave_");
|
||||
|
||||
if(firstCall > 0) //new game, not loaded
|
||||
{
|
||||
int index = getLastIndex(prefix + "Newgame_");
|
||||
index %= SAVES_COUNT;
|
||||
cb->save("Saves/" + prefix + "Newgame_Autosave_" + std::to_string(index + 1));
|
||||
}
|
||||
firstCall = 0;
|
||||
}
|
||||
else if(frequency > 0 && cb->getDate() % frequency == 0)
|
||||
{
|
||||
LOCPLINT->cb->save("Saves/" + prefix + "Autosave_" + std::to_string(autosaveCount++ + 1));
|
||||
autosaveCount %= 5;
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::yourTurn()
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -258,38 +214,13 @@ void CPlayerInterface::yourTurn()
|
||||
|
||||
LOCPLINT = this;
|
||||
GH.curInt = this;
|
||||
adventureInt->selection = nullptr;
|
||||
|
||||
NotificationHandler::notify("Your turn");
|
||||
|
||||
std::string prefix = settings["session"]["saveprefix"].String();
|
||||
int frequency = static_cast<int>(settings["general"]["saveFrequency"].Integer());
|
||||
if (firstCall)
|
||||
{
|
||||
if(CSH->howManyPlayerInterfaces() == 1)
|
||||
adventureInt->setPlayer(playerID);
|
||||
|
||||
autosaveCount = getLastIndex(prefix + "Autosave_");
|
||||
|
||||
if (firstCall > 0) //new game, not loaded
|
||||
{
|
||||
int index = getLastIndex(prefix + "Newgame_");
|
||||
index %= SAVES_COUNT;
|
||||
cb->save("Saves/" + prefix + "Newgame_Autosave_" + std::to_string(index + 1));
|
||||
}
|
||||
firstCall = 0;
|
||||
}
|
||||
else if(frequency > 0 && cb->getDate() % frequency == 0)
|
||||
{
|
||||
LOCPLINT->cb->save("Saves/" + prefix + "Autosave_" + std::to_string(autosaveCount++ + 1));
|
||||
autosaveCount %= 5;
|
||||
}
|
||||
|
||||
adventureInt->setPlayer(playerID);
|
||||
performAutosave();
|
||||
|
||||
if (CSH->howManyPlayerInterfaces() > 1) //hot seat message
|
||||
{
|
||||
adventureInt->startHotSeatWait(playerID);
|
||||
adventureInt->onHotseatWaitStarted(playerID);
|
||||
|
||||
makingTurn = true;
|
||||
std::string msg = CGI->generaltexth->allTexts[13];
|
||||
@ -301,13 +232,60 @@ void CPlayerInterface::yourTurn()
|
||||
else
|
||||
{
|
||||
makingTurn = true;
|
||||
adventureInt->startTurn();
|
||||
adventureInt->onPlayerTurnStarted(playerID);
|
||||
}
|
||||
}
|
||||
|
||||
acceptTurn();
|
||||
}
|
||||
|
||||
void CPlayerInterface::acceptTurn()
|
||||
{
|
||||
if (settings["session"]["autoSkip"].Bool())
|
||||
{
|
||||
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
|
||||
iw->close();
|
||||
}
|
||||
|
||||
if(CSH->howManyPlayerInterfaces() > 1)
|
||||
{
|
||||
waitWhileDialog(); // wait for player to accept turn in hot-seat mode
|
||||
|
||||
adventureInt->onPlayerTurnStarted(playerID);
|
||||
}
|
||||
|
||||
// warn player if he has no town
|
||||
if (cb->howManyTowns() == 0)
|
||||
{
|
||||
auto playerColor = *cb->getPlayerID();
|
||||
|
||||
std::vector<Component> components;
|
||||
components.emplace_back(Component::EComponentType::FLAG, playerColor.getNum(), 0, 0);
|
||||
MetaString text;
|
||||
|
||||
const auto & optDaysWithoutCastle = cb->getPlayerState(playerColor)->daysWithoutCastle;
|
||||
|
||||
if(optDaysWithoutCastle)
|
||||
{
|
||||
auto daysWithoutCastle = optDaysWithoutCastle.value();
|
||||
if (daysWithoutCastle < 6)
|
||||
{
|
||||
text.addTxt(MetaString::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land.
|
||||
text.addReplacement(MetaString::COLOR, playerColor.getNum());
|
||||
text.addReplacement(7 - daysWithoutCastle);
|
||||
}
|
||||
else if (daysWithoutCastle == 6)
|
||||
{
|
||||
text.addTxt(MetaString::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land.
|
||||
text.addReplacement(MetaString::COLOR, playerColor.getNum());
|
||||
}
|
||||
|
||||
showInfoDialogAndWait(components, text);
|
||||
}
|
||||
else
|
||||
logGlobal->warn("Player has no towns, but daysWithoutCastle is not set");
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -324,37 +302,40 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
if (!hero)
|
||||
return;
|
||||
|
||||
adventureInt->infoBar->requestPopAll();
|
||||
if (details.result == TryMoveHero::EMBARK || details.result == TryMoveHero::DISEMBARK)
|
||||
{
|
||||
if(hero->getRemovalSound() && hero->tempOwner == playerID)
|
||||
CCS->soundh->playSound(hero->getRemovalSound().value());
|
||||
}
|
||||
|
||||
adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.start));
|
||||
adventureInt->minimap->updateTile(hero->convertToVisitablePos(details.end));
|
||||
std::unordered_set<int3> changedTiles {
|
||||
hero->convertToVisitablePos(details.start),
|
||||
hero->convertToVisitablePos(details.end)
|
||||
};
|
||||
adventureInt->onMapTilesChanged(changedTiles);
|
||||
adventureInt->onHeroMovementStarted(hero);
|
||||
|
||||
bool directlyAttackingCreature = details.attackedFrom && paths.hasPath(hero) && paths.getPath(hero).endPos() == *details.attackedFrom;
|
||||
bool directlyAttackingCreature = details.attackedFrom && localState->hasPath(hero) && localState->getPath(hero).endPos() == *details.attackedFrom;
|
||||
|
||||
if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
|
||||
{
|
||||
if(details.result == TryMoveHero::TELEPORTATION)
|
||||
{
|
||||
if(paths.hasPath(hero))
|
||||
if(localState->hasPath(hero))
|
||||
{
|
||||
assert(paths.getPath(hero).nodes.size() >= 2);
|
||||
auto nodesIt = paths.getPath(hero).nodes.end() - 1;
|
||||
assert(localState->getPath(hero).nodes.size() >= 2);
|
||||
auto nodesIt = localState->getPath(hero).nodes.end() - 1;
|
||||
|
||||
if((nodesIt)->coord == hero->convertToVisitablePos(details.start)
|
||||
&& (nodesIt - 1)->coord == hero->convertToVisitablePos(details.end))
|
||||
{
|
||||
//path was between entrance and exit of teleport -> OK, erase node as usual
|
||||
paths.removeLastNode(hero);
|
||||
localState->removeLastNode(hero);
|
||||
}
|
||||
else
|
||||
{
|
||||
//teleport was not along current path, it'll now be invalid (hero is somewhere else)
|
||||
paths.erasePath(hero);
|
||||
localState->erasePath(hero);
|
||||
|
||||
}
|
||||
}
|
||||
@ -363,28 +344,26 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
if(hero->pos != details.end //hero didn't change tile but visit succeeded
|
||||
|| directlyAttackingCreature) // or creature was attacked from endangering tile.
|
||||
{
|
||||
paths.erasePath(hero);
|
||||
localState->erasePath(hero);
|
||||
}
|
||||
else if(paths.hasPath(hero) && hero->pos == details.end) //&& hero is moving
|
||||
else if(localState->hasPath(hero) && hero->pos == details.end) //&& hero is moving
|
||||
{
|
||||
if(details.start != details.end) //so we don't touch path when revisiting with spacebar
|
||||
paths.removeLastNode(hero);
|
||||
localState->removeLastNode(hero);
|
||||
}
|
||||
}
|
||||
|
||||
if(details.stopMovement()) //hero failed to move
|
||||
{
|
||||
stillMoveHero.setn(STOP_MOVE);
|
||||
adventureInt->heroList->update(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
return;
|
||||
}
|
||||
|
||||
adventureInt->heroList->redraw();
|
||||
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
|
||||
//move finished
|
||||
adventureInt->heroList->update(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
|
||||
//check if user cancelled movement
|
||||
{
|
||||
@ -428,33 +407,9 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
LOG_TRACE_PARAMS(logGlobal, "Hero %s killed handler for player %s", hero->getNameTranslated() % playerID);
|
||||
|
||||
const CArmedInstance *newSelection = nullptr;
|
||||
if (makingTurn)
|
||||
{
|
||||
//find new object for selection: either hero
|
||||
int next = adventureInt->getNextHeroIndex(vstd::find_pos(wanderingHeroes, hero));
|
||||
if (next >= 0)
|
||||
newSelection = wanderingHeroes[next];
|
||||
|
||||
//or town
|
||||
if (!newSelection || newSelection == hero)
|
||||
{
|
||||
if (towns.empty())
|
||||
newSelection = nullptr;
|
||||
else
|
||||
newSelection = towns.front();
|
||||
}
|
||||
}
|
||||
|
||||
wanderingHeroes -= hero;
|
||||
|
||||
adventureInt->heroList->update(hero);
|
||||
if (makingTurn && newSelection)
|
||||
adventureInt->select(newSelection, true);
|
||||
else if (adventureInt->selection == hero)
|
||||
adventureInt->selection = nullptr;
|
||||
|
||||
paths.erasePath(hero);
|
||||
localState->removeWanderingHero(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
localState->erasePath(hero);
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start)
|
||||
@ -470,8 +425,8 @@ void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectI
|
||||
void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
wanderingHeroes.push_back(hero);
|
||||
adventureInt->heroList->update(hero);
|
||||
localState->addWanderingHero(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
}
|
||||
void CPlayerInterface::openTownWindow(const CGTownInstance * town)
|
||||
{
|
||||
@ -484,13 +439,6 @@ void CPlayerInterface::openTownWindow(const CGTownInstance * town)
|
||||
GH.pushInt(newCastleInt);
|
||||
}
|
||||
|
||||
void CPlayerInterface::activateForSpectator()
|
||||
{
|
||||
adventureInt->state = CAdvMapInt::INGAME;
|
||||
adventureInt->activate();
|
||||
adventureInt->minimap->activate();
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -499,8 +447,8 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
|
||||
if (CAltarWindow *ctw = dynamic_cast<CAltarWindow *>(GH.topInt().get()))
|
||||
ctw->setExpToLevel();
|
||||
}
|
||||
else if (which < GameConstants::PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4)
|
||||
updateInfo(hero);
|
||||
else
|
||||
adventureInt->onHeroChanged(hero);
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
||||
@ -516,15 +464,15 @@ void CPlayerInterface::heroSecondarySkillChanged(const CGHeroInstance * hero, in
|
||||
void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
if (makingTurn && hero->tempOwner == playerID)
|
||||
adventureInt->heroList->update(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
}
|
||||
void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
if (makingTurn && hero->tempOwner == playerID)
|
||||
adventureInt->heroList->update(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
}
|
||||
void CPlayerInterface::receivedResource()
|
||||
{
|
||||
@ -560,21 +508,22 @@ void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander,
|
||||
void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
updateInfo(town);
|
||||
|
||||
if (town->garrisonHero) //wandering hero moved to the garrison
|
||||
if(town->garrisonHero) //wandering hero moved to the garrison
|
||||
{
|
||||
if (town->garrisonHero->tempOwner == playerID && vstd::contains(wanderingHeroes,town->garrisonHero)) // our hero
|
||||
wanderingHeroes -= town->garrisonHero;
|
||||
// This method also gets called on hero recruitment -> garrisoned hero is already in garrison
|
||||
if(town->garrisonHero->tempOwner == playerID && !vstd::contains(localState->getWanderingHeroes(), town->visitingHero))
|
||||
localState->removeWanderingHero(town->garrisonHero);
|
||||
}
|
||||
|
||||
if (town->visitingHero) //hero leaves garrison
|
||||
if(town->visitingHero) //hero leaves garrison
|
||||
{
|
||||
if (town->visitingHero->tempOwner == playerID && !vstd::contains(wanderingHeroes,town->visitingHero)) // our hero
|
||||
wanderingHeroes.push_back(town->visitingHero);
|
||||
// This method also gets called on hero recruitment -> wandering heroes already contains new hero
|
||||
if(town->visitingHero->tempOwner == playerID && !vstd::contains(localState->getWanderingHeroes(), town->visitingHero))
|
||||
localState->addWanderingHero(town->visitingHero);
|
||||
}
|
||||
adventureInt->heroList->update();
|
||||
adventureInt->updateNextHero(nullptr);
|
||||
adventureInt->onHeroChanged(nullptr);
|
||||
adventureInt->onTownChanged(town);
|
||||
|
||||
if(castleInt)
|
||||
{
|
||||
@ -627,7 +576,15 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||
for (auto object : objs)
|
||||
updateInfo(object);
|
||||
{
|
||||
auto * hero = dynamic_cast<const CGHeroInstance*>(object);
|
||||
auto * town = dynamic_cast<const CGTownInstance*>(object);
|
||||
|
||||
if (hero)
|
||||
adventureInt->onHeroChanged(hero);
|
||||
if (town)
|
||||
adventureInt->onTownChanged(town);
|
||||
}
|
||||
|
||||
for (auto & elem : GH.listInt)
|
||||
{
|
||||
@ -645,23 +602,9 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
|
||||
GH.totalRedraw();
|
||||
}
|
||||
|
||||
void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj)
|
||||
{
|
||||
garrisonsChanged(std::vector<const CGObjectInstance *>(1, obj));
|
||||
}
|
||||
|
||||
void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) //what: 1 - built, 2 - demolished
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
switch (buildingID)
|
||||
{
|
||||
case BuildingID::FORT: case BuildingID::CITADEL: case BuildingID::CASTLE:
|
||||
case BuildingID::VILLAGE_HALL: case BuildingID::TOWN_HALL: case BuildingID::CITY_HALL: case BuildingID::CAPITOL:
|
||||
case BuildingID::RESOURCE_SILO:
|
||||
updateInfo(town);
|
||||
break;
|
||||
}
|
||||
|
||||
if (castleInt)
|
||||
{
|
||||
castleInt->townlist->update(town);
|
||||
@ -680,7 +623,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
|
||||
}
|
||||
}
|
||||
}
|
||||
adventureInt->townList->update(town);
|
||||
adventureInt->onTownChanged(town);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
||||
@ -709,7 +652,6 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
|
||||
isAutoFightOn = true;
|
||||
cb->registerBattleInterface(autofightingAI);
|
||||
// Player shouldn't be able to move on adventure map if quick combat is going
|
||||
adventureInt->quickCombatLock();
|
||||
allowBattleReplay = true;
|
||||
}
|
||||
|
||||
@ -920,7 +862,6 @@ void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
|
||||
// #1490 - during AI turn when quick combat is on, we need to display the message and wait for user to close it.
|
||||
// Otherwise NewTurn causes freeze.
|
||||
waitWhileDialog();
|
||||
adventureInt->quickCombatUnlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -928,7 +869,6 @@ void CPlayerInterface::battleEnd(const BattleResult *br, QueryID queryID)
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
battleInt->battleFinished(*br, queryID);
|
||||
adventureInt->quickCombatUnlock();
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleLogMessage(const std::vector<MetaString> & lines)
|
||||
@ -1070,7 +1010,7 @@ void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &t
|
||||
if(autoTryHover || type == EInfoWindowMode::INFO)
|
||||
{
|
||||
waitWhileDialog(); //Fix for mantis #98
|
||||
adventureInt->infoBar->pushComponents(components, text, timer);
|
||||
adventureInt->showInfoBoxMessage(components, text, timer);
|
||||
|
||||
if (makingTurn && GH.listInt.size() && LOCPLINT == this)
|
||||
CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
|
||||
@ -1230,19 +1170,17 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component
|
||||
GH.pushInt(wnd);
|
||||
}
|
||||
|
||||
void CPlayerInterface::tileRevealed(const std::unordered_set<int3, ShashInt3> &pos)
|
||||
void CPlayerInterface::tileRevealed(const std::unordered_set<int3> &pos)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
//FIXME: wait for dialog? Magi hut/eye would benefit from this but may break other areas
|
||||
for (auto & po : pos)
|
||||
adventureInt->minimap->updateTile(po);
|
||||
adventureInt->onMapTilesChanged(pos);
|
||||
}
|
||||
|
||||
void CPlayerInterface::tileHidden(const std::unordered_set<int3, ShashInt3> &pos)
|
||||
void CPlayerInterface::tileHidden(const std::unordered_set<int3> &pos)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
for (auto & po : pos)
|
||||
adventureInt->minimap->updateTile(po);
|
||||
adventureInt->onMapTilesChanged(pos);
|
||||
}
|
||||
|
||||
void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
|
||||
@ -1286,33 +1224,24 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
|
||||
if (bonus.type == Bonus::NONE)
|
||||
return;
|
||||
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain)
|
||||
{
|
||||
//recalculate paths because hero has lost bonus influencing pathfinding
|
||||
paths.erasePath(hero);
|
||||
localState->erasePath(hero);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version )
|
||||
{
|
||||
h & wanderingHeroes;
|
||||
h & towns;
|
||||
h & sleepingHeroes;
|
||||
h & paths;
|
||||
h & spellbookSettings;
|
||||
}
|
||||
|
||||
void CPlayerInterface::saveGame( BinarySerializer & h, const int version )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
serializeTempl(h,version);
|
||||
localState->serialize(h, version);
|
||||
}
|
||||
|
||||
void CPlayerInterface::loadGame( BinaryDeserializer & h, const int version )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
serializeTempl(h,version);
|
||||
localState->serialize(h, version);
|
||||
firstCall = -1;
|
||||
}
|
||||
|
||||
@ -1330,14 +1259,8 @@ void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path )
|
||||
|
||||
setMovementStatus(true);
|
||||
|
||||
if (adventureInt && adventureInt->isHeroSleeping(h))
|
||||
{
|
||||
adventureInt->sleepWake->clickLeft(true, false);
|
||||
adventureInt->sleepWake->clickLeft(false, true);
|
||||
//could've just called
|
||||
//adventureInt->fsleepWake();
|
||||
//but no authentic button click/sound ;-)
|
||||
}
|
||||
if (localState->isHeroSleeping(h))
|
||||
localState->setHeroAwaken(h);
|
||||
|
||||
boost::thread moveHeroTask(std::bind(&CPlayerInterface::doMoveHero,this,h,path));
|
||||
}
|
||||
@ -1347,7 +1270,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto onEnd = [=](){ cb->selectionMade(0, queryID); };
|
||||
|
||||
if (stillMoveHero.get() == DURING_MOVE && paths.hasPath(down) && paths.getPath(down).nodes.size() > 1) //to ignore calls on passing through garrisons
|
||||
if (stillMoveHero.get() == DURING_MOVE && localState->hasPath(down) && localState->getPath(down).nodes.size() > 1) //to ignore calls on passing through garrisons
|
||||
{
|
||||
onEnd();
|
||||
return;
|
||||
@ -1406,6 +1329,12 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CPlayerInterface::showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)
|
||||
{
|
||||
heroExchangeStarted(hero1, hero2, QueryID(-1));
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -1415,48 +1344,51 @@ void CPlayerInterface::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanc
|
||||
void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
|
||||
//redraw minimap if owner changed
|
||||
if (sop->what == ObjProperty::OWNER)
|
||||
{
|
||||
const CGObjectInstance * obj = cb->getObj(sop->id);
|
||||
std::set<int3> pos = obj->getBlockedPos();
|
||||
|
||||
for(auto & po : pos)
|
||||
{
|
||||
if(cb->isVisible(po))
|
||||
adventureInt->minimap->updateTile(po);
|
||||
}
|
||||
if(obj->ID == Obj::TOWN)
|
||||
{
|
||||
if(obj->tempOwner == playerID)
|
||||
towns.push_back(static_cast<const CGTownInstance *>(obj));
|
||||
else
|
||||
towns -= obj;
|
||||
auto town = static_cast<const CGTownInstance *>(obj);
|
||||
|
||||
adventureInt->townList->update();
|
||||
adventureInt->minimap->update();
|
||||
if(obj->tempOwner == playerID)
|
||||
localState->addOwnedTown(town);
|
||||
else
|
||||
localState->removeOwnedTown(town);
|
||||
|
||||
adventureInt->onTownChanged(town);
|
||||
}
|
||||
assert(cb->getTownsInfo().size() == towns.size());
|
||||
|
||||
std::set<int3> pos = obj->getBlockedPos();
|
||||
std::unordered_set<int3> upos(pos.begin(), pos.end());
|
||||
adventureInt->onMapTilesChanged(upos);
|
||||
|
||||
assert(cb->getTownsInfo().size() == localState->getOwnedTowns().size());
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::initializeHeroTownList()
|
||||
{
|
||||
if(!wanderingHeroes.size())
|
||||
if(localState->getWanderingHeroes().empty())
|
||||
{
|
||||
std::vector<const CGHeroInstance*> heroes = cb->getHeroesInfo();
|
||||
for(auto & hero : heroes)
|
||||
for(auto & hero : cb->getHeroesInfo())
|
||||
{
|
||||
if(!hero->inTownGarrison)
|
||||
wanderingHeroes.push_back(hero);
|
||||
localState->addWanderingHero(hero);
|
||||
}
|
||||
}
|
||||
|
||||
if(!towns.size())
|
||||
towns = cb->getTownsInfo();
|
||||
if(localState->getOwnedTowns().empty())
|
||||
{
|
||||
for(auto & town : cb->getTownsInfo())
|
||||
localState->addOwnedTown(town);
|
||||
}
|
||||
|
||||
if(adventureInt)
|
||||
adventureInt->updateNextHero(nullptr);
|
||||
adventureInt->onHeroChanged(nullptr);
|
||||
}
|
||||
|
||||
void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level)
|
||||
@ -1545,7 +1477,7 @@ void CPlayerInterface::objectRemoved(const CGObjectInstance * obj)
|
||||
void CPlayerInterface::objectRemovedAfter()
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
adventureInt->minimap->update();
|
||||
adventureInt->onMapTilesChanged(boost::none);
|
||||
}
|
||||
|
||||
void CPlayerInterface::playerBlocked(int reason, bool start)
|
||||
@ -1558,8 +1490,7 @@ void CPlayerInterface::playerBlocked(int reason, bool start)
|
||||
boost::unique_lock<boost::mutex> lock(eventsM); //TODO: copied from yourTurn, no idea if it's needed
|
||||
LOCPLINT = this;
|
||||
GH.curInt = this;
|
||||
adventureInt->selection = nullptr;
|
||||
adventureInt->setPlayer(playerID);
|
||||
adventureInt->onCurrentPlayerChanged(playerID);
|
||||
std::string msg = CGI->generaltexth->translate("vcmi.adventureMap.playerAttacked");
|
||||
boost::replace_first(msg, "%s", cb->getStartInfo()->playerInfos.find(playerID)->second.name);
|
||||
std::vector<std::shared_ptr<CComponent>> cmp;
|
||||
@ -1636,10 +1567,12 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul
|
||||
if (victoryLossCheckResult.loss())
|
||||
showInfoDialog(CGI->generaltexth->allTexts[95]);
|
||||
|
||||
//we assume GH.curInt == LOCPLINT
|
||||
assert(GH.curInt == LOCPLINT);
|
||||
auto previousInterface = LOCPLINT; //without multiple player interfaces some of lines below are useless, but for hotseat we wanna swap player interface temporarily
|
||||
|
||||
LOCPLINT = this; //this is needed for dialog to show and avoid freeze, dialog showing logic should be reworked someday
|
||||
GH.curInt = this; //waiting for dialogs requires this to get events
|
||||
|
||||
if(!makingTurn)
|
||||
{
|
||||
makingTurn = true; //also needed for dialog to show with current implementation
|
||||
@ -1657,9 +1590,7 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul
|
||||
if(adventureInt)
|
||||
{
|
||||
GH.terminate_cond->setn(true);
|
||||
adventureInt->deactivate();
|
||||
if (GH.topInt() == adventureInt)
|
||||
GH.popInt(adventureInt);
|
||||
GH.popInts(GH.listInt.size());
|
||||
adventureInt.reset();
|
||||
}
|
||||
}
|
||||
@ -1677,7 +1608,8 @@ void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResul
|
||||
requestReturningToMainMenu(false);
|
||||
}
|
||||
|
||||
if (GH.curInt == this) GH.curInt = nullptr;
|
||||
if (GH.curInt == this)
|
||||
GH.curInt = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1720,7 +1652,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
|
||||
GH.popInts(1);
|
||||
|
||||
if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
|
||||
paths.erasePath(caster);
|
||||
localState->erasePath(caster);
|
||||
|
||||
const spells::Spell * spell = CGI->spells()->getByIndex(spellID);
|
||||
auto castSoundPath = spell->getCastSound();
|
||||
@ -1728,56 +1660,6 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
|
||||
CCS->soundh->playSound(castSoundPath);
|
||||
}
|
||||
|
||||
void CPlayerInterface::acceptTurn()
|
||||
{
|
||||
if (settings["session"]["autoSkip"].Bool())
|
||||
{
|
||||
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt().get()))
|
||||
iw->close();
|
||||
}
|
||||
|
||||
if(CSH->howManyPlayerInterfaces() > 1)
|
||||
{
|
||||
waitWhileDialog(); // wait for player to accept turn in hot-seat mode
|
||||
|
||||
adventureInt->startTurn();
|
||||
}
|
||||
|
||||
adventureInt->initializeNewTurn();
|
||||
|
||||
// warn player if he has no town
|
||||
if (cb->howManyTowns() == 0)
|
||||
{
|
||||
auto playerColor = *cb->getPlayerID();
|
||||
|
||||
std::vector<Component> components;
|
||||
components.emplace_back(Component::EComponentType::FLAG, playerColor.getNum(), 0, 0);
|
||||
MetaString text;
|
||||
|
||||
const auto & optDaysWithoutCastle = cb->getPlayerState(playerColor)->daysWithoutCastle;
|
||||
|
||||
if(optDaysWithoutCastle)
|
||||
{
|
||||
auto daysWithoutCastle = optDaysWithoutCastle.value();
|
||||
if (daysWithoutCastle < 6)
|
||||
{
|
||||
text.addTxt(MetaString::ARRAY_TXT,128); //%s, you only have %d days left to capture a town or you will be banished from this land.
|
||||
text.addReplacement(MetaString::COLOR, playerColor.getNum());
|
||||
text.addReplacement(7 - daysWithoutCastle);
|
||||
}
|
||||
else if (daysWithoutCastle == 6)
|
||||
{
|
||||
text.addTxt(MetaString::ARRAY_TXT,129); //%s, this is your last day to capture a town or you will be banished from this land.
|
||||
text.addReplacement(MetaString::COLOR, playerColor.getNum());
|
||||
}
|
||||
|
||||
showInfoDialogAndWait(components, text);
|
||||
}
|
||||
else
|
||||
logGlobal->warn("Player has no towns, but daysWithoutCastle is not set");
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::tryDiggging(const CGHeroInstance * h)
|
||||
{
|
||||
int msgToShow = -1;
|
||||
@ -1810,21 +1692,6 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance * h)
|
||||
showInfoDialog(CGI->generaltexth->allTexts[msgToShow]);
|
||||
}
|
||||
|
||||
void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
|
||||
{
|
||||
bool isHero = dynamic_cast<const CGHeroInstance *>(specific) != nullptr;
|
||||
bool changedHero = dynamic_cast<const CGHeroInstance *>(specific) != adventureInt->curHero();
|
||||
bool isTown = dynamic_cast<const CGTownInstance *>(specific) != nullptr;
|
||||
|
||||
bool update = (isHero && changedHero) || (isTown);
|
||||
// If infobar is showing components and we request an update to hero
|
||||
// do not force infobar tick here, it will prevents us to show components just picked up
|
||||
if(adventureInt->infoBar->showingComponents() && !update)
|
||||
return;
|
||||
|
||||
adventureInt->infoBar->showSelection();
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleNewRoundFirst( int round )
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -1933,14 +1800,14 @@ void CPlayerInterface::artifactPut(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
}
|
||||
|
||||
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
for(auto isa : GH.listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
@ -1955,7 +1822,7 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), dst.artHolder);
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
|
||||
bool redraw = true;
|
||||
// If a bulk transfer has arrived, then redrawing only the last art movement.
|
||||
@ -1984,7 +1851,7 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
for(auto isa : GH.listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
@ -1997,7 +1864,7 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
||||
updateInfo(hero);
|
||||
adventureInt->onHeroChanged(hero);
|
||||
for(auto isa : GH.listInt)
|
||||
{
|
||||
auto artWin = dynamic_cast<CArtifactHolder*>(isa.get());
|
||||
@ -2006,34 +1873,6 @@ void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::playerStartsTurn(PlayerColor player)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
if (!vstd::contains (GH.listInt, adventureInt))
|
||||
{
|
||||
GH.popInts ((int)GH.listInt.size()); //after map load - remove everything else
|
||||
GH.pushInt (adventureInt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player == playerID)
|
||||
adventureInt->infoBar->showSelection();
|
||||
while (GH.listInt.front() != adventureInt && !dynamic_cast<CInfoWindow*>(GH.listInt.front().get())) //don't remove dialogs that expect query answer
|
||||
GH.popInts(1);
|
||||
}
|
||||
|
||||
if(CSH->howManyPlayerInterfaces() == 1)
|
||||
{
|
||||
GH.curInt = this;
|
||||
adventureInt->startTurn();
|
||||
}
|
||||
if (player != playerID && this == LOCPLINT)
|
||||
{
|
||||
waitWhileDialog();
|
||||
adventureInt->aiTurnStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayerInterface::waitForAllDialogs(bool unlockPim)
|
||||
{
|
||||
while(!dialogs.empty())
|
||||
@ -2049,15 +1888,9 @@ void CPlayerInterface::proposeLoadingGame()
|
||||
showYesNoDialog(CGI->generaltexth->allTexts[68], [](){ GH.pushUserEvent(EUserEvent::RETURN_TO_MENU_LOAD); }, nullptr);
|
||||
}
|
||||
|
||||
CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
|
||||
{
|
||||
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;
|
||||
spellbookLastTabBattle = spellbookLastTabAdvmap = 4;
|
||||
}
|
||||
|
||||
bool CPlayerInterface::capturedAllEvents()
|
||||
{
|
||||
if (duringMovement)
|
||||
if(duringMovement)
|
||||
{
|
||||
//just inform that we are capturing events. they will be processed by heroMoved() in client thread.
|
||||
return true;
|
||||
@ -2065,7 +1898,7 @@ bool CPlayerInterface::capturedAllEvents()
|
||||
|
||||
bool needToLockAdventureMap = adventureInt && adventureInt->active && CGI->mh->hasOngoingAnimations();
|
||||
|
||||
if (ignoreEvents || needToLockAdventureMap)
|
||||
if (ignoreEvents || needToLockAdventureMap || isAutoFightOn)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> un(eventsM);
|
||||
while(!SDLEventsQueue.empty())
|
||||
@ -2245,15 +2078,6 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
if (!showingDialog->get())
|
||||
GH.fakeMouseMove();
|
||||
|
||||
|
||||
//todo: this should be in main thread
|
||||
if (adventureInt)
|
||||
{
|
||||
// (i == 0) means hero went through all the path
|
||||
adventureInt->updateMoveHero(h, (i != 0));
|
||||
adventureInt->updateNextHero(h);
|
||||
}
|
||||
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
setMovementStatus(false);
|
||||
}
|
||||
|
@ -9,16 +9,10 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../lib/FunctionList.h"
|
||||
#include "../lib/CGameInterface.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "gui/CIntObject.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define sprintf_s snprintf
|
||||
#endif
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class Artifact;
|
||||
@ -37,7 +31,7 @@ struct CPathsInfo;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CButton;
|
||||
class CAdvMapInt;
|
||||
class CAdventureMapInterface;
|
||||
class CCastleInterface;
|
||||
class BattleInterface;
|
||||
class CComponent;
|
||||
@ -51,103 +45,63 @@ class ClickableR;
|
||||
class Hoverable;
|
||||
class KeyInterested;
|
||||
class MotionInterested;
|
||||
class PlayerLocalState;
|
||||
class TimeInterested;
|
||||
class IShowable;
|
||||
|
||||
struct SDL_Surface;
|
||||
union SDL_Event;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class mutex;
|
||||
class recursive_mutex;
|
||||
}
|
||||
|
||||
class CPlayerInterface;
|
||||
|
||||
class HeroPathStorage
|
||||
{
|
||||
CPlayerInterface & owner;
|
||||
|
||||
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
|
||||
|
||||
public:
|
||||
explicit HeroPathStorage(CPlayerInterface &owner);
|
||||
|
||||
void setPath(const CGHeroInstance *h, const CGPath & path);
|
||||
bool setPath(const CGHeroInstance *h, const int3 & destination);
|
||||
|
||||
const CGPath & getPath(const CGHeroInstance *h) const;
|
||||
bool hasPath(const CGHeroInstance *h) const;
|
||||
|
||||
void removeLastNode(const CGHeroInstance *h);
|
||||
void erasePath(const CGHeroInstance *h);
|
||||
void verifyPath(const CGHeroInstance *h);
|
||||
|
||||
template <typename Handler>
|
||||
void serialize( Handler &h, int version );
|
||||
};
|
||||
|
||||
/// Central class for managing user interface logic
|
||||
class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
{
|
||||
public:
|
||||
HeroPathStorage paths;
|
||||
bool duringMovement;
|
||||
bool ignoreEvents;
|
||||
size_t numOfMovedArts;
|
||||
|
||||
// -1 - just loaded game; 1 - just started game; 0 otherwise
|
||||
int firstCall;
|
||||
int autosaveCount;
|
||||
static const int SAVES_COUNT = 5;
|
||||
|
||||
std::pair<const CCreatureSet *, const CCreatureSet *> lastBattleArmies;
|
||||
bool allowBattleReplay = false;
|
||||
std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
|
||||
|
||||
std::shared_ptr<Environment> env;
|
||||
ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
|
||||
int3 destinationTeleportPos;
|
||||
|
||||
public: // TODO: make private
|
||||
std::shared_ptr<Environment> env;
|
||||
|
||||
std::unique_ptr<PlayerLocalState> localState;
|
||||
|
||||
//minor interfaces
|
||||
CondSh<bool> *showingDialog; //indicates if dialog box is displayed
|
||||
|
||||
static boost::recursive_mutex *pim;
|
||||
bool makingTurn; //if player is already making his turn
|
||||
int firstCall; // -1 - just loaded game; 1 - just started game; 0 otherwise
|
||||
int autosaveCount;
|
||||
static const int SAVES_COUNT = 5;
|
||||
|
||||
CCastleInterface * castleInt; //nullptr if castle window isn't opened
|
||||
static std::shared_ptr<BattleInterface> battleInt; //nullptr if no battle
|
||||
CInGameConsole * cingconsole;
|
||||
|
||||
std::shared_ptr<CCallback> cb; //to communicate with engine
|
||||
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
|
||||
|
||||
std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||
|
||||
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
|
||||
std::vector<const CGTownInstance *> towns; //our towns on the adventure map
|
||||
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
|
||||
|
||||
//During battle is quick combat mode is used
|
||||
std::shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
|
||||
bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
|
||||
bool allowBattleReplay = false;
|
||||
std::pair<const CCreatureSet *, const CCreatureSet *> lastBattleArmies;
|
||||
|
||||
struct SpellbookLastSetting
|
||||
{
|
||||
int spellbookLastPageBattle, spellbokLastPageAdvmap; //on which page we left spellbook
|
||||
int spellbookLastTabBattle, spellbookLastTabAdvmap; //on which page we left spellbook
|
||||
|
||||
SpellbookLastSetting();
|
||||
template <typename Handler> void serialize( Handler &h, const int version )
|
||||
{
|
||||
h & spellbookLastPageBattle;
|
||||
h & spellbokLastPageAdvmap;
|
||||
h & spellbookLastTabBattle;
|
||||
h & spellbookLastTabAdvmap;
|
||||
}
|
||||
} spellbookSettings;
|
||||
protected: // Call-ins from server, should not be called directly, but only via GameInterface
|
||||
|
||||
void update() override;
|
||||
void initializeHeroTownList();
|
||||
int getLastIndex(std::string namePrefix);
|
||||
void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
|
||||
|
||||
//overridden funcs from CGameInterface
|
||||
void garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override;
|
||||
|
||||
void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override; //what: 1 - built, 2 - demolished
|
||||
|
||||
void artifactPut(const ArtifactLocation &al) override;
|
||||
@ -172,22 +126,16 @@ public:
|
||||
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 showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
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(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) 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 showPuzzleMap() override;
|
||||
void viewWorldMap() override;
|
||||
void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override;
|
||||
void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
|
||||
void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
|
||||
void showTavernWindow(const CGObjectInstance *townOrTavern) override;
|
||||
void showThievesGuildWindow (const CGObjectInstance * obj) override;
|
||||
void showQuestLog() override;
|
||||
void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; //called when a hero casts a spell
|
||||
void tileHidden(const std::unordered_set<int3, ShashInt3> &pos) override; //called when given tiles become hidden under fog of war
|
||||
void tileRevealed(const std::unordered_set<int3, ShashInt3> &pos) override; //called when fog of war disappears from given tiles
|
||||
void tileHidden(const std::unordered_set<int3> &pos) override; //called when given tiles become hidden under fog of war
|
||||
void tileRevealed(const std::unordered_set<int3> &pos) override; //called when fog of war disappears from given tiles
|
||||
void newObject(const CGObjectInstance * obj) override;
|
||||
void availableArtifactsChanged(const CGBlackMarket *bm = nullptr) override; //bm may be nullptr, then artifacts are changed in the global pool (used by merchants in towns)
|
||||
void yourTurn() override;
|
||||
@ -230,21 +178,23 @@ public:
|
||||
void yourTacticPhase(int distance) override;
|
||||
void forceEndTacticPhase() override;
|
||||
|
||||
//-------------//
|
||||
public: // public interface for use by client via LOCPLINT access
|
||||
|
||||
// part of GameInterface that is also used by client code
|
||||
void showPuzzleMap() override;
|
||||
void viewWorldMap() override;
|
||||
void showQuestLog() override;
|
||||
void showThievesGuildWindow (const CGObjectInstance * obj) override;
|
||||
void showTavernWindow(const CGObjectInstance *townOrTavern) override;
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
|
||||
void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2);
|
||||
void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<bool()> onYes);
|
||||
void garrisonsChanged(std::vector<const CGObjectInstance *> objs);
|
||||
void garrisonChanged(const CGObjectInstance * obj);
|
||||
void heroKilled(const CGHeroInstance* hero);
|
||||
void waitWhileDialog(bool unlockPim = true);
|
||||
void waitForAllDialogs(bool unlockPim = true);
|
||||
void redrawHeroWin(const CGHeroInstance * hero);
|
||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
||||
void updateInfo(const CGObjectInstance * specific);
|
||||
void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
|
||||
void activateForSpectator(); // TODO: spectator probably need own player interface class
|
||||
|
||||
// show dialogs
|
||||
void showInfoDialog(const std::string &text, std::shared_ptr<CComponent> component);
|
||||
void showInfoDialog(const std::string &text, const std::vector<std::shared_ptr<CComponent>> & components = std::vector<std::shared_ptr<CComponent>>(), int soundID = 0);
|
||||
void showInfoDialogAndWait(std::vector<Component> & components, const MetaString & text);
|
||||
@ -253,10 +203,8 @@ public:
|
||||
void stopMovement();
|
||||
void moveHero(const CGHeroInstance *h, const CGPath& path);
|
||||
|
||||
void acceptTurn(); //used during hot seat after your turn message is close
|
||||
void tryDiggging(const CGHeroInstance *h);
|
||||
void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard;
|
||||
void requestReturningToMainMenu(bool won);
|
||||
void proposeLoadingGame();
|
||||
|
||||
///returns true if all events are processed internally
|
||||
@ -266,11 +214,6 @@ public:
|
||||
~CPlayerInterface();
|
||||
|
||||
private:
|
||||
|
||||
template <typename Handler> void serializeTempl(Handler &h, const int version);
|
||||
|
||||
private:
|
||||
|
||||
struct IgnoreEvents
|
||||
{
|
||||
CPlayerInterface & owner;
|
||||
@ -285,14 +228,18 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool duringMovement;
|
||||
bool ignoreEvents;
|
||||
size_t numOfMovedArts;
|
||||
|
||||
void heroKilled(const CGHeroInstance* hero);
|
||||
void garrisonsChanged(std::vector<const CGObjectInstance *> objs);
|
||||
void requestReturningToMainMenu(bool won);
|
||||
void acceptTurn(); //used during hot seat after your turn message is close
|
||||
void initializeHeroTownList();
|
||||
int getLastIndex(std::string namePrefix);
|
||||
void doMoveHero(const CGHeroInstance *h, CGPath path);
|
||||
void setMovementStatus(bool value);
|
||||
|
||||
/// Performs autosave, if needed according to settings
|
||||
void performAutosave();
|
||||
};
|
||||
|
||||
/// Provides global access to instance of interface of currently active player
|
||||
extern CPlayerInterface * LOCPLINT;
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "CPlayerInterface.h"
|
||||
#include "CServerHandler.h"
|
||||
#include "ClientNetPackVisitors.h"
|
||||
#include "adventureMap/CAdvMapInt.h"
|
||||
#include "adventureMap/CAdventureMapInterface.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "mapView/mapHandler.h"
|
||||
|
@ -235,7 +235,7 @@ public:
|
||||
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override {};
|
||||
|
||||
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {}
|
||||
void changeFogOfWar(std::unordered_set<int3, ShashInt3> & tiles, PlayerColor player, bool hide) override {}
|
||||
void changeFogOfWar(std::unordered_set<int3> & tiles, PlayerColor player, bool hide) override {}
|
||||
|
||||
void setObjProperty(ObjectInstanceID objid, int prop, si64 val) override {}
|
||||
|
||||
|
@ -8,13 +8,12 @@
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "ClientCommandManager.h"
|
||||
|
||||
#include "Client.h"
|
||||
#include "adventureMap/CInGameConsole.h"
|
||||
#include "adventureMap/CAdvMapInt.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "PlayerLocalState.h"
|
||||
#include "CServerHandler.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "../lib/NetPacks.h"
|
||||
@ -387,12 +386,12 @@ void ClientCommandManager::handleBonusesCommand(std::istringstream & singleWordB
|
||||
ss << b;
|
||||
return ss.str();
|
||||
};
|
||||
printCommandMessage("Bonuses of " + adventureInt->curArmy()->getObjectName() + "\n");
|
||||
printCommandMessage(format(adventureInt->curArmy()->getBonusList()) + "\n");
|
||||
printCommandMessage("Bonuses of " + LOCPLINT->localState->getCurrentArmy()->getObjectName() + "\n");
|
||||
printCommandMessage(format(LOCPLINT->localState->getCurrentArmy()->getBonusList()) + "\n");
|
||||
|
||||
printCommandMessage("\nInherited bonuses:\n");
|
||||
TCNodes parents;
|
||||
adventureInt->curArmy()->getParents(parents);
|
||||
LOCPLINT->localState->getCurrentArmy()->getParents(parents);
|
||||
for(const CBonusSystemNode *parent : parents)
|
||||
{
|
||||
printCommandMessage(std::string("\nBonuses from ") + typeid(*parent).name() + "\n" + format(*parent->getAllBonuses(Selector::all, Selector::all)) + "\n");
|
||||
@ -416,7 +415,7 @@ void ClientCommandManager::handleTellCommand(std::istringstream& singleWordBuffe
|
||||
|
||||
void ClientCommandManager::handleMpCommand()
|
||||
{
|
||||
if(const CGHeroInstance* h = adventureInt->curHero())
|
||||
if(const CGHeroInstance* h = LOCPLINT->localState->getCurrentHero())
|
||||
printCommandMessage(std::to_string(h->movement) + "; max: " + std::to_string(h->maxMovePoints(true)) + "/" + std::to_string(h->maxMovePoints(false)) + "\n");
|
||||
}
|
||||
|
||||
@ -602,7 +601,7 @@ void ClientCommandManager::processCommand(const std::string & message, bool call
|
||||
else if(commandName == "tell")
|
||||
handleTellCommand(singleWordBuffer);
|
||||
|
||||
else if(commandName == "mp" && adventureInt)
|
||||
else if(commandName == "mp" && LOCPLINT)
|
||||
handleMpCommand();
|
||||
|
||||
else if (commandName == "set")
|
||||
|
268
client/PlayerLocalState.cpp
Normal file
268
client/PlayerLocalState.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* PlayerLocalState.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "PlayerLocalState.h"
|
||||
|
||||
#include "../CCallback.h"
|
||||
#include "../lib/CPathfinder.h"
|
||||
#include "../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../lib/mapObjects/CGTownInstance.h"
|
||||
#include "CPlayerInterface.h"
|
||||
#include "adventureMap/CAdventureMapInterface.h"
|
||||
|
||||
PlayerLocalState::PlayerLocalState(CPlayerInterface & owner)
|
||||
: owner(owner)
|
||||
, currentSelection(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void PlayerLocalState::saveHeroPaths(std::map<const CGHeroInstance *, int3> & pathsMap)
|
||||
{
|
||||
for(auto & p : paths)
|
||||
{
|
||||
if(p.second.nodes.size())
|
||||
pathsMap[p.first] = p.second.endPos();
|
||||
else
|
||||
logGlobal->debug("%s has assigned an empty path! Ignoring it...", p.first->getNameTranslated());
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerLocalState::loadHeroPaths(std::map<const CGHeroInstance *, int3> & pathsMap)
|
||||
{
|
||||
if(owner.cb)
|
||||
{
|
||||
for(auto & p : pathsMap)
|
||||
{
|
||||
CGPath path;
|
||||
owner.cb->getPathsInfo(p.first)->getPath(path, p.second);
|
||||
paths[p.first] = path;
|
||||
logGlobal->trace("Restored path for hero %s leading to %s with %d nodes", p.first->nodeName(), p.second.toString(), path.nodes.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerLocalState::setPath(const CGHeroInstance * h, const CGPath & path)
|
||||
{
|
||||
paths[h] = path;
|
||||
}
|
||||
|
||||
const CGPath & PlayerLocalState::getPath(const CGHeroInstance * h) const
|
||||
{
|
||||
assert(hasPath(h));
|
||||
return paths.at(h);
|
||||
}
|
||||
|
||||
bool PlayerLocalState::hasPath(const CGHeroInstance * h) const
|
||||
{
|
||||
return paths.count(h) > 0;
|
||||
}
|
||||
|
||||
bool PlayerLocalState::setPath(const CGHeroInstance * h, const int3 & destination)
|
||||
{
|
||||
CGPath path;
|
||||
if(!owner.cb->getPathsInfo(h)->getPath(path, destination))
|
||||
return false;
|
||||
|
||||
setPath(h, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerLocalState::removeLastNode(const CGHeroInstance * h)
|
||||
{
|
||||
assert(hasPath(h));
|
||||
if(!hasPath(h))
|
||||
return;
|
||||
|
||||
auto & path = paths[h];
|
||||
path.nodes.pop_back();
|
||||
if(path.nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
|
||||
erasePath(h);
|
||||
}
|
||||
|
||||
void PlayerLocalState::erasePath(const CGHeroInstance * h)
|
||||
{
|
||||
paths.erase(h);
|
||||
adventureInt->onHeroChanged(h);
|
||||
}
|
||||
|
||||
void PlayerLocalState::verifyPath(const CGHeroInstance * h)
|
||||
{
|
||||
if(!hasPath(h))
|
||||
return;
|
||||
setPath(h, getPath(h).endPos());
|
||||
}
|
||||
|
||||
const CGHeroInstance * PlayerLocalState::getCurrentHero() const
|
||||
{
|
||||
if(currentSelection && currentSelection->ID == Obj::HERO)
|
||||
return dynamic_cast<const CGHeroInstance *>(currentSelection);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CGHeroInstance * PlayerLocalState::getNextWanderingHero(const CGHeroInstance * currentHero)
|
||||
{
|
||||
bool currentHeroFound = false;
|
||||
const CGHeroInstance * firstSuitable = nullptr;
|
||||
const CGHeroInstance * nextSuitable = nullptr;
|
||||
|
||||
for(const auto * hero : getWanderingHeroes())
|
||||
{
|
||||
if (hero == currentHero)
|
||||
{
|
||||
currentHeroFound = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isHeroSleeping(hero))
|
||||
continue;
|
||||
|
||||
if (hero->movement == 0)
|
||||
continue;
|
||||
|
||||
if (!firstSuitable)
|
||||
firstSuitable = hero;
|
||||
|
||||
if (!nextSuitable && currentHeroFound)
|
||||
nextSuitable = hero;
|
||||
}
|
||||
|
||||
// if we found suitable hero after currently selected hero -> return this hero
|
||||
if (nextSuitable)
|
||||
return nextSuitable;
|
||||
|
||||
// othervice -> loop over and return first suitable hero in the list (or null if none)
|
||||
return firstSuitable;
|
||||
}
|
||||
|
||||
const CGTownInstance * PlayerLocalState::getCurrentTown() const
|
||||
{
|
||||
if(currentSelection && currentSelection->ID == Obj::TOWN)
|
||||
return dynamic_cast<const CGTownInstance *>(currentSelection);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CArmedInstance * PlayerLocalState::getCurrentArmy() const
|
||||
{
|
||||
if(currentSelection)
|
||||
return dynamic_cast<const CArmedInstance *>(currentSelection);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PlayerLocalState::setSelection(const CArmedInstance * selection)
|
||||
{
|
||||
if (currentSelection == selection)
|
||||
return;
|
||||
|
||||
currentSelection = selection;
|
||||
|
||||
if (selection)
|
||||
adventureInt->onSelectionChanged(selection);
|
||||
}
|
||||
|
||||
bool PlayerLocalState::isHeroSleeping(const CGHeroInstance * hero) const
|
||||
{
|
||||
return vstd::contains(sleepingHeroes, hero);
|
||||
}
|
||||
|
||||
void PlayerLocalState::setHeroAsleep(const CGHeroInstance * hero)
|
||||
{
|
||||
assert(hero);
|
||||
assert(vstd::contains(wanderingHeroes, hero));
|
||||
assert(!vstd::contains(sleepingHeroes, hero));
|
||||
|
||||
sleepingHeroes.push_back(hero);
|
||||
}
|
||||
|
||||
void PlayerLocalState::setHeroAwaken(const CGHeroInstance * hero)
|
||||
{
|
||||
assert(hero);
|
||||
assert(vstd::contains(wanderingHeroes, hero));
|
||||
assert(vstd::contains(sleepingHeroes, hero));
|
||||
|
||||
vstd::erase(sleepingHeroes, hero);
|
||||
}
|
||||
|
||||
const std::vector<const CGHeroInstance *> & PlayerLocalState::getWanderingHeroes()
|
||||
{
|
||||
return wanderingHeroes;
|
||||
}
|
||||
|
||||
const CGHeroInstance * PlayerLocalState::getWanderingHero(size_t index)
|
||||
{
|
||||
if(index < wanderingHeroes.size())
|
||||
return wanderingHeroes[index];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PlayerLocalState::addWanderingHero(const CGHeroInstance * hero)
|
||||
{
|
||||
assert(hero);
|
||||
assert(!vstd::contains(wanderingHeroes, hero));
|
||||
wanderingHeroes.push_back(hero);
|
||||
}
|
||||
|
||||
void PlayerLocalState::removeWanderingHero(const CGHeroInstance * hero)
|
||||
{
|
||||
assert(hero);
|
||||
assert(vstd::contains(wanderingHeroes, hero));
|
||||
|
||||
if (hero == currentSelection)
|
||||
{
|
||||
auto const * nextHero = getNextWanderingHero(hero);
|
||||
setSelection(nextHero);
|
||||
}
|
||||
|
||||
vstd::erase(wanderingHeroes, hero);
|
||||
vstd::erase(sleepingHeroes, hero);
|
||||
|
||||
if (currentSelection == nullptr && !wanderingHeroes.empty())
|
||||
setSelection(wanderingHeroes.front());
|
||||
|
||||
if (currentSelection == nullptr && !ownedTowns.empty())
|
||||
setSelection(ownedTowns.front());
|
||||
}
|
||||
|
||||
const std::vector<const CGTownInstance *> & PlayerLocalState::getOwnedTowns()
|
||||
{
|
||||
return ownedTowns;
|
||||
}
|
||||
|
||||
const CGTownInstance * PlayerLocalState::getOwnedTown(size_t index)
|
||||
{
|
||||
if(index < ownedTowns.size())
|
||||
return ownedTowns[index];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PlayerLocalState::addOwnedTown(const CGTownInstance * town)
|
||||
{
|
||||
assert(town);
|
||||
assert(!vstd::contains(ownedTowns, town));
|
||||
ownedTowns.push_back(town);
|
||||
}
|
||||
|
||||
void PlayerLocalState::removeOwnedTown(const CGTownInstance * town)
|
||||
{
|
||||
assert(town);
|
||||
assert(vstd::contains(ownedTowns, town));
|
||||
vstd::erase(ownedTowns, town);
|
||||
|
||||
if (town == currentSelection)
|
||||
setSelection(nullptr);
|
||||
|
||||
if (currentSelection == nullptr && !wanderingHeroes.empty())
|
||||
setSelection(wanderingHeroes.front());
|
||||
|
||||
if (currentSelection == nullptr && !ownedTowns.empty())
|
||||
setSelection(ownedTowns.front());
|
||||
}
|
111
client/PlayerLocalState.h
Normal file
111
client/PlayerLocalState.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* PlayerLocalState.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
class CArmedInstance;
|
||||
struct CGPath;
|
||||
class int3;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CPlayerInterface;
|
||||
|
||||
/// Class that contains potentially serializeable state of a local player
|
||||
class PlayerLocalState
|
||||
{
|
||||
CPlayerInterface & owner;
|
||||
|
||||
/// Currently selected object, can be town, hero or null
|
||||
const CArmedInstance * currentSelection;
|
||||
|
||||
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
|
||||
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
|
||||
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
|
||||
std::vector<const CGTownInstance *> ownedTowns; //our towns on the adventure map
|
||||
|
||||
void saveHeroPaths(std::map<const CGHeroInstance *, int3> & paths);
|
||||
void loadHeroPaths(std::map<const CGHeroInstance *, int3> & paths);
|
||||
|
||||
public:
|
||||
struct SpellbookLastSetting
|
||||
{
|
||||
//on which page we left spellbook
|
||||
int spellbookLastPageBattle = 0;
|
||||
int spellbokLastPageAdvmap = 0;
|
||||
int spellbookLastTabBattle = 4;
|
||||
int spellbookLastTabAdvmap = 4;
|
||||
|
||||
template<typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & spellbookLastPageBattle;
|
||||
h & spellbokLastPageAdvmap;
|
||||
h & spellbookLastTabBattle;
|
||||
h & spellbookLastTabAdvmap;
|
||||
}
|
||||
} spellbookSettings;
|
||||
|
||||
explicit PlayerLocalState(CPlayerInterface & owner);
|
||||
|
||||
bool isHeroSleeping(const CGHeroInstance * hero) const;
|
||||
void setHeroAsleep(const CGHeroInstance * hero);
|
||||
void setHeroAwaken(const CGHeroInstance * hero);
|
||||
|
||||
const std::vector<const CGTownInstance *> & getOwnedTowns();
|
||||
const CGTownInstance * getOwnedTown(size_t index);
|
||||
void addOwnedTown(const CGTownInstance * hero);
|
||||
void removeOwnedTown(const CGTownInstance * hero);
|
||||
|
||||
const std::vector<const CGHeroInstance *> & getWanderingHeroes();
|
||||
const CGHeroInstance * getWanderingHero(size_t index);
|
||||
const CGHeroInstance * getNextWanderingHero(const CGHeroInstance * hero);
|
||||
void addWanderingHero(const CGHeroInstance * hero);
|
||||
void removeWanderingHero(const CGHeroInstance * hero);
|
||||
|
||||
void setPath(const CGHeroInstance * h, const CGPath & path);
|
||||
bool setPath(const CGHeroInstance * h, const int3 & destination);
|
||||
|
||||
const CGPath & getPath(const CGHeroInstance * h) const;
|
||||
bool hasPath(const CGHeroInstance * h) const;
|
||||
|
||||
void removeLastNode(const CGHeroInstance * h);
|
||||
void erasePath(const CGHeroInstance * h);
|
||||
void verifyPath(const CGHeroInstance * h);
|
||||
|
||||
/// Returns currently selected object
|
||||
const CGHeroInstance * getCurrentHero() const;
|
||||
const CGTownInstance * getCurrentTown() const;
|
||||
const CArmedInstance * getCurrentArmy() const;
|
||||
|
||||
/// Changes currently selected object
|
||||
void setSelection(const CArmedInstance *sel);
|
||||
|
||||
template<typename Handler>
|
||||
void serialize(Handler & h, int version)
|
||||
{
|
||||
//WARNING: this code is broken and not used. See CClient::loadGame
|
||||
std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
|
||||
if(h.saving)
|
||||
saveHeroPaths(pathsMap);
|
||||
|
||||
h & pathsMap;
|
||||
|
||||
if(!h.saving)
|
||||
loadHeroPaths(pathsMap);
|
||||
|
||||
h & ownedTowns;
|
||||
h & wanderingHeroes;
|
||||
h & sleepingHeroes;
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -11,9 +11,6 @@
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
#include "../../lib/int3.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGObjectInstance;
|
||||
@ -23,6 +20,8 @@ class CArmedInstance;
|
||||
class IShipyard;
|
||||
struct CGPathNode;
|
||||
struct ObjectPosInfo;
|
||||
struct Component;
|
||||
class int3;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@ -43,38 +42,28 @@ class MapAudioPlayer;
|
||||
|
||||
struct MapDrawingInfo;
|
||||
|
||||
enum class EAdvMapMode
|
||||
{
|
||||
NORMAL,
|
||||
WORLD_VIEW
|
||||
};
|
||||
|
||||
/// That's a huge class which handles general adventure map actions and
|
||||
/// shows the right menu(questlog, spellbook, end turn,..) from where you
|
||||
/// can get to the towns and heroes.
|
||||
class CAdvMapInt : public CIntObject
|
||||
class CAdventureMapInterface : public CIntObject
|
||||
{
|
||||
//TODO: remove
|
||||
friend class CPlayerInterface;
|
||||
|
||||
private:
|
||||
enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8};
|
||||
enum EGameStates {NA, INGAME, WAITING};
|
||||
enum class EGameState
|
||||
{
|
||||
NOT_INITIALIZED,
|
||||
HOTSEAT_WAIT,
|
||||
MAKING_TURN,
|
||||
ENEMY_TURN,
|
||||
WORLD_VIEW
|
||||
};
|
||||
|
||||
EGameStates state;
|
||||
EAdvMapMode mode;
|
||||
|
||||
/// Currently selected object, can be town, hero or null
|
||||
const CArmedInstance *selection;
|
||||
EGameState state;
|
||||
|
||||
/// currently acting player
|
||||
PlayerColor player;
|
||||
|
||||
bool duringAITurn;
|
||||
PlayerColor currentPlayerID;
|
||||
|
||||
/// uses EDirections enum
|
||||
ui8 scrollingDir;
|
||||
bool scrollingState;
|
||||
bool scrollingCursorSet;
|
||||
|
||||
const CSpell *spellBeingCasted; //nullptr if none
|
||||
|
||||
@ -127,15 +116,13 @@ private:
|
||||
void fnextHero();
|
||||
void fendTurn();
|
||||
|
||||
void setScrollingCursor(ui8 direction) const;
|
||||
void selectionChanged();
|
||||
bool isActive();
|
||||
void adjustActiveness(bool aiTurnStart); //should be called every time at AI/human turn transition; blocks GUI during AI turn
|
||||
|
||||
const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; //checks if obj is our ashipyard and cursor is 0,0 -> returns shipyard or nullptr else
|
||||
//button updates
|
||||
void updateSleepWake(const CGHeroInstance *h);
|
||||
void updateSpellbook(const CGHeroInstance *h);
|
||||
|
||||
// update locked state of buttons
|
||||
void updateButtons();
|
||||
|
||||
void handleMapScrollingUpdate();
|
||||
|
||||
@ -145,9 +132,15 @@ private:
|
||||
|
||||
std::optional<Point> keyToMoveDirection(const SDL_Keycode & key);
|
||||
|
||||
public:
|
||||
CAdvMapInt();
|
||||
void endingTurn();
|
||||
|
||||
/// exits currently opened world view mode and returns to normal map
|
||||
void exitWorldView();
|
||||
void exitCastingMode();
|
||||
void leaveCastingMode(const int3 & castTarget);
|
||||
void abortCastingMode();
|
||||
|
||||
protected:
|
||||
// CIntObject interface implementation
|
||||
|
||||
void activate() override;
|
||||
@ -157,58 +150,69 @@ public:
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void keyPressed(const SDL_Keycode & key) override;
|
||||
void keyReleased(const SDL_Keycode & key) override;
|
||||
void mouseMoved (const Point & cursorPosition) override;
|
||||
|
||||
// public interface
|
||||
public:
|
||||
CAdventureMapInterface();
|
||||
|
||||
/// called by MapView whenever currently visible area changes
|
||||
/// visibleArea describen now visible map section measured in tiles
|
||||
void onMapViewMoved(const Rect & visibleArea, int mapLevel);
|
||||
/// Called by PlayerInterface when specified player is ready to start his turn
|
||||
void onHotseatWaitStarted(PlayerColor playerID);
|
||||
|
||||
/// Called when map audio should be paused, e.g. on combat or town scren access
|
||||
/// Called by PlayerInterface when AI or remote human player starts his turn
|
||||
void onEnemyTurnStarted(PlayerColor playerID);
|
||||
|
||||
/// Called by PlayerInterface when local human player starts his turn
|
||||
void onPlayerTurnStarted(PlayerColor playerID);
|
||||
|
||||
/// Called by PlayerInterface when interface should be switched to specified player without starting turn
|
||||
void onCurrentPlayerChanged(PlayerColor playerID);
|
||||
|
||||
/// Called by PlayerInterface when specific map tile changed and must be updated on minimap
|
||||
void onMapTilesChanged(boost::optional<std::unordered_set<int3>> positions);
|
||||
|
||||
/// Called by PlayerInterface when hero starts movement
|
||||
void onHeroMovementStarted(const CGHeroInstance * hero);
|
||||
|
||||
/// Called by PlayerInterface when hero state changed and hero list must be updated
|
||||
void onHeroChanged(const CGHeroInstance * hero);
|
||||
|
||||
/// Called by PlayerInterface when town state changed and town list must be updated
|
||||
void onTownChanged(const CGTownInstance * town);
|
||||
|
||||
/// Called when currently selected object changes
|
||||
void onSelectionChanged(const CArmedInstance *sel);
|
||||
|
||||
/// Called when map audio should be paused, e.g. on combat or town screen access
|
||||
void onAudioPaused();
|
||||
|
||||
/// Called when map audio should be resume, opposite to onPaused
|
||||
void onAudioResumed();
|
||||
|
||||
void select(const CArmedInstance *sel, bool centerView = true);
|
||||
/// Requests to display provided information inside infobox
|
||||
void showInfoBoxMessage(const std::vector<Component> & components, std::string message, int timer);
|
||||
|
||||
/// Changes position on map to center selected location
|
||||
void centerOnTile(int3 on);
|
||||
void centerOnObject(const CGObjectInstance *obj);
|
||||
|
||||
bool isHeroSleeping(const CGHeroInstance *hero);
|
||||
void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
|
||||
int getNextHeroIndex(int startIndex); //for Next Hero button - cycles awake heroes with movement only
|
||||
|
||||
void setPlayer(PlayerColor Player);
|
||||
void startHotSeatWait(PlayerColor Player);
|
||||
void startTurn();
|
||||
void initializeNewTurn();
|
||||
void endingTurn();
|
||||
void aiTurnStarted();
|
||||
|
||||
void quickCombatLock(); //should be called when quick battle started
|
||||
void quickCombatUnlock();
|
||||
/// called by MapView whenever currently visible area changes
|
||||
/// visibleArea describes now visible map section measured in tiles
|
||||
void onMapViewMoved(const Rect & visibleArea, int mapLevel);
|
||||
|
||||
/// called by MapView whenever tile is clicked
|
||||
void onTileLeftClicked(const int3 & mapPos);
|
||||
|
||||
/// called by MapView whenever tile is hovered
|
||||
void onTileHovered(const int3 & mapPos);
|
||||
|
||||
/// called by MapView whenever tile is clicked
|
||||
void onTileRightClicked(const int3 & mapPos);
|
||||
|
||||
/// called by spell window when spell to cast has been selected
|
||||
void enterCastingMode(const CSpell * sp);
|
||||
void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1));
|
||||
const CGHeroInstance * curHero() const;
|
||||
const CGTownInstance * curTown() const;
|
||||
const CArmedInstance * curArmy() const;
|
||||
|
||||
void updateMoveHero(const CGHeroInstance *h, tribool hasPath = boost::logic::indeterminate);
|
||||
void updateNextHero(const CGHeroInstance *h);
|
||||
|
||||
/// returns area of screen covered by terrain (main game area)
|
||||
Rect terrainAreaPixels() const;
|
||||
|
||||
/// exits currently opened world view mode and returns to normal map
|
||||
void exitWorldView();
|
||||
|
||||
/// opens world view at default scale
|
||||
void openWorldView();
|
||||
|
||||
@ -219,4 +223,4 @@ public:
|
||||
void openWorldView(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain);
|
||||
};
|
||||
|
||||
extern std::shared_ptr<CAdvMapInt> adventureInt;
|
||||
extern std::shared_ptr<CAdventureMapInterface> adventureInt;
|
@ -11,10 +11,9 @@
|
||||
#include "StdInc.h"
|
||||
#include "CAdventureOptions.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../lobby/CCampaignInfoScreen.h"
|
||||
#include "../lobby/CScenarioInfoScreen.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
@ -41,7 +40,7 @@ CAdventureOptions::CAdventureOptions()
|
||||
puzzle->addCallback(std::bind(&CPlayerInterface::showPuzzleMap, LOCPLINT));
|
||||
|
||||
dig = std::make_shared<CButton>(Point(24, 139), "ADVDIG.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_d);
|
||||
if(const CGHeroInstance *h = adventureInt->curHero())
|
||||
if(const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero())
|
||||
dig->addCallback(std::bind(&CPlayerInterface::tryDiggging, LOCPLINT, h));
|
||||
else
|
||||
dig->block(true);
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../ClientCommandManager.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Colors.h"
|
||||
|
||||
@ -259,7 +259,7 @@ void CInGameConsole::endEnteringText(bool processEnteredText)
|
||||
clientCommandThread.detach();
|
||||
}
|
||||
else
|
||||
LOCPLINT->cb->sendMessage(txt, adventureInt->curArmy());
|
||||
LOCPLINT->cb->sendMessage(txt, LOCPLINT->localState->getCurrentArmy());
|
||||
}
|
||||
enteredText.clear();
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "CInfoBar.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
#include "CAdventureMapInterface.h"
|
||||
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/Images.h"
|
||||
@ -22,6 +22,7 @@
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
@ -114,7 +115,7 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
//get amount of halls of each level
|
||||
std::vector<int> halls(4, 0);
|
||||
for(auto town : LOCPLINT->towns)
|
||||
for(auto town : LOCPLINT->localState->getOwnedTowns())
|
||||
{
|
||||
int hallLevel = town->hallLevel();
|
||||
//negative value means no village hall, unlikely but possible
|
||||
@ -237,15 +238,15 @@ void CInfoBar::reset()
|
||||
void CInfoBar::showSelection()
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||
if(adventureInt->curHero())
|
||||
if(LOCPLINT->localState->getCurrentHero())
|
||||
{
|
||||
showHeroSelection(adventureInt->curHero());
|
||||
showHeroSelection(LOCPLINT->localState->getCurrentHero());
|
||||
return;
|
||||
}
|
||||
|
||||
if(adventureInt->curTown())
|
||||
if(LOCPLINT->localState->getCurrentTown())
|
||||
{
|
||||
showTownSelection(adventureInt->curTown());
|
||||
showTownSelection(LOCPLINT->localState->getCurrentTown());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -11,13 +11,14 @@
|
||||
#include "StdInc.h"
|
||||
#include "CList.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
#include "CAdventureMapInterface.h"
|
||||
|
||||
#include "../widgets/Images.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
@ -203,8 +204,8 @@ std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
|
||||
|
||||
void CHeroList::CHeroItem::select(bool on)
|
||||
{
|
||||
if(on && adventureInt->curHero() != hero)
|
||||
adventureInt->select(hero);
|
||||
if(on)
|
||||
LOCPLINT->localState->setSelection(hero);
|
||||
}
|
||||
|
||||
void CHeroList::CHeroItem::open()
|
||||
@ -224,19 +225,19 @@ std::string CHeroList::CHeroItem::getHoverText()
|
||||
|
||||
std::shared_ptr<CIntObject> CHeroList::createHeroItem(size_t index)
|
||||
{
|
||||
if (LOCPLINT->wanderingHeroes.size() > index)
|
||||
return std::make_shared<CHeroItem>(this, LOCPLINT->wanderingHeroes[index]);
|
||||
if (LOCPLINT->localState->getWanderingHeroes().size() > index)
|
||||
return std::make_shared<CHeroItem>(this, LOCPLINT->localState->getWanderingHero(index));
|
||||
return std::make_shared<CEmptyHeroItem>();
|
||||
}
|
||||
|
||||
CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
|
||||
CList(size, position, btnUp, btnDown, LOCPLINT->wanderingHeroes.size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
|
||||
CList(size, position, btnUp, btnDown, LOCPLINT->localState->getWanderingHeroes().size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
|
||||
{
|
||||
}
|
||||
|
||||
void CHeroList::select(const CGHeroInstance * hero)
|
||||
{
|
||||
selectIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
|
||||
selectIndex(vstd::find_pos(LOCPLINT->localState->getWanderingHeroes(), hero));
|
||||
}
|
||||
|
||||
void CHeroList::update(const CGHeroInstance * hero)
|
||||
@ -245,7 +246,7 @@ void CHeroList::update(const CGHeroInstance * hero)
|
||||
for(auto & elem : listBox->getItems())
|
||||
{
|
||||
auto item = std::dynamic_pointer_cast<CHeroItem>(elem);
|
||||
if(item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
|
||||
if(item && item->hero == hero && vstd::contains(LOCPLINT->localState->getWanderingHeroes(), hero))
|
||||
{
|
||||
item->update();
|
||||
return;
|
||||
@ -253,17 +254,17 @@ void CHeroList::update(const CGHeroInstance * hero)
|
||||
}
|
||||
//simplest solution for now: reset list and restore selection
|
||||
|
||||
listBox->resize(LOCPLINT->wanderingHeroes.size());
|
||||
if (adventureInt->curHero())
|
||||
select(adventureInt->curHero());
|
||||
listBox->resize(LOCPLINT->localState->getWanderingHeroes().size());
|
||||
if (LOCPLINT->localState->getCurrentHero())
|
||||
select(LOCPLINT->localState->getCurrentHero());
|
||||
|
||||
CList::update();
|
||||
}
|
||||
|
||||
std::shared_ptr<CIntObject> CTownList::createTownItem(size_t index)
|
||||
{
|
||||
if (LOCPLINT->towns.size() > index)
|
||||
return std::make_shared<CTownItem>(this, LOCPLINT->towns[index]);
|
||||
if (LOCPLINT->localState->getOwnedTowns().size() > index)
|
||||
return std::make_shared<CTownItem>(this, LOCPLINT->localState->getOwnedTown(index));
|
||||
return std::make_shared<CAnimImage>("ITPA", 0);
|
||||
}
|
||||
|
||||
@ -292,8 +293,8 @@ void CTownList::CTownItem::update()
|
||||
|
||||
void CTownList::CTownItem::select(bool on)
|
||||
{
|
||||
if (on && adventureInt->curTown() != town)
|
||||
adventureInt->select(town);
|
||||
if(on)
|
||||
LOCPLINT->localState->setSelection(town);
|
||||
}
|
||||
|
||||
void CTownList::CTownItem::open()
|
||||
@ -312,22 +313,22 @@ std::string CTownList::CTownItem::getHoverText()
|
||||
}
|
||||
|
||||
CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown):
|
||||
CList(size, position, btnUp, btnDown, LOCPLINT->towns.size(), 306, 307, std::bind(&CTownList::createTownItem, this, _1))
|
||||
CList(size, position, btnUp, btnDown, LOCPLINT->localState->getOwnedTowns().size(), 306, 307, std::bind(&CTownList::createTownItem, this, _1))
|
||||
{
|
||||
}
|
||||
|
||||
void CTownList::select(const CGTownInstance * town)
|
||||
{
|
||||
selectIndex(vstd::find_pos(LOCPLINT->towns, town));
|
||||
selectIndex(vstd::find_pos(LOCPLINT->localState->getOwnedTowns(), town));
|
||||
}
|
||||
|
||||
void CTownList::update(const CGTownInstance *)
|
||||
{
|
||||
//simplest solution for now: reset list and restore selection
|
||||
|
||||
listBox->resize(LOCPLINT->towns.size());
|
||||
if (adventureInt->curTown())
|
||||
select(adventureInt->curTown());
|
||||
listBox->resize(LOCPLINT->localState->getOwnedTowns().size());
|
||||
if (LOCPLINT->localState->getCurrentTown())
|
||||
select(LOCPLINT->localState->getCurrentTown());
|
||||
|
||||
CList::update();
|
||||
}
|
||||
|
@ -11,14 +11,15 @@
|
||||
#include "StdInc.h"
|
||||
#include "CMinimap.h"
|
||||
|
||||
#include "CAdvMapInt.h"
|
||||
#include "CAdventureMapInterface.h"
|
||||
|
||||
#include "../widgets/Images.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Colors.h"
|
||||
#include "../renderSDL/SDL_PixelAccess.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../windows/InfoWindows.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
@ -27,6 +28,8 @@
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapping/CMapDefines.h"
|
||||
|
||||
#include <SDL_pixels.h>
|
||||
|
||||
ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
|
||||
{
|
||||
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
|
||||
@ -225,10 +228,13 @@ void CMinimap::setAIRadar(bool on)
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CMinimap::updateTile(const int3 &pos)
|
||||
void CMinimap::updateTiles(std::unordered_set<int3> positions)
|
||||
{
|
||||
if(minimap)
|
||||
minimap->refreshTile(pos);
|
||||
{
|
||||
for (auto const & tile : positions)
|
||||
minimap->refreshTile(tile);
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../../lib/GameConstants.h"
|
||||
#include "../render/Canvas.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class ColorRGBA;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class Canvas;
|
||||
class CMinimap;
|
||||
|
||||
class CMinimapInstance : public CIntObject
|
||||
@ -68,6 +67,6 @@ public:
|
||||
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void updateTile(const int3 &pos);
|
||||
void updateTiles(std::unordered_set<int3> positions);
|
||||
};
|
||||
|
||||
|
@ -157,7 +157,7 @@ void MapAudioPlayer::updateAmbientSounds()
|
||||
};
|
||||
|
||||
int3 pos = currentSelection->getSightCenter();
|
||||
std::unordered_set<int3, ShashInt3> tiles;
|
||||
std::unordered_set<int3> tiles;
|
||||
LOCPLINT->cb->getVisibleTilesInRange(tiles, pos, CCS->soundh->ambientGetRange(), int3::DIST_CHEBYSHEV);
|
||||
for(int3 tile : tiles)
|
||||
{
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CStack.h"
|
||||
|
@ -246,14 +246,6 @@ void BattleStacksController::setActiveStack(const CStack *stack)
|
||||
|
||||
bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) const
|
||||
{
|
||||
BattleHex currentActionTarget;
|
||||
if(owner.curInt->curAction)
|
||||
{
|
||||
auto target = owner.curInt->curAction->getTarget(owner.curInt->cb.get());
|
||||
if(!target.empty())
|
||||
currentActionTarget = target.at(0).hexValue;
|
||||
}
|
||||
|
||||
//do not show box for singular war machines, stacked war machines with box shown are supported as extension feature
|
||||
if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->getCount() == 1)
|
||||
return false;
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/Point.h"
|
||||
@ -73,9 +73,9 @@ bool MapRendererBaseContext::isActiveHero(const CGObjectInstance * obj) const
|
||||
if(obj->ID == Obj::HERO)
|
||||
{
|
||||
assert(dynamic_cast<const CGHeroInstance *>(obj) != nullptr);
|
||||
if(adventureInt->curHero() != nullptr)
|
||||
if(LOCPLINT->localState->getCurrentHero() != nullptr)
|
||||
{
|
||||
if(obj->id == adventureInt->curHero()->id)
|
||||
if(obj->id == LOCPLINT->localState->getCurrentHero()->id)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -206,15 +206,15 @@ MapRendererAdventureContext::MapRendererAdventureContext(const MapRendererContex
|
||||
|
||||
const CGPath * MapRendererAdventureContext::currentPath() const
|
||||
{
|
||||
const auto * hero = adventureInt->curHero();
|
||||
const auto * hero = LOCPLINT->localState->getCurrentHero();
|
||||
|
||||
if(!hero)
|
||||
return nullptr;
|
||||
|
||||
if(!LOCPLINT->paths.hasPath(hero))
|
||||
if(!LOCPLINT->localState->hasPath(hero))
|
||||
return nullptr;
|
||||
|
||||
return &LOCPLINT->paths.getPath(hero);
|
||||
return &LOCPLINT->localState->getPath(hero);
|
||||
}
|
||||
|
||||
size_t MapRendererAdventureContext::objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "MapViewModel.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "MapViewModel.h"
|
||||
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
@ -27,7 +28,7 @@
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../render/ColorFilter.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../adventureMap/CList.h"
|
||||
#include "../adventureMap/CResDataBar.h"
|
||||
|
||||
@ -495,7 +496,7 @@ void HeroSlots::splitClicked()
|
||||
{
|
||||
if(!!town->visitingHero && town->garrisonHero && (visitingHero->isSelected() || garrisonedHero->isSelected()))
|
||||
{
|
||||
LOCPLINT->heroExchangeStarted(town->visitingHero->id, town->garrisonHero->id, QueryID(-1));
|
||||
LOCPLINT->showHeroExchange(town->visitingHero->id, town->garrisonHero->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1229,9 +1230,9 @@ void CCastleInterface::close()
|
||||
if(town->tempOwner == LOCPLINT->playerID) //we may have opened window for an allied town
|
||||
{
|
||||
if(town->visitingHero && town->visitingHero->tempOwner == LOCPLINT->playerID)
|
||||
adventureInt->select(town->visitingHero);
|
||||
LOCPLINT->localState->setSelection(town->visitingHero);
|
||||
else
|
||||
adventureInt->select(town);
|
||||
LOCPLINT->localState->setSelection(town);
|
||||
}
|
||||
CWindowObject::close();
|
||||
}
|
||||
@ -1239,15 +1240,15 @@ void CCastleInterface::close()
|
||||
void CCastleInterface::castleTeleport(int where)
|
||||
{
|
||||
const CGTownInstance * dest = LOCPLINT->cb->getTown(ObjectInstanceID(where));
|
||||
adventureInt->select(town->visitingHero);//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
|
||||
LOCPLINT->localState->setSelection(town->visitingHero);//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
|
||||
LOCPLINT->cb->teleportHero(town->visitingHero, dest);
|
||||
LOCPLINT->paths.erasePath(town->visitingHero);
|
||||
LOCPLINT->localState->erasePath(town->visitingHero);
|
||||
}
|
||||
|
||||
void CCastleInterface::townChange()
|
||||
{
|
||||
//TODO: do not recreate window
|
||||
const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()];
|
||||
const CGTownInstance * dest = LOCPLINT->localState->getOwnedTown(townlist->getSelectedIndex());
|
||||
const CGTownInstance * town = this->town;// "this" is going to be deleted
|
||||
if ( dest == town )
|
||||
return;
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../adventureMap/CMinimap.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../CVideoHandler.h"
|
||||
|
||||
#include "../battle/BattleInterface.h"
|
||||
@ -25,7 +26,7 @@
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
@ -221,9 +222,9 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
|
||||
}
|
||||
}
|
||||
|
||||
selectedTab = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap;
|
||||
selectedTab = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap;
|
||||
schoolTab->setFrame(selectedTab, 0);
|
||||
int cp = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap;
|
||||
int cp = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbokLastPageAdvmap;
|
||||
// spellbook last page battle index is not reset after battle, so this needs to stay here
|
||||
vstd::abetween(cp, 0, std::max(0, pagesWithinCurrentTab() - 1));
|
||||
setCurrentPage(cp);
|
||||
@ -237,8 +238,8 @@ CSpellWindow::~CSpellWindow()
|
||||
|
||||
void CSpellWindow::fexitb()
|
||||
{
|
||||
(myInt->battleInt ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
|
||||
(myInt->battleInt ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
|
||||
(myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
|
||||
(myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
|
||||
|
||||
close();
|
||||
}
|
||||
@ -556,8 +557,8 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
|
||||
|
||||
auto guard = vstd::makeScopeGuard([this]()
|
||||
{
|
||||
owner->myInt->spellbookSettings.spellbookLastTabAdvmap = owner->selectedTab;
|
||||
owner->myInt->spellbookSettings.spellbokLastPageAdvmap = owner->currentPage;
|
||||
owner->myInt->localState->spellbookSettings.spellbookLastTabAdvmap = owner->selectedTab;
|
||||
owner->myInt->localState->spellbookSettings.spellbokLastPageAdvmap = owner->currentPage;
|
||||
});
|
||||
|
||||
if(mySpell->getTargetType() == spells::AimType::LOCATION)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "InfoWindows.h"
|
||||
|
||||
#include "../CGameInfo.h"
|
||||
#include "../PlayerLocalState.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CMusicHandler.h"
|
||||
|
||||
@ -21,7 +22,7 @@
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../battle/BattleInterface.h"
|
||||
#include "../battle/BattleInterfaceClasses.h"
|
||||
#include "../adventureMap/CAdvMapInt.h"
|
||||
#include "../adventureMap/CAdventureMapInterface.h"
|
||||
#include "../windows/CMessage.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../gui/CursorHandler.h"
|
||||
@ -332,8 +333,8 @@ void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p,
|
||||
}
|
||||
else
|
||||
{
|
||||
if(adventureInt->curHero())
|
||||
CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero()));
|
||||
if(LOCPLINT->localState->getCurrentHero())
|
||||
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->localState->getCurrentHero()));
|
||||
else
|
||||
CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID));
|
||||
}
|
||||
@ -376,7 +377,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
|
||||
: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutTown iah;
|
||||
LOCPLINT->cb->getTownInfo(town, iah, adventureInt->curTown()); //todo: should this be nearest hero?
|
||||
LOCPLINT->cb->getTownInfo(town, iah, LOCPLINT->localState->getCurrentTown()); //todo: should this be nearest hero?
|
||||
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
|
||||
@ -386,7 +387,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
|
||||
: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position))
|
||||
{
|
||||
InfoAboutHero iah;
|
||||
LOCPLINT->cb->getHeroInfo(hero, iah, adventureInt->curHero());//todo: should this be nearest hero?
|
||||
LOCPLINT->cb->getHeroInfo(hero, iah, LOCPLINT->localState->getCurrentHero());//todo: should this be nearest hero?
|
||||
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
|
||||
@ -405,7 +406,7 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
|
||||
std::shared_ptr<WindowBase> CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
|
||||
{
|
||||
if(nullptr == specific)
|
||||
specific = adventureInt->curArmy();
|
||||
specific = LOCPLINT->localState->getCurrentArmy();
|
||||
|
||||
if(nullptr == specific)
|
||||
{
|
||||
|
@ -935,7 +935,7 @@ bool CGameInfoCallback::isInTheMap(const int3 &pos) const
|
||||
return gs->map->isInTheMap(pos);
|
||||
}
|
||||
|
||||
void CGameInfoCallback::getVisibleTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula) const
|
||||
void CGameInfoCallback::getVisibleTilesInRange(std::unordered_set<int3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula) const
|
||||
{
|
||||
gs->getTilesInRange(tiles, pos, radious, getLocalPlayer(), -1, distanceFormula);
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ struct SThievesGuildInfo;
|
||||
class CMapHeader;
|
||||
struct TeamState;
|
||||
struct QuestInfo;
|
||||
struct ShashInt3;
|
||||
class CGameState;
|
||||
class PathfinderConfig;
|
||||
|
||||
@ -99,7 +98,7 @@ public:
|
||||
// const TerrainTile * getTile(int3 tile, bool verbose = true) const;
|
||||
// std::shared_ptr<boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
|
||||
// bool isInTheMap(const int3 &pos) const;
|
||||
// void getVisibleTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const;
|
||||
// void getVisibleTilesInRange(std::unordered_set<int3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const;
|
||||
|
||||
//town
|
||||
// const CGTownInstance* getTown(ObjectInstanceID objid) const;
|
||||
@ -194,7 +193,7 @@ public:
|
||||
virtual const TerrainTile * getTile(int3 tile, bool verbose = true) const;
|
||||
virtual std::shared_ptr<const boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
|
||||
virtual bool isInTheMap(const int3 &pos) const;
|
||||
virtual void getVisibleTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const;
|
||||
virtual void getVisibleTilesInRange(std::unordered_set<int3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const;
|
||||
virtual void calculatePaths(const std::shared_ptr<PathfinderConfig> & config);
|
||||
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out);
|
||||
virtual EDiggingStatus getTileDigStatus(int3 tile, bool verbose = true) const;
|
||||
|
@ -1641,7 +1641,7 @@ void CGameState::initFogOfWar()
|
||||
{
|
||||
if(!obj || !vstd::contains(elem.second.players, obj->tempOwner)) continue; //not a flagged object
|
||||
|
||||
std::unordered_set<int3, ShashInt3> tiles;
|
||||
std::unordered_set<int3> tiles;
|
||||
getTilesInRange(tiles, obj->getSightCenter(), obj->getSightRadius(), obj->tempOwner, 1);
|
||||
for(const int3 & tile : tiles)
|
||||
{
|
||||
|
@ -548,7 +548,7 @@ public:
|
||||
PATROL_LOCKED = 1,
|
||||
PATROL_RADIUS
|
||||
} patrolState;
|
||||
std::unordered_set<int3, ShashInt3> patrolTiles;
|
||||
std::unordered_set<int3> patrolTiles;
|
||||
|
||||
int turn;
|
||||
PlayerColor owner;
|
||||
|
@ -63,7 +63,7 @@ void CPrivilegedInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
|
||||
}
|
||||
}
|
||||
|
||||
void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3, ShashInt3> & tiles,
|
||||
void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3> & tiles,
|
||||
const int3 & pos,
|
||||
int radious,
|
||||
std::optional<PlayerColor> player,
|
||||
@ -100,7 +100,7 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3, ShashInt3
|
||||
}
|
||||
}
|
||||
|
||||
void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3, ShashInt3> & tiles, std::optional<PlayerColor> Player, int level, MapTerrainFilterMode tileFilterMode) const
|
||||
void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3> & tiles, std::optional<PlayerColor> Player, int level, MapTerrainFilterMode tileFilterMode) const
|
||||
{
|
||||
if(!!Player && *Player >= PlayerColor::PLAYER_LIMIT)
|
||||
{
|
||||
|
@ -26,7 +26,6 @@ struct ArtifactLocation;
|
||||
class CCreatureSet;
|
||||
class CStackBasicDescriptor;
|
||||
class CGCreature;
|
||||
struct ShashInt3;
|
||||
|
||||
namespace spells
|
||||
{
|
||||
@ -59,7 +58,7 @@ public:
|
||||
void getFreeTiles(std::vector<int3> &tiles) const;
|
||||
|
||||
//mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only revealed
|
||||
void getTilesInRange(std::unordered_set<int3, ShashInt3> & tiles,
|
||||
void getTilesInRange(std::unordered_set<int3> & tiles,
|
||||
const int3 & pos,
|
||||
int radious,
|
||||
std::optional<PlayerColor> player = std::optional<PlayerColor>(),
|
||||
@ -67,7 +66,7 @@ public:
|
||||
int3::EDistanceFormula formula = int3::DIST_2D) const;
|
||||
|
||||
//returns all tiles on given level (-1 - both levels, otherwise number of level)
|
||||
void getAllTiles(std::unordered_set<int3, ShashInt3> &tiles, std::optional<PlayerColor> player = std::optional<PlayerColor>(),
|
||||
void getAllTiles(std::unordered_set<int3> &tiles, std::optional<PlayerColor> player = std::optional<PlayerColor>(),
|
||||
int level = -1, MapTerrainFilterMode tileFilterMode = MapTerrainFilterMode::NONE) const;
|
||||
|
||||
//gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||
@ -136,7 +135,7 @@ public:
|
||||
virtual void sendAndApply(CPackForClient * pack) = 0;
|
||||
virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
|
||||
virtual void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) = 0;
|
||||
virtual void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) = 0;
|
||||
virtual void changeFogOfWar(std::unordered_set<int3> &tiles, PlayerColor player, bool hide) = 0;
|
||||
|
||||
virtual void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) = 0;
|
||||
};
|
||||
|
@ -117,8 +117,8 @@ public:
|
||||
virtual void showThievesGuildWindow (const CGObjectInstance * obj){};
|
||||
virtual void showQuestLog(){};
|
||||
virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID){}; //called when a hero casts a spell
|
||||
virtual void tileHidden(const std::unordered_set<int3, ShashInt3> &pos){};
|
||||
virtual void tileRevealed(const std::unordered_set<int3, ShashInt3> &pos){};
|
||||
virtual void tileHidden(const std::unordered_set<int3> &pos){};
|
||||
virtual void tileRevealed(const std::unordered_set<int3> &pos){};
|
||||
virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard
|
||||
virtual void availableArtifactsChanged(const CGBlackMarket *bm = nullptr){}; //bm may be nullptr, then artifacts are changed in the global pool (used by merchants in towns)
|
||||
virtual void centerView (int3 pos, int focusTime){};
|
||||
|
@ -308,7 +308,7 @@ struct DLL_LINKAGE FoWChange : public CPackForClient
|
||||
{
|
||||
void applyGs(CGameState * gs);
|
||||
|
||||
std::unordered_set<int3, struct ShashInt3 > tiles;
|
||||
std::unordered_set<int3> tiles;
|
||||
PlayerColor player;
|
||||
ui8 mode = 0; //mode==0 - hide, mode==1 - reveal
|
||||
bool waitForDialogs = false;
|
||||
@ -590,7 +590,7 @@ struct DLL_LINKAGE TryMoveHero : public CPackForClient
|
||||
ui32 movePoints = 0;
|
||||
EResult result = FAILED; //uses EResult
|
||||
int3 start, end; //h3m format
|
||||
std::unordered_set<int3, ShashInt3> fowRevealed; //revealed tiles
|
||||
std::unordered_set<int3> fowRevealed; //revealed tiles
|
||||
std::optional<int3> attackedFrom; // Set when stepping into endangered tile.
|
||||
|
||||
virtual void visitTyped(ICPackVisitor & visitor) override;
|
||||
|
@ -915,7 +915,7 @@ void FoWChange::applyGs(CGameState *gs)
|
||||
(*fogOfWarMap)[t.z][t.x][t.y] = mode;
|
||||
if (mode == 0) //do not hide too much
|
||||
{
|
||||
std::unordered_set<int3, ShashInt3> tilesRevealed;
|
||||
std::unordered_set<int3> tilesRevealed;
|
||||
for (auto & elem : gs->map->objects)
|
||||
{
|
||||
const CGObjectInstance *o = elem;
|
||||
@ -1918,7 +1918,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
|
||||
[[maybe_unused]] const CArtifactInstance *transformedArt = al.getArt();
|
||||
assert(transformedArt);
|
||||
bool combineEquipped = !ArtifactUtils::isSlotBackpack(al.slot);
|
||||
assert(vstd::contains_if(transformedArt->assemblyPossibilities(artSet, combineEquipped), [=](const CArtifact * art)->bool
|
||||
assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(artSet, transformedArt->artType->getId(), combineEquipped), [=](const CArtifact * art)->bool
|
||||
{
|
||||
return art->getId() == builtArt->getId();
|
||||
}));
|
||||
|
24
lib/int3.h
24
lib/int3.h
@ -182,18 +182,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//Why not normal function?
|
||||
struct ShashInt3
|
||||
{
|
||||
size_t operator()(int3 const& pos) const
|
||||
{
|
||||
size_t ret = std::hash<int>()(pos.x);
|
||||
vstd::hash_combine(ret, pos.y);
|
||||
vstd::hash_combine(ret, pos.z);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
int3 findClosestTile (Container & container, int3 dest)
|
||||
{
|
||||
@ -215,3 +203,15 @@ int3 findClosestTile (Container & container, int3 dest)
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
|
||||
template<>
|
||||
struct std::hash<VCMI_LIB_WRAP_NAMESPACE(int3)> {
|
||||
size_t operator()(VCMI_LIB_WRAP_NAMESPACE(int3) const& pos) const
|
||||
{
|
||||
size_t ret = std::hash<int>()(pos.x);
|
||||
VCMI_LIB_WRAP_NAMESPACE(vstd)::hash_combine(ret, pos.y);
|
||||
VCMI_LIB_WRAP_NAMESPACE(vstd)::hash_combine(ret, pos.z);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
@ -7136,11 +7136,11 @@ void CGameHandler::removeAfterVisit(const CGObjectInstance *object)
|
||||
|
||||
void CGameHandler::changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide)
|
||||
{
|
||||
std::unordered_set<int3, ShashInt3> tiles;
|
||||
std::unordered_set<int3> tiles;
|
||||
getTilesInRange(tiles, center, radius, player, hide? -1 : 1);
|
||||
if (hide)
|
||||
{
|
||||
std::unordered_set<int3, ShashInt3> observedTiles; //do not hide tiles observed by heroes. May lead to disastrous AI problems
|
||||
std::unordered_set<int3> observedTiles; //do not hide tiles observed by heroes. May lead to disastrous AI problems
|
||||
auto p = getPlayerState(player);
|
||||
for (auto h : p->heroes)
|
||||
{
|
||||
@ -7156,7 +7156,7 @@ void CGameHandler::changeFogOfWar(int3 center, ui32 radius, PlayerColor player,
|
||||
changeFogOfWar(tiles, player, hide);
|
||||
}
|
||||
|
||||
void CGameHandler::changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide)
|
||||
void CGameHandler::changeFogOfWar(std::unordered_set<int3> &tiles, PlayerColor player, bool hide)
|
||||
{
|
||||
FoWChange fow;
|
||||
fow.tiles = tiles;
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override;
|
||||
|
||||
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override;
|
||||
void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) override;
|
||||
void changeFogOfWar(std::unordered_set<int3> &tiles, PlayerColor player, bool hide) override;
|
||||
|
||||
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user