CGameState.cpp 43 KB

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