IGameCallback.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368
  1. #include "StdInc.h"
  2. #include "IGameCallback.h"
  3. #include "../lib/CGameState.h"
  4. #include "../lib/map.h"
  5. #include "CObjectHandler.h"
  6. #include "CHeroHandler.h"
  7. #include "StartInfo.h"
  8. #include "CArtHandler.h"
  9. #include "CSpellHandler.h"
  10. #include "../lib/VCMI_Lib.h"
  11. #include <boost/random/linear_congruential.hpp>
  12. #include "CTownHandler.h"
  13. #include "BattleState.h"
  14. #include "NetPacks.h"
  15. #include "CBuildingHandler.h"
  16. #include "GameConstants.h"
  17. /*
  18. * IGameCallback.cpp, part of VCMI engine
  19. *
  20. * Authors: listed in file AUTHORS in main folder
  21. *
  22. * License: GNU General Public License v2.0 or later
  23. * Full text of license available in license.txt file, in main folder
  24. *
  25. */
  26. //TODO make clean
  27. #define ERROR_SILENT_RET_VAL_IF(cond, txt, retVal) do {if(cond){return retVal;}} while(0)
  28. #define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return retVal;}} while(0)
  29. #define ERROR_RET_IF(cond, txt) do {if(cond){tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return;}} while(0)
  30. #define ERROR_RET_VAL_IF(cond, txt, retVal) do {if(cond){tlog1 << BOOST_CURRENT_FUNCTION << ": " << txt << std::endl; return retVal;}} while(0)
  31. extern boost::rand48 ran;
  32. boost::shared_mutex& CCallbackBase::getGsMutex()
  33. {
  34. return *gs->mx;
  35. }
  36. si8 CBattleInfoCallback::battleHasDistancePenalty( const CStack * stack, BattleHex destHex )
  37. {
  38. return gs->curB->hasDistancePenalty(stack, destHex);
  39. }
  40. si8 CBattleInfoCallback::battleHasWallPenalty( const CStack * stack, BattleHex destHex )
  41. {
  42. return gs->curB->hasWallPenalty(stack, destHex);
  43. }
  44. si8 CBattleInfoCallback::battleCanTeleportTo(const CStack * stack, BattleHex destHex, int telportLevel)
  45. {
  46. return gs->curB->canTeleportTo(stack, destHex, telportLevel);
  47. }
  48. std::vector<int> CBattleInfoCallback::battleGetDistances(const CStack * stack, BattleHex hex /*= BattleHex::INVALID*/, BattleHex * predecessors /*= NULL*/)
  49. {
  50. if(!hex.isValid())
  51. hex = stack->position;
  52. std::vector<int> ret(GameConstants::BFIELD_SIZE, -1); //fill initial ret with -1's
  53. if(!hex.isValid()) //stack has bad position? probably castle turret, return initial values (they can't move)
  54. return ret;
  55. bool ac[GameConstants::BFIELD_SIZE] = {0};
  56. std::set<BattleHex> occupyable;
  57. gs->curB->getAccessibilityMap(ac, stack->doubleWide(), stack->attackerOwned, false, occupyable, stack->hasBonusOfType(Bonus::FLYING), stack);
  58. BattleHex pr[GameConstants::BFIELD_SIZE];
  59. int dist[GameConstants::BFIELD_SIZE];
  60. gs->curB->makeBFS(stack->position, ac, pr, dist, stack->doubleWide(), stack->attackerOwned, stack->hasBonusOfType(Bonus::FLYING), false);
  61. for(int i=0; i<GameConstants::BFIELD_SIZE; ++i)
  62. {
  63. if(pr[i] != -1)
  64. ret[i] = dist[i];
  65. }
  66. if(predecessors)
  67. {
  68. memcpy(predecessors, pr, GameConstants::BFIELD_SIZE * sizeof(BattleHex));
  69. }
  70. return ret;
  71. }
  72. std::set<BattleHex> CBattleInfoCallback::battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos /*= BattleHex::INVALID*/)
  73. {
  74. if(!gs->curB)
  75. {
  76. tlog1 << "battleGetAttackedHexes called when there is no battle!\n";
  77. std::set<BattleHex> set;
  78. return set;
  79. }
  80. return gs->curB->getAttackedHexes(attacker, destinationTile, attackerPos);
  81. }
  82. ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell( const CSpell * spell )
  83. {
  84. if(!gs->curB)
  85. {
  86. tlog1 << "battleCanCastThisSpell called when there is no battle!\n";
  87. return ESpellCastProblem::NO_HERO_TO_CAST_SPELL;
  88. }
  89. return gs->curB->battleCanCastThisSpell(player, spell, ECastingMode::HERO_CASTING);
  90. }
  91. ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell(const CSpell * spell, BattleHex destination)
  92. {
  93. if(!gs->curB)
  94. {
  95. tlog1 << "battleCanCastThisSpell called when there is no battle!\n";
  96. return ESpellCastProblem::NO_HERO_TO_CAST_SPELL;
  97. }
  98. return gs->curB->battleCanCastThisSpellHere(player, spell, ECastingMode::HERO_CASTING, destination);
  99. }
  100. ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination)
  101. {
  102. if(!gs->curB)
  103. {
  104. tlog1 << "battleCanCastThisSpell called when there is no battle!\n";
  105. return ESpellCastProblem::NO_HERO_TO_CAST_SPELL;
  106. }
  107. return gs->curB->battleCanCastThisSpellHere(player, spell, ECastingMode::CREATURE_ACTIVE_CASTING, destination);
  108. }
  109. si32 CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode)
  110. {
  111. switch (mode)
  112. {
  113. case RANDOM_GENIE:
  114. return gs->curB->getRandomBeneficialSpell(stack); //target
  115. break;
  116. case RANDOM_AIMED:
  117. return gs->curB->getRandomCastedSpell(stack); //caster
  118. break;
  119. default:
  120. tlog1 << "Incorrect mode of battleGetRandomSpell (" << mode <<")\n";
  121. return -1;
  122. }
  123. }
  124. si8 CBattleInfoCallback::battleGetTacticDist()
  125. {
  126. if (!gs->curB)
  127. {
  128. tlog1 << "battleGetTacticDist called when no battle!\n";
  129. return 0;
  130. }
  131. if (gs->curB->sides[gs->curB->tacticsSide] == player)
  132. {
  133. return gs->curB->tacticDistance;
  134. }
  135. return 0;
  136. }
  137. ui8 CBattleInfoCallback::battleGetMySide()
  138. {
  139. if (!gs->curB)
  140. {
  141. tlog1 << "battleGetMySide called when no battle!\n";
  142. return 0;
  143. }
  144. return gs->curB->sides[1] == player;
  145. }
  146. int CBattleInfoCallback::battleGetSurrenderCost()
  147. {
  148. if (!gs->curB)
  149. {
  150. tlog1 << "battleGetSurrenderCost called when no battle!\n";
  151. return -1;
  152. }
  153. return gs->curB->getSurrenderingCost(player);
  154. }
  155. int CBattleInfoCallback::battleGetBattlefieldType()
  156. {
  157. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  158. //return gs->battleGetBattlefieldType();
  159. if(!gs->curB)
  160. {
  161. tlog2<<"battleGetBattlefieldType called when there is no battle!"<<std::endl;
  162. return -1;
  163. }
  164. return gs->curB->battlefieldType;
  165. }
  166. // int CBattleInfoCallback::battleGetObstaclesAtTile(BattleHex tile) //returns bitfield
  167. // {
  168. // //TODO - write
  169. // return -1;
  170. // }
  171. std::vector<shared_ptr<const CObstacleInstance> > CBattleInfoCallback::battleGetAllObstacles()
  172. {
  173. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  174. std::vector<shared_ptr<const CObstacleInstance> > ret;
  175. if(gs->curB)
  176. {
  177. BOOST_FOREACH(auto oi, gs->curB->obstacles)
  178. {
  179. if(player < 0 || gs->curB->isObstacleVisibleForSide(*oi, battleGetMySide()))
  180. ret.push_back(oi);
  181. }
  182. }
  183. return ret;
  184. }
  185. const CStack* CBattleInfoCallback::battleGetStackByID(int ID, bool onlyAlive)
  186. {
  187. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  188. if(!gs->curB) return NULL;
  189. return gs->curB->getStack(ID, onlyAlive);
  190. }
  191. const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyAlive)
  192. {
  193. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  194. return gs->curB->battleGetStack(pos, onlyAlive);
  195. }
  196. BattleHex CBattleInfoCallback::battleGetPos(int stack)
  197. {
  198. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  199. if(!gs->curB)
  200. {
  201. tlog2<<"battleGetPos called when there is no battle!"<<std::endl;
  202. return BattleHex::INVALID;
  203. }
  204. for(size_t g=0; g<gs->curB->stacks.size(); ++g)
  205. {
  206. if(gs->curB->stacks[g]->ID == stack)
  207. return gs->curB->stacks[g]->position;
  208. }
  209. return BattleHex::INVALID;
  210. }
  211. TStacks CBattleInfoCallback::battleGetStacks(EStackOwnership whose /*= MINE_AND_ENEMY*/, bool onlyAlive /*= true*/)
  212. {
  213. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  214. TStacks ret;
  215. if(!gs->curB) //there is no battle
  216. {
  217. tlog2<<"battleGetStacks called when there is no battle!"<<std::endl;
  218. return ret;
  219. }
  220. BOOST_FOREACH(const CStack *s, gs->curB->stacks)
  221. {
  222. bool ownerMatches = (whose == MINE_AND_ENEMY) || (whose == ONLY_MINE && s->owner == player) || (whose == ONLY_ENEMY && s->owner != player);
  223. bool alivenessMatches = s->alive() || !onlyAlive;
  224. if(ownerMatches && alivenessMatches)
  225. ret.push_back(s);
  226. }
  227. return ret;
  228. }
  229. void CBattleInfoCallback::getStackQueue( std::vector<const CStack *> &out, int howMany )
  230. {
  231. if(!gs->curB)
  232. {
  233. tlog2 << "battleGetStackQueue called when there is not battle!" << std::endl;
  234. return;
  235. }
  236. gs->curB->getStackQueue(out, howMany);
  237. }
  238. void CBattleInfoCallback::battleGetStackCountOutsideHexes(bool *ac)
  239. {
  240. if(!gs->curB)
  241. {
  242. tlog2<<"battleGetAvailableHexes called when there is no battle!"<<std::endl;
  243. for (int i = 0; i < GameConstants::BFIELD_SIZE; ++i) ac[i] = false;
  244. }
  245. else {
  246. std::set<BattleHex> ignored;
  247. gs->curB->getAccessibilityMap(ac, false /*ignored*/, false, false, ignored, false /*ignored*/, NULL);
  248. }
  249. }
  250. std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable)
  251. {
  252. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  253. if(!gs->curB)
  254. {
  255. tlog2<<"battleGetAvailableHexes called when there is no battle!"<<std::endl;
  256. return std::vector<BattleHex>();
  257. }
  258. return gs->curB->getAccessibility(stack, addOccupiable, attackable);
  259. //return gs->battleGetRange(ID);
  260. }
  261. bool CBattleInfoCallback::battleCanShoot(const CStack * stack, BattleHex dest)
  262. {
  263. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  264. if(!gs->curB) return false;
  265. return gs->curB->battleCanShoot(stack, dest);
  266. }
  267. bool CBattleInfoCallback::battleCanCastSpell()
  268. {
  269. if(!gs->curB) //there is no battle
  270. return false;
  271. return gs->curB->battleCanCastSpell(player, ECastingMode::HERO_CASTING) == ESpellCastProblem::OK;
  272. }
  273. bool CBattleInfoCallback::battleCanFlee()
  274. {
  275. return gs->curB->battleCanFlee(player);
  276. }
  277. const CGTownInstance *CBattleInfoCallback::battleGetDefendedTown()
  278. {
  279. if(!gs->curB || gs->curB->town == NULL)
  280. return NULL;
  281. return gs->curB->town;
  282. }
  283. ui8 CBattleInfoCallback::battleGetWallState(int partOfWall)
  284. {
  285. if(!gs->curB || gs->curB->siege == 0)
  286. {
  287. return 0;
  288. }
  289. return gs->curB->si.wallState[partOfWall];
  290. }
  291. int CBattleInfoCallback::battleGetWallUnderHex(BattleHex hex)
  292. {
  293. if(!gs->curB || gs->curB->siege == 0)
  294. {
  295. return -1;
  296. }
  297. return gs->curB->hexToWallPart(hex);
  298. }
  299. TDmgRange CBattleInfoCallback::battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg)
  300. {
  301. if(!gs->curB)
  302. return std::make_pair(0, 0);
  303. const CGHeroInstance * attackerHero, * defenderHero;
  304. bool shooting = battleCanShoot(attacker, defender->position);
  305. if(gs->curB->sides[0] == attacker->owner)
  306. {
  307. attackerHero = gs->curB->heroes[0];
  308. defenderHero = gs->curB->heroes[1];
  309. }
  310. else
  311. {
  312. attackerHero = gs->curB->heroes[1];
  313. defenderHero = gs->curB->heroes[0];
  314. }
  315. TDmgRange ret = gs->curB->calculateDmgRange(attacker, defender, attackerHero, defenderHero, shooting, 0, false, false, false);
  316. if(retaliationDmg)
  317. {
  318. if(shooting)
  319. {
  320. retaliationDmg->first = retaliationDmg->second = 0;
  321. }
  322. else
  323. {
  324. ui32 TDmgRange::* pairElems[] = {&TDmgRange::first, &TDmgRange::second};
  325. for (int i=0; i<2; ++i)
  326. {
  327. BattleStackAttacked bsa;
  328. bsa.damageAmount = ret.*pairElems[i];
  329. retaliationDmg->*pairElems[!i] = gs->curB->calculateDmgRange(defender, attacker, bsa.newAmount, attacker->count, attackerHero, defenderHero, false, 0, false, false, false).*pairElems[!i];
  330. }
  331. }
  332. }
  333. return ret;
  334. }
  335. ui8 CBattleInfoCallback::battleGetSiegeLevel()
  336. {
  337. if(!gs->curB)
  338. return 0;
  339. return gs->curB->siege;
  340. }
  341. const CGHeroInstance * CBattleInfoCallback::battleGetFightingHero(ui8 side) const
  342. {
  343. if(!gs->curB)
  344. return 0;
  345. //TODO: this method should not exist... you shouldn't be able to get info about enemy hero
  346. return gs->curB->heroes[side];
  347. }
  348. shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking /*= true*/)
  349. {
  350. if(!gs->curB)
  351. return NULL;
  352. auto ptr = gs->curB->obstacles.front();
  353. shared_ptr<const CObstacleInstance> nastala = ptr;
  354. BOOST_FOREACH(auto &obs, battleGetAllObstacles())
  355. {
  356. if(vstd::contains(obs->getBlockedTiles(), tile)
  357. || (!onlyBlocking && vstd::contains(obs->getAffectedTiles(), tile)))
  358. {
  359. return obs;
  360. }
  361. }
  362. return NULL;
  363. }
  364. int CBattleInfoCallback::battleGetMoatDmg()
  365. {
  366. if(!gs->curB || !gs->curB->town)
  367. return 0;
  368. //TODO move to config file
  369. static const int dmgs[] = {70, 70, -1,
  370. 90, 70, 90,
  371. 70, 90, 70};
  372. if(gs->curB->town->subID < ARRAY_COUNT(dmgs))
  373. return dmgs[gs->curB->town->subID];
  374. return 0;
  375. }
  376. CGameState *const CPrivilagedInfoCallback::gameState ()
  377. {
  378. return gs;
  379. }
  380. int CGameInfoCallback::getOwner(int heroID) const
  381. {
  382. const CGObjectInstance *obj = getObj(heroID);
  383. ERROR_RET_VAL_IF(!obj, "No such object!", -1);
  384. return gs->map->objects[heroID]->tempOwner;
  385. }
  386. int CGameInfoCallback::getResource(int Player, int which) const
  387. {
  388. const PlayerState *p = getPlayer(Player);
  389. ERROR_RET_VAL_IF(!p, "No player info!", -1);
  390. ERROR_RET_VAL_IF(p->resources.size() <= which || which < 0, "No such resource!", -1);
  391. return p->resources[which];
  392. }
  393. const CGHeroInstance* CGameInfoCallback::getSelectedHero( int Player ) const
  394. {
  395. const PlayerState *p = getPlayer(Player);
  396. ERROR_RET_VAL_IF(!p, "No player info!", NULL);
  397. return getHero(p->currentSelection);
  398. }
  399. const CGHeroInstance* CGameInfoCallback::getSelectedHero() const
  400. {
  401. return getSelectedHero(gs->currentPlayer);
  402. }
  403. const PlayerSettings * CGameInfoCallback::getPlayerSettings(int color) const
  404. {
  405. return &gs->scenarioOps->getIthPlayersSettings(color);
  406. }
  407. void CPrivilagedInfoCallback::getTilesInRange( boost::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int player/*=-1*/, int mode/*=0*/ ) const
  408. {
  409. if(player >= GameConstants::PLAYER_LIMIT)
  410. {
  411. tlog1 << "Illegal call to getTilesInRange!\n";
  412. return;
  413. }
  414. if (radious == -1) //reveal entire map
  415. getAllTiles (tiles, player, -1, 0);
  416. else
  417. {
  418. const TeamState * team = gs->getPlayerTeam(player);
  419. for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++)
  420. {
  421. for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++)
  422. {
  423. double distance = pos.dist2d(int3(xd,yd,pos.z)) - 0.5;
  424. if(distance <= radious)
  425. {
  426. if(player < 0
  427. || (mode == 1 && team->fogOfWarMap[xd][yd][pos.z]==0)
  428. || (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1)
  429. )
  430. tiles.insert(int3(xd,yd,pos.z));
  431. }
  432. }
  433. }
  434. }
  435. }
  436. void CPrivilagedInfoCallback::getAllTiles (boost::unordered_set<int3, ShashInt3> &tiles, int Player/*=-1*/, int level, int surface ) const
  437. {
  438. if(Player >= GameConstants::PLAYER_LIMIT)
  439. {
  440. tlog1 << "Illegal call to getAllTiles !\n";
  441. return;
  442. }
  443. bool water = surface == 0 || surface == 2,
  444. land = surface == 0 || surface == 1;
  445. std::vector<int> floors;
  446. if(level == -1)
  447. {
  448. for (int xd = 0; xd <= gs->map->width - 1; xd++)
  449. for(int b=0; b<gs->map->twoLevel + 1; ++b) //if gs->map->twoLevel is false then false (0) + 1 is 1, if it's true (1) then we have 2
  450. {
  451. floors.push_back(b);
  452. }
  453. }
  454. else
  455. floors.push_back(level);
  456. for (std::vector<int>::const_iterator i = floors.begin(); i!= floors.end(); i++)
  457. {
  458. register int zd = *i;
  459. for (int xd = 0; xd < gs->map->width; xd++)
  460. {
  461. for (int yd = 0; yd < gs->map->height; yd++)
  462. {
  463. if ((getTile (int3 (xd,yd,zd))->tertype == 8 && water)
  464. || (getTile (int3 (xd,yd,zd))->tertype != 8 && land))
  465. tiles.insert(int3(xd,yd,zd));
  466. }
  467. }
  468. }
  469. }
  470. void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
  471. {
  472. std::vector<int> floors;
  473. for (int b=0; b<gs->map->twoLevel + 1; ++b) //if gs->map->twoLevel is false then false (0) + 1 is 1, if it's true (1) then we have 2
  474. {
  475. floors.push_back(b);
  476. }
  477. const TerrainTile *tinfo;
  478. for (std::vector<int>::const_iterator i = floors.begin(); i!= floors.end(); i++)
  479. {
  480. register int zd = *i;
  481. for (int xd = 0; xd < gs->map->width; xd++)
  482. {
  483. for (int yd = 0; yd < gs->map->height; yd++)
  484. {
  485. tinfo = getTile(int3 (xd,yd,zd));
  486. if (tinfo->tertype != 8 && !tinfo->blocked) //land and free
  487. tiles.push_back (int3 (xd,yd,zd));
  488. }
  489. }
  490. }
  491. }
  492. bool CGameInfoCallback::isAllowed( int type, int id )
  493. {
  494. switch(type)
  495. {
  496. case 0:
  497. return gs->map->allowedSpell[id];
  498. case 1:
  499. return gs->map->allowedArtifact[id];
  500. case 2:
  501. return gs->map->allowedAbilities[id];
  502. default:
  503. ERROR_RET_VAL_IF(1, "Wrong type!", false);
  504. }
  505. }
  506. void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out)
  507. {
  508. for (int i = 0; i < 2; i++)
  509. {
  510. for (int j = 0; j < 3 ; j++)
  511. {
  512. out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_TREASURE << i)]);
  513. }
  514. }
  515. out.push_back(VLC->arth->artifacts[getRandomArt(CArtifact::ART_MAJOR)]);
  516. }
  517. ui16 CPrivilagedInfoCallback::getRandomArt (int flags)
  518. {
  519. return VLC->arth->getRandomArt(flags);
  520. }
  521. ui16 CPrivilagedInfoCallback::getArtSync (ui32 rand, int flags)
  522. {
  523. return VLC->arth->getArtSync (rand, flags);
  524. }
  525. void CPrivilagedInfoCallback::erasePickedArt (si32 id)
  526. {
  527. VLC->arth->erasePickedArt(id);
  528. }
  529. void CPrivilagedInfoCallback::getAllowedSpells(std::vector<ui16> &out, ui16 level)
  530. {
  531. CSpell *spell;
  532. for (ui32 i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?)
  533. {
  534. spell = VLC->spellh->spells[i];
  535. if (isAllowed (0, spell->id) && spell->level == level)
  536. {
  537. out.push_back(spell->id);
  538. }
  539. }
  540. }
  541. inline TerrainTile * CNonConstInfoCallback::getTile( int3 pos )
  542. {
  543. if(!gs->map->isInTheMap(pos))
  544. return NULL;
  545. return &gs->map->getTile(pos);
  546. }
  547. const PlayerState * CGameInfoCallback::getPlayer(int color, bool verbose) const
  548. {
  549. ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!hasAccess(color), verbose, "Cannot access player " << color << "info!", NULL);
  550. ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!vstd::contains(gs->players,color), verbose, "Cannot find player " << color << "info!", NULL);
  551. return &gs->players[color];
  552. }
  553. const CTown * CGameInfoCallback::getNativeTown(int color) const
  554. {
  555. const PlayerSettings *ps = getPlayerSettings(color);
  556. ERROR_RET_VAL_IF(!ps, "There is no such player!", NULL);
  557. return &VLC->townh->towns[ps->castle];
  558. }
  559. const CGObjectInstance * CGameInfoCallback::getObjByQuestIdentifier(int identifier) const
  560. {
  561. ERROR_RET_VAL_IF(!vstd::contains(gs->map->questIdentifierToId, identifier), "There is no object with such quest identifier!", NULL);
  562. return getObj(gs->map->questIdentifierToId[identifier]);
  563. }
  564. /************************************************************************/
  565. /* */
  566. /************************************************************************/
  567. const CGObjectInstance* CGameInfoCallback::getObj(int objid, bool verbose) const
  568. {
  569. if(objid < 0 || objid >= gs->map->objects.size())
  570. {
  571. if(verbose)
  572. tlog1 << "Cannot get object with id " << objid << std::endl;
  573. return NULL;
  574. }
  575. const CGObjectInstance *ret = gs->map->objects[objid];
  576. if(!ret)
  577. {
  578. if(verbose)
  579. tlog1 << "Cannot get object with id " << objid << ". Object was removed.\n";
  580. return NULL;
  581. }
  582. if(!isVisible(ret, player))
  583. {
  584. if(verbose)
  585. tlog1 << "Cannot get object with id " << objid << ". Object is not visible.\n";
  586. return NULL;
  587. }
  588. return ret;
  589. }
  590. const CGHeroInstance* CGameInfoCallback::getHero(int objid) const
  591. {
  592. const CGObjectInstance *obj = getObj(objid, false);
  593. if(obj)
  594. return dynamic_cast<const CGHeroInstance*>(obj);
  595. else
  596. return NULL;
  597. }
  598. const CGTownInstance* CGameInfoCallback::getTown(int objid) const
  599. {
  600. const CGObjectInstance *obj = getObj(objid, false);
  601. if(obj)
  602. return dynamic_cast<const CGTownInstance*>(gs->map->objects[objid].get());
  603. else
  604. return NULL;
  605. }
  606. void CGameInfoCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos, UpgradeInfo &out) const
  607. {
  608. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  609. ERROR_RET_IF(!canGetFullInfo(obj), "Cannot get info about not owned object!");
  610. ERROR_RET_IF(!obj->hasStackAtSlot(stackPos), "There is no such stack!");
  611. out = gs->getUpgradeInfo(obj->getStack(stackPos));
  612. //return gs->getUpgradeInfo(obj->getStack(stackPos));
  613. }
  614. const StartInfo * CGameInfoCallback::getStartInfo() const
  615. {
  616. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  617. return gs->scenarioOps;
  618. }
  619. int CGameInfoCallback::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const
  620. {
  621. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  622. ERROR_RET_VAL_IF(!canGetFullInfo(caster), "Cannot get info about caster!", -1);
  623. //if there is a battle
  624. if(gs->curB)
  625. return gs->curB->getSpellCost(sp, caster);
  626. //if there is no battle
  627. return caster->getSpellCost(sp);
  628. }
  629. int CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const
  630. {
  631. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  632. ERROR_RET_VAL_IF(hero && !canGetFullInfo(hero), "Cannot get info about caster!", -1);
  633. if(!gs->curB) //no battle
  634. {
  635. if (hero) //but we see hero's spellbook
  636. return gs->curB->calculateSpellDmg(sp, hero, NULL, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(2));
  637. else
  638. return 0; //mage guild
  639. }
  640. //gs->getHero(gs->currentPlayer)
  641. //const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
  642. const CGHeroInstance * ourHero = hero;
  643. return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(2));
  644. }
  645. void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)
  646. {
  647. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  648. ERROR_RET_IF(!obj, "No guild object!");
  649. ERROR_RET_IF(obj->ID == GameConstants::TOWNI_TYPE && !canGetFullInfo(obj), "Cannot get info about town guild object!");
  650. //TODO: advmap object -> check if they're visited by our hero
  651. if(obj->ID == GameConstants::TOWNI_TYPE || obj->ID == 95) //it is a town or adv map tavern
  652. {
  653. gs->obtainPlayersStats(thi, gs->players[obj->tempOwner].towns.size());
  654. }
  655. else if(obj->ID == 97) //Den of Thieves
  656. {
  657. gs->obtainPlayersStats(thi, 20);
  658. }
  659. }
  660. int CGameInfoCallback::howManyTowns(int Player) const
  661. {
  662. ERROR_RET_VAL_IF(!hasAccess(Player), "Access forbidden!", -1);
  663. return gs->players[Player].towns.size();
  664. }
  665. bool CGameInfoCallback::getTownInfo( const CGObjectInstance *town, InfoAboutTown &dest ) const
  666. {
  667. ERROR_RET_VAL_IF(!isVisible(town, player), "Town is not visible!", false); //it's not a town or it's not visible for layer
  668. bool detailed = hasAccess(town->tempOwner);
  669. //TODO vision support
  670. if(town->ID == GameConstants::TOWNI_TYPE)
  671. dest.initFromTown(static_cast<const CGTownInstance *>(town), detailed);
  672. else if(town->ID == 33 || town->ID == 219)
  673. dest.initFromGarrison(static_cast<const CGGarrison *>(town), detailed);
  674. else
  675. return false;
  676. return true;
  677. }
  678. int3 CGameInfoCallback::guardingCreaturePosition (int3 pos) const
  679. {
  680. ERROR_RET_VAL_IF(!isVisible(pos), "Tile is not visible!", int3(-1,-1,-1));
  681. return gs->guardingCreaturePosition(pos);
  682. }
  683. bool CGameInfoCallback::getHeroInfo( const CGObjectInstance *hero, InfoAboutHero &dest ) const
  684. {
  685. const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(hero);
  686. ERROR_RET_VAL_IF(!h, "That's not a hero!", false);
  687. ERROR_RET_VAL_IF(!isVisible(h->getPosition(false)), "That hero is not visible!", false);
  688. //TODO vision support
  689. dest.initFromHero(h, hasAccess(h->tempOwner));
  690. return true;
  691. }
  692. int CGameInfoCallback::getDate(int mode) const
  693. {
  694. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  695. return gs->getDate(mode);
  696. }
  697. std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) const
  698. {
  699. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  700. std::vector<std::string> ret;
  701. const TerrainTile *t = getTile(pos);
  702. ERROR_RET_VAL_IF(!t, "Not a valid tile given!", ret);
  703. BOOST_FOREACH(const CGObjectInstance * obj, t->blockingObjects)
  704. ret.push_back(obj->getHoverText());
  705. return ret;
  706. }
  707. bool CGameInfoCallback::verifyPath(CPath * path, bool blockSea) const
  708. {
  709. for (size_t i=0; i < path->nodes.size(); ++i)
  710. {
  711. const TerrainTile *t = getTile(path->nodes[i].coord); //current tile
  712. ERROR_RET_VAL_IF(!t, "Path contains not visible tile: " << path->nodes[i].coord << "!", false);
  713. if (t->blocked && !t->visitable)
  714. return false; //path is wrong - one of the tiles is blocked
  715. if (blockSea)
  716. {
  717. if (i==0)
  718. continue;
  719. const TerrainTile *prev = getTile(path->nodes[i-1].coord); //tile of previous node on the path
  720. if (( t->tertype == TerrainTile::water && prev->tertype != TerrainTile::water)
  721. || (t->tertype != TerrainTile::water && prev->tertype == TerrainTile::water)
  722. || prev->tertype == TerrainTile::rock
  723. )
  724. return false;
  725. }
  726. }
  727. return true;
  728. }
  729. bool CGameInfoCallback::isVisible(int3 pos, int Player) const
  730. {
  731. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  732. return gs->map->isInTheMap(pos) && (Player == -1 || gs->isVisible(pos, Player));
  733. }
  734. bool CGameInfoCallback::isVisible(int3 pos) const
  735. {
  736. return isVisible(pos,player);
  737. }
  738. bool CGameInfoCallback::isVisible( const CGObjectInstance *obj, int Player ) const
  739. {
  740. return gs->isVisible(obj, Player);
  741. }
  742. bool CGameInfoCallback::isVisible(const CGObjectInstance *obj) const
  743. {
  744. return isVisible(obj, player);
  745. }
  746. // const CCreatureSet* CInfoCallback::getGarrison(const CGObjectInstance *obj) const
  747. // {
  748. // //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  749. // if()
  750. // const CArmedInstance *armi = dynamic_cast<const CArmedInstance*>(obj);
  751. // if(!armi)
  752. // return NULL;
  753. // else
  754. // return armi;
  755. // }
  756. std::vector < const CGObjectInstance * > CGameInfoCallback::getBlockingObjs( int3 pos ) const
  757. {
  758. std::vector<const CGObjectInstance *> ret;
  759. const TerrainTile *t = getTile(pos);
  760. ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
  761. BOOST_FOREACH(const CGObjectInstance * obj, t->blockingObjects)
  762. ret.push_back(obj);
  763. return ret;
  764. }
  765. std::vector <const CGObjectInstance * > CGameInfoCallback::getVisitableObjs(int3 pos, bool verbose /*= true*/) const
  766. {
  767. std::vector<const CGObjectInstance *> ret;
  768. const TerrainTile *t = getTile(pos, verbose);
  769. ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!t, verbose, pos << " is not visible!", ret);
  770. BOOST_FOREACH(const CGObjectInstance * obj, t->visitableObjects)
  771. {
  772. if(player < 0 || obj->ID != GameConstants::EVENTI_TYPE) //hide events from players
  773. ret.push_back(obj);
  774. }
  775. return ret;
  776. }
  777. std::vector < const CGObjectInstance * > CGameInfoCallback::getFlaggableObjects(int3 pos) const
  778. {
  779. std::vector<const CGObjectInstance *> ret;
  780. const TerrainTile *t = getTile(pos);
  781. ERROR_RET_VAL_IF(!t, "Not a valid tile requested!", ret);
  782. BOOST_FOREACH(const CGObjectInstance *obj, t->blockingObjects)
  783. if(obj->tempOwner != 254)
  784. ret.push_back(obj);
  785. // const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects;
  786. // for(size_t b=0; b<objs.size(); ++b)
  787. // {
  788. // if(objs[b].first->tempOwner!=254 && !((objs[b].first->defInfo->blockMap[pos.y - objs[b].first->pos.y + 5] >> (objs[b].first->pos.x - pos.x)) & 1))
  789. // ret.push_back(CGI->mh->ttiles[pos.x][pos.y][pos.z].objects[b].first);
  790. // }
  791. return ret;
  792. }
  793. int3 CGameInfoCallback::getMapSize() const
  794. {
  795. return int3(gs->map->width, gs->map->height, gs->map->twoLevel+1);
  796. }
  797. std::vector<const CGHeroInstance *> CGameInfoCallback::getAvailableHeroes(const CGObjectInstance * townOrTavern) const
  798. {
  799. std::vector<const CGHeroInstance *> ret;
  800. //ERROR_RET_VAL_IF(!isOwnedOrVisited(townOrTavern), "Town or tavern must be owned or visited!", ret);
  801. //TODO: town needs to be owned, advmap tavern needs to be visited; to be reimplemented when visit tracking is done
  802. ret.resize(gs->players[player].availableHeroes.size());
  803. std::copy(gs->players[player].availableHeroes.begin(),gs->players[player].availableHeroes.end(),ret.begin());
  804. return ret;
  805. }
  806. const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
  807. {
  808. ERROR_VERBOSE_OR_NOT_RET_VAL_IF(!isVisible(tile), verbose, tile << " is not visible!", NULL);
  809. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  810. return &gs->map->getTile(tile);
  811. }
  812. int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
  813. {
  814. ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", -1);
  815. int ret = EBuildingState::ALLOWED;
  816. if(t->builded >= GameConstants::MAX_BUILDING_PER_TURN)
  817. ret = EBuildingState::CANT_BUILD_TODAY; //building limit
  818. CBuilding * pom = VLC->buildh->buildings[t->subID][ID];
  819. if(!pom)
  820. return EBuildingState::BUILDING_ERROR;
  821. //checking resources
  822. if(!pom->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
  823. ret = EBuildingState::NO_RESOURCES; //lack of res
  824. //checking for requirements
  825. std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requirements
  826. for( std::set<int>::iterator ri = reqs.begin(); ri != reqs.end(); ri++ )
  827. {
  828. if(t->builtBuildings.find(*ri)==t->builtBuildings.end())
  829. ret = EBuildingState::PREREQUIRES; //lack of requirements - cannot build
  830. }
  831. //can we build it?
  832. if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
  833. ret = EBuildingState::FORBIDDEN; //forbidden
  834. if(ID == 13) //capitol
  835. {
  836. const PlayerState *ps = getPlayer(t->tempOwner);
  837. if(ps)
  838. {
  839. BOOST_FOREACH(const CGTownInstance *t, ps->towns)
  840. {
  841. if(vstd::contains(t->builtBuildings, 13))
  842. {
  843. ret = EBuildingState::HAVE_CAPITAL; //no more than one capitol
  844. break;
  845. }
  846. }
  847. }
  848. }
  849. else if(ID == 6) //shipyard
  850. {
  851. const TerrainTile *tile = getTile(t->bestLocation());
  852. if(!tile || tile->tertype != TerrainTile::water )
  853. ret = EBuildingState::NO_WATER; //lack of water
  854. }
  855. if(t->builtBuildings.find(ID)!=t->builtBuildings.end()) //already built
  856. ret = EBuildingState::ALREADY_PRESENT;
  857. return ret;
  858. }
  859. std::set<int> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t, int ID )
  860. {
  861. ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", std::set<int>());
  862. std::set<int> used;
  863. used.insert(ID);
  864. std::set<int> reqs = VLC->townh->requirements[t->subID][ID];
  865. while(true)
  866. {
  867. size_t noloop=0;
  868. for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
  869. {
  870. if(used.find(*i)==used.end()) //we haven't added requirements for this building
  871. {
  872. used.insert(*i);
  873. for(
  874. std::set<int>::iterator j=VLC->townh->requirements[t->subID][*i].begin();
  875. j!=VLC->townh->requirements[t->subID][*i].end();
  876. j++)
  877. {
  878. reqs.insert(*j);//creating full list of requirements
  879. }
  880. }
  881. else
  882. {
  883. noloop++;
  884. }
  885. }
  886. if(noloop==reqs.size())
  887. break;
  888. }
  889. return reqs;
  890. }
  891. const CMapHeader * CGameInfoCallback::getMapHeader() const
  892. {
  893. return gs->map;
  894. }
  895. bool CGameInfoCallback::hasAccess(int playerId) const
  896. {
  897. return player < 0 || gs->getPlayerRelations( playerId, player );
  898. }
  899. int CGameInfoCallback::getPlayerStatus(int player) const
  900. {
  901. const PlayerState *ps = gs->getPlayer(player, false);
  902. if(!ps)
  903. return -1;
  904. return ps->status;
  905. }
  906. std::string CGameInfoCallback::getTavernGossip(const CGObjectInstance * townOrTavern) const
  907. {
  908. return "GOSSIP TEST";
  909. }
  910. int CGameInfoCallback::getPlayerRelations( ui8 color1, ui8 color2 ) const
  911. {
  912. return gs->getPlayerRelations(color1, color2);
  913. }
  914. bool CGameInfoCallback::canGetFullInfo(const CGObjectInstance *obj) const
  915. {
  916. return !obj || hasAccess(obj->tempOwner);
  917. }
  918. int CGameInfoCallback::getHeroCount( int player, bool includeGarrisoned ) const
  919. {
  920. int ret = 0;
  921. const PlayerState *p = gs->getPlayer(player);
  922. ERROR_RET_VAL_IF(!p, "No such player!", -1);
  923. if(includeGarrisoned)
  924. return p->heroes.size();
  925. else
  926. for(ui32 i = 0; i < p->heroes.size(); i++)
  927. if(!p->heroes[i]->inTownGarrison)
  928. ret++;
  929. return ret;
  930. }
  931. bool CGameInfoCallback::isOwnedOrVisited(const CGObjectInstance *obj) const
  932. {
  933. if(canGetFullInfo(obj))
  934. return true;
  935. const TerrainTile *t = getTile(obj->visitablePos()); //get entrance tile
  936. const CGObjectInstance *visitor = t->visitableObjects.back(); //visitong hero if present or the obejct itself at last
  937. return visitor->ID == GameConstants::HEROI_TYPE && canGetFullInfo(visitor); //owned or allied hero is a visitor
  938. }
  939. int CGameInfoCallback::getCurrentPlayer() const
  940. {
  941. return gs->currentPlayer;
  942. }
  943. CGameInfoCallback::CGameInfoCallback()
  944. {
  945. }
  946. CGameInfoCallback::CGameInfoCallback(CGameState *GS, int Player)
  947. {
  948. gs = GS;
  949. player = Player;
  950. }
  951. const std::vector< std::vector< std::vector<ui8> > > & CPlayerSpecificInfoCallback::getVisibilityMap() const
  952. {
  953. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  954. return gs->getPlayerTeam(player)->fogOfWarMap;
  955. }
  956. int CPlayerSpecificInfoCallback::howManyTowns() const
  957. {
  958. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  959. ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", -1);
  960. return CGameInfoCallback::howManyTowns(player);
  961. }
  962. std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(bool onlyOur) const
  963. {
  964. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  965. std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
  966. for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  967. {
  968. for (size_t j = 0; j < (*i).second.towns.size(); ++j)
  969. {
  970. if ((*i).first==player
  971. || (isVisible((*i).second.towns[j],player) && !onlyOur))
  972. {
  973. ret.push_back((*i).second.towns[j]);
  974. }
  975. }
  976. } // for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  977. return ret;
  978. }
  979. std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo(bool onlyOur) const
  980. {
  981. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  982. std::vector < const CGHeroInstance *> ret;
  983. for(size_t i=0;i<gs->map->heroes.size();i++)
  984. {
  985. if( (gs->map->heroes[i]->tempOwner==player) ||
  986. (isVisible(gs->map->heroes[i]->getPosition(false),player) && !onlyOur) )
  987. {
  988. ret.push_back(gs->map->heroes[i]);
  989. }
  990. }
  991. return ret;
  992. }
  993. int CPlayerSpecificInfoCallback::getMyColor() const
  994. {
  995. return player;
  996. }
  997. int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const
  998. {
  999. if (hero->inTownGarrison && !includeGarrisoned)
  1000. return -1;
  1001. size_t index = 0;
  1002. auto & heroes = gs->players[player].heroes;
  1003. for (auto curHero= heroes.begin(); curHero!=heroes.end(); curHero++)
  1004. {
  1005. if (includeGarrisoned || !(*curHero)->inTownGarrison)
  1006. index++;
  1007. if (*curHero == hero)
  1008. return index;
  1009. }
  1010. return -1;
  1011. }
  1012. int3 CPlayerSpecificInfoCallback::getGrailPos( double &outKnownRatio )
  1013. {
  1014. if (CGObelisk::obeliskCount == 0)
  1015. {
  1016. outKnownRatio = 0.0;
  1017. }
  1018. else
  1019. {
  1020. outKnownRatio = static_cast<double>(CGObelisk::visited[gs->getPlayerTeam(player)->id]) / CGObelisk::obeliskCount;
  1021. }
  1022. return gs->map->grailPos;
  1023. }
  1024. std::vector < const CGObjectInstance * > CPlayerSpecificInfoCallback::getMyObjects() const
  1025. {
  1026. std::vector < const CGObjectInstance * > ret;
  1027. BOOST_FOREACH(const CGObjectInstance * obj, gs->map->objects)
  1028. {
  1029. if(obj && obj->tempOwner == player)
  1030. ret.push_back(obj);
  1031. }
  1032. return ret;
  1033. }
  1034. std::vector < const CGDwelling * > CPlayerSpecificInfoCallback::getMyDwellings() const
  1035. {
  1036. std::vector < const CGDwelling * > ret;
  1037. BOOST_FOREACH(CGDwelling * dw, gs->getPlayer(player)->dwellings)
  1038. {
  1039. ret.push_back(dw);
  1040. }
  1041. return ret;
  1042. }
  1043. int CPlayerSpecificInfoCallback::howManyHeroes(bool includeGarrisoned) const
  1044. {
  1045. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  1046. ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", -1);
  1047. return getHeroCount(player,includeGarrisoned);
  1048. }
  1049. const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId, bool includeGarrisoned) const
  1050. {
  1051. const PlayerState *p = getPlayer(player);
  1052. ERROR_RET_VAL_IF(!p, "No player info", NULL);
  1053. if (!includeGarrisoned)
  1054. {
  1055. for(ui32 i = 0; i < p->heroes.size() && i<=serialId; i++)
  1056. if(p->heroes[i]->inTownGarrison)
  1057. serialId++;
  1058. }
  1059. ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->heroes.size(), "No player info", NULL);
  1060. return p->heroes[serialId];
  1061. }
  1062. const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId) const
  1063. {
  1064. const PlayerState *p = getPlayer(player);
  1065. ERROR_RET_VAL_IF(!p, "No player info", NULL);
  1066. ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->towns.size(), "No player info", NULL);
  1067. return p->towns[serialId];
  1068. }
  1069. int CPlayerSpecificInfoCallback::getResourceAmount(int type) const
  1070. {
  1071. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  1072. ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", -1);
  1073. return getResource(player, type);
  1074. }
  1075. TResources CPlayerSpecificInfoCallback::getResourceAmount() const
  1076. {
  1077. //boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  1078. ERROR_RET_VAL_IF(player == -1, "Applicable only for player callbacks", TResources());
  1079. return gs->players[player].resources;
  1080. }
  1081. CGHeroInstance *CNonConstInfoCallback::getHero(int objid)
  1082. {
  1083. return const_cast<CGHeroInstance*>(CGameInfoCallback::getHero(objid));
  1084. }
  1085. CGTownInstance *CNonConstInfoCallback::getTown(int objid)
  1086. {
  1087. return const_cast<CGTownInstance*>(CGameInfoCallback::getTown(objid));
  1088. }
  1089. TeamState *CNonConstInfoCallback::getTeam(ui8 teamID)
  1090. {
  1091. return const_cast<TeamState*>(CGameInfoCallback::getTeam(teamID));
  1092. }
  1093. TeamState *CNonConstInfoCallback::getPlayerTeam(ui8 color)
  1094. {
  1095. return const_cast<TeamState*>(CGameInfoCallback::getPlayerTeam(color));
  1096. }
  1097. PlayerState * CNonConstInfoCallback::getPlayer( ui8 color, bool verbose )
  1098. {
  1099. return const_cast<PlayerState*>(CGameInfoCallback::getPlayer(color, verbose));
  1100. }
  1101. const TeamState * CGameInfoCallback::getTeam( ui8 teamID ) const
  1102. {
  1103. ERROR_RET_VAL_IF(!vstd::contains(gs->teams, teamID), "Cannot find info for team " << int(teamID), NULL);
  1104. const TeamState *ret = &gs->teams[teamID];
  1105. ERROR_RET_VAL_IF(player != -1 && !vstd::contains(ret->players, player), "Illegal attempt to access team data!", NULL);
  1106. return ret;
  1107. }
  1108. const TeamState * CGameInfoCallback::getPlayerTeam( ui8 teamID ) const
  1109. {
  1110. const PlayerState * ps = getPlayer(teamID);
  1111. if (ps)
  1112. return getTeam(ps->team);
  1113. return NULL;
  1114. }
  1115. const CGHeroInstance* CGameInfoCallback::getHeroWithSubid( int subid ) const
  1116. {
  1117. BOOST_FOREACH(const CGHeroInstance *h, gs->map->heroes)
  1118. if(h->subID == subid)
  1119. return h;
  1120. return NULL;
  1121. }
  1122. int CGameInfoCallback::getLocalPlayer() const
  1123. {
  1124. return getCurrentPlayer();
  1125. }
  1126. bool CGameInfoCallback::isInTheMap(const int3 &pos) const
  1127. {
  1128. return gs->map->isInTheMap(pos);
  1129. }
  1130. void IGameEventRealizer::showInfoDialog( InfoWindow *iw )
  1131. {
  1132. commitPackage(iw);
  1133. }
  1134. void IGameEventRealizer::showInfoDialog(const std::string &msg, int player)
  1135. {
  1136. InfoWindow iw;
  1137. iw.player = player;
  1138. iw.text << msg;
  1139. showInfoDialog(&iw);
  1140. }
  1141. void IGameEventRealizer::setObjProperty(int objid, int prop, si64 val)
  1142. {
  1143. SetObjectProperty sob;
  1144. sob.id = objid;
  1145. sob.what = prop;
  1146. sob.val = static_cast<ui32>(val);
  1147. commitPackage(&sob);
  1148. }
  1149. const CGObjectInstance * IGameCallback::putNewObject(int ID, int subID, int3 pos)
  1150. {
  1151. NewObject no;
  1152. no.ID = ID; //creature
  1153. no.subID= subID;
  1154. no.pos = pos;
  1155. commitPackage(&no);
  1156. return getObj(no.id); //id field will be filled during applying on gs
  1157. }
  1158. const CGCreature * IGameCallback::putNewMonster(int creID, int count, int3 pos)
  1159. {
  1160. const CGObjectInstance *m = putNewObject(54, creID, pos);
  1161. setObjProperty(m->id, ObjProperty::MONSTER_COUNT, count);
  1162. setObjProperty(m->id, ObjProperty::MONSTER_POWER, (si64)1000*count);
  1163. return dynamic_cast<const CGCreature*>(m);
  1164. }