CGameState.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489
  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. case 3009:
  589. {
  590. SpellCasted *sc = static_cast<SpellCasted*>(pack);
  591. CGHeroInstance *h = (sc->side) ? getHero(curB->hero2) : getHero(curB->hero1);
  592. if(h)
  593. h->mana -= VLC->spellh->spells[sc->id].costs[sc->skill];
  594. //TODO: counter
  595. break;
  596. }
  597. }
  598. }
  599. void CGameState::apply(IPack * pack)
  600. {
  601. while(!mx->try_lock())
  602. boost::this_thread::sleep(boost::posix_time::milliseconds(50)); //give other threads time to finish
  603. applyNL(pack);
  604. mx->unlock();
  605. }
  606. int CGameState::pickHero(int owner)
  607. {
  608. int h=-1;
  609. if(!map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero
  610. return h;
  611. int f = scenarioOps->getIthPlayersSettings(owner).castle;
  612. int i=0;
  613. do //try to find free hero of our faction
  614. {
  615. i++;
  616. h = scenarioOps->getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
  617. } while( map->getHero(h) && i<175);
  618. if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
  619. {
  620. tlog3 << "Warning: cannot find free hero - trying to get first available..."<<std::endl;
  621. for(int j=0; j<HEROES_PER_TYPE * 2 * F_NUMBER; j++)
  622. if(!map->getHero(j))
  623. h=j;
  624. }
  625. return h;
  626. }
  627. CGHeroInstance *CGameState::getHero(int objid)
  628. {
  629. if(objid<0 || objid>=map->objects.size())
  630. return NULL;
  631. return static_cast<CGHeroInstance *>(map->objects[objid]);
  632. }
  633. CGTownInstance *CGameState::getTown(int objid)
  634. {
  635. if(objid<0 || objid>=map->objects.size())
  636. return NULL;
  637. return static_cast<CGTownInstance *>(map->objects[objid]);
  638. }
  639. std::pair<int,int> CGameState::pickObject(CGObjectInstance *obj)
  640. {
  641. switch(obj->ID)
  642. {
  643. case 65: //random artifact
  644. return std::pair<int,int>(5,(ran()%136)+7); //tylko sensowny zakres - na poczatku sa katapulty itp, na koncu specjalne i blanki
  645. case 66: //random treasure artifact
  646. return std::pair<int,int>(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id);
  647. case 67: //random minor artifact
  648. return std::pair<int,int>(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id);
  649. case 68: //random major artifact
  650. return std::pair<int,int>(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id);
  651. case 69: //random relic artifact
  652. return std::pair<int,int>(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id);
  653. case 70: //random hero
  654. {
  655. return std::pair<int,int>(34,pickHero(obj->tempOwner));
  656. }
  657. case 71: //random monster
  658. {
  659. int r;
  660. do
  661. {
  662. r = ran()%197;
  663. } while (vstd::contains(VLC->creh->notUsedMonsters,r));
  664. return std::pair<int,int>(54,r);
  665. }
  666. case 72: //random monster lvl1
  667. return std::pair<int,int>(54,VLC->creh->levelCreatures[1][ran()%VLC->creh->levelCreatures[1].size()]->idNumber);
  668. case 73: //random monster lvl2
  669. return std::pair<int,int>(54,VLC->creh->levelCreatures[2][ran()%VLC->creh->levelCreatures[2].size()]->idNumber);
  670. case 74: //random monster lvl3
  671. return std::pair<int,int>(54,VLC->creh->levelCreatures[3][ran()%VLC->creh->levelCreatures[3].size()]->idNumber);
  672. case 75: //random monster lvl4
  673. return std::pair<int,int>(54,VLC->creh->levelCreatures[4][ran()%VLC->creh->levelCreatures[4].size()]->idNumber);
  674. case 76: //random resource
  675. return std::pair<int,int>(79,ran()%7); //now it's OH3 style, use %8 for mithril
  676. case 77: //random town
  677. {
  678. int align = ((CGTownInstance*)obj)->alignment,
  679. f;
  680. if(align>PLAYER_LIMIT-1)//same as owner / random
  681. {
  682. if(obj->tempOwner > PLAYER_LIMIT-1)
  683. f = -1; //random
  684. else
  685. f = scenarioOps->getIthPlayersSettings(obj->tempOwner).castle;
  686. }
  687. else
  688. {
  689. f = scenarioOps->getIthPlayersSettings(align).castle;
  690. }
  691. if(f<0) f = ran()%VLC->townh->towns.size();
  692. return std::pair<int,int>(98,f);
  693. }
  694. case 162: //random monster lvl5
  695. return std::pair<int,int>(54,VLC->creh->levelCreatures[5][ran()%VLC->creh->levelCreatures[5].size()]->idNumber);
  696. case 163: //random monster lvl6
  697. return std::pair<int,int>(54,VLC->creh->levelCreatures[6][ran()%VLC->creh->levelCreatures[6].size()]->idNumber);
  698. case 164: //random monster lvl7
  699. return std::pair<int,int>(54,VLC->creh->levelCreatures[7][ran()%VLC->creh->levelCreatures[7].size()]->idNumber);
  700. case 216: //random dwelling
  701. {
  702. int faction = ran()%F_NUMBER;
  703. CCreGen2ObjInfo* info =(CCreGen2ObjInfo*)obj->info;
  704. if (info->asCastle)
  705. {
  706. for(int i=0;i<map->objects.size();i++)
  707. {
  708. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  709. {
  710. randomizeObject(map->objects[i]); //we have to randomize the castle first
  711. faction = map->objects[i]->subID;
  712. break;
  713. }
  714. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  715. {
  716. faction = map->objects[i]->subID;
  717. break;
  718. }
  719. }
  720. }
  721. else
  722. {
  723. while((!(info->castles[0]&(1<<faction))))
  724. {
  725. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  726. break;
  727. faction = ran()%F_NUMBER;
  728. }
  729. }
  730. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  731. int cid = VLC->townh->towns[faction].basicCreatures[level];
  732. for(int i=0;i<VLC->objh->cregens.size();i++)
  733. if(VLC->objh->cregens[i]==cid)
  734. return std::pair<int,int>(17,i);
  735. tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
  736. return std::pair<int,int>(17,0);
  737. }
  738. case 217:
  739. {
  740. int faction = ran()%F_NUMBER;
  741. CCreGenObjInfo* info =(CCreGenObjInfo*)obj->info;
  742. if (info->asCastle)
  743. {
  744. for(int i=0;i<map->objects.size();i++)
  745. {
  746. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  747. {
  748. randomizeObject(map->objects[i]); //we have to randomize the castle first
  749. faction = map->objects[i]->subID;
  750. break;
  751. }
  752. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  753. {
  754. faction = map->objects[i]->subID;
  755. break;
  756. }
  757. }
  758. }
  759. else
  760. {
  761. while((!(info->castles[0]&(1<<faction))))
  762. {
  763. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  764. break;
  765. faction = ran()%F_NUMBER;
  766. }
  767. }
  768. int cid = VLC->townh->towns[faction].basicCreatures[obj->subID];
  769. for(int i=0;i<VLC->objh->cregens.size();i++)
  770. if(VLC->objh->cregens[i]==cid)
  771. return std::pair<int,int>(17,i);
  772. tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
  773. return std::pair<int,int>(17,0);
  774. }
  775. case 218:
  776. {
  777. CCreGen3ObjInfo* info =(CCreGen3ObjInfo*)obj->info;
  778. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  779. int cid = VLC->townh->towns[obj->subID].basicCreatures[level];
  780. for(int i=0;i<VLC->objh->cregens.size();i++)
  781. if(VLC->objh->cregens[i]==cid)
  782. return std::pair<int,int>(17,i);
  783. tlog3 << "Cannot find a dwelling for creature "<<cid <<std::endl;
  784. return std::pair<int,int>(17,0);
  785. }
  786. }
  787. return std::pair<int,int>(-1,-1);
  788. }
  789. void CGameState::randomizeObject(CGObjectInstance *cur)
  790. {
  791. std::pair<int,int> ran = pickObject(cur);
  792. if(ran.first<0 || ran.second<0) //this is not a random object, or we couldn't find anything
  793. {
  794. if(cur->ID==98) //town - set def
  795. {
  796. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  797. if(t->hasCapitol())
  798. t->defInfo = capitols[t->subID];
  799. else if(t->hasFort())
  800. t->defInfo = forts[t->subID];
  801. else
  802. t->defInfo = villages[t->subID];
  803. }
  804. return;
  805. }
  806. else if(ran.first==34)//special code for hero
  807. {
  808. CGHeroInstance *h = dynamic_cast<CGHeroInstance *>(cur);
  809. if(!h) {tlog2<<"Wrong random hero at "<<cur->pos<<std::endl; return;}
  810. cur->ID = ran.first;
  811. h->portrait = cur->subID = ran.second;
  812. h->type = VLC->heroh->heroes[ran.second];
  813. map->heroes.push_back(h);
  814. return; //TODO: maybe we should do something with definfo?
  815. }
  816. else if(ran.first==98)//special code for town
  817. {
  818. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  819. if(!t) {tlog2<<"Wrong random town at "<<cur->pos<<std::endl; return;}
  820. cur->ID = ran.first;
  821. cur->subID = ran.second;
  822. t->town = &VLC->townh->towns[ran.second];
  823. if(t->hasCapitol())
  824. t->defInfo = capitols[t->subID];
  825. else if(t->hasFort())
  826. t->defInfo = forts[t->subID];
  827. else
  828. t->defInfo = villages[t->subID];
  829. map->towns.push_back(t);
  830. return;
  831. }
  832. //we have to replace normal random object
  833. cur->ID = ran.first;
  834. cur->subID = ran.second;
  835. map->defs.insert(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
  836. if(!cur->defInfo)
  837. {
  838. tlog1<<"*BIG* WARNING: Missing def declaration for "<<cur->ID<<" "<<cur->subID<<std::endl;
  839. return;
  840. }
  841. }
  842. int CGameState::getDate(int mode) const
  843. {
  844. int temp;
  845. switch (mode)
  846. {
  847. case 0:
  848. return day;
  849. break;
  850. case 1:
  851. temp = (day)%7;
  852. if (temp)
  853. return temp;
  854. else return 7;
  855. break;
  856. case 2:
  857. temp = ((day-1)/7)+1;
  858. if (!(temp%4))
  859. return 4;
  860. else
  861. return (temp%4);
  862. break;
  863. case 3:
  864. return ((day-1)/28)+1;
  865. break;
  866. }
  867. return 0;
  868. }
  869. CGameState::CGameState()
  870. {
  871. mx = new boost::shared_mutex();
  872. }
  873. CGameState::~CGameState()
  874. {
  875. delete mx;
  876. }
  877. void CGameState::init(StartInfo * si, Mapa * map, int Seed)
  878. {
  879. day = 0;
  880. seed = Seed;
  881. ran.seed((boost::int32_t)seed);
  882. scenarioOps = si;
  883. this->map = map;
  884. for(int i=0;i<F_NUMBER;i++)
  885. {
  886. villages[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  887. forts[i] = VLC->dobjinfo->castles[i];
  888. capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  889. }
  890. //picking random factions for players
  891. for(int i=0;i<scenarioOps->playerInfos.size();i++)
  892. {
  893. if(scenarioOps->playerInfos[i].castle==-1)
  894. {
  895. int f;
  896. do
  897. {
  898. f = ran()%F_NUMBER;
  899. }while(!(map->players[scenarioOps->playerInfos[i].color].allowedFactions & 1<<f));
  900. scenarioOps->playerInfos[i].castle = f;
  901. }
  902. }
  903. //randomizing objects
  904. for(int no=0; no<map->objects.size(); ++no)
  905. {
  906. randomizeObject(map->objects[no]);
  907. if(map->objects[no]->ID==26)
  908. {
  909. map->objects[no]->defInfo->handler=NULL;
  910. map->removeBlockVisTiles(map->objects[no]);
  911. map->objects[no]->defInfo->blockMap[5] = 255;
  912. map->addBlockVisTiles(map->objects[no]);
  913. }
  914. map->objects[no]->hoverName = VLC->objh->names[map->objects[no]->ID];
  915. }
  916. //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
  917. /*********give starting hero****************************************/
  918. for(int i=0;i<PLAYER_LIMIT;i++)
  919. {
  920. if((map->players[i].generateHeroAtMainTown && map->players[i].hasMainTown) || (map->players[i].hasMainTown && map->version==RoE))
  921. {
  922. int3 hpos = map->players[i].posOfMainTown;
  923. hpos.x+=1;// hpos.y+=1;
  924. int j;
  925. for(j=0; j<scenarioOps->playerInfos.size(); j++)
  926. if(scenarioOps->playerInfos[j].color == i)
  927. break;
  928. if(j == scenarioOps->playerInfos.size())
  929. continue;
  930. int h=pickHero(i);
  931. CGHeroInstance * nnn = static_cast<CGHeroInstance*>(createObject(34,h,hpos,i));
  932. nnn->id = map->objects.size();
  933. hpos = map->players[i].posOfMainTown;hpos.x+=2;
  934. for(int o=0;o<map->towns.size();o++) //find main town
  935. {
  936. if(map->towns[o]->pos == hpos)
  937. {
  938. map->towns[o]->visitingHero = nnn;
  939. nnn->visitedTown = map->towns[o];
  940. nnn->inTownGarrison = false;
  941. break;
  942. }
  943. }
  944. map->heroes.push_back(nnn);
  945. map->objects.push_back(nnn);
  946. map->addBlockVisTiles(nnn);
  947. }
  948. }
  949. /*********creating players entries in gs****************************************/
  950. for (int i=0; i<scenarioOps->playerInfos.size();i++)
  951. {
  952. std::pair<int,PlayerState> ins(scenarioOps->playerInfos[i].color,PlayerState());
  953. ins.second.color=ins.first;
  954. ins.second.serial=i;
  955. players.insert(ins);
  956. }
  957. /******************RESOURCES****************************************************/
  958. //TODO: computer player should receive other amount of resource than computer (depending on difficulty)
  959. std::vector<int> startres;
  960. std::ifstream tis("config/startres.txt");
  961. int k;
  962. for (int j=0;j<scenarioOps->difficulty;j++)
  963. {
  964. tis >> k;
  965. for (int z=0;z<RESOURCE_QUANTITY;z++)
  966. tis>>k;
  967. }
  968. tis >> k;
  969. for (int i=0;i<RESOURCE_QUANTITY;i++)
  970. {
  971. tis >> k;
  972. startres.push_back(k);
  973. }
  974. tis.close();
  975. tis.clear();
  976. for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
  977. {
  978. (*i).second.resources.resize(RESOURCE_QUANTITY);
  979. for (int x=0;x<RESOURCE_QUANTITY;x++)
  980. (*i).second.resources[x] = startres[x];
  981. }
  982. tis.open("config/resources.txt");
  983. tis >> k;
  984. int pom;
  985. for(int i=0;i<k;i++)
  986. {
  987. tis >> pom;
  988. resVals.push_back(pom);
  989. }
  990. /*************************HEROES************************************************/
  991. for (int i=0; i<map->heroes.size();i++) //heroes instances
  992. {
  993. if (map->heroes[i]->getOwner()<0)
  994. continue;
  995. CGHeroInstance * vhi = (map->heroes[i]);
  996. if(!vhi->type)
  997. vhi->type = VLC->heroh->heroes[vhi->subID];
  998. if (vhi->level<1)
  999. {
  1000. vhi->exp=40+ran()%50;
  1001. vhi->level = 1;
  1002. }
  1003. if(vhi->secSkills.size() == 1 && vhi->secSkills[0] == std::make_pair(-1, -1)) //set secondary skills to default
  1004. {
  1005. vhi->secSkills = vhi->type->secSkillsInit;
  1006. }
  1007. if ((!vhi->primSkills.size()) || (vhi->primSkills[0]<0))
  1008. {
  1009. if (vhi->primSkills.size()<PRIMARY_SKILLS)
  1010. vhi->primSkills.resize(PRIMARY_SKILLS);
  1011. vhi->primSkills[0] = vhi->type->heroClass->initialAttack;
  1012. vhi->primSkills[1] = vhi->type->heroClass->initialDefence;
  1013. vhi->primSkills[2] = vhi->type->heroClass->initialPower;
  1014. vhi->primSkills[3] = vhi->type->heroClass->initialKnowledge;
  1015. }
  1016. vhi->mana = vhi->getPrimSkillLevel(3)*10;
  1017. if (!vhi->name.length())
  1018. {
  1019. vhi->name = vhi->type->name;
  1020. }
  1021. if (!vhi->biography.length())
  1022. {
  1023. vhi->biography = vhi->type->biography;
  1024. }
  1025. if (vhi->portrait < 0)
  1026. vhi->portrait = vhi->type->ID;
  1027. vhi->artifWorn[16] = 3;
  1028. if(vhi->type->heroType % 2 == 1) //it's a magical hero
  1029. {
  1030. vhi->artifWorn[17] = 0; //give him spellbook
  1031. }
  1032. //initial army
  1033. if (!vhi->army.slots.size()) //standard army
  1034. {
  1035. int pom, pom2=0;
  1036. for(int x=0;x<3;x++)
  1037. {
  1038. pom = (VLC->creh->nameToID[vhi->type->refTypeStack[x]]);
  1039. if(pom>=145 && pom<=149) //war machine
  1040. {
  1041. pom2++;
  1042. switch (pom)
  1043. {
  1044. case 145: //catapult
  1045. vhi->artifWorn[16] = 3;
  1046. break;
  1047. default:
  1048. vhi->artifWorn[9+CArtHandler::convertMachineID(pom,true)] = CArtHandler::convertMachineID(pom,true);
  1049. break;
  1050. }
  1051. continue;
  1052. }
  1053. vhi->army.slots[x-pom2].first = pom;
  1054. if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0)
  1055. vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
  1056. else
  1057. vhi->army.slots[x-pom2].second = +vhi->type->lowStack[x];
  1058. vhi->army.formation = false;
  1059. }
  1060. }
  1061. players[vhi->getOwner()].heroes.push_back(vhi);
  1062. }
  1063. /*************************FOG**OF**WAR******************************************/
  1064. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  1065. {
  1066. k->second.fogOfWarMap.resize(map->width);
  1067. for(int g=0; g<map->width; ++g)
  1068. k->second.fogOfWarMap[g].resize(map->height);
  1069. for(int g=-0; g<map->width; ++g)
  1070. for(int h=0; h<map->height; ++h)
  1071. k->second.fogOfWarMap[g][h].resize(map->twoLevel+1, 0);
  1072. for(int g=0; g<map->width; ++g)
  1073. for(int h=0; h<map->height; ++h)
  1074. for(int v=0; v<map->twoLevel+1; ++v)
  1075. k->second.fogOfWarMap[g][h][v] = 0;
  1076. for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
  1077. {
  1078. for(int yd=0; yd<map->height; ++yd)
  1079. {
  1080. for(int ch=0; ch<k->second.heroes.size(); ++ch)
  1081. {
  1082. int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
  1083. int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
  1084. if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
  1085. k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
  1086. }
  1087. }
  1088. }
  1089. //starting bonus
  1090. if(si->playerInfos[k->second.serial].bonus==brandom)
  1091. si->playerInfos[k->second.serial].bonus = ran()%3;
  1092. switch(si->playerInfos[k->second.serial].bonus)
  1093. {
  1094. case bgold:
  1095. k->second.resources[6] += 500 + (ran()%6)*100;
  1096. break;
  1097. case bresource:
  1098. {
  1099. int res = VLC->townh->towns[si->playerInfos[k->second.serial].castle].primaryRes;
  1100. if(res == 127)
  1101. {
  1102. k->second.resources[0] += 5 + ran()%6;
  1103. k->second.resources[2] += 5 + ran()%6;
  1104. }
  1105. else
  1106. {
  1107. k->second.resources[res] += 3 + ran()%4;
  1108. }
  1109. break;
  1110. }
  1111. case bartifact:
  1112. {
  1113. if(!k->second.heroes.size())
  1114. {
  1115. tlog5 << "Cannot give starting artifact - no heroes!" << std::endl;
  1116. break;
  1117. }
  1118. CArtifact *toGive;
  1119. do
  1120. {
  1121. toGive = VLC->arth->treasures[ran() % VLC->arth->treasures.size()];
  1122. } while (!map->allowedArtifact[toGive->id]);
  1123. CGHeroInstance *hero = k->second.heroes[0];
  1124. std::vector<ui16>::iterator slot = vstd::findFirstNot(hero->artifWorn,toGive->possibleSlots);
  1125. if(slot!=toGive->possibleSlots.end())
  1126. hero->artifWorn[*slot] = toGive->id;
  1127. else
  1128. hero->artifacts.push_back(toGive->id);
  1129. }
  1130. }
  1131. }
  1132. /****************************TOWNS************************************************/
  1133. for (int i=0;i<map->towns.size();i++)
  1134. {
  1135. CGTownInstance * vti =(map->towns[i]);
  1136. if(!vti->town)
  1137. vti->town = &VLC->townh->towns[vti->subID];
  1138. if (vti->name.length()==0) // if town hasn't name we draw it
  1139. vti->name=vti->town->names[ran()%vti->town->names.size()];
  1140. //init buildings
  1141. if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
  1142. {
  1143. vti->builtBuildings.erase(-50);
  1144. vti->builtBuildings.insert(10);
  1145. vti->builtBuildings.insert(5);
  1146. vti->builtBuildings.insert(30);
  1147. if(ran()%2)
  1148. vti->builtBuildings.insert(31);
  1149. }
  1150. //init spells
  1151. vti->spells.resize(SPELL_LEVELS);
  1152. CSpell *s;
  1153. for(int z=0; z<vti->obligatorySpells.size();z++)
  1154. {
  1155. s = &VLC->spellh->spells[vti->obligatorySpells[z]];
  1156. vti->spells[s->level-1].push_back(s->id);
  1157. vti->possibleSpells -= s->id;
  1158. }
  1159. while(vti->possibleSpells.size())
  1160. {
  1161. ui32 total=0, sel=-1;
  1162. for(int ps=0;ps<vti->possibleSpells.size();ps++)
  1163. total += VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
  1164. int r = (total)? ran()%total : -1;
  1165. for(int ps=0; ps<vti->possibleSpells.size();ps++)
  1166. {
  1167. r -= VLC->spellh->spells[vti->possibleSpells[ps]].probabilities[vti->subID];
  1168. if(r<0)
  1169. {
  1170. sel = ps;
  1171. break;
  1172. }
  1173. }
  1174. if(sel<0)
  1175. sel=0;
  1176. CSpell *s = &VLC->spellh->spells[vti->possibleSpells[sel]];
  1177. vti->spells[s->level-1].push_back(s->id);
  1178. vti->possibleSpells -= s->id;
  1179. }
  1180. //init garrisons
  1181. for (std::map<si32,std::pair<ui32,si32> >::iterator j=vti->army.slots.begin(); j!=vti->army.slots.end();j++)
  1182. {
  1183. if(j->second.first > 196 && j->second.first < 211)
  1184. {
  1185. if(j->second.first%2)
  1186. j->second.first = vti->town->basicCreatures[ (j->second.first-197) / 2 ];
  1187. else
  1188. j->second.first = vti->town->upgradedCreatures[ (j->second.first-197) / 2 ];
  1189. }
  1190. }
  1191. players[vti->getOwner()].towns.push_back(vti);
  1192. }
  1193. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  1194. {
  1195. if(k->first==-1 || k->first==255)
  1196. continue;
  1197. for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
  1198. {
  1199. for(int yd=0; yd<map->height; ++yd)
  1200. {
  1201. for(int ch=0; ch<k->second.towns.size(); ++ch)
  1202. {
  1203. int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
  1204. int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
  1205. if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
  1206. k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
  1207. }
  1208. }
  1209. }
  1210. //init visiting and garrisoned heroes
  1211. for(int l=0; l<k->second.heroes.size();l++)
  1212. {
  1213. for(int m=0; m<k->second.towns.size();m++)
  1214. {
  1215. int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
  1216. if(vistile == k->second.heroes[l]->pos || k->second.heroes[l]->pos==k->second.towns[m]->pos)
  1217. {
  1218. k->second.towns[m]->visitingHero = k->second.heroes[l];
  1219. k->second.heroes[l]->visitedTown = k->second.towns[m];
  1220. k->second.heroes[l]->inTownGarrison = false;
  1221. if(k->second.heroes[l]->pos==k->second.towns[m]->pos)
  1222. k->second.heroes[l]->pos.x -= 1;
  1223. break;
  1224. }
  1225. //else if(k->second.heroes[l]->pos == k->second.towns[m]->pos)
  1226. //{
  1227. // k->second.towns[m]->garrisonHero = k->second.heroes[l];
  1228. // k->second.towns[m]->army = k->second.heroes[l]->army;
  1229. // k->second.heroes[l]->visitedTown = k->second.towns[m];
  1230. // k->second.heroes[l]->inTownGarrison = true;
  1231. // k->second.heroes[l]->pos.x -= 1;
  1232. // goto mainplheloop;
  1233. //}
  1234. }
  1235. }
  1236. }
  1237. }
  1238. bool CGameState::battleShootCreatureStack(int ID, int dest)
  1239. {
  1240. return true;
  1241. }
  1242. int CGameState::battleGetStack(int pos)
  1243. {
  1244. if(!curB)
  1245. return -1;
  1246. for(int g=0; g<curB->stacks.size(); ++g)
  1247. {
  1248. if(curB->stacks[g]->position == pos ||
  1249. ( curB->stacks[g]->creature->isDoubleWide() &&
  1250. ( (curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos) ||
  1251. (!curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == pos)
  1252. )
  1253. )
  1254. )
  1255. return curB->stacks[g]->ID;
  1256. }
  1257. return -1;
  1258. }
  1259. UpgradeInfo CGameState::getUpgradeInfo(CArmedInstance *obj, int stackPos)
  1260. {
  1261. UpgradeInfo ret;
  1262. CCreature *base = &VLC->creh->creatures[obj->army.slots[stackPos].first];
  1263. if((obj->ID == 98) || ((obj->ID == 34) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
  1264. {
  1265. CGTownInstance * t;
  1266. if(obj->ID == 98)
  1267. t = static_cast<CGTownInstance *>(const_cast<CArmedInstance *>(obj));
  1268. else
  1269. t = static_cast<const CGHeroInstance*>(obj)->visitedTown;
  1270. for(std::set<si32>::iterator i=t->builtBuildings.begin(); i!=t->builtBuildings.end(); i++)
  1271. {
  1272. if( (*i) >= 37 && (*i) < 44 ) //upgraded creature dwelling
  1273. {
  1274. int nid = t->town->upgradedCreatures[(*i)-37]; //upgrade offered by that building
  1275. if(base->upgrades.find(nid) != base->upgrades.end()) //possible upgrade
  1276. {
  1277. ret.newID.push_back(nid);
  1278. ret.cost.push_back(std::set<std::pair<int,int> >());
  1279. for(int j=0;j<RESOURCE_QUANTITY;j++)
  1280. {
  1281. int dif = VLC->creh->creatures[nid].cost[j] - base->cost[j];
  1282. if(dif)
  1283. ret.cost[ret.cost.size()-1].insert(std::make_pair(j,dif));
  1284. }
  1285. }
  1286. }
  1287. }//end for
  1288. }
  1289. //TODO: check if hero ability makes some upgrades possible
  1290. if(ret.newID.size())
  1291. ret.oldID = base->idNumber;
  1292. return ret;
  1293. }
  1294. float CGameState::getMarketEfficiency( int player, int mode/*=0*/ )
  1295. {
  1296. boost::shared_lock<boost::shared_mutex> lock(*mx);
  1297. if(mode) return -1; //todo - support other modes
  1298. int mcount = 0;
  1299. for(int i=0;i<players[player].towns.size();i++)
  1300. if(vstd::contains(players[player].towns[i]->builtBuildings,14))
  1301. mcount++;
  1302. float ret = std::min(((float)mcount+1.0f)/20.0f,0.5f);
  1303. return ret;
  1304. }
  1305. std::set<int3> CGameState::tilesToReveal(int3 pos, int radious, int player)
  1306. {
  1307. std::set<int3> ret;
  1308. int xbeg = pos.x - radious - 2;
  1309. if(xbeg < 0)
  1310. xbeg = 0;
  1311. int xend = pos.x + radious + 2;
  1312. if(xend >= map->width)
  1313. xend = map->width;
  1314. int ybeg = pos.y - radious - 2;
  1315. if(ybeg < 0)
  1316. ybeg = 0;
  1317. int yend = pos.y + radious + 2;
  1318. if(yend >= map->height)
  1319. yend = map->height;
  1320. for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes
  1321. {
  1322. for(int yd=ybeg; yd<yend; ++yd)
  1323. {
  1324. int deltaX = (pos.x-xd)*(pos.x-xd);
  1325. int deltaY = (pos.y-yd)*(pos.y-yd);
  1326. if(deltaX+deltaY<radious*radious)
  1327. {
  1328. if(player<0 || players[player].fogOfWarMap[xd][yd][pos.z]==0)
  1329. {
  1330. ret.insert(int3(xd,yd,pos.z));
  1331. }
  1332. }
  1333. }
  1334. }
  1335. return ret;
  1336. }
  1337. int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
  1338. {
  1339. int attackDefenseBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0) - (defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0));
  1340. int damageBase = 0;
  1341. if(attacker->creature->damageMax == attacker->creature->damageMin) //constant damage
  1342. {
  1343. damageBase = attacker->creature->damageMin;
  1344. }
  1345. else
  1346. {
  1347. damageBase = rand()%(attacker->creature->damageMax - attacker->creature->damageMin) + attacker->creature->damageMin + 1;
  1348. }
  1349. float dmgBonusMultiplier = 1.0f;
  1350. if(attackDefenseBonus < 0) //decreasing dmg
  1351. {
  1352. if(0.02f * (-attackDefenseBonus) > 0.3f)
  1353. {
  1354. dmgBonusMultiplier += -0.3f;
  1355. }
  1356. else
  1357. {
  1358. dmgBonusMultiplier += 0.02f * attackDefenseBonus;
  1359. }
  1360. }
  1361. else //increasing dmg
  1362. {
  1363. if(0.05f * attackDefenseBonus > 4.0f)
  1364. {
  1365. dmgBonusMultiplier += 4.0f;
  1366. }
  1367. else
  1368. {
  1369. dmgBonusMultiplier += 0.05f * attackDefenseBonus;
  1370. }
  1371. }
  1372. //handling secondary abilities
  1373. if(attackerHero)
  1374. {
  1375. if(shooting)
  1376. {
  1377. switch(attackerHero->getSecSkillLevel(1)) //archery
  1378. {
  1379. case 1: //basic
  1380. dmgBonusMultiplier *= 1.1f;
  1381. break;
  1382. case 2: //advanced
  1383. dmgBonusMultiplier *= 1.25f;
  1384. break;
  1385. case 3: //expert
  1386. dmgBonusMultiplier *= 1.5f;
  1387. break;
  1388. }
  1389. }
  1390. else
  1391. {
  1392. switch(attackerHero->getSecSkillLevel(22)) //offence
  1393. {
  1394. case 1: //basic
  1395. dmgBonusMultiplier *= 1.1f;
  1396. break;
  1397. case 2: //advanced
  1398. dmgBonusMultiplier *= 1.2f;
  1399. break;
  1400. case 3: //expert
  1401. dmgBonusMultiplier *= 1.3f;
  1402. break;
  1403. }
  1404. }
  1405. }
  1406. if(defendingHero)
  1407. {
  1408. switch(defendingHero->getSecSkillLevel(23)) //armourer
  1409. {
  1410. case 1: //basic
  1411. dmgBonusMultiplier *= 0.95f;
  1412. break;
  1413. case 2: //advanced
  1414. dmgBonusMultiplier *= 0.9f;
  1415. break;
  1416. case 3: //expert
  1417. dmgBonusMultiplier *= 0.85f;
  1418. break;
  1419. }
  1420. }
  1421. return (float)damageBase * (float)attacker->amount * dmgBonusMultiplier;
  1422. }
  1423. void BattleInfo::calculateCasualties( std::set<std::pair<ui32,si32> > *casualties )
  1424. {
  1425. for(int i=0; i<stacks.size();i++)//setting casualties
  1426. {
  1427. if(!stacks[i]->alive())
  1428. {
  1429. casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount));
  1430. }
  1431. else if(stacks[i]->amount != stacks[i]->baseAmount)
  1432. {
  1433. casualties[!stacks[i]->attackerOwned].insert(std::pair<ui32,si32>(stacks[i]->creature->idNumber,stacks[i]->baseAmount - stacks[i]->amount));
  1434. }
  1435. }
  1436. }