CObjectHandler.cpp 31 KB

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