HeroBonus.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #define VCMI_DLL
  2. #include "HeroBonus.h"
  3. #include <boost/foreach.hpp>
  4. #include "VCMI_Lib.h"
  5. #include "../hch/CSpellHandler.h"
  6. #include <sstream>
  7. #include "../hch/CCreatureHandler.h"
  8. #define FOREACH_CONST_PARENT(pname, source) TCNodes parents; getParents(parents, source); BOOST_FOREACH(const CBonusSystemNode *pname, parents)
  9. #define FOREACH_PARENT(pname, source) TNodes parents; getParents(parents, source); BOOST_FOREACH(CBonusSystemNode *pname, parents)
  10. int DLL_EXPORT BonusList::totalValue() const
  11. {
  12. int base = 0;
  13. int percentToBase = 0;
  14. int percentToAll = 0;
  15. int additive = 0;
  16. for(const_iterator i = begin(); i != end(); i++)
  17. {
  18. switch(i->valType)
  19. {
  20. case Bonus::BASE_NUMBER:
  21. base += i->val;
  22. break;
  23. case Bonus::PERCENT_TO_ALL:
  24. percentToAll += i->val;
  25. break;
  26. case Bonus::PERCENT_TO_BASE:
  27. percentToBase += i->val;
  28. break;
  29. case Bonus::ADDITIVE_VALUE:
  30. additive += i->val;
  31. break;
  32. }
  33. }
  34. int modifiedBase = base + (base * percentToBase) / 100;
  35. modifiedBase += additive;
  36. return (modifiedBase * (100 + percentToAll)) / 100;
  37. }
  38. const DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &selector) const
  39. {
  40. for (const_iterator i = begin(); i != end(); i++)
  41. if(selector(*i))
  42. return &*i;
  43. return NULL;
  44. }
  45. DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &select)
  46. {
  47. for (iterator i = begin(); i != end(); i++)
  48. if(select(*i))
  49. return &*i;
  50. return NULL;
  51. }
  52. void DLL_EXPORT BonusList::getModifiersWDescr(TModDescr &out) const
  53. {
  54. for(const_iterator i = begin(); i != end(); i++)
  55. out.push_back(std::make_pair(i->val, i->Description()));
  56. }
  57. void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *source /*= NULL*/) const
  58. {
  59. for(const_iterator i = begin(); i != end(); i++)
  60. if(selector(*i) && i->effectRange == Bonus::NO_LIMIT)
  61. out.push_back(*i);
  62. }
  63. void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *source /*= NULL*/) const
  64. {
  65. for(const_iterator i = begin(); i != end(); i++)
  66. if(selector(*i) && (!limit || limit(*i)))
  67. out.push_back(*i);
  68. }
  69. int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
  70. {
  71. CSelector s = Selector::type(type);
  72. if(subtype != -1)
  73. s = s && Selector::subtype(subtype);
  74. return valOfBonuses(s);
  75. }
  76. int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
  77. {
  78. return valOfBonuses(Selector::type(type) && selector);
  79. }
  80. int CBonusSystemNode::valOfBonuses(const CSelector &selector, const CBonusSystemNode *root/* = NULL*/) const
  81. {
  82. BonusList hlp;
  83. getBonuses(hlp, selector, root);
  84. return hlp.totalValue();
  85. }
  86. bool CBonusSystemNode::hasBonus(const CSelector &selector, const CBonusSystemNode *root/* = NULL*/) const
  87. {
  88. return getBonuses(selector).size() > 0;
  89. }
  90. bool CBonusSystemNode::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
  91. {
  92. CSelector s = Selector::type(type);
  93. if(subtype != -1)
  94. s = s && Selector::subtype(subtype);
  95. return hasBonus(s);
  96. }
  97. Bonus * CBonusSystemNode::getBonus(const CSelector &selector)
  98. {
  99. Bonus *ret = bonuses.getFirst(selector);
  100. if(ret)
  101. return ret;
  102. FOREACH_PARENT(p, this)
  103. if(ret = p->getBonus(selector))
  104. return ret;
  105. return NULL;
  106. }
  107. void CBonusSystemNode::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
  108. {
  109. getModifiersWDescr(out, Selector::typeSybtype(type, subtype));
  110. }
  111. void CBonusSystemNode::getModifiersWDescr(TModDescr &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
  112. {
  113. getBonuses(selector).getModifiersWDescr(out);
  114. }
  115. int CBonusSystemNode::getBonusesCount(int from, int id) const
  116. {
  117. return getBonusesCount(Selector::source(from, id));
  118. }
  119. int CBonusSystemNode::getBonusesCount(const CSelector &selector, const CBonusSystemNode *root/* = NULL*/) const
  120. {
  121. return getBonuses(selector, root).size();
  122. }
  123. void CBonusSystemNode::getParents(TCNodes &out, const CBonusSystemNode *root) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
  124. {
  125. return;
  126. }
  127. void CBonusSystemNode::getParents(TNodes &out, const CBonusSystemNode *root /*= NULL*/)
  128. {
  129. //de-constify above
  130. TCNodes hlp;
  131. getParents(hlp, root);
  132. BOOST_FOREACH(const CBonusSystemNode *pname, hlp)
  133. out.insert(const_cast<CBonusSystemNode*>(pname));
  134. }
  135. void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
  136. {
  137. bonuses.getBonuses(out, selector);
  138. FOREACH_CONST_PARENT(p, root ? root : this)
  139. p->getBonuses(out, selector, root ? root : this);
  140. }
  141. BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
  142. {
  143. BonusList ret;
  144. getBonuses(ret, selector, root);
  145. return ret;
  146. }
  147. void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
  148. {
  149. bonuses.getBonuses(out, selector, limit);
  150. FOREACH_CONST_PARENT(p, root ? root : this)
  151. p->getBonuses(out, selector, limit, root ? root : this);
  152. }
  153. BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
  154. {
  155. BonusList ret;
  156. getBonuses(ret, selector, limit, root);
  157. return ret;
  158. }
  159. bool CBonusSystemNode::hasBonusFrom(ui8 source, ui32 sourceID) const
  160. {
  161. return hasBonus(Selector::source(source,sourceID));
  162. }
  163. int CBonusSystemNode::MoraleVal() const
  164. {
  165. if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
  166. hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
  167. return 0;
  168. int ret = valOfBonuses(Selector::type(Bonus::MORALE));
  169. if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
  170. amax(ret, +1);
  171. return abetw(ret, -3, +3);
  172. }
  173. int CBonusSystemNode::LuckVal() const
  174. {
  175. if(hasBonusOfType(Bonus::NO_LUCK))
  176. return 0;
  177. int ret = valOfBonuses(Selector::type(Bonus::LUCK));
  178. if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
  179. amax(ret, +1);
  180. return abetw(ret, -3, +3);
  181. }
  182. si32 CBonusSystemNode::Attack() const
  183. {
  184. si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
  185. if(int frenzyPower = valOfBonuses(Bonus::IN_FRENZY)) //frenzy for attacker
  186. {
  187. ret += frenzyPower * Defense(false);
  188. }
  189. return ret;
  190. }
  191. si32 CBonusSystemNode::Defense(bool withFrenzy /*= true*/) const
  192. {
  193. si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
  194. if(withFrenzy && hasBonusOfType(Bonus::IN_FRENZY)) //frenzy for defender
  195. {
  196. return 0;
  197. }
  198. return ret;
  199. }
  200. ui16 CBonusSystemNode::MaxHealth() const
  201. {
  202. return valOfBonuses(Bonus::STACK_HEALTH);
  203. }
  204. int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
  205. {
  206. if(obj)
  207. return obj->valOfBonuses(type, subtype);
  208. return 0;
  209. }
  210. bool NBonus::hasOfType(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/)
  211. {
  212. if(obj)
  213. return obj->hasBonusOfType(type, subtype);
  214. return false;
  215. }
  216. void NBonus::getModifiersWDescr(const CBonusSystemNode *obj, TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */)
  217. {
  218. if(obj)
  219. return obj->getModifiersWDescr(out, type, subtype);
  220. }
  221. int NBonus::getCount(const CBonusSystemNode *obj, int from, int id)
  222. {
  223. if(obj)
  224. return obj->getBonusesCount(from, id);
  225. return 0;
  226. }
  227. const CSpell * Bonus::sourceSpell() const
  228. {
  229. if(source == SPELL_EFFECT)
  230. return &VLC->spellh->spells[id];
  231. return NULL;
  232. }
  233. std::string Bonus::Description() const
  234. {
  235. if(description.size())
  236. return description;
  237. std::ostringstream str;
  238. if(val < 0)
  239. str << '-';
  240. else if(val > 0)
  241. str << '+';
  242. str << val << " ";
  243. switch(source)
  244. {
  245. case CREATURE_ABILITY:
  246. str << VLC->creh->creatures[id]->namePl;
  247. break;
  248. }
  249. return str.str();
  250. }
  251. CSelector DLL_EXPORT operator&&(const CSelector &first, const CSelector &second)
  252. {
  253. return CSelectorsConjunction(first, second);
  254. }
  255. namespace Selector
  256. {
  257. DLL_EXPORT CSelectFieldEqual<TBonusType> type(&Bonus::type, 0);
  258. DLL_EXPORT CSelectFieldEqual<TBonusSubtype> subtype(&Bonus::subtype, 0);
  259. DLL_EXPORT CSelectFieldEqual<si32> info(&Bonus::additionalInfo, 0);
  260. DLL_EXPORT CSelectFieldEqual<ui8> sourceType(&Bonus::source, 0);
  261. DLL_EXPORT CSelectFieldEqual<ui8> effectRange(&Bonus::effectRange, Bonus::NO_LIMIT);
  262. DLL_EXPORT CWillLastTurns turns;;
  263. CSelector DLL_EXPORT typeSybtype(TBonusType Type, TBonusSubtype Subtype)
  264. {
  265. return type(Type) && subtype(Subtype);
  266. }
  267. CSelector DLL_EXPORT typeSybtypeInfo(TBonusType type, TBonusSubtype subtype, si32 info)
  268. {
  269. return CSelectFieldEqual<TBonusType>(&Bonus::type, type) && CSelectFieldEqual<TBonusSubtype>(&Bonus::subtype, subtype) && CSelectFieldEqual<si32>(&Bonus::additionalInfo, info);
  270. }
  271. CSelector DLL_EXPORT source(ui8 source, ui32 sourceID)
  272. {
  273. return CSelectFieldEqual<ui8>(&Bonus::source, source) && CSelectFieldEqual<ui32>(&Bonus::id, sourceID);
  274. }
  275. bool matchesType(const CSelector &sel, TBonusType type)
  276. {
  277. Bonus dummy;
  278. dummy.type = type;
  279. return sel(dummy);
  280. }
  281. }