CHeroHandler.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. #define VCMI_DLL
  2. #include "../stdafx.h"
  3. #include "CHeroHandler.h"
  4. #include <sstream>
  5. #include "CLodHandler.h"
  6. #include "../lib/VCMI_Lib.h"
  7. extern CLodHandler * bitmaph;
  8. void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
  9. CHeroClass::CHeroClass()
  10. {
  11. skillLimit = 8;
  12. }
  13. CHeroClass::~CHeroClass()
  14. {
  15. }
  16. int CHeroClass::chooseSecSkill(const std::set<int> & possibles) const //picks secondary skill out from given possibilities
  17. {
  18. if(possibles.size()==1)
  19. return *possibles.begin();
  20. int totalProb = 0;
  21. for(std::set<int>::const_iterator i=possibles.begin(); i!=possibles.end(); i++)
  22. {
  23. totalProb += proSec[*i];
  24. }
  25. int ran = rand()%totalProb;
  26. for(std::set<int>::const_iterator i=possibles.begin(); i!=possibles.end(); i++)
  27. {
  28. ran -= proSec[*i];
  29. if(ran<0)
  30. return *i;
  31. }
  32. throw std::string("Cannot pick secondary skill!");
  33. }
  34. int CObstacleInfo::getWidth()
  35. {
  36. int ret = 1;
  37. int line = 1;
  38. for(int h=0; h<blockmap.size(); ++h)
  39. {
  40. int cur = - line/2;
  41. switch(blockmap[h])
  42. {
  43. case 'X' : case 'N':
  44. ++cur;
  45. break;
  46. case 'L':
  47. if(cur > ret)
  48. ret = cur;
  49. ++line;
  50. break;
  51. }
  52. }
  53. return ret;
  54. }
  55. int CObstacleInfo::getHeight()
  56. {
  57. int ret = 1;
  58. for(int h=0; h<blockmap.size(); ++h)
  59. {
  60. if(blockmap[h] == 'L')
  61. {
  62. ++ret;
  63. }
  64. }
  65. return ret;
  66. }
  67. std::vector<int> CObstacleInfo::getBlocked(int hex)
  68. {
  69. std::vector<int> ret;
  70. int cur = hex; //currently browsed hex
  71. int curBeg = hex; //beginning of current line
  72. for(int h=0; h<blockmap.size(); ++h)
  73. {
  74. switch(blockmap[h])
  75. {
  76. case 'X':
  77. ret.push_back(cur);
  78. ++cur;
  79. break;
  80. case 'L':
  81. if((cur/17)%2 == 0)
  82. {
  83. cur = curBeg + 17;
  84. curBeg = cur;
  85. }
  86. else
  87. {
  88. cur = curBeg + 16;
  89. curBeg = cur;
  90. }
  91. break;
  92. case 'N':
  93. ++cur;
  94. break;
  95. }
  96. }
  97. return ret;
  98. }
  99. CHeroHandler::~CHeroHandler()
  100. {
  101. for (int i = 0; i < heroes.size(); i++)
  102. delete heroes[i];
  103. for (int i = 0; i < heroClasses.size(); i++)
  104. delete heroClasses[i];
  105. }
  106. CHeroHandler::CHeroHandler()
  107. {}
  108. void CHeroHandler::loadObstacles()
  109. {
  110. std::ifstream inp;
  111. inp.open("config" PATHSEPARATOR "obstacles.txt", std::ios_base::in|std::ios_base::binary);
  112. if(!inp.is_open())
  113. {
  114. tlog1<<"missing file: config/heroes_sec_skills.txt"<<std::endl;
  115. }
  116. else
  117. {
  118. std::string dump;
  119. for(int i=0; i<99; ++i)
  120. {
  121. inp>>dump;
  122. }
  123. while(true)
  124. {
  125. CObstacleInfo obi;
  126. inp>>obi.ID;
  127. if(obi.ID == -1) break;
  128. inp>>obi.defName;
  129. inp>>obi.blockmap;
  130. inp>>obi.allowedTerrains;
  131. obstacles[obi.ID] = obi;
  132. }
  133. inp.close();
  134. }
  135. }
  136. void CHeroHandler::loadHeroes()
  137. {
  138. VLC->heroh = this;
  139. int ID=0;
  140. std::string buf = bitmaph->getTextFile("HOTRAITS.TXT");
  141. int it=0;
  142. std::string dump;
  143. for(int i=0; i<2; ++i)
  144. {
  145. loadToIt(dump,buf,it,3);
  146. }
  147. int numberOfCurrentClassHeroes = 0;
  148. int currentClass = 0;
  149. int additHero = 0;
  150. EHeroClasses addTab[12];
  151. addTab[0] = HERO_KNIGHT;
  152. addTab[1] = HERO_WITCH;
  153. addTab[2] = HERO_KNIGHT;
  154. addTab[3] = HERO_WIZARD;
  155. addTab[4] = HERO_RANGER;
  156. addTab[5] = HERO_BARBARIAN;
  157. addTab[6] = HERO_DEATHKNIGHT;
  158. addTab[7] = HERO_WARLOCK;
  159. addTab[8] = HERO_KNIGHT;
  160. addTab[9] = HERO_WARLOCK;
  161. addTab[10] = HERO_BARBARIAN;
  162. addTab[11] = HERO_DEMONIAC;
  163. for (int i=0; i<HEROES_QUANTITY; i++)
  164. {
  165. CHero * nher = new CHero;
  166. if(currentClass<18)
  167. {
  168. nher->heroType = (EHeroClasses)currentClass;
  169. ++numberOfCurrentClassHeroes;
  170. if(numberOfCurrentClassHeroes==8)
  171. {
  172. numberOfCurrentClassHeroes = 0;
  173. ++currentClass;
  174. }
  175. }
  176. else
  177. {
  178. nher->heroType = addTab[additHero++];
  179. }
  180. std::string pom ;
  181. loadToIt(nher->name,buf,it,4);
  182. for(int x=0;x<3;x++)
  183. {
  184. loadToIt(pom,buf,it,4);
  185. nher->lowStack[x] = atoi(pom.c_str());
  186. loadToIt(pom,buf,it,4);
  187. nher->highStack[x] = atoi(pom.c_str());
  188. loadToIt(nher->refTypeStack[x],buf,it,(x==2) ? (3) : (4));
  189. int hlp = nher->refTypeStack[x].find_first_of(' ',0);
  190. if(hlp>=0)
  191. nher->refTypeStack[x].replace(hlp,1,"");
  192. }
  193. nher->ID = heroes.size();
  194. heroes.push_back(nher);
  195. }
  196. //loading initial secondary skills
  197. std::ifstream inp;
  198. inp.open("config" PATHSEPARATOR "heroes_sec_skills.txt", std::ios_base::in|std::ios_base::binary);
  199. if(!inp.is_open())
  200. {
  201. tlog1<<"missing file: config/heroes_sec_skills.txt"<<std::endl;
  202. }
  203. else
  204. {
  205. inp>>dump;
  206. int hid; //ID of currently read hero
  207. int secQ; //number of secondary abilities
  208. while(true)
  209. {
  210. inp>>hid;
  211. if(hid == -1)
  212. break;
  213. inp>>secQ;
  214. for(int g=0; g<secQ; ++g)
  215. {
  216. int a, b;
  217. inp>>a; inp>>b;
  218. heroes[hid]->secSkillsInit.push_back(std::make_pair(a, b));
  219. }
  220. }
  221. inp.close();
  222. }
  223. //initial skills loaded
  224. loadHeroClasses();
  225. initHeroClasses();
  226. expPerLevel.push_back(0);
  227. expPerLevel.push_back(1000);
  228. expPerLevel.push_back(2000);
  229. expPerLevel.push_back(3200);
  230. expPerLevel.push_back(4500);
  231. expPerLevel.push_back(6000);
  232. expPerLevel.push_back(7700);
  233. expPerLevel.push_back(9000);
  234. expPerLevel.push_back(11000);
  235. expPerLevel.push_back(13200);
  236. expPerLevel.push_back(15500);
  237. expPerLevel.push_back(18500);
  238. expPerLevel.push_back(22100);
  239. expPerLevel.push_back(26420);
  240. expPerLevel.push_back(31604);
  241. //ballistics info
  242. buf = bitmaph->getTextFile("BALLIST.TXT");
  243. it = 0;
  244. for(int i=0; i<22; ++i)
  245. {
  246. loadToIt(dump,buf,it,4);
  247. }
  248. for(int lvl=0; lvl<4; ++lvl)
  249. {
  250. CHeroHandler::SBallisticsLevelInfo bli;
  251. si32 tempNum;
  252. loadToIt(tempNum,buf,it,4);
  253. bli.keep = tempNum;
  254. loadToIt(tempNum,buf,it,4);
  255. bli.tower = tempNum;
  256. loadToIt(tempNum,buf,it,4);
  257. bli.gate = tempNum;
  258. loadToIt(tempNum,buf,it,4);
  259. bli.wall = tempNum;
  260. loadToIt(tempNum,buf,it,4);
  261. bli.shots = tempNum;
  262. loadToIt(tempNum,buf,it,4);
  263. bli.noDmg = tempNum;
  264. loadToIt(tempNum,buf,it,4);
  265. bli.oneDmg = tempNum;
  266. loadToIt(tempNum,buf,it,4);
  267. bli.twoDmg = tempNum;
  268. loadToIt(tempNum,buf,it,4);
  269. bli.sum = tempNum;
  270. if(lvl!=3)
  271. {
  272. loadToIt(dump,buf,it,4);
  273. }
  274. ballistics.push_back(bli);
  275. }
  276. }
  277. void CHeroHandler::loadHeroClasses()
  278. {
  279. std::string buf = bitmaph->getTextFile("HCTRAITS.TXT");
  280. int andame = buf.size();
  281. for(int y=0; y<andame; ++y)
  282. if(buf[y]==',')
  283. buf[y]='.';
  284. int i = 0; //buf iterator
  285. int hmcr = 0;
  286. for(i; i<andame; ++i) //omitting rubbish
  287. {
  288. if(buf[i]=='\r')
  289. ++hmcr;
  290. if(hmcr==2)
  291. break;
  292. }
  293. i+=2;
  294. for(int ss=0; ss<18; ++ss) //18 classes of hero (including conflux)
  295. {
  296. CHeroClass * hc = new CHeroClass;
  297. int befi=i;
  298. for(i; i<andame; ++i)
  299. {
  300. if(buf[i]=='\t')
  301. break;
  302. }
  303. hc->name = buf.substr(befi, i-befi);
  304. ++i;
  305. befi=i;
  306. for(i; i<andame; ++i)
  307. {
  308. if(buf[i]=='\t')
  309. break;
  310. }
  311. hc->aggression = atof(buf.substr(befi, i-befi).c_str());
  312. ++i;
  313. befi=i;
  314. for(i; i<andame; ++i)
  315. {
  316. if(buf[i]=='\t')
  317. break;
  318. }
  319. hc->initialAttack = atoi(buf.substr(befi, i-befi).c_str());
  320. ++i;
  321. befi=i;
  322. for(i; i<andame; ++i)
  323. {
  324. if(buf[i]=='\t')
  325. break;
  326. }
  327. hc->initialDefence = atoi(buf.substr(befi, i-befi).c_str());
  328. ++i;
  329. befi=i;
  330. for(i; i<andame; ++i)
  331. {
  332. if(buf[i]=='\t')
  333. break;
  334. }
  335. hc->initialPower = atoi(buf.substr(befi, i-befi).c_str());
  336. ++i;
  337. befi=i;
  338. for(i; i<andame; ++i)
  339. {
  340. if(buf[i]=='\t')
  341. break;
  342. }
  343. hc->initialKnowledge = atoi(buf.substr(befi, i-befi).c_str());
  344. ++i;
  345. hc->primChance.resize(PRIMARY_SKILLS);
  346. for(int x=0;x<PRIMARY_SKILLS;x++)
  347. {
  348. befi=i;
  349. for(i; i<andame; ++i)
  350. {
  351. if(buf[i]=='\t')
  352. break;
  353. }
  354. hc->primChance[x].first = atoi(buf.substr(befi, i-befi).c_str());
  355. ++i;
  356. }
  357. for(int x=0;x<PRIMARY_SKILLS;x++)
  358. {
  359. befi=i;
  360. for(i; i<andame; ++i)
  361. {
  362. if(buf[i]=='\t')
  363. break;
  364. }
  365. hc->primChance[x].second = atoi(buf.substr(befi, i-befi).c_str());
  366. ++i;
  367. }
  368. //CHero kkk = heroes[0];
  369. for(int dd=0; dd<SKILL_QUANTITY; ++dd)
  370. {
  371. befi=i;
  372. for(i; i<andame; ++i)
  373. {
  374. if(buf[i]=='\t')
  375. break;
  376. }
  377. int buff = atoi(buf.substr(befi, i-befi).c_str());
  378. ++i;
  379. hc->proSec.push_back(buff);
  380. }
  381. for(int dd=0; dd<9; ++dd)
  382. {
  383. befi=i;
  384. for(i; i<andame; ++i)
  385. {
  386. if(buf[i]=='\t' || buf[i]=='\r')
  387. break;
  388. }
  389. hc->selectionProbability[dd] = atoi(buf.substr(befi, i-befi).c_str());
  390. ++i;
  391. }
  392. ++i;
  393. heroClasses.push_back(hc);
  394. }
  395. }
  396. void CHeroHandler::initHeroClasses()
  397. {
  398. for(int gg=0; gg<heroes.size(); ++gg)
  399. {
  400. heroes[gg]->heroClass = heroClasses[heroes[gg]->heroType];
  401. }
  402. initTerrainCosts();
  403. }
  404. unsigned int CHeroHandler::level(unsigned int experience)
  405. {
  406. int add=0;
  407. while(experience>=expPerLevel[expPerLevel.size()-1])
  408. {
  409. experience/=1.2;
  410. add+=1;
  411. }
  412. for(int i=expPerLevel.size()-1; i>=0; --i)
  413. {
  414. if(experience>=expPerLevel[i])
  415. return 1+i+add;
  416. }
  417. return -1;
  418. }
  419. unsigned int CHeroHandler::reqExp(unsigned int level)
  420. {
  421. level-=1;
  422. if(level<expPerLevel.size())
  423. return expPerLevel[level];
  424. else
  425. {
  426. unsigned int exp = expPerLevel[expPerLevel.size()-1];
  427. level-=(expPerLevel.size()-1);
  428. while(level>0)
  429. {
  430. --level;
  431. exp*=1.2;
  432. }
  433. return exp;
  434. }
  435. return -1;
  436. }
  437. void CHeroHandler::initTerrainCosts()
  438. {
  439. std::ifstream inp;
  440. inp.open("config" PATHSEPARATOR "TERCOSTS.TXT", std::ios_base::in|std::ios_base::binary);
  441. int tynum;
  442. inp>>tynum;
  443. for(int i=0; i<2*tynum; i+=2)
  444. {
  445. int catNum;
  446. inp>>catNum;
  447. for(int k=0; k<catNum; ++k)
  448. {
  449. int curCost;
  450. inp>>curCost;
  451. heroClasses[i]->terrCosts.push_back(curCost);
  452. heroClasses[i+1]->terrCosts.push_back(curCost);
  453. }
  454. }
  455. inp.close();
  456. }