1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Lazy updates of hero paths.

This commit is contained in:
Michał W. Urbańczyk 2011-09-03 02:54:33 +00:00
parent 5072bda7e6
commit 6b9e64de91
7 changed files with 27 additions and 28 deletions

View File

@ -312,7 +312,7 @@ bool CCallback::getPath2( int3 dest, CGPath &ret )
const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(player); const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(player);
assert(cl->pathInfo->hero == h); assert(cl->pathInfo->hero == h);
if(cl->pathInfo->hpos != h->getPosition(false)) //hero position changed, must update paths if(cl->pathInfo->hpos != h->getPosition(false) || !cl->pathInfo->isValid) //hero position changed, must update paths
{ {
recalculatePaths(); recalculatePaths();
} }

View File

@ -263,7 +263,6 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
{ {
if(adventureInt->terrain.currentPath) if(adventureInt->terrain.currentPath)
eraseCurrentPathOf(ho); eraseCurrentPathOf(ho);
cb->recalculatePaths();
return; //teleport - no fancy moving animation return; //teleport - no fancy moving animation
//TODO: smooth disappear / appear effect //TODO: smooth disappear / appear effect
} }
@ -1079,7 +1078,6 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain) if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain)
{ {
//recalculate paths because hero has lost bonus influencing pathfinding //recalculate paths because hero has lost bonus influencing pathfinding
cb->recalculatePaths();
eraseCurrentPathOf(hero, false); eraseCurrentPathOf(hero, false);
} }
} }
@ -1172,7 +1170,6 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
cb->getGsMutex().lock_shared(); cb->getGsMutex().lock_shared();
pim->lock(); pim->lock();
eventsM.lock(); eventsM.lock();
cb->recalculatePaths();
return result; return result;
} }
@ -1936,7 +1933,6 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
{ {
if (spellID == Spells::FLY || spellID == Spells::WATER_WALK) if (spellID == Spells::FLY || spellID == Spells::WATER_WALK)
{ {
cb->recalculatePaths();
eraseCurrentPathOf(caster, false); eraseCurrentPathOf(caster, false);
} }
} }

View File

@ -647,6 +647,12 @@ void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
} HANDLE_EXCEPTION } HANDLE_EXCEPTION
} }
void CClient::invalidatePaths(const CGHeroInstance *h /*= NULL*/)
{
if(!h || pathInfo->hero == h)
pathInfo->isValid = false;
}
template void CClient::serialize( CISer<CLoadFile> &h, const int version ); template void CClient::serialize( CISer<CLoadFile> &h, const int version );
template void CClient::serialize( COSer<CSaveFile> &h, const int version ); template void CClient::serialize( COSer<CSaveFile> &h, const int version );

View File

@ -100,6 +100,7 @@ public:
void run(); void run();
void finishCampaign( CCampaignState * camp ); void finishCampaign( CCampaignState * camp );
void proposeNextMission( CCampaignState * camp ); void proposeNextMission( CCampaignState * camp );
void invalidatePaths(const CGHeroInstance *h = NULL); //invalidates paths for hero h or for any hero if h is NULL => they'll got recalculated when the next query comes
void calculatePaths(const CGHeroInstance *h); void calculatePaths(const CGHeroInstance *h);
void updatePaths(); //calls calculatePaths for same hero for which we previously calculated paths void updatePaths(); //calls calculatePaths for same hero for which we previously calculated paths

View File

@ -151,12 +151,7 @@ void SetMana::applyCl( CClient *cl )
void SetMovePoints::applyCl( CClient *cl ) void SetMovePoints::applyCl( CClient *cl )
{ {
const CGHeroInstance *h = cl->getHero(hid); const CGHeroInstance *h = cl->getHero(hid);
cl->invalidatePaths(h);
if (cl->IGameCallback::getSelectedHero(LOCPLINT->playerID) == h)//if we have selected that hero
{
cl->calculatePaths(h);
}
INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroMovePointsChanged, h); INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroMovePointsChanged, h);
} }
@ -167,7 +162,7 @@ void FoWChange::applyCl( CClient *cl )
else else
INTERFACE_CALL_IF_PRESENT(player, tileHidden, tiles); INTERFACE_CALL_IF_PRESENT(player, tileHidden, tiles);
cl->updatePaths(); cl->invalidatePaths();
} }
void SetAvailableHeroes::applyCl( CClient *cl ) void SetAvailableHeroes::applyCl( CClient *cl )
@ -243,14 +238,13 @@ void HeroVisit::applyCl( CClient *cl )
void NewTurn::applyCl( CClient *cl ) void NewTurn::applyCl( CClient *cl )
{ {
//cl->updatePaths(); => may fail when there is no selected (mechanically) hero cl->invalidatePaths();
if(cl->pathInfo->hero)
cl->calculatePaths(cl->pathInfo->hero);
} }
void GiveBonus::applyCl( CClient *cl ) void GiveBonus::applyCl( CClient *cl )
{ {
cl->invalidatePaths();
switch(who) switch(who)
{ {
case HERO: case HERO:
@ -280,7 +274,7 @@ void ChangeObjPos::applyCl( CClient *cl )
if(flags & 1) if(flags & 1)
CGI->mh->printObject(obj); CGI->mh->printObject(obj);
cl->updatePaths(); cl->invalidatePaths();
} }
void PlayerEndsGame::applyCl( CClient *cl ) void PlayerEndsGame::applyCl( CClient *cl )
@ -290,6 +284,7 @@ void PlayerEndsGame::applyCl( CClient *cl )
void RemoveBonus::applyCl( CClient *cl ) void RemoveBonus::applyCl( CClient *cl )
{ {
cl->invalidatePaths();
switch(who) switch(who)
{ {
case HERO: case HERO:
@ -325,18 +320,14 @@ void RemoveObject::applyFirstCl( CClient *cl )
//notify interfaces about removal //notify interfaces about removal
for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++) for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
{ {
if(i->first >= PLAYER_LIMIT) continue; if(GS(cl)->isVisible(o, i->first))
if(GS(cl)->getPlayerTeam(i->first)->fogOfWarMap[pos.x][pos.y][pos.z])
{
i->second->objectRemoved(o); i->second->objectRemoved(o);
}
} }
} }
void RemoveObject::applyCl( CClient *cl ) void RemoveObject::applyCl( CClient *cl )
{ {
if(cl->pathInfo->hero && cl->pathInfo->hero->id != id) cl->invalidatePaths();
cl->updatePaths();
} }
void TryMoveHero::applyFirstCl( CClient *cl ) void TryMoveHero::applyFirstCl( CClient *cl )
@ -365,6 +356,7 @@ void TryMoveHero::applyFirstCl( CClient *cl )
void TryMoveHero::applyCl( CClient *cl ) void TryMoveHero::applyCl( CClient *cl )
{ {
const CGHeroInstance *h = cl->getHero(id); const CGHeroInstance *h = cl->getHero(id);
cl->invalidatePaths();
if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK) if(result == TELEPORTATION || result == EMBARK || result == DISEMBARK)
{ {
@ -781,7 +773,9 @@ void ShowInInfobox::applyCl(CClient *cl)
void AdvmapSpellCast::applyCl(CClient *cl) void AdvmapSpellCast::applyCl(CClient *cl)
{ {
cl->playerint[caster->getOwner()]->advmapSpellCast(caster, spellID); cl->invalidatePaths();
//consider notifying other interfaces that see hero?
INTERFACE_CALL_IF_PRESENT(caster->getOwner(),advmapSpellCast, caster, spellID);
} }
void OpenWindow::applyCl(CClient *cl) void OpenWindow::applyCl(CClient *cl)
@ -870,12 +864,8 @@ void NewObject::applyCl(CClient *cl)
for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++) for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
{ {
//TODO: check if any covered tile is visible if(GS(cl)->isVisible(obj, i->first))
if(i->first >= PLAYER_LIMIT) continue;
if(GS(cl)->getPlayerTeam(i->first)->fogOfWarMap[obj->pos.x][obj->pos.y][obj->pos.z])
{
i->second->newObject(obj); i->second->newObject(obj);
}
} }
} }

View File

@ -2005,6 +2005,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src, int movement) void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int3 src, int movement)
{ {
assert(hero); assert(hero);
assert(hero == getHero(hero->id));
if(src.x < 0) if(src.x < 0)
src = hero->getPosition(false); src = hero->getPosition(false);
if(movement < 0) if(movement < 0)
@ -2209,6 +2210,8 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
} }
} //neighbours loop } //neighbours loop
} //queue loop } //queue loop
out.isValid = true;
} }
/** /**
@ -2824,6 +2827,8 @@ CGPathNode::CGPathNode()
bool CPathsInfo::getPath( const int3 &dst, CGPath &out ) bool CPathsInfo::getPath( const int3 &dst, CGPath &out )
{ {
assert(isValid);
out.nodes.clear(); out.nodes.clear();
const CGPathNode *curnode = &nodes[dst.x][dst.y][dst.z]; const CGPathNode *curnode = &nodes[dst.x][dst.y][dst.z];
if(!curnode->theNodeBefore || curnode->accessible == CGPathNode::FLYABLE) if(!curnode->theNodeBefore || curnode->accessible == CGPathNode::FLYABLE)

View File

@ -267,6 +267,7 @@ struct DLL_EXPORT CGPath
struct DLL_EXPORT CPathsInfo struct DLL_EXPORT CPathsInfo
{ {
bool isValid;
const CGHeroInstance *hero; const CGHeroInstance *hero;
int3 hpos; int3 hpos;
int3 sizes; int3 sizes;