CObjectHandler.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. #define VCMI_DLL
  2. #include "../stdafx.h"
  3. #include "CObjectHandler.h"
  4. #include "CDefObjInfoHandler.h"
  5. #include "CLodHandler.h"
  6. #include "CGeneralTextHandler.h"
  7. #include "CDefObjInfoHandler.h"
  8. #include "CHeroHandler.h"
  9. #include "CSpellHandler.h"
  10. #include <boost/bind.hpp>
  11. #include <boost/algorithm/string/replace.hpp>
  12. #include <boost/random/linear_congruential.hpp>
  13. #include "CTownHandler.h"
  14. #include "CArtHandler.h"
  15. #include "../lib/VCMI_Lib.h"
  16. #include "../lib/IGameCallback.h"
  17. #include "../CGameState.h"
  18. #include "../lib/NetPacks.h"
  19. std::map<int,std::map<int, std::vector<int> > > CGTeleport::objs;
  20. IGameCallback * IObjectInterface::cb = NULL;
  21. DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
  22. extern CLodHandler * bitmaph;
  23. extern boost::rand48 ran;
  24. void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
  25. {};
  26. void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const
  27. {};
  28. void IObjectInterface::newTurn () const
  29. {};
  30. IObjectInterface::~IObjectInterface()
  31. {}
  32. IObjectInterface::IObjectInterface()
  33. {}
  34. void IObjectInterface::initObj()
  35. {}
  36. void CObjectHandler::loadObjects()
  37. {
  38. VLC->objh = this;
  39. // int ID=0; //TODO use me
  40. tlog5 << "\t\tReading OBJNAMES \n";
  41. std::string buf = bitmaph->getTextFile("OBJNAMES.TXT");
  42. int it=0; //hope that -1 will not break this
  43. while (it<buf.length()-1)
  44. {
  45. std::string nobj;
  46. loadToIt(nobj, buf, it, 3);
  47. if(nobj.size() && (nobj[nobj.size()-1]==(char)10 || nobj[nobj.size()-1]==(char)13 || nobj[nobj.size()-1]==(char)9))
  48. {
  49. nobj = nobj.substr(0, nobj.size()-1);
  50. }
  51. names.push_back(nobj);
  52. }
  53. tlog5 << "\t\tReading ADVEVENT \n";
  54. buf = bitmaph->getTextFile("ADVEVENT.TXT");
  55. it=0;
  56. std::string temp;
  57. while (it<buf.length()-1)
  58. {
  59. loadToIt(temp,buf,it,3);
  60. if (temp[0]=='\"')
  61. {
  62. temp = temp.substr(1,temp.length()-2);
  63. }
  64. boost::algorithm::replace_all(temp,"\"\"","\"");
  65. advobtxt.push_back(temp);
  66. }
  67. tlog5 << "\t\tReading XTRAINFO \n";
  68. buf = bitmaph->getTextFile("XTRAINFO.TXT");
  69. it=0;
  70. while (it<buf.length()-1)
  71. {
  72. loadToIt(temp,buf,it,3);
  73. xtrainfo.push_back(temp);
  74. }
  75. tlog5 << "\t\tReading MINENAME \n";
  76. buf = bitmaph->getTextFile("MINENAME.TXT");
  77. it=0;
  78. while (it<buf.length()-1)
  79. {
  80. loadToIt(temp,buf,it,3);
  81. mines.push_back(std::pair<std::string,std::string>(temp,""));
  82. }
  83. tlog5 << "\t\tReading MINEEVNT \n";
  84. buf = bitmaph->getTextFile("MINEEVNT.TXT");
  85. it=0;
  86. int i=0;
  87. while (it<buf.length()-1)
  88. {
  89. loadToIt(temp,buf,it,3);
  90. temp = temp.substr(1,temp.length()-2);
  91. mines[i++].second = temp;
  92. }
  93. tlog5 << "\t\tReading RESTYPES \n";
  94. buf = bitmaph->getTextFile("RESTYPES.TXT");
  95. it=0;
  96. while (it<buf.length()-1)
  97. {
  98. loadToIt(temp,buf,it,3);
  99. restypes.push_back(temp);
  100. }
  101. tlog5 << "\t\tReading cregens \n";
  102. cregens.resize(110); //TODO: hardcoded value - change
  103. for(size_t i=0; i < cregens.size(); ++i)
  104. {
  105. cregens[i]=-1;
  106. }
  107. std::ifstream ifs("config/cregens.txt");
  108. while(!ifs.eof())
  109. {
  110. int dw, cr;
  111. ifs >> dw >> cr;
  112. cregens[dw]=cr;
  113. }
  114. ifs.close();
  115. ifs.clear();
  116. tlog5 << "\t\tReading ZCRGN1 \n";
  117. buf = bitmaph->getTextFile("ZCRGN1.TXT");
  118. it=0;
  119. while (it<buf.length()-1)
  120. {
  121. loadToIt(temp,buf,it,3);
  122. creGens.push_back(temp);
  123. }
  124. tlog5 << "\t\tDone loading objects!\n";
  125. }
  126. int CGObjectInstance::getOwner() const
  127. {
  128. //if (state)
  129. // return state->owner;
  130. //else
  131. return tempOwner; //won't have owner
  132. }
  133. CGObjectInstance::CGObjectInstance(): animPhaseShift(rand()%0xff)
  134. {
  135. pos = int3(-1,-1,-1);
  136. //std::cout << "Tworze obiekt "<<this<<std::endl;
  137. //state = new CLuaObjectScript();
  138. ID = subID = id = -1;
  139. defInfo = NULL;
  140. info = NULL;
  141. tempOwner = 254;
  142. blockVisit = false;
  143. }
  144. CGObjectInstance::~CGObjectInstance()
  145. {
  146. //std::cout << "Usuwam obiekt "<<this<<std::endl;
  147. //if (state)
  148. // delete state;
  149. //state=NULL;
  150. }
  151. //CGObjectInstance::CGObjectInstance(const CGObjectInstance & right)
  152. //{
  153. // pos = right.pos;
  154. // ID = right.ID;
  155. // subID = right.subID;
  156. // id = right.id;
  157. // defInfo = right.defInfo;
  158. // info = right.info;
  159. // blockVisit = right.blockVisit;
  160. // //state = new CLuaObjectScript(right.state->);
  161. // //*state = *right.state;
  162. // //state = right.state;
  163. // tempOwner = right.tempOwner;
  164. //}
  165. //CGObjectInstance& CGObjectInstance::operator=(const CGObjectInstance & right)
  166. //{
  167. // pos = right.pos;
  168. // ID = right.ID;
  169. // subID = right.subID;
  170. // id = right.id;
  171. // defInfo = right.defInfo;
  172. // info = right.info;
  173. // blockVisit = right.blockVisit;
  174. // //state = new CLuaObjectScript();
  175. // //*state = *right.state;
  176. // tempOwner = right.tempOwner;
  177. // return *this;
  178. //}
  179. const std::string & CGObjectInstance::getHoverText() const
  180. {
  181. return hoverName;
  182. }
  183. void CGObjectInstance::setOwner(int ow)
  184. {
  185. //if (state)
  186. // state->owner = ow;
  187. //else
  188. tempOwner = ow;
  189. }
  190. int CGObjectInstance::getWidth() const//returns width of object graphic in tiles
  191. {
  192. return defInfo->width;
  193. }
  194. int CGObjectInstance::getHeight() const //returns height of object graphic in tiles
  195. {
  196. return defInfo->width;
  197. }
  198. bool CGObjectInstance::visitableAt(int x, int y) const //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
  199. {
  200. if(x<0 || y<0 || x>=getWidth() || y>=getHeight() || defInfo==NULL)
  201. return false;
  202. if((defInfo->visitMap[y+6-getHeight()] >> (7-(8-getWidth()+x) )) & 1)
  203. return true;
  204. return false;
  205. }
  206. bool CGObjectInstance::blockingAt(int x, int y) const
  207. {
  208. if(x<0 || y<0 || x>=getWidth() || y>=getHeight() || defInfo==NULL)
  209. return false;
  210. if((defInfo->blockMap[y+6-getHeight()] >> (7-(8-getWidth()+x) )) & 1)
  211. return true;
  212. return false;
  213. }
  214. bool CGObjectInstance::operator<(const CGObjectInstance & cmp) const //screen printing priority comparing
  215. {
  216. if(defInfo->printPriority==1 && cmp.defInfo->printPriority==0)
  217. return true;
  218. if(cmp.defInfo->printPriority==1 && defInfo->printPriority==0)
  219. return false;
  220. if(this->pos.y<cmp.pos.y)
  221. return true;
  222. if(this->pos.y>cmp.pos.y)
  223. return false;
  224. if(cmp.ID==34 && ID!=34)
  225. return true;
  226. if(cmp.ID!=34 && ID==34)
  227. return false;
  228. if(!defInfo->isVisitable() && cmp.defInfo->isVisitable())
  229. return true;
  230. if(!cmp.defInfo->isVisitable() && defInfo->isVisitable())
  231. return false;
  232. if(this->pos.x<cmp.pos.x)
  233. return true;
  234. return false;
  235. }
  236. void CGObjectInstance::initObj()
  237. {
  238. }
  239. int lowestSpeed(const CGHeroInstance * chi)
  240. {
  241. if(!chi->army.slots.size())
  242. {
  243. tlog1 << "Error! Hero " << chi->id << " ("<<chi->name<<") has no army!\n";
  244. return 20;
  245. }
  246. std::map<si32,std::pair<ui32,si32> >::const_iterator i = chi->army.slots.begin();
  247. ui32 ret = VLC->creh->creatures[(*i++).second.first].speed;
  248. for (;i!=chi->army.slots.end();i++)
  249. {
  250. ret = std::min(ret,VLC->creh->creatures[(*i).second.first].speed);
  251. }
  252. return ret;
  253. }
  254. unsigned int CGHeroInstance::getTileCost(const EterrainType & ttype, const Eroad & rdtype, const Eriver & rvtype) const
  255. {
  256. unsigned int ret = type->heroClass->terrCosts[ttype];
  257. //applying pathfinding skill
  258. switch(getSecSkillLevel(0))
  259. {
  260. case 1: //basic
  261. switch(ttype)
  262. {
  263. case rough:
  264. ret = 100;
  265. break;
  266. case sand: case snow:
  267. if(ret>125)
  268. ret = 125;
  269. break;
  270. case swamp:
  271. if(ret>150)
  272. ret = 150;
  273. break;
  274. default:
  275. //TODO do something nasty here throw maybe? or some def value asing
  276. break;
  277. }
  278. break;
  279. case 2: //advanced
  280. switch(ttype)
  281. {
  282. case rough:
  283. case sand:
  284. case snow:
  285. ret = 100;
  286. break;
  287. case swamp:
  288. if(ret>125)
  289. ret = 125;
  290. break;
  291. default:
  292. //TODO look up
  293. break;
  294. }
  295. break;
  296. case 3: //expert
  297. ret = 100;
  298. break;
  299. default:
  300. //TODO look up
  301. break;
  302. }
  303. //calculating road influence
  304. switch(rdtype)
  305. {
  306. case dirtRoad:
  307. ret*=0.75;
  308. break;
  309. case grazvelRoad:
  310. ret*=0.667;
  311. break;
  312. case cobblestoneRoad:
  313. ret*=0.5;
  314. break;
  315. default:
  316. //TODO killllll me
  317. break;
  318. }
  319. return ret;
  320. }
  321. unsigned int CGHeroInstance::getLowestCreatureSpeed() const
  322. {
  323. unsigned int sl = 100;
  324. for(size_t h=0; h < army.slots.size(); ++h)
  325. {
  326. if(VLC->creh->creatures[army.slots.find(h)->first].speed<sl)
  327. sl = VLC->creh->creatures[army.slots.find(h)->first].speed;
  328. }
  329. return sl;
  330. }
  331. int3 CGHeroInstance::convertPosition(int3 src, bool toh3m) //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
  332. {
  333. if (toh3m)
  334. {
  335. src.x+=1;
  336. return src;
  337. }
  338. else
  339. {
  340. src.x-=1;
  341. return src;
  342. }
  343. }
  344. int3 CGHeroInstance::getPosition(bool h3m) const //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
  345. {
  346. if (h3m)
  347. {
  348. return pos;
  349. }
  350. else
  351. {
  352. return convertPosition(pos,false);
  353. }
  354. }
  355. int CGHeroInstance::getSightDistance() const //returns sight distance of this hero
  356. {
  357. return 6 + getSecSkillLevel(3); //default + scouting
  358. }
  359. si32 CGHeroInstance::manaLimit() const
  360. {
  361. double modifier = 1.0;
  362. switch(getSecSkillLevel(24)) //intelligence level
  363. {
  364. case 1: modifier+=0.25; break;
  365. case 2: modifier+=0.5; break;
  366. case 3: modifier+=1.0; break;
  367. }
  368. return 10*getPrimSkillLevel(3)*modifier;
  369. }
  370. //void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
  371. //{
  372. // if (h3m)
  373. // pos = Pos;
  374. // else
  375. // pos = convertPosition(Pos,true);
  376. //}
  377. bool CGHeroInstance::canWalkOnSea() const
  378. {
  379. //TODO: write it - it should check if hero is flying, or something similiar
  380. return false;
  381. }
  382. int CGHeroInstance::getCurrentLuck() const
  383. {
  384. //TODO: write it
  385. return 0;
  386. }
  387. int CGHeroInstance::getCurrentMorale() const
  388. {
  389. //TODO: write it
  390. return 0;
  391. }
  392. int CGHeroInstance::getPrimSkillLevel(int id) const
  393. {
  394. return primSkills[id];
  395. }
  396. ui8 CGHeroInstance::getSecSkillLevel(const int & ID) const
  397. {
  398. for(size_t i=0; i < secSkills.size(); ++i)
  399. if(secSkills[i].first==ID)
  400. return secSkills[i].second;
  401. return 0;
  402. }
  403. int CGHeroInstance::maxMovePoints(bool onLand) const
  404. {
  405. int ret = 1270+70*lowestSpeed(this);
  406. if (ret>2000)
  407. ret=2000;
  408. if(onLand)
  409. {
  410. //logistics:
  411. switch(getSecSkillLevel(2))
  412. {
  413. case 1:
  414. ret *= 1.1f;
  415. break;
  416. case 2:
  417. ret *= 1.2f;
  418. break;
  419. case 3:
  420. ret *= 1.3f;
  421. break;
  422. }
  423. }
  424. else
  425. {
  426. //navigation:
  427. switch(getSecSkillLevel(2))
  428. {
  429. case 1:
  430. ret *= 1.5f;
  431. break;
  432. case 2:
  433. ret *= 2.0f;
  434. break;
  435. case 3:
  436. ret *= 2.5f;
  437. break;
  438. }
  439. }
  440. return ret;
  441. }
  442. ui32 CGHeroInstance::getArtAtPos(ui16 pos) const
  443. {
  444. if(pos<19)
  445. if(vstd::contains(artifWorn,pos))
  446. return artifWorn.find(pos)->second;
  447. else
  448. return -1;
  449. else
  450. if(pos-19 < artifacts.size())
  451. return artifacts[pos-19];
  452. else
  453. return -1;
  454. }
  455. void CGHeroInstance::setArtAtPos(ui16 pos, int art)
  456. {
  457. if(art<0)
  458. {
  459. if(pos<19)
  460. artifWorn.erase(pos);
  461. else
  462. artifacts -= artifacts[pos-19];
  463. }
  464. else
  465. {
  466. if(pos<19)
  467. artifWorn[pos] = art;
  468. else
  469. if(pos-19 < artifacts.size())
  470. artifacts[pos-19] = art;
  471. else
  472. artifacts.push_back(art);
  473. }
  474. }
  475. const CArtifact * CGHeroInstance::getArt(int pos) const
  476. {
  477. int id = getArtAtPos(pos);
  478. if(id>=0)
  479. return &VLC->arth->artifacts[id];
  480. else
  481. return NULL;
  482. }
  483. int CGHeroInstance::getSpellSecLevel(int spell) const
  484. {
  485. int bestslvl = 0;
  486. if(VLC->spellh->spells[spell].air)
  487. if(getSecSkillLevel(15) >= bestslvl)
  488. {
  489. bestslvl = getSecSkillLevel(15);
  490. }
  491. if(VLC->spellh->spells[spell].fire)
  492. if(getSecSkillLevel(14) >= bestslvl)
  493. {
  494. bestslvl = getSecSkillLevel(14);
  495. }
  496. if(VLC->spellh->spells[spell].water)
  497. if(getSecSkillLevel(16) >= bestslvl)
  498. {
  499. bestslvl = getSecSkillLevel(16);
  500. }
  501. if(VLC->spellh->spells[spell].earth)
  502. if(getSecSkillLevel(17) >= bestslvl)
  503. {
  504. bestslvl = getSecSkillLevel(17);
  505. }
  506. return bestslvl;
  507. }
  508. CGHeroInstance::CGHeroInstance()
  509. {
  510. ID = 34;
  511. tacticFormationEnabled = inTownGarrison = false;
  512. mana = movement = portrait = level = -1;
  513. isStanding = true;
  514. moveDir = 4;
  515. exp = 0xffffffff;
  516. visitedTown = NULL;
  517. type = NULL;
  518. secSkills.push_back(std::make_pair(-1, -1));
  519. }
  520. void CGHeroInstance::initHero(int SUBID)
  521. {
  522. subID = SUBID;
  523. initHero();
  524. }
  525. void CGHeroInstance::initHero()
  526. {
  527. if(!defInfo)
  528. {
  529. defInfo = new CGDefInfo();
  530. defInfo->id = 34;
  531. defInfo->subid = subID;
  532. defInfo->printPriority = 0;
  533. defInfo->visitDir = 0xff;
  534. }
  535. if(!type)
  536. type = VLC->heroh->heroes[subID];
  537. for(int i=0;i<6;i++)
  538. {
  539. defInfo->blockMap[i]=255;
  540. defInfo->visitMap[i]=0;
  541. }
  542. defInfo->handler=NULL;
  543. defInfo->blockMap[5] = 253;
  544. defInfo->visitMap[5] = 2;
  545. artifWorn[16] = 3;
  546. if(type->heroType % 2 == 1) //it's a magical hero
  547. {
  548. artifWorn[17] = 0; //give him spellbook
  549. }
  550. if(portrait < 0 || portrait == 255)
  551. portrait = subID;
  552. if((!primSkills.size()) || (getPrimSkillLevel(0)<0))
  553. {
  554. primSkills.resize(4);
  555. primSkills[0] = type->heroClass->initialAttack;
  556. primSkills[1] = type->heroClass->initialDefence;
  557. primSkills[2] = type->heroClass->initialPower;
  558. primSkills[3] = type->heroClass->initialKnowledge;
  559. }
  560. if(secSkills.size() == 1 && secSkills[0] == std::pair<ui8,ui8>(-1, -1)) //set secondary skills to default
  561. secSkills = type->secSkillsInit;
  562. if(mana < 0)
  563. mana = manaLimit();
  564. if (!name.length())
  565. name = type->name;
  566. if (exp == 0xffffffff)
  567. {
  568. exp=40+ (ran()) % 50;
  569. level = 1;
  570. }
  571. else
  572. {
  573. level = VLC->heroh->level(exp);
  574. }
  575. if (!army.slots.size()) //standard army//initial army
  576. {
  577. int pom, pom2=0;
  578. for(int x=0;x<3;x++)
  579. {
  580. pom = (VLC->creh->nameToID[type->refTypeStack[x]]);
  581. if(pom>=145 && pom<=149) //war machine
  582. {
  583. pom2++;
  584. switch (pom)
  585. {
  586. case 145: //catapult
  587. artifWorn[16] = 3;
  588. break;
  589. default:
  590. artifWorn[9+CArtHandler::convertMachineID(pom,true)] = CArtHandler::convertMachineID(pom,true);
  591. break;
  592. }
  593. continue;
  594. }
  595. army.slots[x-pom2].first = pom;
  596. if((pom = (type->highStack[x]-type->lowStack[x])) > 0)
  597. army.slots[x-pom2].second = (ran()%pom)+type->lowStack[x];
  598. else
  599. army.slots[x-pom2].second = +type->lowStack[x];
  600. army.formation = false;
  601. }
  602. }
  603. hoverName = VLC->generaltexth->allTexts[15];
  604. boost::algorithm::replace_first(hoverName,"%s",name);
  605. boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
  606. }
  607. CGHeroInstance::~CGHeroInstance()
  608. {
  609. }
  610. bool CGHeroInstance::needsLastStack() const
  611. {
  612. return true;
  613. }
  614. void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
  615. {
  616. //TODO: check for allies
  617. if(tempOwner == h->tempOwner) //our hero
  618. {
  619. //exchange
  620. }
  621. else
  622. {
  623. cb->startBattleI(
  624. &h->army,
  625. &army,
  626. h->pos,
  627. h,
  628. this,
  629. 0);
  630. }
  631. }
  632. const std::string & CGHeroInstance::getBiography() const
  633. {
  634. if (biography.length())
  635. return biography;
  636. else
  637. return VLC->generaltexth->hTxts[subID].biography;
  638. }
  639. void CGHeroInstance::initObj()
  640. {
  641. blockVisit = true;
  642. }
  643. int CGTownInstance::getSightDistance() const //returns sight distance
  644. {
  645. return 10;
  646. }
  647. int CGTownInstance::fortLevel() const //0 - none, 1 - fort, 2 - citadel, 3 - castle
  648. {
  649. if((builtBuildings.find(9))!=builtBuildings.end())
  650. return 3;
  651. if((builtBuildings.find(8))!=builtBuildings.end())
  652. return 2;
  653. if((builtBuildings.find(7))!=builtBuildings.end())
  654. return 1;
  655. return 0;
  656. }
  657. int CGTownInstance::hallLevel() const // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
  658. {
  659. if ((builtBuildings.find(13))!=builtBuildings.end())
  660. return 3;
  661. if ((builtBuildings.find(12))!=builtBuildings.end())
  662. return 2;
  663. if ((builtBuildings.find(11))!=builtBuildings.end())
  664. return 1;
  665. if ((builtBuildings.find(10))!=builtBuildings.end())
  666. return 0;
  667. return -1;
  668. }
  669. int CGTownInstance::mageGuildLevel() const
  670. {
  671. if ((builtBuildings.find(4))!=builtBuildings.end())
  672. return 5;
  673. if ((builtBuildings.find(3))!=builtBuildings.end())
  674. return 4;
  675. if ((builtBuildings.find(2))!=builtBuildings.end())
  676. return 3;
  677. if ((builtBuildings.find(1))!=builtBuildings.end())
  678. return 2;
  679. if ((builtBuildings.find(0))!=builtBuildings.end())
  680. return 1;
  681. return 0;
  682. }
  683. bool CGTownInstance::creatureDwelling(const int & level, bool upgraded) const
  684. {
  685. return builtBuildings.find(30+level+upgraded*7)!=builtBuildings.end();
  686. }
  687. int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present
  688. {
  689. return town->hordeLvl[HID];
  690. }
  691. int CGTownInstance::creatureGrowth(const int & level) const
  692. {
  693. int ret = VLC->creh->creatures[town->basicCreatures[level]].growth;
  694. switch(fortLevel())
  695. {
  696. case 3:
  697. ret*=2;break;
  698. case 2:
  699. ret*=(1.5); break;
  700. }
  701. if(builtBuildings.find(26)!=builtBuildings.end()) //grail
  702. ret+=VLC->creh->creatures[town->basicCreatures[level]].growth;
  703. if(getHordeLevel(0)==level)
  704. if((builtBuildings.find(18)!=builtBuildings.end()) || (builtBuildings.find(19)!=builtBuildings.end()))
  705. ret+=VLC->creh->creatures[town->basicCreatures[level]].hordeGrowth;
  706. if(getHordeLevel(1)==level)
  707. if((builtBuildings.find(24)!=builtBuildings.end()) || (builtBuildings.find(25)!=builtBuildings.end()))
  708. ret+=VLC->creh->creatures[town->basicCreatures[level]].hordeGrowth;
  709. return ret;
  710. }
  711. int CGTownInstance::dailyIncome() const
  712. {
  713. int ret = 0;
  714. if ((builtBuildings.find(26))!=builtBuildings.end())
  715. ret+=5000;
  716. if ((builtBuildings.find(13))!=builtBuildings.end())
  717. ret+=4000;
  718. else if ((builtBuildings.find(12))!=builtBuildings.end())
  719. ret+=2000;
  720. else if ((builtBuildings.find(11))!=builtBuildings.end())
  721. ret+=1000;
  722. else if ((builtBuildings.find(10))!=builtBuildings.end())
  723. ret+=500;
  724. return ret;
  725. }
  726. bool CGTownInstance::hasFort() const
  727. {
  728. return (builtBuildings.find(7))!=builtBuildings.end();
  729. }
  730. bool CGTownInstance::hasCapitol() const
  731. {
  732. return (builtBuildings.find(13))!=builtBuildings.end();
  733. }
  734. CGTownInstance::CGTownInstance()
  735. {
  736. builded=-1;
  737. destroyed=-1;
  738. garrisonHero=NULL;
  739. town=NULL;
  740. visitingHero = NULL;
  741. }
  742. CGTownInstance::~CGTownInstance()
  743. {}
  744. int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
  745. {
  746. if(checkGuild && mageGuildLevel() < level)
  747. return 0;
  748. int ret = 6 - level; //how many spells are available at this level
  749. if(subID == 2 && vstd::contains(builtBuildings,22)) //magic library in Tower
  750. ret++;
  751. return ret;
  752. }
  753. bool CGTownInstance::needsLastStack() const
  754. {
  755. if(garrisonHero)
  756. return true;
  757. else return false;
  758. }
  759. void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
  760. {
  761. if(getOwner() != h->getOwner())
  762. {
  763. return;
  764. }
  765. cb->heroVisitCastle(id,h->id);
  766. }
  767. void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
  768. {
  769. cb->stopHeroVisitCastle(id,h->id);
  770. }
  771. void CGTownInstance::initObj()
  772. {
  773. MetaString ms;
  774. ms << name << ", " << town->Name();
  775. hoverName = toString(ms);
  776. }
  777. void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
  778. {
  779. if(visitors.find(h->id)==visitors.end())
  780. {
  781. onNAHeroVisit(h->id, false);
  782. if(ID != 102) //not tree
  783. cb->setObjProperty(id,4,h->id); //add to the visitors
  784. }
  785. else
  786. {
  787. onNAHeroVisit(h->id, true);
  788. }
  789. }
  790. void CGVisitableOPH::initObj()
  791. {
  792. if(ID==102)
  793. ttype = ran()%3;
  794. else
  795. ttype = -1;
  796. }
  797. void CGVisitableOPH::treeSelected( int heroID, int resType, int resVal, int expVal, ui32 result ) const
  798. {
  799. if(result==0) //player agreed to give res for exp
  800. {
  801. cb->giveResource(cb->getOwner(heroID),resType,-resVal); //take resource
  802. cb->changePrimSkill(heroID,4,expVal); //give exp
  803. cb->setObjProperty(id,4,heroID); //add to the visitors
  804. }
  805. }
  806. void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
  807. {
  808. int id=0, subid=0, ot=0, val=1;
  809. switch(ID)
  810. {
  811. case 51:
  812. subid=0;
  813. ot=80;
  814. break;
  815. case 23:
  816. subid=1;
  817. ot=39;
  818. break;
  819. case 61:
  820. subid=2;
  821. ot=100;
  822. break;
  823. case 32:
  824. subid=3;
  825. ot=59;
  826. break;
  827. case 100:
  828. id=5;
  829. ot=143;
  830. val=1000;
  831. break;
  832. case 102:
  833. id = 5;
  834. subid = 1;
  835. ot = 146;
  836. val = 1;
  837. break;
  838. }
  839. if (!alreadyVisited)
  840. {
  841. switch (ID)
  842. {
  843. case 51:
  844. case 23:
  845. case 61:
  846. case 32:
  847. {
  848. cb->changePrimSkill(heroID,subid,val);
  849. InfoWindow iw;
  850. iw.components.push_back(Component(0,subid,val,0));
  851. iw.text << std::pair<ui8,ui32>(11,ot);
  852. iw.player = cb->getOwner(heroID);
  853. cb->showInfoDialog(&iw);
  854. break;
  855. }
  856. case 100: //give exp
  857. {
  858. InfoWindow iw;
  859. iw.components.push_back(Component(id,subid,val,0));
  860. iw.player = cb->getOwner(heroID);
  861. iw.text << std::pair<ui8,ui32>(11,ot);
  862. cb->showInfoDialog(&iw);
  863. cb->changePrimSkill(heroID,4,val);
  864. break;
  865. }
  866. case 102:
  867. {
  868. const CGHeroInstance *h = cb->getHero(heroID);
  869. val = VLC->heroh->reqExp(h->level+val) - VLC->heroh->reqExp(h->level);
  870. if(!ttype)
  871. {
  872. cb->setObjProperty(id,4,heroID); //add to the visitors
  873. InfoWindow iw;
  874. iw.components.push_back(Component(id,subid,1,0));
  875. iw.player = cb->getOwner(heroID);
  876. iw.text << std::pair<ui8,ui32>(11,148);
  877. cb->showInfoDialog(&iw);
  878. cb->changePrimSkill(heroID,4,val);
  879. break;
  880. }
  881. else
  882. {
  883. int res, resval;
  884. if(ttype==1)
  885. {
  886. res = 6;
  887. resval = 2000;
  888. ot = 149;
  889. }
  890. else
  891. {
  892. res = 5;
  893. resval = 10;
  894. ot = 151;
  895. }
  896. if(cb->getResource(h->tempOwner,res) < resval) //not enough resources
  897. {
  898. ot++;
  899. InfoWindow iw;
  900. iw.player = h->tempOwner;
  901. iw.text << std::pair<ui8,ui32>(11,ot);
  902. cb->showInfoDialog(&iw);
  903. return;
  904. }
  905. YesNoDialog sd;
  906. sd.player = cb->getOwner(heroID);
  907. sd.text << std::pair<ui8,ui32>(11,ot);
  908. sd.components.push_back(Component(id,subid,val,0));
  909. cb->showYesNoDialog(&sd,boost::bind(&CGVisitableOPH::treeSelected,this,heroID,res,resval,val,_1));
  910. }
  911. break;
  912. }
  913. }
  914. }
  915. else
  916. {
  917. ot++;
  918. InfoWindow iw;
  919. iw.player = cb->getOwner(heroID);
  920. iw.text << std::pair<ui8,ui32>(11,ot);
  921. cb->showInfoDialog(&iw);
  922. }
  923. }
  924. const std::string & CGVisitableOPH::getHoverText() const
  925. {
  926. int pom;
  927. switch(ID)
  928. {
  929. case 51:
  930. pom = 8;
  931. break;
  932. case 23:
  933. pom = 7;
  934. break;
  935. case 61:
  936. pom = 11;
  937. break;
  938. case 32:
  939. pom = 4;
  940. break;
  941. case 100:
  942. pom = 5;
  943. break;
  944. case 102:
  945. pom = 18;
  946. break;
  947. default:
  948. throw "Wrong CGVisitableOPH object ID!\n";
  949. }
  950. hoverName = VLC->objh->names[ID] + " " + VLC->objh->xtrainfo[pom];
  951. const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
  952. if(h)
  953. {
  954. hoverName += ' ';
  955. hoverName += (vstd::contains(visitors,h->id))
  956. ? (VLC->generaltexth->allTexts[352]) //visited
  957. : ( VLC->generaltexth->allTexts[353]); //not visited
  958. }
  959. return hoverName;
  960. }
  961. bool CArmedInstance::needsLastStack() const
  962. {
  963. return false;
  964. }
  965. void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
  966. {
  967. cb->startBattleI(h->id,army,pos,boost::bind(&CGCreature::endBattle,this,_1));
  968. }
  969. void CGCreature::endBattle( BattleResult *result ) const
  970. {
  971. if(result->winner==0)
  972. {
  973. cb->removeObject(id);
  974. }
  975. else
  976. {
  977. int killedAmount=0;
  978. for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
  979. if(i->first == subID)
  980. killedAmount += i->second;
  981. cb->setAmount(id, army.slots.find(0)->second.second - killedAmount);
  982. MetaString ms;
  983. int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
  984. pom = 174 + 3*pom + 1;
  985. ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
  986. cb->setHoverName(id,&ms);
  987. }
  988. }
  989. void CGCreature::initObj()
  990. {
  991. army.slots[0].first = subID;
  992. si32 &amount = army.slots[0].second;
  993. CCreature &c = VLC->creh->creatures[subID];
  994. if(!amount)
  995. if(c.ammMax == c.ammMin)
  996. amount = c.ammMax;
  997. else
  998. amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
  999. MetaString ms;
  1000. int pom = CCreature::getQuantityID(army.slots.find(0)->second.second);
  1001. pom = 174 + 3*pom + 1;
  1002. ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,subID);
  1003. hoverName = toString(ms);
  1004. }
  1005. void CGMine::onHeroVisit( const CGHeroInstance * h ) const
  1006. {
  1007. if(subID == 7) //TODO: support for abandoned mine
  1008. return;
  1009. if(h->tempOwner == tempOwner) //we're visiting our mine
  1010. return; //TODO: leaving garrison
  1011. //TODO: check if mine is guarded
  1012. cb->setOwner(id,h->tempOwner); //not ours? flag it!
  1013. MetaString ms;
  1014. ms << std::pair<ui8,ui32>(9,subID) << " (" << std::pair<ui8,ui32>(6,23+h->tempOwner) << ")";
  1015. cb->setHoverName(id,&ms);
  1016. int vv=1; //amount of resource per turn
  1017. if (subID==0 || subID==2)
  1018. vv++;
  1019. else if (subID==6)
  1020. vv = 1000;
  1021. InfoWindow iw;
  1022. iw.text << std::pair<ui8,ui32>(10,subID);
  1023. iw.player = h->tempOwner;
  1024. iw.components.push_back(Component(2,subID,vv,-1));
  1025. cb->showInfoDialog(&iw);
  1026. }
  1027. void CGMine::newTurn() const
  1028. {
  1029. if (tempOwner == NEUTRAL_PLAYER)
  1030. return;
  1031. int vv = 1;
  1032. if (subID==0 || subID==2)
  1033. vv++;
  1034. else if (subID==6)
  1035. vv = 1000;
  1036. cb->giveResource(tempOwner,subID,vv);
  1037. }
  1038. void CGMine::initObj()
  1039. {
  1040. MetaString ms;
  1041. ms << std::pair<ui8,ui32>(9,subID);
  1042. if(tempOwner >= PLAYER_LIMIT)
  1043. tempOwner = NEUTRAL_PLAYER;
  1044. else
  1045. ms << " (" << std::pair<ui8,ui32>(6,23+tempOwner) << ")";
  1046. hoverName = toString(ms);
  1047. }
  1048. void CGResource::initObj()
  1049. {
  1050. blockVisit = true;
  1051. hoverName = VLC->objh->restypes[subID];
  1052. if(!amount)
  1053. {
  1054. switch(subID)
  1055. {
  1056. case 6:
  1057. amount = 500 + (rand()%6)*100;
  1058. break;
  1059. case 0: case 2:
  1060. amount = 6 + (rand()%5);
  1061. break;
  1062. default:
  1063. amount = 3 + (rand()%3);
  1064. break;
  1065. }
  1066. }
  1067. }
  1068. void CGResource::onHeroVisit( const CGHeroInstance * h ) const
  1069. {
  1070. //TODO: handle guards (when battles are finished)
  1071. if(message.length())
  1072. {
  1073. InfoWindow iw;
  1074. iw.player = h->tempOwner;
  1075. iw.text << message;
  1076. cb->showInfoDialog(&iw);
  1077. }
  1078. cb->giveResource(h->tempOwner,subID,amount);
  1079. ShowInInfobox sii;
  1080. sii.player = h->tempOwner;
  1081. sii.c = Component(2,subID,amount,0);
  1082. sii.text << std::pair<ui8,ui32>(11,113);
  1083. sii.text.replacements.push_back(VLC->objh->restypes[subID]);
  1084. cb->showCompInfo(&sii);
  1085. cb->removeObject(id);
  1086. }
  1087. void CGVisitableOPW::newTurn() const
  1088. {
  1089. if (cb->getDate(1)==1) //first day of week
  1090. {
  1091. cb->setObjProperty(id,5,false);
  1092. MetaString ms; //set text to "not visited"
  1093. ms << std::pair<ui8,ui32>(3,ID) << " " << std::pair<ui8,ui32>(1,353);
  1094. cb->setHoverName(id,&ms);
  1095. }
  1096. }
  1097. void CGVisitableOPW::onHeroVisit( const CGHeroInstance * h ) const
  1098. {
  1099. int mid;
  1100. switch (ID)
  1101. {
  1102. case 55:
  1103. mid = 92;
  1104. break;
  1105. case 112:
  1106. mid = 170;
  1107. break;
  1108. case 109:
  1109. mid = 164;
  1110. break;
  1111. }
  1112. if (visited)
  1113. {
  1114. if (ID!=112)
  1115. mid++;
  1116. else
  1117. mid--;
  1118. InfoWindow iw;
  1119. iw.player = h->tempOwner;
  1120. iw.text << std::pair<ui8,ui32>(11,mid);
  1121. cb->showInfoDialog(&iw);
  1122. }
  1123. else
  1124. {
  1125. int type, sub, val;
  1126. type = 2;
  1127. switch (ID)
  1128. {
  1129. case 55:
  1130. if (rand()%2)
  1131. {
  1132. sub = 5;
  1133. val = 5;
  1134. }
  1135. else
  1136. {
  1137. sub = 6;
  1138. val = 500;
  1139. }
  1140. break;
  1141. case 112:
  1142. mid = 170;
  1143. sub = (rand() % 5) + 1;
  1144. val = (rand() % 4) + 3;
  1145. break;
  1146. case 109:
  1147. mid = 164;
  1148. sub = 6;
  1149. if(cb->getDate(2)<2)
  1150. val = 500;
  1151. else
  1152. val = 1000;
  1153. }
  1154. cb->giveResource(h->tempOwner,sub,val);
  1155. InfoWindow iw;
  1156. iw.player = h->tempOwner;
  1157. iw.components.push_back(Component(type,sub,val,0));
  1158. iw.text << std::pair<ui8,ui32>(11,mid);
  1159. cb->showInfoDialog(&iw);
  1160. cb->setObjProperty(id,5,true);
  1161. MetaString ms; //set text to "visited"
  1162. ms << std::pair<ui8,ui32>(3,ID) << " " << std::pair<ui8,ui32>(1,352);
  1163. cb->setHoverName(id,&ms);
  1164. }
  1165. }
  1166. void CGTeleport::onHeroVisit( const CGHeroInstance * h ) const
  1167. {
  1168. int destinationid=-1;
  1169. switch(ID)
  1170. {
  1171. case 43: //one way - find correspong exit monolith
  1172. if(vstd::contains(objs,44) && vstd::contains(objs[44],subID) && objs[44][subID].size())
  1173. destinationid = objs[44][subID][rand()%objs[44][subID].size()];
  1174. else
  1175. tlog2 << "Cannot find corresponding exit monolith for "<< id << std::endl;
  1176. break;
  1177. case 45: //two way monolith - pick any other one
  1178. if(vstd::contains(objs,45) && vstd::contains(objs[45],subID) && objs[45][subID].size()>1)
  1179. while ((destinationid = objs[45][subID][rand()%objs[45][subID].size()])==id);
  1180. else
  1181. tlog2 << "Cannot find corresponding exit monolith for "<< id << std::endl;
  1182. break;
  1183. case 103: //find nearest subterranean gate on the other level
  1184. {
  1185. std::pair<int,double> best(-1,150000); //pair<id,dist>
  1186. for(int i=0; i<objs[103][0].size(); i++)
  1187. {
  1188. if(cb->getObj(objs[103][0][i])->pos.z == pos.z) continue; //gates on our level are not interesting
  1189. double hlp = cb->getObj(objs[103][0][i])->pos.dist2d(pos);
  1190. if(hlp<best.second)
  1191. {
  1192. best.first = objs[103][0][i];
  1193. best.second = hlp;
  1194. }
  1195. }
  1196. if(best.first<0)
  1197. return;
  1198. else
  1199. destinationid = best.first;
  1200. break;
  1201. }
  1202. }
  1203. if(destinationid < 0)
  1204. {
  1205. tlog2 << "Cannot find exit... :( \n";
  1206. return;
  1207. }
  1208. cb->moveHero(h->id,
  1209. (ID!=103)
  1210. ? (CGHeroInstance::convertPosition(cb->getObj(destinationid)->pos,true))
  1211. : (cb->getObj(destinationid)->pos),
  1212. true);
  1213. }
  1214. void CGTeleport::initObj()
  1215. {
  1216. objs[ID][subID].push_back(id);
  1217. }
  1218. void CGArtifact::initObj()
  1219. {
  1220. blockVisit = true;
  1221. if(ID == 5)
  1222. hoverName = VLC->arth->artifacts[subID].Name();
  1223. }
  1224. void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
  1225. {
  1226. cb->giveHeroArtifact(subID,h->id,-2);
  1227. InfoWindow iw;
  1228. iw.player = h->tempOwner;
  1229. iw.components.push_back(Component(4,subID,0,0));
  1230. iw.text << std::pair<ui8,ui32>(12,subID);
  1231. cb->showInfoDialog(&iw);
  1232. }
  1233. void CGPickable::initObj()
  1234. {
  1235. blockVisit = true;
  1236. switch(ID)
  1237. {
  1238. case 12: //campfire
  1239. val2 = (ran()%3) + 4; //4 - 6
  1240. val1 = val2 * 100;
  1241. type = ran()%6; //given resource
  1242. break;
  1243. case 101: //treasure chest
  1244. {
  1245. int hlp = ran()%100;
  1246. if(hlp >= 95)
  1247. {
  1248. type = 1;
  1249. val1 = VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id;
  1250. return;
  1251. }
  1252. else if (hlp >= 65)
  1253. {
  1254. val1 = 2000;
  1255. }
  1256. else if(hlp >= 33)
  1257. {
  1258. val1 = 1500;
  1259. }
  1260. else
  1261. {
  1262. val1 = 1000;
  1263. }
  1264. val2 = val1 - 500;
  1265. type = 0;
  1266. break;
  1267. }
  1268. }
  1269. }
  1270. void CGPickable::onHeroVisit( const CGHeroInstance * h ) const
  1271. {
  1272. switch(ID)
  1273. {
  1274. case 12: //campfire
  1275. {
  1276. cb->giveResource(h->tempOwner,type,val2); //non-gold resource
  1277. cb->giveResource(h->tempOwner,6,val1);//gold
  1278. InfoWindow iw;
  1279. iw.player = h->tempOwner;
  1280. iw.components.push_back(Component(2,6,val1,0));
  1281. iw.components.push_back(Component(2,type,val2,0));
  1282. iw.text << std::pair<ui8,ui32>(11,23);
  1283. cb->showInfoDialog(&iw);
  1284. break;
  1285. }
  1286. case 101: //treasure chest
  1287. {
  1288. if (subID) //not OH3 treasure chest
  1289. {
  1290. tlog2 << "Not supported WoG treasure chest!\n";
  1291. return;
  1292. }
  1293. if(type) //there is an artifact
  1294. {
  1295. cb->giveHeroArtifact(val1,h->id,-2);
  1296. InfoWindow iw;
  1297. iw.player = h->tempOwner;
  1298. iw.components.push_back(Component(4,val1,1,0));
  1299. iw.text << std::pair<ui8,ui32>(11,145);
  1300. iw.text.replacements.push_back(VLC->arth->artifacts[val1].Name());
  1301. cb->showInfoDialog(&iw);
  1302. break;
  1303. }
  1304. else
  1305. {
  1306. SelectionDialog sd;
  1307. sd.player = h->tempOwner;
  1308. sd.text << std::pair<ui8,ui32>(11,146);
  1309. sd.components.push_back(Component(2,6,val1,0));
  1310. sd.components.push_back(Component(5,0,val2,0));
  1311. boost::function<void(ui32)> fun = boost::bind(&CGPickable::chosen,this,_1,h->id);
  1312. cb->showSelectionDialog(&sd,fun);
  1313. return;
  1314. }
  1315. }
  1316. }
  1317. cb->removeObject(id);
  1318. }
  1319. void CGPickable::chosen( int which, int heroID ) const
  1320. {
  1321. switch(which)
  1322. {
  1323. case 0: //player pick gold
  1324. cb->giveResource(cb->getOwner(heroID),6,val1);
  1325. break;
  1326. case 1: //player pick exp
  1327. cb->changePrimSkill(heroID, 4, val2);
  1328. break;
  1329. default:
  1330. throw std::string("Unhandled treasure choice");
  1331. }
  1332. }