CGameState.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  1. #define VCMI_DLL
  2. #include <algorithm>
  3. #include <queue>
  4. #include <fstream>
  5. #include "CGameState.h"
  6. #include <boost/random/linear_congruential.hpp>
  7. #include "hch/CDefObjInfoHandler.h"
  8. #include "hch/CArtHandler.h"
  9. #include "hch/CTownHandler.h"
  10. #include "hch/CHeroHandler.h"
  11. #include "hch/CObjectHandler.h"
  12. #include "hch/CCreatureHandler.h"
  13. #include "lib/VCMI_Lib.h"
  14. #include "map.h"
  15. #include "StartInfo.h"
  16. #include "lib/NetPacks.h"
  17. #include <boost/foreach.hpp>
  18. #include <boost/thread.hpp>
  19. #include <boost/thread/shared_mutex.hpp>
  20. boost::rand48 ran;
  21. class CMP_stack
  22. {
  23. public:
  24. bool operator ()(const CStack* a, const CStack* b)
  25. {
  26. return (a->creature->speed)>(b->creature->speed);
  27. }
  28. } cmpst ;
  29. CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
  30. {
  31. CGObjectInstance * nobj;
  32. switch(id)
  33. {
  34. case 34: //hero
  35. {
  36. CGHeroInstance * nobj;
  37. nobj = new CGHeroInstance();
  38. nobj->pos = pos;
  39. nobj->tempOwner = owner;
  40. nobj->defInfo = new CGDefInfo();
  41. nobj->defInfo->id = 34;
  42. nobj->defInfo->subid = subid;
  43. nobj->defInfo->printPriority = 0;
  44. nobj->type = VLC->heroh->heroes[subid];
  45. for(int i=0;i<6;i++)
  46. {
  47. nobj->defInfo->blockMap[i]=255;
  48. nobj->defInfo->visitMap[i]=0;
  49. }
  50. nobj->ID = id;
  51. nobj->subID = subid;
  52. nobj->defInfo->handler=NULL;
  53. nobj->defInfo->blockMap[5] = 253;
  54. nobj->defInfo->visitMap[5] = 2;
  55. nobj->artifacts.resize(20);
  56. nobj->artifWorn[16] = 3;
  57. nobj->primSkills.resize(4);
  58. nobj->primSkills[0] = nobj->type->heroClass->initialAttack;
  59. nobj->primSkills[1] = nobj->type->heroClass->initialDefence;
  60. nobj->primSkills[2] = nobj->type->heroClass->initialPower;
  61. nobj->primSkills[3] = nobj->type->heroClass->initialKnowledge;
  62. nobj->mana = 10 * nobj->primSkills[3];
  63. return nobj;
  64. }
  65. case 98: //town
  66. nobj = new CGTownInstance;
  67. break;
  68. default: //rest of objects
  69. nobj = new CGObjectInstance;
  70. nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
  71. break;
  72. }
  73. nobj->ID = id;
  74. nobj->subID = subid;
  75. if(!nobj->defInfo)
  76. std::cout <<"No def declaration for " <<id <<" "<<subid<<std::endl;
  77. nobj->pos = pos;
  78. //nobj->state = NULL;//new CLuaObjectScript();
  79. nobj->tempOwner = owner;
  80. nobj->info = NULL;
  81. nobj->defInfo->id = id;
  82. nobj->defInfo->subid = subid;
  83. //assigning defhandler
  84. if(nobj->ID==34 || nobj->ID==98)
  85. return nobj;
  86. nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
  87. //if(!nobj->defInfo->handler)
  88. //{
  89. // nobj->defInfo->handler = CDefHandler::giveDef(nobj->defInfo->name);
  90. // nobj->defInfo->width = nobj->defInfo->handler->ourImages[0].bitmap->w/32;
  91. // nobj->defInfo->height = nobj->defInfo->handler->ourImages[0].bitmap->h/32;
  92. //}
  93. return nobj;
  94. }
  95. CStack::CStack(CCreature * C, int A, int O, int I, bool AO)
  96. :creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints)
  97. {
  98. }
  99. void CGameState::apply(IPack * pack)
  100. {
  101. mx->lock();
  102. switch(pack->getType())
  103. {
  104. case 101://NewTurn
  105. {
  106. NewTurn * n = static_cast<NewTurn*>(pack);
  107. day = n->day;
  108. BOOST_FOREACH(NewTurn::Hero h, n->heroes) //give mana/movement point
  109. {
  110. static_cast<CGHeroInstance*>(map->objects[h.id])->movement = h.move;
  111. static_cast<CGHeroInstance*>(map->objects[h.id])->mana = h.mana;
  112. }
  113. BOOST_FOREACH(NewTurn::Resources h, n->res) //give resources
  114. {
  115. for(int i=0;i<RESOURCE_QUANTITY;i++)
  116. players[h.player].resources[i] = h.resources[i];
  117. }
  118. if(n->resetBuilded) //reset amount of structures set in this turn in towns
  119. BOOST_FOREACH(CGTownInstance* t, map->towns)
  120. t->builded = 0;
  121. break;
  122. }
  123. case 501://hero try-move
  124. {
  125. TryMoveHero * n = static_cast<TryMoveHero*>(pack);
  126. CGHeroInstance *h = static_cast<CGHeroInstance*>(map->objects[n->id]);
  127. h->movement = n->movePoints;
  128. if(n->result)
  129. h->pos = n->end;
  130. else
  131. h->pos = n->start;
  132. BOOST_FOREACH(int3 t, n->fowRevealed)
  133. players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1;
  134. break;
  135. }
  136. case 1001://set object property
  137. {
  138. SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
  139. int CGObjectInstance::*point;
  140. switch(p->what)
  141. {
  142. case 1:
  143. point = &CGObjectInstance::tempOwner;
  144. break;
  145. case 2:
  146. point = &CGObjectInstance::blockVisit;
  147. break;
  148. }
  149. map->objects[p->id]->*point = p->val;
  150. break;
  151. }
  152. //case 1002://set hover name
  153. // {
  154. // SetHoverName * shn = static_cast<SetHoverName*>(pack);
  155. // map->objects[shn->id]->hoverName = toString(shn->name);
  156. // break;
  157. // }
  158. }
  159. mx->unlock();
  160. }
  161. int CGameState::pickHero(int owner)
  162. {
  163. int h=-1;
  164. if(map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero
  165. return h;
  166. int f = scenarioOps->getIthPlayersSettings(owner).castle;
  167. int i=0;
  168. do //try to find free hero of our faction
  169. {
  170. i++;
  171. h = scenarioOps->getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
  172. } while( map->getHero(h) && i<175);
  173. if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
  174. {
  175. std::cout << "Warning: cannot find free hero - trying to get first available..."<<std::endl;
  176. for(int j=0; j<HEROES_PER_TYPE * 2 * F_NUMBER; j++)
  177. if(!map->getHero(j))
  178. h=j;
  179. }
  180. return h;
  181. }
  182. std::pair<int,int> CGameState::pickObject(CGObjectInstance *obj)
  183. {
  184. switch(obj->ID)
  185. {
  186. case 65: //random artifact
  187. return std::pair<int,int>(5,(ran()%136)+7); //tylko sensowny zakres - na poczatku sa katapulty itp, na koncu specjalne i blanki
  188. case 66: //random treasure artifact
  189. return std::pair<int,int>(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id);
  190. case 67: //random minor artifact
  191. return std::pair<int,int>(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id);
  192. case 68: //random major artifact
  193. return std::pair<int,int>(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id);
  194. case 69: //random relic artifact
  195. return std::pair<int,int>(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id);
  196. case 70: //random hero
  197. {
  198. return std::pair<int,int>(34,pickHero(obj->tempOwner));
  199. }
  200. case 71: //random monster
  201. return std::pair<int,int>(54,ran()%(VLC->creh->creatures.size()));
  202. case 72: //random monster lvl1
  203. return std::pair<int,int>(54,VLC->creh->levelCreatures[1][ran()%VLC->creh->levelCreatures[1].size()]->idNumber);
  204. case 73: //random monster lvl2
  205. return std::pair<int,int>(54,VLC->creh->levelCreatures[2][ran()%VLC->creh->levelCreatures[2].size()]->idNumber);
  206. case 74: //random monster lvl3
  207. return std::pair<int,int>(54,VLC->creh->levelCreatures[3][ran()%VLC->creh->levelCreatures[3].size()]->idNumber);
  208. case 75: //random monster lvl4
  209. return std::pair<int,int>(54,VLC->creh->levelCreatures[4][ran()%VLC->creh->levelCreatures[4].size()]->idNumber);
  210. case 76: //random resource
  211. return std::pair<int,int>(79,ran()%7); //now it's OH3 style, use %8 for mithril
  212. case 77: //random town
  213. {
  214. int align = ((CGTownInstance*)obj)->alignment,
  215. f;
  216. if(align>PLAYER_LIMIT-1)//same as owner / random
  217. {
  218. if(obj->tempOwner > PLAYER_LIMIT-1)
  219. f = -1; //random
  220. else
  221. f = scenarioOps->getIthPlayersSettings(obj->tempOwner).castle;
  222. }
  223. else
  224. {
  225. f = scenarioOps->getIthPlayersSettings(align).castle;
  226. }
  227. if(f<0) f = ran()%VLC->townh->towns.size();
  228. return std::pair<int,int>(98,f);
  229. }
  230. case 162: //random monster lvl5
  231. return std::pair<int,int>(54,VLC->creh->levelCreatures[5][ran()%VLC->creh->levelCreatures[5].size()]->idNumber);
  232. case 163: //random monster lvl6
  233. return std::pair<int,int>(54,VLC->creh->levelCreatures[6][ran()%VLC->creh->levelCreatures[6].size()]->idNumber);
  234. case 164: //random monster lvl7
  235. return std::pair<int,int>(54,VLC->creh->levelCreatures[7][ran()%VLC->creh->levelCreatures[7].size()]->idNumber);
  236. case 216: //random dwelling
  237. {
  238. int faction = ran()%F_NUMBER;
  239. CCreGen2ObjInfo* info =(CCreGen2ObjInfo*)obj->info;
  240. if (info->asCastle)
  241. {
  242. for(int i=0;i<map->objects.size();i++)
  243. {
  244. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  245. {
  246. randomizeObject(map->objects[i]); //we have to randomize the castle first
  247. faction = map->objects[i]->subID;
  248. break;
  249. }
  250. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  251. {
  252. faction = map->objects[i]->subID;
  253. break;
  254. }
  255. }
  256. }
  257. else
  258. {
  259. while((!(info->castles[0]&(1<<faction))))
  260. {
  261. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  262. break;
  263. faction = ran()%F_NUMBER;
  264. }
  265. }
  266. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  267. int cid = VLC->townh->towns[faction].basicCreatures[level];
  268. for(int i=0;i<VLC->objh->cregens.size();i++)
  269. if(VLC->objh->cregens[i]==cid)
  270. return std::pair<int,int>(17,i);
  271. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  272. return std::pair<int,int>(17,0);
  273. }
  274. case 217:
  275. {
  276. int faction = ran()%F_NUMBER;
  277. CCreGenObjInfo* info =(CCreGenObjInfo*)obj->info;
  278. if (info->asCastle)
  279. {
  280. for(int i=0;i<map->objects.size();i++)
  281. {
  282. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  283. {
  284. randomizeObject(map->objects[i]); //we have to randomize the castle first
  285. faction = map->objects[i]->subID;
  286. break;
  287. }
  288. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  289. {
  290. faction = map->objects[i]->subID;
  291. break;
  292. }
  293. }
  294. }
  295. else
  296. {
  297. while((!(info->castles[0]&(1<<faction))))
  298. {
  299. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  300. break;
  301. faction = ran()%F_NUMBER;
  302. }
  303. }
  304. int cid = VLC->townh->towns[faction].basicCreatures[obj->subID];
  305. for(int i=0;i<VLC->objh->cregens.size();i++)
  306. if(VLC->objh->cregens[i]==cid)
  307. return std::pair<int,int>(17,i);
  308. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  309. return std::pair<int,int>(17,0);
  310. }
  311. case 218:
  312. {
  313. CCreGen3ObjInfo* info =(CCreGen3ObjInfo*)obj->info;
  314. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  315. int cid = VLC->townh->towns[obj->subID].basicCreatures[level];
  316. for(int i=0;i<VLC->objh->cregens.size();i++)
  317. if(VLC->objh->cregens[i]==cid)
  318. return std::pair<int,int>(17,i);
  319. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  320. return std::pair<int,int>(17,0);
  321. }
  322. }
  323. return std::pair<int,int>(-1,-1);
  324. }
  325. void CGameState::randomizeObject(CGObjectInstance *cur)
  326. {
  327. std::pair<int,int> ran = pickObject(cur);
  328. if(ran.first<0 || ran.second<0) //this is not a random object, or we couldn't find anything
  329. {
  330. if(cur->ID==98) //town - set def
  331. {
  332. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  333. if(t->hasCapitol())
  334. t->defInfo = capitols[t->subID];
  335. else if(t->hasFort())
  336. t->defInfo = forts[t->subID];
  337. else
  338. t->defInfo = villages[t->subID];
  339. }
  340. return;
  341. }
  342. else if(ran.first==34)//special code for hero
  343. {
  344. CGHeroInstance *h = dynamic_cast<CGHeroInstance *>(cur);
  345. if(!h) {std::cout<<"Wrong random hero at "<<cur->pos<<std::endl; return;}
  346. cur->ID = ran.first;
  347. cur->subID = ran.second;
  348. h->type = VLC->heroh->heroes[ran.second];
  349. map->heroes.push_back(h);
  350. return; //TODO: maybe we should do something with definfo?
  351. }
  352. else if(ran.first==98)//special code for town
  353. {
  354. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  355. if(!t) {std::cout<<"Wrong random town at "<<cur->pos<<std::endl; return;}
  356. cur->ID = ran.first;
  357. cur->subID = ran.second;
  358. t->town = &VLC->townh->towns[ran.second];
  359. if(t->hasCapitol())
  360. t->defInfo = capitols[t->subID];
  361. else if(t->hasFort())
  362. t->defInfo = forts[t->subID];
  363. else
  364. t->defInfo = villages[t->subID];
  365. map->towns.push_back(t);
  366. return;
  367. }
  368. //we have to replace normal random object
  369. cur->ID = ran.first;
  370. cur->subID = ran.second;
  371. map->defs.insert(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
  372. if(!cur->defInfo){std::cout<<"Missing def declaration for "<<cur->ID<<" "<<cur->subID<<std::endl;return;}
  373. }
  374. int CGameState::getDate(int mode) const
  375. {
  376. int temp;
  377. switch (mode)
  378. {
  379. case 0:
  380. return day;
  381. break;
  382. case 1:
  383. temp = (day)%7;
  384. if (temp)
  385. return temp;
  386. else return 7;
  387. break;
  388. case 2:
  389. temp = ((day-1)/7)+1;
  390. if (!(temp%4))
  391. return 4;
  392. else
  393. return (temp%4);
  394. break;
  395. case 3:
  396. return ((day-1)/28)+1;
  397. break;
  398. }
  399. return 0;
  400. }
  401. CGameState::CGameState()
  402. {
  403. mx = new boost::shared_mutex();
  404. }
  405. CGameState::~CGameState()
  406. {
  407. delete mx;
  408. }
  409. void CGameState::init(StartInfo * si, Mapa * map, int Seed)
  410. {
  411. day = 0;
  412. seed = Seed;
  413. ran.seed((long)seed);
  414. scenarioOps = si;
  415. this->map = map;
  416. for(int i=0;i<F_NUMBER;i++)
  417. {
  418. villages[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  419. forts[i] = VLC->dobjinfo->castles[i];
  420. capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  421. }
  422. //picking random factions for players
  423. for(int i=0;i<scenarioOps->playerInfos.size();i++)
  424. {
  425. if(scenarioOps->playerInfos[i].castle==-1)
  426. {
  427. int f;
  428. do
  429. {
  430. f = ran()%F_NUMBER;
  431. }while(!(map->players[scenarioOps->playerInfos[i].color].allowedFactions & 1<<f));
  432. scenarioOps->playerInfos[i].castle = f;
  433. }
  434. }
  435. //randomizing objects
  436. for(int no=0; no<map->objects.size(); ++no)
  437. {
  438. randomizeObject(map->objects[no]);
  439. if(map->objects[no]->ID==26)
  440. map->objects[no]->defInfo->handler=NULL;
  441. map->objects[no]->hoverName = VLC->objh->names[map->objects[no]->ID];
  442. }
  443. //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
  444. //giving starting hero
  445. for(int i=0;i<PLAYER_LIMIT;i++)
  446. {
  447. if((map->players[i].generateHeroAtMainTown && map->players[i].hasMainTown) || (map->players[i].hasMainTown && map->version==RoE))
  448. {
  449. int3 hpos = map->players[i].posOfMainTown;
  450. hpos.x+=1;// hpos.y+=1;
  451. int j;
  452. for(j=0; j<scenarioOps->playerInfos.size(); j++)
  453. if(scenarioOps->playerInfos[j].color == i)
  454. break;
  455. if(j == scenarioOps->playerInfos.size())
  456. continue;
  457. int h=pickHero(i);
  458. CGHeroInstance * nnn = static_cast<CGHeroInstance*>(createObject(34,h,hpos,i));
  459. nnn->id = map->objects.size();
  460. //nnn->defInfo->handler = graphics->flags1[0];
  461. map->heroes.push_back(nnn);
  462. map->objects.push_back(nnn);
  463. }
  464. }
  465. //std::cout<<"\tGiving starting heroes: "<<th.getDif()<<std::endl;
  466. /*********creating players entries in gs****************************************/
  467. for (int i=0; i<scenarioOps->playerInfos.size();i++)
  468. {
  469. std::pair<int,PlayerState> ins(scenarioOps->playerInfos[i].color,PlayerState());
  470. ins.second.color=ins.first;
  471. ins.second.serial=i;
  472. players.insert(ins);
  473. }
  474. /******************RESOURCES****************************************************/
  475. //TODO: zeby komputer dostawal inaczej niz gracz
  476. std::vector<int> startres;
  477. std::ifstream tis("config/startres.txt");
  478. int k;
  479. for (int j=0;j<scenarioOps->difficulty;j++)
  480. {
  481. tis >> k;
  482. for (int z=0;z<RESOURCE_QUANTITY;z++)
  483. tis>>k;
  484. }
  485. tis >> k;
  486. for (int i=0;i<RESOURCE_QUANTITY;i++)
  487. {
  488. tis >> k;
  489. startres.push_back(k);
  490. }
  491. tis.close();
  492. for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
  493. {
  494. (*i).second.resources.resize(RESOURCE_QUANTITY);
  495. for (int x=0;x<RESOURCE_QUANTITY;x++)
  496. (*i).second.resources[x] = startres[x];
  497. }
  498. /*************************HEROES************************************************/
  499. for (int i=0; i<map->heroes.size();i++) //heroes instances
  500. {
  501. if (map->heroes[i]->getOwner()<0)
  502. continue;
  503. CGHeroInstance * vhi = (map->heroes[i]);
  504. if(!vhi->type)
  505. vhi->type = VLC->heroh->heroes[vhi->subID];
  506. //vhi->subID = vhi->type->ID;
  507. if (vhi->level<1)
  508. {
  509. vhi->exp=40+ran()%50;
  510. vhi->level = 1;
  511. }
  512. if (vhi->level>1) ;//TODO dodac um dr, ale potrzebne los
  513. if ((!vhi->primSkills.size()) || (vhi->primSkills[0]<0))
  514. {
  515. if (vhi->primSkills.size()<PRIMARY_SKILLS)
  516. vhi->primSkills.resize(PRIMARY_SKILLS);
  517. vhi->primSkills[0] = vhi->type->heroClass->initialAttack;
  518. vhi->primSkills[1] = vhi->type->heroClass->initialDefence;
  519. vhi->primSkills[2] = vhi->type->heroClass->initialPower;
  520. vhi->primSkills[3] = vhi->type->heroClass->initialKnowledge;
  521. }
  522. vhi->mana = vhi->primSkills[3]*10;
  523. if (!vhi->name.length())
  524. {
  525. vhi->name = vhi->type->name;
  526. }
  527. if (!vhi->biography.length())
  528. {
  529. vhi->biography = vhi->type->biography;
  530. }
  531. if (vhi->portrait < 0)
  532. vhi->portrait = vhi->type->ID;
  533. //initial army
  534. if (!vhi->army.slots.size()) //standard army
  535. {
  536. int pom, pom2=0;
  537. for(int x=0;x<3;x++)
  538. {
  539. pom = (VLC->creh->nameToID[vhi->type->refTypeStack[x]]);
  540. if(pom>=145 && pom<=149) //war machine
  541. {
  542. pom2++;
  543. switch (pom)
  544. {
  545. case 145: //catapult
  546. vhi->artifWorn[16] = 3;
  547. break;
  548. default:
  549. pom-=145;
  550. vhi->artifWorn[13+pom] = 4+pom;
  551. break;
  552. }
  553. continue;
  554. }
  555. vhi->army.slots[x-pom2].first = &(VLC->creh->creatures[pom]);
  556. if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0)
  557. vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
  558. else
  559. vhi->army.slots[x-pom2].second = +vhi->type->lowStack[x];
  560. }
  561. }
  562. players[vhi->getOwner()].heroes.push_back(vhi);
  563. }
  564. /*************************FOG**OF**WAR******************************************/
  565. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  566. {
  567. k->second.fogOfWarMap.resize(map->width);
  568. for(int g=0; g<map->width; ++g)
  569. k->second.fogOfWarMap[g].resize(map->height);
  570. for(int g=-0; g<map->width; ++g)
  571. for(int h=0; h<map->height; ++h)
  572. k->second.fogOfWarMap[g][h].resize(map->twoLevel+1, 0);
  573. for(int g=0; g<map->width; ++g)
  574. for(int h=0; h<map->height; ++h)
  575. for(int v=0; v<map->twoLevel+1; ++v)
  576. k->second.fogOfWarMap[g][h][v] = 0;
  577. for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
  578. {
  579. for(int yd=0; yd<map->height; ++yd)
  580. {
  581. for(int ch=0; ch<k->second.heroes.size(); ++ch)
  582. {
  583. int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
  584. int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
  585. if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
  586. k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
  587. }
  588. }
  589. }
  590. }
  591. /****************************TOWNS************************************************/
  592. for (int i=0;i<map->towns.size();i++)
  593. {
  594. CGTownInstance * vti =(map->towns[i]);
  595. if(!vti->town)
  596. vti->town = &VLC->townh->towns[vti->subID];
  597. if (vti->name.length()==0) // if town hasn't name we draw it
  598. vti->name=vti->town->names[ran()%vti->town->names.size()];
  599. if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
  600. {
  601. vti->builtBuildings.erase(-50);
  602. vti->builtBuildings.insert(10);
  603. vti->builtBuildings.insert(5);
  604. vti->builtBuildings.insert(30);
  605. if(ran()%2)
  606. vti->builtBuildings.insert(31);
  607. }
  608. players[vti->getOwner()].towns.push_back(vti);
  609. }
  610. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  611. {
  612. if(k->first==-1 || k->first==255)
  613. continue;
  614. for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
  615. {
  616. for(int yd=0; yd<map->height; ++yd)
  617. {
  618. for(int ch=0; ch<k->second.towns.size(); ++ch)
  619. {
  620. int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
  621. int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
  622. if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
  623. k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
  624. }
  625. }
  626. }
  627. //init visiting heroes
  628. for(int l=0; l<k->second.heroes.size();l++)
  629. {
  630. for(int m=0; m<k->second.towns.size();m++)
  631. {
  632. int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
  633. if(vistile == k->second.heroes[l]->pos)
  634. {
  635. k->second.towns[m]->visitingHero = k->second.heroes[l];
  636. break;
  637. }
  638. }
  639. }
  640. }
  641. }
  642. void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2)
  643. {/*
  644. curB = new BattleInfo();
  645. std::vector<CStack*> & stacks = (curB->stacks);
  646. curB->army1=army1;
  647. curB->army2=army2;
  648. curB->hero1=dynamic_cast<CGHeroInstance*>(hero1);
  649. curB->hero2=dynamic_cast<CGHeroInstance*>(hero2);
  650. curB->side1=(hero1)?(hero1->tempOwner):(-1);
  651. curB->side2=(hero2)?(hero2->tempOwner):(-1);
  652. curB->round = -2;
  653. curB->stackActionPerformed = false;
  654. for(std::map<int,std::pair<CCreature*,int> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
  655. {
  656. stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true));
  657. stacks[stacks.size()-1]->ID = stacks.size()-1;
  658. }
  659. //initialization of positions
  660. switch(army1->slots.size()) //for attacker
  661. {
  662. case 0:
  663. break;
  664. case 1:
  665. stacks[0]->position = 86; //6
  666. break;
  667. case 2:
  668. stacks[0]->position = 35; //3
  669. stacks[1]->position = 137; //9
  670. break;
  671. case 3:
  672. stacks[0]->position = 35; //3
  673. stacks[1]->position = 86; //6
  674. stacks[2]->position = 137; //9
  675. break;
  676. case 4:
  677. stacks[0]->position = 1; //1
  678. stacks[1]->position = 69; //5
  679. stacks[2]->position = 103; //7
  680. stacks[3]->position = 171; //11
  681. break;
  682. case 5:
  683. stacks[0]->position = 1; //1
  684. stacks[1]->position = 35; //3
  685. stacks[2]->position = 86; //6
  686. stacks[3]->position = 137; //9
  687. stacks[4]->position = 171; //11
  688. break;
  689. case 6:
  690. stacks[0]->position = 1; //1
  691. stacks[1]->position = 35; //3
  692. stacks[2]->position = 69; //5
  693. stacks[3]->position = 103; //7
  694. stacks[4]->position = 137; //9
  695. stacks[5]->position = 171; //11
  696. break;
  697. case 7:
  698. stacks[0]->position = 1; //1
  699. stacks[1]->position = 35; //3
  700. stacks[2]->position = 69; //5
  701. stacks[3]->position = 86; //6
  702. stacks[4]->position = 103; //7
  703. stacks[5]->position = 137; //9
  704. stacks[6]->position = 171; //11
  705. break;
  706. default: //fault
  707. break;
  708. }
  709. for(std::map<int,std::pair<CCreature*,int> >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++)
  710. stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false));
  711. switch(army2->slots.size()) //for defender
  712. {
  713. case 0:
  714. break;
  715. case 1:
  716. stacks[0+army1->slots.size()]->position = 100; //6
  717. break;
  718. case 2:
  719. stacks[0+army1->slots.size()]->position = 49; //3
  720. stacks[1+army1->slots.size()]->position = 151; //9
  721. break;
  722. case 3:
  723. stacks[0+army1->slots.size()]->position = 49; //3
  724. stacks[1+army1->slots.size()]->position = 100; //6
  725. stacks[2+army1->slots.size()]->position = 151; //9
  726. break;
  727. case 4:
  728. stacks[0+army1->slots.size()]->position = 15; //1
  729. stacks[1+army1->slots.size()]->position = 83; //5
  730. stacks[2+army1->slots.size()]->position = 117; //7
  731. stacks[3+army1->slots.size()]->position = 185; //11
  732. break;
  733. case 5:
  734. stacks[0+army1->slots.size()]->position = 15; //1
  735. stacks[1+army1->slots.size()]->position = 49; //3
  736. stacks[2+army1->slots.size()]->position = 100; //6
  737. stacks[3+army1->slots.size()]->position = 151; //9
  738. stacks[4+army1->slots.size()]->position = 185; //11
  739. break;
  740. case 6:
  741. stacks[0+army1->slots.size()]->position = 15; //1
  742. stacks[1+army1->slots.size()]->position = 49; //3
  743. stacks[2+army1->slots.size()]->position = 83; //5
  744. stacks[3+army1->slots.size()]->position = 117; //7
  745. stacks[4+army1->slots.size()]->position = 151; //9
  746. stacks[5+army1->slots.size()]->position = 185; //11
  747. break;
  748. case 7:
  749. stacks[0+army1->slots.size()]->position = 15; //1
  750. stacks[1+army1->slots.size()]->position = 49; //3
  751. stacks[2+army1->slots.size()]->position = 83; //5
  752. stacks[3+army1->slots.size()]->position = 100; //6
  753. stacks[4+army1->slots.size()]->position = 117; //7
  754. stacks[5+army1->slots.size()]->position = 151; //9
  755. stacks[6+army1->slots.size()]->position = 185; //11
  756. break;
  757. default: //fault
  758. break;
  759. }
  760. for(int g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
  761. {
  762. if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
  763. {
  764. stacks[g]->position += 1;
  765. }
  766. else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
  767. {
  768. stacks[g]->position -= 1;
  769. }
  770. }
  771. std::stable_sort(stacks.begin(),stacks.end(),cmpst);
  772. //for start inform players about battle
  773. for(std::map<int, PlayerState>::iterator j=players.begin(); j!=players.end(); ++j)//->players.size(); ++j) //for testing
  774. {
  775. if (j->first > PLAYER_LIMIT)
  776. break;
  777. if(j->second.fogOfWarMap[tile.x][tile.y][tile.z])
  778. { //player should be notified
  779. tribool side = tribool::indeterminate_value;
  780. if(j->first == curB->side1) //player is attacker
  781. side = false;
  782. else if(j->first == curB->side2) //player is defender
  783. side = true;
  784. else
  785. continue; //no witnesses
  786. if(VLC->playerint[j->second.serial]->human)
  787. {
  788. ((CPlayerInterface*)( VLC->playerint[j->second.serial] ))->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side);
  789. }
  790. else
  791. {
  792. //VLC->playerint[j->second.serial]->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side);
  793. }
  794. }
  795. }
  796. curB->round++;
  797. if( (curB->hero1 && curB->hero1->getSecSkillLevel(19)>=0) || ( curB->hero2 && curB->hero2->getSecSkillLevel(19)>=0) )//someone has tactics
  798. {
  799. //TODO: wywolania dla rundy -1, ograniczenie pola ruchu, etc
  800. }
  801. curB->round++;
  802. //SDL_Thread * eventh = SDL_CreateThread(battleEventThread, NULL);
  803. while(true) //till the end of the battle ;]
  804. {
  805. bool battleEnd = false;
  806. //tell players about next round
  807. for(int v=0; v<VLC->playerint.size(); ++v)
  808. VLC->playerint[v]->battleNewRound(curB->round);
  809. //stack loop
  810. for(int i=0;i<stacks.size();i++)
  811. {
  812. curB->activeStack = i;
  813. curB->stackActionPerformed = false;
  814. if(stacks[i]->alive) //indicate posiibility of making action for this unit
  815. {
  816. unsigned char owner = (stacks[i]->owner)?(hero2 ? hero2->tempOwner : 255):(hero1->tempOwner);
  817. unsigned char serialOwner = -1;
  818. for(int g=0; g<VLC->playerint.size(); ++g)
  819. {
  820. if(VLC->playerint[g]->playerID == owner)
  821. {
  822. serialOwner = g;
  823. break;
  824. }
  825. }
  826. if(serialOwner==255) //neutral unit
  827. {
  828. }
  829. else if(VLC->playerint[serialOwner]->human)
  830. {
  831. BattleAction ba = ((CPlayerInterface*)VLC->playerint[serialOwner])->activeStack(stacks[i]->ID);
  832. switch(ba.actionType)
  833. {
  834. case 2: //walk
  835. {
  836. battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
  837. }
  838. case 3: //defend
  839. {
  840. break;
  841. }
  842. case 4: //retreat/flee
  843. {
  844. for(int v=0; v<VLC->playerint.size(); ++v) //tell about the end of this battle to interfaces
  845. VLC->playerint[v]->battleEnd(army1, army2, hero1, hero2, std::vector<int>(), 0, false);
  846. battleEnd = true;
  847. break;
  848. }
  849. case 6: //walk or attack
  850. {
  851. battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
  852. battleAttackCreatureStack(ba.stackNumber, ba.destinationTile);
  853. break;
  854. }
  855. }
  856. }
  857. else
  858. {
  859. //VLC->playerint[serialOwner]->activeStack(stacks[i]->ID);
  860. }
  861. }
  862. if(battleEnd)
  863. break;
  864. //sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy
  865. }
  866. if(battleEnd)
  867. break;
  868. curB->round++;
  869. SDL_Delay(50);
  870. }
  871. for(int i=0;i<stacks.size();i++)
  872. delete stacks[i];
  873. delete curB;
  874. curB = NULL;*/
  875. }
  876. bool CGameState::battleMoveCreatureStack(int ID, int dest)
  877. {/*
  878. //first checks
  879. if(curB->stackActionPerformed) //because unit cannot be moved more than once
  880. return false;
  881. unsigned char owner = -1; //owner moved of unit
  882. for(int g=0; g<curB->stacks.size(); ++g)
  883. {
  884. if(curB->stacks[g]->ID == ID)
  885. {
  886. owner = curB->stacks[g]->owner;
  887. break;
  888. }
  889. }
  890. bool stackAtEnd = false; //true if there is a stack at the end of the path (we should attack it)
  891. int numberOfStackAtEnd = -1;
  892. for(int g=0; g<curB->stacks.size(); ++g)
  893. {
  894. if(curB->stacks[g]->position == dest
  895. || (curB->stacks[g]->creature->isDoubleWide() && curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == dest)
  896. || (curB->stacks[g]->creature->isDoubleWide() && !curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == dest))
  897. {
  898. if(curB->stacks[g]->alive)
  899. {
  900. stackAtEnd = true;
  901. numberOfStackAtEnd = g;
  902. break;
  903. }
  904. }
  905. }
  906. //selecting moved stack
  907. CStack * curStack = NULL;
  908. for(int y=0; y<curB->stacks.size(); ++y)
  909. {
  910. if(curB->stacks[y]->ID == ID)
  911. {
  912. curStack = curB->stacks[y];
  913. break;
  914. }
  915. }
  916. if(!curStack)
  917. return false;
  918. //initing necessary tables
  919. bool accessibility[187]; //accesibility of hexes
  920. for(int k=0; k<187; k++)
  921. accessibility[k] = true;
  922. for(int g=0; g<curB->stacks.size(); ++g)
  923. {
  924. if(curB->stacks[g]->ID != ID && curB->stacks[g]->alive) //we don't want to lock enemy's positions and this units' position
  925. {
  926. accessibility[curB->stacks[g]->position] = false;
  927. if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
  928. {
  929. if(curB->stacks[g]->attackerOwned)
  930. accessibility[curB->stacks[g]->position-1] = false;
  931. else
  932. accessibility[curB->stacks[g]->position+1] = false;
  933. }
  934. }
  935. }
  936. accessibility[dest] = true;
  937. if(curStack->creature->isDoubleWide()) //locking positions unreachable by two-hex creatures
  938. {
  939. bool mac[187];
  940. for(int b=0; b<187; ++b)
  941. {
  942. //
  943. // && ( ? (curStack->attackerOwned ? accessibility[curNext-1] : accessibility[curNext+1]) : true )
  944. mac[b] = accessibility[b];
  945. if( accessibility[b] && !(curStack->attackerOwned ? accessibility[b-1] : accessibility[b+1]))
  946. {
  947. mac[b] = false;
  948. }
  949. }
  950. mac[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;
  951. for(int v=0; v<187; ++v)
  952. accessibility[v] = mac[v];
  953. //removing accessibility for side hexes
  954. for(int v=0; v<187; ++v)
  955. if(curStack->attackerOwned ? (v%17)==1 : (v%17)==15)
  956. accessibility[v] = false;
  957. }
  958. if(!accessibility[dest])
  959. return false;
  960. int predecessor[187]; //for getting the Path
  961. for(int b=0; b<187; ++b)
  962. predecessor[b] = -1;
  963. //bfsing
  964. int dists[187]; //calculated distances
  965. std::queue<int> hexq; //bfs queue
  966. hexq.push(curStack->position);
  967. for(int g=0; g<187; ++g)
  968. dists[g] = 100000000;
  969. dists[hexq.front()] = 0;
  970. int curNext = -1; //for bfs loop only (helper var)
  971. while(!hexq.empty()) //bfs loop
  972. {
  973. int curHex = hexq.front();
  974. hexq.pop();
  975. curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
  976. if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
  977. {
  978. hexq.push(curNext);
  979. dists[curNext] = dists[curHex] + 1;
  980. predecessor[curNext] = curHex;
  981. }
  982. curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
  983. if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
  984. {
  985. hexq.push(curNext);
  986. dists[curNext] = dists[curHex] + 1;
  987. predecessor[curNext] = curHex;
  988. }
  989. curNext = curHex - 1;
  990. if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
  991. {
  992. hexq.push(curNext);
  993. dists[curNext] = dists[curHex] + 1;
  994. predecessor[curNext] = curHex;
  995. }
  996. curNext = curHex + 1;
  997. if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
  998. {
  999. hexq.push(curNext);
  1000. dists[curNext] = dists[curHex] + 1;
  1001. predecessor[curNext] = curHex;
  1002. }
  1003. curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
  1004. if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
  1005. {
  1006. hexq.push(curNext);
  1007. dists[curNext] = dists[curHex] + 1;
  1008. predecessor[curNext] = curHex;
  1009. }
  1010. curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
  1011. if((curNext < 187) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
  1012. {
  1013. hexq.push(curNext);
  1014. dists[curNext] = dists[curHex] + 1;
  1015. predecessor[curNext] = curHex;
  1016. }
  1017. }
  1018. //following the Path
  1019. if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
  1020. return false;
  1021. std::vector<int> path;
  1022. int curElem = dest;
  1023. while(curElem!=curStack->position)
  1024. {
  1025. path.push_back(curElem);
  1026. curElem = predecessor[curElem];
  1027. }
  1028. for(int v=path.size()-1; v>=0; --v)
  1029. {
  1030. if(v!=0 || !stackAtEnd) //it's not the last step
  1031. {
  1032. LOCPLINT->battleStackMoved(ID, path[v], v==path.size()-1, v==0 || (stackAtEnd && v==1) );
  1033. curStack->position = path[v];
  1034. }
  1035. else //if it's last step and we should attack unit at the end
  1036. {
  1037. LOCPLINT->battleStackAttacking(ID, path[v]);
  1038. //counting dealt damage
  1039. int numberOfCres = curStack->amount; //number of attacking creatures
  1040. int attackDefenseBonus = curStack->creature->attack - curB->stacks[numberOfStackAtEnd]->creature->defence;
  1041. int damageBase = 0;
  1042. if(curStack->creature->damageMax == curStack->creature->damageMin) //constant damage
  1043. {
  1044. damageBase = curStack->creature->damageMin;
  1045. }
  1046. else
  1047. {
  1048. damageBase = ran()%(curStack->creature->damageMax - curStack->creature->damageMin) + curStack->creature->damageMin + 1;
  1049. }
  1050. float dmgBonusMultiplier = 1.0;
  1051. if(attackDefenseBonus < 0) //decreasing dmg
  1052. {
  1053. if(0.02f * (-attackDefenseBonus) > 0.3f)
  1054. {
  1055. dmgBonusMultiplier += -0.3f;
  1056. }
  1057. else
  1058. {
  1059. dmgBonusMultiplier += 0.02f * attackDefenseBonus;
  1060. }
  1061. }
  1062. else //increasing dmg
  1063. {
  1064. if(0.05f * attackDefenseBonus > 4.0f)
  1065. {
  1066. dmgBonusMultiplier += 4.0f;
  1067. }
  1068. else
  1069. {
  1070. dmgBonusMultiplier += 0.05f * attackDefenseBonus;
  1071. }
  1072. }
  1073. int finalDmg = (float)damageBase * (float)curStack->amount * dmgBonusMultiplier;
  1074. //applying damages
  1075. int cresKilled = finalDmg / curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
  1076. int damageFirst = finalDmg % curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
  1077. if( curB->stacks[numberOfStackAtEnd]->firstHPleft <= damageFirst )
  1078. {
  1079. curB->stacks[numberOfStackAtEnd]->amount -= 1;
  1080. curB->stacks[numberOfStackAtEnd]->firstHPleft += curB->stacks[numberOfStackAtEnd]->creature->hitPoints - damageFirst;
  1081. }
  1082. else
  1083. {
  1084. curB->stacks[numberOfStackAtEnd]->firstHPleft -= damageFirst;
  1085. }
  1086. int cresInstackBefore = curB->stacks[numberOfStackAtEnd]->amount;
  1087. curB->stacks[numberOfStackAtEnd]->amount -= cresKilled;
  1088. if(curB->stacks[numberOfStackAtEnd]->amount<=0) //stack killed
  1089. {
  1090. curB->stacks[numberOfStackAtEnd]->amount = 0;
  1091. LOCPLINT->battleStackKilled(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore) , ID);
  1092. curB->stacks[numberOfStackAtEnd]->alive = false;
  1093. }
  1094. else
  1095. {
  1096. LOCPLINT->battleStackIsAttacked(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore), ID);
  1097. }
  1098. //damage applied
  1099. }
  1100. }
  1101. curB->stackActionPerformed = true;
  1102. LOCPLINT->actionFinished(BattleAction());*/
  1103. return true;
  1104. }
  1105. bool CGameState::battleAttackCreatureStack(int ID, int dest)
  1106. {
  1107. int attackedCreaure = -1; //-1 - there is no attacked creature
  1108. for(int b=0; b<curB->stacks.size(); ++b) //TODO: make upgrades for two-hex cres.
  1109. {
  1110. if(curB->stacks[b]->position == dest)
  1111. {
  1112. attackedCreaure = curB->stacks[b]->ID;
  1113. break;
  1114. }
  1115. }
  1116. if(attackedCreaure == -1)
  1117. return false;
  1118. //LOCPLINT->cb->
  1119. return true;
  1120. }
  1121. std::vector<int> CGameState::battleGetRange(int ID)
  1122. {/*
  1123. int initialPlace=-1; //position of unit
  1124. int radius=-1; //range of unit
  1125. unsigned char owner = -1; //owner of unit
  1126. //selecting stack
  1127. CStack * curStack = NULL;
  1128. for(int y=0; y<curB->stacks.size(); ++y)
  1129. {
  1130. if(curB->stacks[y]->ID == ID)
  1131. {
  1132. curStack = curB->stacks[y];
  1133. break;
  1134. }
  1135. }
  1136. for(int g=0; g<curB->stacks.size(); ++g)
  1137. {
  1138. if(curB->stacks[g]->ID == ID)
  1139. {
  1140. initialPlace = curB->stacks[g]->position;
  1141. radius = curB->stacks[g]->creature->speed;
  1142. owner = curB->stacks[g]->owner;
  1143. break;
  1144. }
  1145. }
  1146. bool accessibility[187]; //accesibility of hexes
  1147. for(int k=0; k<187; k++)
  1148. accessibility[k] = true;
  1149. for(int g=0; g<curB->stacks.size(); ++g)
  1150. {
  1151. if(curB->stacks[g]->ID != ID && curB->stacks[g]->alive) //we don't want to lock current unit's position
  1152. {
  1153. accessibility[curB->stacks[g]->position] = false;
  1154. if(curB->stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
  1155. {
  1156. if(curB->stacks[g]->attackerOwned)
  1157. accessibility[curB->stacks[g]->position-1] = false;
  1158. else
  1159. accessibility[curB->stacks[g]->position+1] = false;
  1160. }
  1161. }
  1162. }
  1163. if(curStack->creature->isDoubleWide()) //locking positions unreachable by two-hex creatures
  1164. {
  1165. bool mac[187];
  1166. for(int b=0; b<187; ++b)
  1167. {
  1168. //
  1169. // && ( ? (curStack->attackerOwned ? accessibility[curNext-1] : accessibility[curNext+1]) : true )
  1170. mac[b] = accessibility[b];
  1171. if( accessibility[b] && !(curStack->attackerOwned ? accessibility[b-1] : accessibility[b+1]))
  1172. {
  1173. mac[b] = false;
  1174. }
  1175. }
  1176. mac[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;
  1177. for(int v=0; v<187; ++v)
  1178. accessibility[v] = mac[v];
  1179. //removing accessibility for side hexes
  1180. for(int v=0; v<187; ++v)
  1181. if(curStack->attackerOwned ? (v%17)==1 : (v%17)==15)
  1182. accessibility[v] = false;
  1183. }
  1184. int dists[187]; //calculated distances
  1185. std::queue<int> hexq; //bfs queue
  1186. hexq.push(initialPlace);
  1187. for(int g=0; g<187; ++g)
  1188. dists[g] = 100000000;
  1189. dists[initialPlace] = 0;
  1190. int curNext = -1; //for bfs loop only (helper var)
  1191. while(!hexq.empty()) //bfs loop
  1192. {
  1193. int curHex = hexq.front();
  1194. hexq.pop();
  1195. curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
  1196. if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
  1197. {
  1198. hexq.push(curNext);
  1199. dists[curNext] = dists[curHex] + 1;
  1200. }
  1201. curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
  1202. if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
  1203. {
  1204. hexq.push(curNext);
  1205. dists[curNext] = dists[curHex] + 1;
  1206. }
  1207. curNext = curHex - 1;
  1208. if((curNext > 0) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
  1209. {
  1210. hexq.push(curNext);
  1211. dists[curNext] = dists[curHex] + 1;
  1212. }
  1213. curNext = curHex + 1;
  1214. if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
  1215. {
  1216. hexq.push(curNext);
  1217. dists[curNext] = dists[curHex] + 1;
  1218. }
  1219. curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
  1220. if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
  1221. {
  1222. hexq.push(curNext);
  1223. dists[curNext] = dists[curHex] + 1;
  1224. }
  1225. curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
  1226. if((curNext < 187) && accessibility[curNext] && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
  1227. {
  1228. hexq.push(curNext);
  1229. dists[curNext] = dists[curHex] + 1;
  1230. }
  1231. }
  1232. std::vector<int> ret;
  1233. for(int i=0; i<187; ++i)
  1234. {
  1235. if(dists[i]<=radius)
  1236. {
  1237. ret.push_back(i);
  1238. }
  1239. }
  1240. std::vector<int> additionals;
  1241. //adding enemies' positions
  1242. for(int c=0; c<curB->stacks.size(); ++c)
  1243. {
  1244. if(curB->stacks[c]->alive && curB->stacks[c]->owner != owner)
  1245. {
  1246. for(int g=0; g<ret.size(); ++g)
  1247. {
  1248. if(CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position) != -1)
  1249. {
  1250. additionals.push_back(curB->stacks[c]->position);
  1251. }
  1252. if(curB->stacks[c]->creature->isDoubleWide() && curB->stacks[c]->attackerOwned && CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position-1) != -1)
  1253. {
  1254. additionals.push_back(curB->stacks[c]->position-1);
  1255. }
  1256. if(curB->stacks[c]->creature->isDoubleWide() && !curB->stacks[c]->attackerOwned && CBattleHex::mutualPosition(ret[g], curB->stacks[c]->position+1) != -1)
  1257. {
  1258. additionals.push_back(curB->stacks[c]->position+1);
  1259. }
  1260. }
  1261. }
  1262. }
  1263. for(int g=0; g<additionals.size(); ++g)
  1264. {
  1265. ret.push_back(additionals[g]);
  1266. }
  1267. std::sort(ret.begin(), ret.end());
  1268. std::vector<int>::iterator nend = std::unique(ret.begin(), ret.end());
  1269. std::vector<int> ret2;
  1270. for(std::vector<int>::iterator it = ret.begin(); it != nend; ++it)
  1271. {
  1272. ret2.push_back(*it);
  1273. }
  1274. return ret2;*/
  1275. return std::vector<int>();
  1276. }