CGameState.cpp 45 KB

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