CGameState.cpp 43 KB

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