Explorar o código

Implemented preserving hero on retreat on 7th day after end of turn

Ivan Savenko %!s(int64=2) %!d(string=hai) anos
pai
achega
cb16636fce

+ 9 - 0
lib/gameState/TavernHeroesPool.cpp

@@ -113,6 +113,15 @@ void TavernHeroesPool::onNewDay()
 		hero.second->setMovementPoints(hero.second->movementPointsLimit(true));
 		hero.second->mana = hero.second->manaLimit();
 	}
+
+	for (auto & slot : currentTavern)
+	{
+		if (slot.role == TavernSlotRole::RETREATED_TODAY)
+			slot.role = TavernSlotRole::RETREATED;
+
+		if (slot.role == TavernSlotRole::SURRENDERED_TODAY)
+			slot.role = TavernSlotRole::SURRENDERED;
+	}
 }
 
 void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero)

+ 3 - 3
lib/gameState/TavernSlot.h

@@ -26,10 +26,10 @@ enum class TavernSlotRole : int8_t
 	FULL_ARMY, // hero was added to tavern on new week and still has full army
 
 	RETREATED, // hero was owned by player before, but have retreated from battle and only has 1 creature in army
-	SURRENDERED, // hero was owned by player before, but have surrendered in battle and kept some troops
+	RETREATED_TODAY,
 
-//	SURRENDERED_DAY7, // helper value for heroes that surrendered after 7th day during enemy turn
-//	RETREATED_DAY7,
+	SURRENDERED, // hero was owned by player before, but have surrendered in battle and kept some troops
+	SURRENDERED_TODAY,
 };
 
 VCMI_LIB_NAMESPACE_END

+ 4 - 3
server/CGameHandler.h

@@ -99,8 +99,6 @@ class CGameHandler : public IGameCallback, public CBattleInfoCallback, public En
 	std::shared_ptr<CApplier<CBaseForGHApply>> applier;
 	std::unique_ptr<boost::thread> battleThread;
 
-	void deserializationFix();
-
 public:
 	std::unique_ptr<HeroPoolProcessor> heroPool;
 
@@ -365,6 +363,8 @@ public:
 	scripting::Pool * getContextPool() const override;
 #endif
 
+	std::list<PlayerColor> generatePlayerTurnOrder() const;
+
 	friend class CVCMIServer;
 private:
 	std::unique_ptr<events::EventBus> serverEventBus;
@@ -373,8 +373,9 @@ private:
 #endif
 
 	void reinitScripting();
+	void deserializationFix();
+
 
-	std::list<PlayerColor> generatePlayerTurnOrder() const;
 	void makeStackDoNothing(const CStack * next);
 	void getVictoryLossMessage(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult, InfoWindow & out) const;
 

+ 55 - 8
server/HeroPoolProcessor.cpp

@@ -32,6 +32,29 @@ HeroPoolProcessor::HeroPoolProcessor(CGameHandler * gameHandler)
 {
 }
 
+bool HeroPoolProcessor::playerEndedTurn(const PlayerColor & player)
+{
+	// our player is acting right now and have not ended turn
+	if (player == gameHandler->gameState()->currentPlayer)
+		return false;
+
+	auto turnOrder = gameHandler->generatePlayerTurnOrder();
+
+	for (auto const & entry : turnOrder)
+	{
+		// our player is yet to start turn
+		if (entry == gameHandler->gameState()->currentPlayer)
+			return false;
+
+		// our player have finished turn
+		if (entry == player)
+			return true;
+	}
+
+	assert(false);
+	return false;
+}
+
 TavernHeroSlot HeroPoolProcessor::selectSlotForRole(const PlayerColor & player, TavernSlotRole roleID)
 {
 	const auto & hpool = gameHandler->gameState()->hpool;
@@ -67,8 +90,12 @@ TavernHeroSlot HeroPoolProcessor::selectSlotForRole(const PlayerColor & player,
 void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHeroInstance * hero)
 {
 	SetAvailableHero sah;
-	sah.slotID = selectSlotForRole(color, TavernSlotRole::SURRENDERED);
-	sah.roleID = TavernSlotRole::SURRENDERED;
+	if (playerEndedTurn(color))
+		sah.roleID = TavernSlotRole::SURRENDERED_TODAY;
+	else
+		sah.roleID = TavernSlotRole::SURRENDERED;
+
+	sah.slotID = selectSlotForRole(color, sah.roleID);
 	sah.player = color;
 	sah.hid = hero->subID;
 	sah.army.clear();
@@ -79,8 +106,12 @@ void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHer
 void HeroPoolProcessor::onHeroEscaped(const PlayerColor & color, const CGHeroInstance * hero)
 {
 	SetAvailableHero sah;
-	sah.slotID = selectSlotForRole(color, TavernSlotRole::RETREATED);
-	sah.roleID = TavernSlotRole::RETREATED;
+	if (playerEndedTurn(color))
+		sah.roleID = TavernSlotRole::RETREATED_TODAY;
+	else
+		sah.roleID = TavernSlotRole::RETREATED;
+
+	sah.slotID = selectSlotForRole(color, sah.roleID);
 	sah.player = color;
 	sah.hid = hero->subID;
 
@@ -131,10 +162,26 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe
 
 void HeroPoolProcessor::onNewWeek(const PlayerColor & color)
 {
-	clearHeroFromSlot(color, TavernHeroSlot::NATIVE);
-	clearHeroFromSlot(color, TavernHeroSlot::RANDOM);
-	selectNewHeroForSlot(color, TavernHeroSlot::NATIVE, true, true);
-	selectNewHeroForSlot(color, TavernHeroSlot::RANDOM, false, true);
+	const auto & hpool = gameHandler->gameState()->hpool;
+	const auto & heroes = hpool->getHeroesFor(color);
+
+	const auto nativeSlotRole = heroes.size() < 1 ? TavernSlotRole::NONE : hpool->getSlotRole(heroes[0]->type->getId());
+	const auto randomSlotRole = heroes.size() < 2 ? TavernSlotRole::NONE : hpool->getSlotRole(heroes[1]->type->getId());
+
+	bool resetNativeSlot = nativeSlotRole != TavernSlotRole::RETREATED_TODAY && nativeSlotRole != TavernSlotRole::SURRENDERED_TODAY;
+	bool resetRandomSlot = randomSlotRole != TavernSlotRole::RETREATED_TODAY && randomSlotRole != TavernSlotRole::SURRENDERED_TODAY;
+
+	if (resetNativeSlot)
+		clearHeroFromSlot(color, TavernHeroSlot::NATIVE);
+
+	if (resetRandomSlot)
+		clearHeroFromSlot(color, TavernHeroSlot::RANDOM);
+
+	if (resetNativeSlot)
+		selectNewHeroForSlot(color, TavernHeroSlot::NATIVE, true, true);
+
+	if (resetRandomSlot)
+		selectNewHeroForSlot(color, TavernHeroSlot::RANDOM, false, true);
 }
 
 bool HeroPoolProcessor::hireHero(const CGObjectInstance *obj, const HeroTypeID & heroToRecruit, const PlayerColor & player)

+ 2 - 1
server/HeroPoolProcessor.h

@@ -17,7 +17,6 @@ class PlayerColor;
 class CGHeroInstance;
 class HeroTypeID;
 class CGObjectInstance;
-class FactionID;
 class CRandomGenerator;
 class CHeroClass;
 
@@ -43,6 +42,8 @@ class HeroPoolProcessor : boost::noncopyable
 	CRandomGenerator & getRandomGenerator(const PlayerColor & player);
 
 	TavernHeroSlot selectSlotForRole(const PlayerColor & player, TavernSlotRole roleID);
+
+	bool playerEndedTurn(const PlayerColor & player);
 public:
 	CGameHandler * gameHandler;