CArmedInstance.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * CArmedInstance.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 "CArmedInstance.h"
  12. #include "../CTownHandler.h"
  13. #include "../CCreatureHandler.h"
  14. #include "../CGeneralTextHandler.h"
  15. #include "../CGameState.h"
  16. void CArmedInstance::randomizeArmy(int type)
  17. {
  18. for (auto & elem : stacks)
  19. {
  20. int & randID = elem.second->idRand;
  21. if(randID >= 0)
  22. {
  23. int level = randID / 2;
  24. bool upgrade = randID % 2;
  25. elem.second->setType(VLC->townh->factions[type]->town->creatures[level][upgrade]);
  26. randID = -1;
  27. }
  28. assert(elem.second->valid(false));
  29. assert(elem.second->armyObj == this);
  30. }
  31. return;
  32. }
  33. CArmedInstance::CArmedInstance()
  34. {
  35. battle = nullptr;
  36. }
  37. void CArmedInstance::updateMoraleBonusFromArmy()
  38. {
  39. if(!validTypes(false)) //object not randomized, don't bother
  40. return;
  41. Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
  42. if(!b)
  43. {
  44. b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
  45. addNewBonus(b);
  46. }
  47. //number of alignments and presence of undead
  48. std::set<TFaction> factions;
  49. bool hasUndead = false;
  50. for(auto slot : Slots())
  51. {
  52. const CStackInstance * inst = slot.second;
  53. const CCreature * creature = VLC->creh->creatures[inst->getCreatureID()];
  54. factions.insert(creature->faction);
  55. // Check for undead flag instead of faction (undead mummies are neutral)
  56. hasUndead |= inst->hasBonusOfType(Bonus::UNDEAD);
  57. }
  58. size_t factionsInArmy = factions.size(); //town garrison seems to take both sets into account
  59. // Take Angelic Alliance troop-mixing freedom of non-evil units into account.
  60. if (hasBonusOfType(Bonus::NONEVIL_ALIGNMENT_MIX))
  61. {
  62. size_t mixableFactions = 0;
  63. for(TFaction f : factions)
  64. {
  65. if (VLC->townh->factions[f]->alignment != EAlignment::EVIL)
  66. mixableFactions++;
  67. }
  68. if (mixableFactions > 0)
  69. factionsInArmy -= mixableFactions - 1;
  70. }
  71. if(factionsInArmy == 1)
  72. {
  73. b->val = +1;
  74. b->description = VLC->generaltexth->arraytxt[115]; //All troops of one alignment +1
  75. }
  76. else if (!factions.empty()) // no bonus from empty garrison
  77. {
  78. b->val = 2 - factionsInArmy;
  79. b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factionsInArmy % b->val); //Troops of %d alignments %d
  80. }
  81. boost::algorithm::trim(b->description);
  82. //-1 modifier for any Undead unit in army
  83. const ui8 UNDEAD_MODIFIER_ID = -2;
  84. Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
  85. if(hasUndead)
  86. {
  87. if(!undeadModifier)
  88. addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]));
  89. }
  90. else if(undeadModifier)
  91. removeBonus(undeadModifier);
  92. }
  93. void CArmedInstance::armyChanged()
  94. {
  95. updateMoraleBonusFromArmy();
  96. }
  97. CBonusSystemNode * CArmedInstance::whereShouldBeAttached(CGameState *gs)
  98. {
  99. if(tempOwner < PlayerColor::PLAYER_LIMIT)
  100. return gs->getPlayer(tempOwner);
  101. else
  102. return &gs->globalEffects;
  103. }
  104. CBonusSystemNode * CArmedInstance::whatShouldBeAttached()
  105. {
  106. return this;
  107. }