mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-29 23:07:48 +02:00
Refactored access to hero paths in CPlayerInterface
This commit is contained in:
@@ -120,7 +120,164 @@ struct HeroObjectRetriever : boost::static_visitor<const CGHeroInstance *>
|
||||
}
|
||||
};
|
||||
|
||||
CPlayerInterface::CPlayerInterface(PlayerColor Player)
|
||||
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());
|
||||
}
|
||||
|
||||
//CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
|
||||
//{
|
||||
// if (vstd::contains(paths,h)) //hero has assigned path
|
||||
// {
|
||||
// CGPath &path = paths[h];
|
||||
// if (!path.nodes.size())
|
||||
// {
|
||||
// logGlobal->warn("Warning: empty path found...");
|
||||
// paths.erasePath(h);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// assert(h->visitablePos() == path.startPos());
|
||||
// //update the hero path in case of something has changed on map
|
||||
// if (LOCPLINT->cb->getPathsInfo(h)->getPath(path, path.endPos()))
|
||||
// return &path;
|
||||
//
|
||||
// paths.erase(h);
|
||||
// return nullptr;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return nullptr;
|
||||
//}
|
||||
//
|
||||
//CGPath * CPlayerInterface::getPath(const CGHeroInstance * h)
|
||||
//{
|
||||
// if (vstd::contains(paths,h)) //hero has assigned path
|
||||
// return &paths[h];
|
||||
//
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
//removeLastNode
|
||||
|
||||
|
||||
//void HeroPathStorage::setPath(const CGHeroInstance *h, const CGPath & path)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
//const CGPath & HeroPathStorage::getPath(const CGHeroInstance *h)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//
|
||||
//void HeroPathStorage::verifyPath(const CGHeroInstance *h)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
//void CPlayerInterface::eraseCurrentPathOf(const CGHeroInstance * ho, bool checkForExistanceOfPath)
|
||||
//{
|
||||
// if (checkForExistanceOfPath)
|
||||
// {
|
||||
// assert(vstd::contains(paths, ho));
|
||||
// }
|
||||
// else if (!vstd::contains(paths, ho))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// assert(ho == adventureInt->selection);
|
||||
//
|
||||
// paths.erasePath(ho);
|
||||
// adventureInt->updateMoveHero(ho, false);
|
||||
//}
|
||||
|
||||
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)
|
||||
{
|
||||
logGlobal->trace("\tHuman player interface for player %s being constructed", Player.getStr());
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
@@ -260,8 +417,8 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
|
||||
bool directlyAttackingCreature =
|
||||
details.attackedFrom
|
||||
&& adventureInt->terrain->currentPath //in case if movement has been canceled in the meantime and path was already erased
|
||||
&& adventureInt->terrain->currentPath->nodes.size() == 3;//FIXME should be 2 but works nevertheless...
|
||||
&& paths.hasPath(hero) //in case if movement has been canceled in the meantime and path was already erased
|
||||
&& paths.getPath(hero).nodes.size() == 3;//FIXME should be 2 but works nevertheless...
|
||||
|
||||
if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
|
||||
{
|
||||
@@ -271,21 +428,21 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
|
||||
if(details.result == TryMoveHero::TELEPORTATION)
|
||||
{
|
||||
if(adventureInt->terrain->currentPath)
|
||||
if(paths.hasPath(hero))
|
||||
{
|
||||
assert(adventureInt->terrain->currentPath->nodes.size() >= 2);
|
||||
std::vector<CGPathNode>::const_iterator nodesIt = adventureInt->terrain->currentPath->nodes.end() - 1;
|
||||
assert(paths.getPath(hero).nodes.size() >= 2);
|
||||
auto nodesIt = paths.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
|
||||
removeLastNodeFromPath(hero);
|
||||
paths.removeLastNode(hero);
|
||||
}
|
||||
else
|
||||
{
|
||||
//teleport was not along current path, it'll now be invalid (hero is somewhere else)
|
||||
eraseCurrentPathOf(hero);
|
||||
paths.erasePath(hero);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -299,12 +456,12 @@ 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.
|
||||
{
|
||||
eraseCurrentPathOf(hero, false);
|
||||
paths.erasePath(hero);
|
||||
}
|
||||
else if(adventureInt->terrain->currentPath && hero->pos == details.end) //&& hero is moving
|
||||
else if(paths.hasPath(hero) && hero->pos == details.end) //&& hero is moving
|
||||
{
|
||||
if(details.start != details.end) //so we don't touch path when revisiting with spacebar
|
||||
removeLastNodeFromPath(hero);
|
||||
paths.removeLastNode(hero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,8 +601,7 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
||||
else if (adventureInt->selection == hero)
|
||||
adventureInt->selection = nullptr;
|
||||
|
||||
if (vstd::contains(paths, hero))
|
||||
paths.erase(hero);
|
||||
paths.erasePath(hero);
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start)
|
||||
@@ -1247,7 +1403,7 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
|
||||
if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain)
|
||||
{
|
||||
//recalculate paths because hero has lost bonus influencing pathfinding
|
||||
eraseCurrentPathOf(hero, false);
|
||||
paths.erasePath(hero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1256,33 +1412,7 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
|
||||
h & wanderingHeroes;
|
||||
h & towns;
|
||||
h & sleepingHeroes;
|
||||
|
||||
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 (cb)
|
||||
for (auto &p : pathsMap)
|
||||
{
|
||||
CGPath path;
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
h & paths;
|
||||
h & spellbookSettings;
|
||||
}
|
||||
|
||||
@@ -1299,7 +1429,7 @@ void CPlayerInterface::loadGame( BinaryDeserializer & h, const int version )
|
||||
firstCall = -1;
|
||||
}
|
||||
|
||||
void CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
|
||||
void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path )
|
||||
{
|
||||
LOG_TRACE(logGlobal);
|
||||
if (!LOCPLINT->makingTurn)
|
||||
@@ -1330,7 +1460,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 && adventureInt->terrain->currentPath && adventureInt->terrain->currentPath->nodes.size() > 1) //to ignore calls on passing through garrisons
|
||||
if (stillMoveHero.get() == DURING_MOVE && paths.hasPath(down) && paths.getPath(down).nodes.size() > 1) //to ignore calls on passing through garrisons
|
||||
{
|
||||
onEnd();
|
||||
return;
|
||||
@@ -1641,7 +1771,7 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
|
||||
bool heroVisibleHere = false;
|
||||
auto & tile = subArr[tileX][tileY];
|
||||
|
||||
for ( auto const & obj : tile.objects)
|
||||
for(const auto & obj : tile.objects)
|
||||
{
|
||||
if (obj.obj == ho)
|
||||
{
|
||||
@@ -1856,7 +1986,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
|
||||
GH.popInts(1);
|
||||
|
||||
if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
|
||||
eraseCurrentPathOf(caster, false);
|
||||
paths.erasePath(caster);
|
||||
|
||||
const spells::Spell * spell = CGI->spells()->getByIndex(spellID);
|
||||
|
||||
@@ -1872,54 +2002,6 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
|
||||
CCS->soundh->playSound(castSoundPath);
|
||||
}
|
||||
|
||||
void CPlayerInterface::eraseCurrentPathOf(const CGHeroInstance * ho, bool checkForExistanceOfPath)
|
||||
{
|
||||
if (checkForExistanceOfPath)
|
||||
{
|
||||
assert(vstd::contains(paths, ho));
|
||||
}
|
||||
else if (!vstd::contains(paths, ho))
|
||||
{
|
||||
return;
|
||||
}
|
||||
assert(ho == adventureInt->selection);
|
||||
|
||||
paths.erase(ho);
|
||||
adventureInt->terrain->currentPath = nullptr;
|
||||
adventureInt->updateMoveHero(ho, false);
|
||||
}
|
||||
|
||||
void CPlayerInterface::removeLastNodeFromPath(const CGHeroInstance *ho)
|
||||
{
|
||||
adventureInt->terrain->currentPath->nodes.erase(adventureInt->terrain->currentPath->nodes.end()-1);
|
||||
if (adventureInt->terrain->currentPath->nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
|
||||
eraseCurrentPathOf(ho);
|
||||
}
|
||||
|
||||
CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
|
||||
{
|
||||
if (vstd::contains(paths,h)) //hero has assigned path
|
||||
{
|
||||
CGPath &path = paths[h];
|
||||
if (!path.nodes.size())
|
||||
{
|
||||
logGlobal->warn("Warning: empty path found...");
|
||||
paths.erase(h);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(h->visitablePos() == path.startPos());
|
||||
//update the hero path in case of something has changed on map
|
||||
if (LOCPLINT->cb->getPathsInfo(h)->getPath(path, path.endPos()))
|
||||
return &path;
|
||||
else
|
||||
paths.erase(h);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CPlayerInterface::acceptTurn()
|
||||
{
|
||||
if (settings["session"]["autoSkip"].Bool())
|
||||
|
||||
Reference in New Issue
Block a user