Przeglądaj źródła

Lazy updates of hero paths.

Michał W. Urbańczyk 14 lat temu
rodzic
commit
6b9e64de91

+ 1 - 1
CCallback.cpp

@@ -312,7 +312,7 @@ bool CCallback::getPath2( int3 dest, CGPath &ret )
 
 	const CGHeroInstance *h = cl->IGameCallback::getSelectedHero(player);
 	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();
 	}

+ 0 - 4
client/CPlayerInterface.cpp

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

+ 6 - 0
client/Client.cpp

@@ -647,6 +647,12 @@ void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt)
 	} 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( COSer<CSaveFile> &h, const int version );
 

+ 1 - 0
client/Client.h

@@ -100,6 +100,7 @@ public:
 	void run();
 	void finishCampaign( 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 updatePaths(); //calls calculatePaths for same hero for which we previously calculated paths
 

+ 13 - 23
client/NetPacksClient.cpp

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

+ 5 - 0
lib/CGameState.cpp

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

+ 1 - 0
lib/CGameState.h

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