CGameState.cpp 46 KB

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