CObjectHandler.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  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. IGameCallback * IObjectInterface::cb = NULL;
  20. DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
  21. extern CLodHandler * bitmaph;
  22. extern boost::rand48 ran;
  23. void IObjectInterface::onHeroVisit(const CGHeroInstance * h)
  24. {};
  25. void IObjectInterface::onHeroLeave(const CGHeroInstance * h)
  26. {};
  27. void IObjectInterface::newTurn ()
  28. {};
  29. IObjectInterface::~IObjectInterface()
  30. {}
  31. IObjectInterface::IObjectInterface()
  32. {}
  33. void IObjectInterface::initObj()
  34. {}
  35. void CObjectHandler::loadObjects()
  36. {
  37. VLC->objh = this;
  38. // int ID=0; //TODO use me
  39. tlog5 << "\t\tReading OBJNAMES \n";
  40. std::string buf = bitmaph->getTextFile("OBJNAMES.TXT");
  41. int it=0; //hope that -1 will not break this
  42. while (it<buf.length()-1)
  43. {
  44. std::string nobj;
  45. loadToIt(nobj, buf, it, 3);
  46. if(nobj.size() && (nobj[nobj.size()-1]==(char)10 || nobj[nobj.size()-1]==(char)13 || nobj[nobj.size()-1]==(char)9))
  47. {
  48. nobj = nobj.substr(0, nobj.size()-1);
  49. }
  50. names.push_back(nobj);
  51. }
  52. tlog5 << "\t\tReading ADVEVENT \n";
  53. buf = bitmaph->getTextFile("ADVEVENT.TXT");
  54. it=0;
  55. std::string temp;
  56. while (it<buf.length()-1)
  57. {
  58. loadToIt(temp,buf,it,3);
  59. if (temp[0]=='\"')
  60. {
  61. temp = temp.substr(1,temp.length()-2);
  62. }
  63. boost::algorithm::replace_all(temp,"\"\"","\"");
  64. advobtxt.push_back(temp);
  65. }
  66. tlog5 << "\t\tReading XTRAINFO \n";
  67. buf = bitmaph->getTextFile("XTRAINFO.TXT");
  68. it=0;
  69. while (it<buf.length()-1)
  70. {
  71. loadToIt(temp,buf,it,3);
  72. xtrainfo.push_back(temp);
  73. }
  74. tlog5 << "\t\tReading MINENAME \n";
  75. buf = bitmaph->getTextFile("MINENAME.TXT");
  76. it=0;
  77. while (it<buf.length()-1)
  78. {
  79. loadToIt(temp,buf,it,3);
  80. mines.push_back(std::pair<std::string,std::string>(temp,""));
  81. }
  82. tlog5 << "\t\tReading MINEEVNT \n";
  83. buf = bitmaph->getTextFile("MINEEVNT.TXT");
  84. it=0;
  85. int i=0;
  86. while (it<buf.length()-1)
  87. {
  88. loadToIt(temp,buf,it,3);
  89. temp = temp.substr(1,temp.length()-2);
  90. mines[i++].second = temp;
  91. }
  92. tlog5 << "\t\tReading RESTYPES \n";
  93. buf = bitmaph->getTextFile("RESTYPES.TXT");
  94. it=0;
  95. while (it<buf.length()-1)
  96. {
  97. loadToIt(temp,buf,it,3);
  98. restypes.push_back(temp);
  99. }
  100. tlog5 << "\t\tReading cregens \n";
  101. cregens.resize(110); //TODO: hardcoded value - change
  102. for(size_t i=0; i < cregens.size(); ++i)
  103. {
  104. cregens[i]=-1;
  105. }
  106. std::ifstream ifs("config/cregens.txt");
  107. while(!ifs.eof())
  108. {
  109. int dw, cr;
  110. ifs >> dw >> cr;
  111. cregens[dw]=cr;
  112. }
  113. ifs.close();
  114. ifs.clear();
  115. tlog5 << "\t\tReading ZCRGN1 \n";
  116. buf = bitmaph->getTextFile("ZCRGN1.TXT");
  117. it=0;
  118. while (it<buf.length()-1)
  119. {
  120. loadToIt(temp,buf,it,3);
  121. creGens.push_back(temp);
  122. }
  123. tlog5 << "\t\tDone loading objects!\n";
  124. }
  125. int CGObjectInstance::getOwner() const
  126. {
  127. //if (state)
  128. // return state->owner;
  129. //else
  130. return tempOwner; //won't have owner
  131. }
  132. CGObjectInstance::CGObjectInstance(): animPhaseShift(rand()%0xff)
  133. {
  134. pos = int3(-1,-1,-1);
  135. //std::cout << "Tworze obiekt "<<this<<std::endl;
  136. //state = new CLuaObjectScript();
  137. ID = subID = id = -1;
  138. defInfo = NULL;
  139. state = 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. int 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. int 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)
  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. cb->setBlockVis(id,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)
  760. {
  761. if(getOwner() != h->getOwner())
  762. {
  763. return;
  764. }
  765. cb->heroVisitCastle(id,h->id);
  766. }
  767. void CGTownInstance::onHeroLeave(const CGHeroInstance * h)
  768. {
  769. cb->stopHeroVisitCastle(id,h->id);
  770. }
  771. void CGTownInstance::initObj()
  772. {
  773. MetaString ms;
  774. ms << name << ", " << town->Name();
  775. cb->setHoverName(id,&ms);
  776. }
  777. //std::vector<int> CVisitableOPH::yourObjects()
  778. //{
  779. // std::vector<int> ret;
  780. // ret.push_back(51);//camp
  781. // ret.push_back(23);//tower
  782. // ret.push_back(61);//axis
  783. // ret.push_back(32);//garden
  784. // ret.push_back(100);//stone
  785. // ret.push_back(102);//tree
  786. // return ret;
  787. //}
  788. void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h )
  789. {
  790. if(visitors.find(h->id)==visitors.end())
  791. {
  792. onNAHeroVisit(h->id, false);
  793. if(ID != 102) //not tree
  794. visitors.insert(h->id);
  795. }
  796. else
  797. {
  798. onNAHeroVisit(h->id, true);
  799. }
  800. }
  801. void CGVisitableOPH::initObj()
  802. {
  803. if(ID==102)
  804. ttype = ran()%3;
  805. else
  806. ttype = -1;
  807. }
  808. void CGVisitableOPH::treeSelected( int heroID, int resType, int resVal, int expVal, ui32 result )
  809. {
  810. if(result==0) //player agreed to give res for exp
  811. {
  812. cb->giveResource(cb->getOwner(heroID),resType,-resVal); //take resource
  813. cb->changePrimSkill(heroID,4,expVal); //give exp
  814. visitors.insert(heroID); //set state to visited
  815. }
  816. }
  817. void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited)
  818. {
  819. int id=0, subid=0, ot=0, val=1;
  820. switch(ID)
  821. {
  822. case 51:
  823. subid=0;
  824. ot=80;
  825. break;
  826. case 23:
  827. subid=1;
  828. ot=39;
  829. break;
  830. case 61:
  831. subid=2;
  832. ot=100;
  833. break;
  834. case 32:
  835. subid=3;
  836. ot=59;
  837. break;
  838. case 100:
  839. id=5;
  840. ot=143;
  841. val=1000;
  842. break;
  843. case 102:
  844. id = 5;
  845. subid = 1;
  846. ot = 146;
  847. val = 1;
  848. break;
  849. }
  850. if (!alreadyVisited)
  851. {
  852. switch (ID)
  853. {
  854. case 51:
  855. case 23:
  856. case 61:
  857. case 32:
  858. {
  859. cb->changePrimSkill(heroID,subid,val);
  860. InfoWindow iw;
  861. iw.components.push_back(Component(0,subid,val,0));
  862. iw.text << std::pair<ui8,ui32>(11,ot);
  863. iw.player = cb->getOwner(heroID);
  864. cb->showInfoDialog(&iw);
  865. break;
  866. }
  867. case 100: //give exp
  868. {
  869. InfoWindow iw;
  870. iw.components.push_back(Component(id,subid,val,0));
  871. iw.player = cb->getOwner(heroID);
  872. iw.text << std::pair<ui8,ui32>(11,ot);
  873. cb->showInfoDialog(&iw);
  874. cb->changePrimSkill(heroID,4,val);
  875. break;
  876. }
  877. case 102:
  878. {
  879. const CGHeroInstance *h = cb->getHero(heroID);
  880. val = VLC->heroh->reqExp(h->level+val) - VLC->heroh->reqExp(h->level);
  881. if(!ttype)
  882. {
  883. visitors.insert(heroID);
  884. InfoWindow iw;
  885. iw.components.push_back(Component(id,subid,1,0));
  886. iw.player = cb->getOwner(heroID);
  887. iw.text << std::pair<ui8,ui32>(11,148);
  888. cb->showInfoDialog(&iw);
  889. cb->changePrimSkill(heroID,4,val);
  890. break;
  891. }
  892. else
  893. {
  894. int res, resval;
  895. if(ttype==1)
  896. {
  897. res = 6;
  898. resval = 2000;
  899. ot = 149;
  900. }
  901. else
  902. {
  903. res = 5;
  904. resval = 10;
  905. ot = 151;
  906. }
  907. if(cb->getResource(h->tempOwner,res) < resval) //not enough resources
  908. {
  909. ot++;
  910. InfoWindow iw;
  911. iw.player = h->tempOwner;
  912. iw.text << std::pair<ui8,ui32>(11,ot);
  913. cb->showInfoDialog(&iw);
  914. return;
  915. }
  916. YesNoDialog sd;
  917. sd.player = cb->getOwner(heroID);
  918. sd.text << std::pair<ui8,ui32>(11,ot);
  919. sd.components.push_back(Component(id,subid,val,0));
  920. cb->showYesNoDialog(&sd,boost::bind(&CGVisitableOPH::treeSelected,this,heroID,res,resval,val,_1));
  921. }
  922. break;
  923. }
  924. }
  925. }
  926. else
  927. {
  928. ot++;
  929. InfoWindow iw;
  930. iw.player = cb->getOwner(heroID);
  931. iw.text << std::pair<ui8,ui32>(11,ot);
  932. cb->showInfoDialog(&iw);
  933. }
  934. }
  935. const std::string & CGVisitableOPH::getHoverText() const
  936. {
  937. int pom;
  938. switch(ID)
  939. {
  940. case 51:
  941. pom = 8;
  942. break;
  943. case 23:
  944. pom = 7;
  945. break;
  946. case 61:
  947. pom = 11;
  948. break;
  949. case 32:
  950. pom = 4;
  951. break;
  952. case 100:
  953. pom = 5;
  954. break;
  955. case 102:
  956. pom = 18;
  957. break;
  958. default:
  959. throw "Wrong CGVisitableOPH object ID!\n";
  960. }
  961. hoverName = VLC->objh->names[ID] + " " + VLC->objh->xtrainfo[pom];
  962. const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
  963. if(h)
  964. {
  965. hoverName += (vstd::contains(visitors,h->id))
  966. ? (VLC->generaltexth->allTexts[353]) //not visited
  967. : ( VLC->generaltexth->allTexts[352]); //visited
  968. }
  969. return hoverName;
  970. }
  971. bool CArmedInstance::needsLastStack() const
  972. {
  973. return false;
  974. }
  975. void CGCreature::onHeroVisit( const CGHeroInstance * h )
  976. {
  977. army.slots[0].first = subID;
  978. cb->startBattleI(h->id,army,pos,boost::bind(&CGCreature::endBattle,this,_1));
  979. }
  980. void CGCreature::endBattle( BattleResult *result )
  981. {
  982. if(result->winner==0)
  983. {
  984. cb->removeObject(id);
  985. }
  986. else
  987. {
  988. int killedAmount=0;
  989. for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
  990. if(i->first == subID)
  991. killedAmount += i->second;
  992. cb->setAmount(id, army.slots[0].second - killedAmount);
  993. }
  994. }
  995. void CGCreature::initObj()
  996. {
  997. si32 &amount = army.slots[0].second;
  998. CCreature &c = VLC->creh->creatures[subID];
  999. if(!amount)
  1000. if(c.ammMax == c.ammMin)
  1001. amount = c.ammMax;
  1002. else
  1003. amount = c.ammMin + (ran() % (c.ammMax - c.ammMin));
  1004. }