CGameState.cpp 42 KB

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