瀏覽代碼

Merge pull request #178 from vmarkovtsev/issue/2406

Fix 2406 reset potentially available heroes
ArseniyShestakov 9 年之前
父節點
當前提交
b0d9b8bf63
共有 4 個文件被更改,包括 54 次插入5 次删除
  1. 17 0
      lib/NetPacksLib.cpp
  2. 14 0
      lib/mapObjects/CGHeroInstance.cpp
  3. 1 0
      lib/mapObjects/CGHeroInstance.h
  4. 22 5
      server/CGameHandler.cpp

+ 17 - 0
lib/NetPacksLib.cpp

@@ -1057,6 +1057,23 @@ DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
 	for(NewTurn::Hero h : heroes) //give mana/movement point
 	{
 		CGHeroInstance *hero = gs->getHero(h.id);
+		if(!hero)
+		{
+			// retreated or surrendered hero who has not been reset yet
+			for(auto& hp : gs->hpool.heroesPool)
+			{
+				if(hp.second->id == h.id)
+				{
+					hero = hp.second;
+					break;
+				}
+			}
+		}
+		if(!hero)
+		{
+			logGlobal->errorStream() << "Hero " << h.id << " not found in NewTurn::applyGs";
+			continue;
+		}
 		hero->movement = h.move;
 		hero->mana = h.mana;
 	}

+ 14 - 0
lib/mapObjects/CGHeroInstance.cpp

@@ -1080,6 +1080,20 @@ si32 CGHeroInstance::manaRegain() const
 	return 1 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 8) + valOfBonuses(Bonus::MANA_REGENERATION); //1 + Mysticism level
 }
 
+si32 CGHeroInstance::getManaNewTurn() const
+{
+	if(visitedTown && visitedTown->hasBuilt(BuildingID::MAGES_GUILD_1))
+	{
+		//if hero starts turn in town with mage guild - restore all mana
+		return std::max(mana, manaLimit());
+	}
+	si32 res = mana + manaRegain();
+	res = std::min(res, manaLimit());
+	res = std::max(res, mana);
+	res = std::max(res, 0);
+	return res;
+}
+
 // /**
 //  * Places an artifact in hero's backpack. If it's a big artifact equips it
 //  * or discards it if it cannot be equipped.

+ 1 - 0
lib/mapObjects/CGHeroInstance.h

@@ -151,6 +151,7 @@ public:
 	ui32 getLowestCreatureSpeed() const;
 	int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
 	si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
+	si32 getManaNewTurn() const; //calculate how much mana this hero is going to have the next day
 	int getCurrentLuck(int stack=-1, bool town=false) const;
 	int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
 

+ 22 - 5
server/CGameHandler.cpp

@@ -1324,6 +1324,25 @@ void CGameHandler::newTurn()
 
 	std::map<ui32, ConstTransitivePtr<CGHeroInstance> > pool = gs->hpool.heroesPool;
 
+	for(auto& hp : pool)
+	{
+		auto hero = hp.second;
+		if(hero->isInitialized() && hero->stacks.size())
+		{
+			// reset retreated or surrendered heroes
+			auto maxmove = hero->maxMovePoints(true);
+			// if movement is greater than maxmove, we should decrease it
+			if(hero->movement != maxmove || hero->mana < hero->manaLimit())
+			{
+				NewTurn::Hero hth;
+				hth.id = hero->id;
+				hth.move = maxmove;
+				hth.mana = hero->getManaNewTurn();
+				n.heroes.insert(hth);
+			}
+		}
+	}
+
 	for (auto & elem : gs->players)
 	{
 		if(elem.first == PlayerColor::NEUTRAL)
@@ -1351,7 +1370,9 @@ void CGameHandler::newTurn()
 					banned = h->type->heroClass;
 				}
 				else
+				{
 					sah.hid[j] = -1;
+				}
 			}
 
 			sendAndApply(&sah);
@@ -1368,11 +1389,7 @@ void CGameHandler::newTurn()
 			hth.id = h->id;
 			// TODO: this code executed when bonuses of previous day not yet updated (this happen in NewTurn::applyGs). See issue 2356
 			hth.move = h->maxMovePoints(gs->map->getTile(h->getPosition(false)).terType != ETerrainType::WATER, new TurnInfo(h, 1));
-
-			if(h->visitedTown && h->visitedTown->hasBuilt(BuildingID::MAGES_GUILD_1)) //if hero starts turn in town with mage guild
-				hth.mana = std::max(h->mana, h->manaLimit()); //restore all mana
-			else
-				hth.mana = std::max((si32)(0), std::max(h->mana, std::min((si32)(h->mana + h->manaRegain()), h->manaLimit())));
+			hth.mana = h->getManaNewTurn();
 
 			n.heroes.insert(hth);