NewTurnProcessor.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * NewTurnProcessor.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "NewTurnProcessor.h"
  12. #include "HeroPoolProcessor.h"
  13. #include "../CGameHandler.h"
  14. #include "../../lib/CPlayerState.h"
  15. #include "../../lib/GameSettings.h"
  16. #include "../../lib/StartInfo.h"
  17. #include "../../lib/TerrainHandler.h"
  18. #include "../../lib/entities/building/CBuilding.h"
  19. #include "../../lib/entities/faction/CTownHandler.h"
  20. #include "../../lib/gameState/CGameState.h"
  21. #include "../../lib/mapObjects/CGHeroInstance.h"
  22. #include "../../lib/mapObjects/CGTownInstance.h"
  23. #include "../../lib/mapObjects/IOwnableObject.h"
  24. #include "../../lib/mapping/CMap.h"
  25. #include "../../lib/networkPacks/PacksForClient.h"
  26. #include "../../lib/pathfinder/TurnInfo.h"
  27. #include <vstd/RNG.h>
  28. NewTurnProcessor::NewTurnProcessor(CGameHandler * gameHandler)
  29. :gameHandler(gameHandler)
  30. {
  31. }
  32. void NewTurnProcessor::onPlayerTurnStarted(PlayerColor which)
  33. {
  34. const auto * playerState = gameHandler->gameState()->getPlayerState(which);
  35. gameHandler->handleTimeEvents(which);
  36. for (const auto * t : playerState->getTowns())
  37. gameHandler->handleTownEvents(t);
  38. for (const auto * t : playerState->getTowns())
  39. {
  40. //garrison hero first - consistent with original H3 Mana Vortex and Battle Scholar Academy levelup windows order
  41. if (t->garrisonHero != nullptr)
  42. gameHandler->objectVisited(t, t->garrisonHero);
  43. if (t->visitingHero != nullptr)
  44. gameHandler->objectVisited(t, t->visitingHero);
  45. }
  46. }
  47. void NewTurnProcessor::onPlayerTurnEnded(PlayerColor which)
  48. {
  49. const auto * playerState = gameHandler->gameState()->getPlayerState(which);
  50. assert(playerState->status == EPlayerStatus::INGAME);
  51. if (playerState->getTowns().empty())
  52. {
  53. DaysWithoutTown pack;
  54. pack.player = which;
  55. pack.daysWithoutCastle = playerState->daysWithoutCastle.value_or(0) + 1;
  56. gameHandler->sendAndApply(&pack);
  57. }
  58. else
  59. {
  60. if (playerState->daysWithoutCastle.has_value())
  61. {
  62. DaysWithoutTown pack;
  63. pack.player = which;
  64. pack.daysWithoutCastle = std::nullopt;
  65. gameHandler->sendAndApply(&pack);
  66. }
  67. }
  68. // check for 7 days without castle
  69. gameHandler->checkVictoryLossConditionsForPlayer(which);
  70. bool newWeek = gameHandler->getDate(Date::DAY_OF_WEEK) == 7; // end of 7th day
  71. if (newWeek) //new heroes in tavern
  72. gameHandler->heroPool->onNewWeek(which);
  73. }
  74. ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool newWeek)
  75. {
  76. const auto & playerSettings = gameHandler->getPlayerSettings(playerID);
  77. const PlayerState & state = gameHandler->gameState()->players.at(playerID);
  78. ResourceSet income;
  79. for (const auto & town : state.getTowns())
  80. {
  81. if (newWeek && town->hasBuilt(BuildingSubID::TREASURY))
  82. {
  83. //give 10% of starting gold
  84. income[EGameResID::GOLD] += state.resources[EGameResID::GOLD] / 10;
  85. }
  86. //give resources if there's a Mystic Pond
  87. if (newWeek && town->hasBuilt(BuildingSubID::MYSTIC_POND))
  88. {
  89. static constexpr std::array rareResources = {
  90. GameResID::MERCURY,
  91. GameResID::SULFUR,
  92. GameResID::CRYSTAL,
  93. GameResID::GEMS
  94. };
  95. auto resID = *RandomGeneratorUtil::nextItem(rareResources, gameHandler->getRandomGenerator());
  96. int resVal = gameHandler->getRandomGenerator().nextInt(1, 4);
  97. income[resID] += resVal;
  98. gameHandler->setObjPropertyValue(town->id, ObjProperty::BONUS_VALUE_FIRST, resID);
  99. gameHandler->setObjPropertyValue(town->id, ObjProperty::BONUS_VALUE_SECOND, resVal);
  100. }
  101. }
  102. for (GameResID k = GameResID::WOOD; k < GameResID::COUNT; k++)
  103. {
  104. income += state.valOfBonuses(BonusType::RESOURCES_CONSTANT_BOOST, BonusSubtypeID(k));
  105. income += state.valOfBonuses(BonusType::RESOURCES_TOWN_MULTIPLYING_BOOST, BonusSubtypeID(k)) * state.getTowns().size();
  106. }
  107. if(newWeek) //weekly crystal generation if 1 or more crystal dragons in any hero army or town garrison
  108. {
  109. bool hasCrystalGenCreature = false;
  110. for (const auto & hero : state.getHeroes())
  111. for(auto stack : hero->stacks)
  112. if(stack.second->hasBonusOfType(BonusType::SPECIAL_CRYSTAL_GENERATION))
  113. hasCrystalGenCreature = true;
  114. for(const auto & town : state.getTowns())
  115. for(auto stack : town->stacks)
  116. if(stack.second->hasBonusOfType(BonusType::SPECIAL_CRYSTAL_GENERATION))
  117. hasCrystalGenCreature = true;
  118. if(hasCrystalGenCreature)
  119. income[EGameResID::CRYSTAL] += 3;
  120. }
  121. TResources incomeHandicapped = income;
  122. incomeHandicapped.applyHandicap(playerSettings->handicap.percentIncome);
  123. for (auto obj : state.getOwnedObjects())
  124. incomeHandicapped += obj->asOwnable()->dailyIncome();
  125. return incomeHandicapped;
  126. }
  127. SetAvailableCreatures NewTurnProcessor::generateTownGrowth(const CGTownInstance * t, EWeekType weekType, CreatureID creatureWeek, bool firstDay)
  128. {
  129. SetAvailableCreatures sac;
  130. PlayerColor player = t->tempOwner;
  131. sac.tid = t->id;
  132. sac.creatures = t->creatures;
  133. for (int k=0; k < t->town->creatures.size(); k++)
  134. {
  135. if (t->creatures.at(k).second.empty())
  136. continue;
  137. uint32_t creaturesBefore = t->creatures.at(k).first;
  138. uint32_t creatureGrowth = 0;
  139. const CCreature *cre = t->creatures.at(k).second.back().toCreature();
  140. if (firstDay)
  141. {
  142. creatureGrowth = cre->getGrowth();
  143. }
  144. else
  145. {
  146. creatureGrowth = t->creatureGrowth(k);
  147. //Deity of fire week - upgrade both imps and upgrades
  148. if (weekType == EWeekType::DEITYOFFIRE && vstd::contains(t->creatures.at(k).second, creatureWeek))
  149. creatureGrowth += 15;
  150. //bonus week, effect applies only to identical creatures
  151. if (weekType == EWeekType::BONUS_GROWTH && cre->getId() == creatureWeek)
  152. creatureGrowth += 5;
  153. }
  154. // Neutral towns have halved creature growth
  155. if (!player.isValidPlayer())
  156. creatureGrowth /= 2;
  157. uint32_t resultingCreatures = 0;
  158. if (weekType == EWeekType::PLAGUE)
  159. resultingCreatures = creaturesBefore / 2;
  160. else if (weekType == EWeekType::DOUBLE_GROWTH)
  161. resultingCreatures = (creaturesBefore + creatureGrowth) * 2;
  162. else
  163. resultingCreatures = creaturesBefore + creatureGrowth;
  164. sac.creatures.at(k).first = resultingCreatures;
  165. }
  166. return sac;
  167. }