CGameState.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. #define VCMI_DLL
  2. #include <algorithm>
  3. #include <queue>
  4. #include <fstream>
  5. #include "CGameState.h"
  6. #include <boost/random/linear_congruential.hpp>
  7. #include "hch/CDefObjInfoHandler.h"
  8. #include "hch/CArtHandler.h"
  9. #include "hch/CTownHandler.h"
  10. #include "hch/CHeroHandler.h"
  11. #include "hch/CObjectHandler.h"
  12. #include "hch/CCreatureHandler.h"
  13. #include "lib/VCMI_Lib.h"
  14. #include "map.h"
  15. #include "StartInfo.h"
  16. #include "lib/NetPacks.h"
  17. #include <boost/foreach.hpp>
  18. #include <boost/thread.hpp>
  19. #include <boost/thread/shared_mutex.hpp>
  20. boost::rand48 ran;
  21. CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
  22. {
  23. CGObjectInstance * nobj;
  24. switch(id)
  25. {
  26. case 34: //hero
  27. {
  28. CGHeroInstance * nobj;
  29. nobj = new CGHeroInstance();
  30. nobj->pos = pos;
  31. nobj->tempOwner = owner;
  32. nobj->defInfo = new CGDefInfo();
  33. nobj->defInfo->id = 34;
  34. nobj->defInfo->subid = subid;
  35. nobj->defInfo->printPriority = 0;
  36. nobj->type = VLC->heroh->heroes[subid];
  37. for(int i=0;i<6;i++)
  38. {
  39. nobj->defInfo->blockMap[i]=255;
  40. nobj->defInfo->visitMap[i]=0;
  41. }
  42. nobj->ID = id;
  43. nobj->subID = subid;
  44. nobj->defInfo->handler=NULL;
  45. nobj->defInfo->blockMap[5] = 253;
  46. nobj->defInfo->visitMap[5] = 2;
  47. nobj->artifacts.resize(20);
  48. nobj->artifWorn[16] = 3;
  49. nobj->portrait = subid;
  50. nobj->primSkills.resize(4);
  51. nobj->primSkills[0] = nobj->type->heroClass->initialAttack;
  52. nobj->primSkills[1] = nobj->type->heroClass->initialDefence;
  53. nobj->primSkills[2] = nobj->type->heroClass->initialPower;
  54. nobj->primSkills[3] = nobj->type->heroClass->initialKnowledge;
  55. nobj->mana = 10 * nobj->primSkills[3];
  56. return nobj;
  57. }
  58. case 98: //town
  59. nobj = new CGTownInstance;
  60. break;
  61. default: //rest of objects
  62. nobj = new CGObjectInstance;
  63. nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
  64. break;
  65. }
  66. nobj->ID = id;
  67. nobj->subID = subid;
  68. if(!nobj->defInfo)
  69. std::cout <<"No def declaration for " <<id <<" "<<subid<<std::endl;
  70. nobj->pos = pos;
  71. //nobj->state = NULL;//new CLuaObjectScript();
  72. nobj->tempOwner = owner;
  73. nobj->info = NULL;
  74. nobj->defInfo->id = id;
  75. nobj->defInfo->subid = subid;
  76. //assigning defhandler
  77. if(nobj->ID==34 || nobj->ID==98)
  78. return nobj;
  79. nobj->defInfo = VLC->dobjinfo->gobjs[id][subid];
  80. //if(!nobj->defInfo->handler)
  81. //{
  82. // nobj->defInfo->handler = CDefHandler::giveDef(nobj->defInfo->name);
  83. // nobj->defInfo->width = nobj->defInfo->handler->ourImages[0].bitmap->w/32;
  84. // nobj->defInfo->height = nobj->defInfo->handler->ourImages[0].bitmap->h/32;
  85. //}
  86. return nobj;
  87. }
  88. CStack * BattleInfo::getStack(int stackID)
  89. {
  90. for(int g=0; g<stacks.size(); ++g)
  91. {
  92. if(stacks[g]->ID == stackID)
  93. return stacks[g];
  94. }
  95. return NULL;
  96. }
  97. CStack * BattleInfo::getStackT(int tileID)
  98. {
  99. for(int g=0; g<stacks.size(); ++g)
  100. {
  101. if(stacks[g]->position == tileID
  102. || (stacks[g]->creature->isDoubleWide() && stacks[g]->attackerOwned && stacks[g]->position-1 == tileID)
  103. || (stacks[g]->creature->isDoubleWide() && !stacks[g]->attackerOwned && stacks[g]->position+1 == tileID))
  104. {
  105. if(stacks[g]->alive)
  106. {
  107. return stacks[g];
  108. }
  109. }
  110. }
  111. return NULL;
  112. }
  113. void BattleInfo::getAccessibilityMap(bool *accessibility, int stackToOmmit)
  114. {
  115. memset(accessibility,1,187); //initialize array with trues
  116. for(int g=0; g<stacks.size(); ++g)
  117. {
  118. if(!stacks[g]->alive || stacks[g]->ID==stackToOmmit) //we don't want to lock position of this stack
  119. continue;
  120. accessibility[stacks[g]->position] = false;
  121. if(stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
  122. {
  123. if(stacks[g]->attackerOwned)
  124. accessibility[stacks[g]->position-1] = false;
  125. else
  126. accessibility[stacks[g]->position+1] = false;
  127. }
  128. }
  129. //TODO: obstacles
  130. }
  131. void BattleInfo::getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide, int stackToOmmit) //send pointer to at least 187 allocated bytes
  132. {
  133. bool mac[187];
  134. getAccessibilityMap(mac,stackToOmmit);
  135. memcpy(accessibility,mac,187);
  136. for(int b=0; b<187; ++b)
  137. {
  138. if( mac[b] && !(atackerSide ? mac[b-1] : mac[b+1]))
  139. {
  140. accessibility[b] = false;
  141. }
  142. }
  143. //removing accessibility for side hexes
  144. for(int v=0; v<187; ++v)
  145. if(atackerSide ? (v%17)==1 : (v%17)==15)
  146. accessibility[v] = false;
  147. }
  148. void BattleInfo::makeBFS(int start, bool*accessibility, int *predecessor, int *dists) //both pointers must point to the at least 187-elements int arrays
  149. {
  150. //inits
  151. for(int b=0; b<187; ++b)
  152. predecessor[b] = -1;
  153. for(int g=0; g<187; ++g)
  154. dists[g] = 100000000;
  155. std::queue<int> hexq; //bfs queue
  156. hexq.push(start);
  157. dists[hexq.front()] = 0;
  158. int curNext = -1; //for bfs loop only (helper var)
  159. while(!hexq.empty()) //bfs loop
  160. {
  161. int curHex = hexq.front();
  162. std::vector<int> neighbours = neighbouringTiles(curHex);
  163. hexq.pop();
  164. for(int nr=0; nr<neighbours.size(); nr++)
  165. {
  166. curNext = neighbours[nr];
  167. if(!accessibility[curNext] || (dists[curHex]+1)>=dists[curNext])
  168. continue;
  169. hexq.push(curNext);
  170. dists[curNext] = dists[curHex] + 1;
  171. predecessor[curNext] = curHex;
  172. }
  173. }
  174. };
  175. std::vector<int> BattleInfo::getAccessibility(int stackID)
  176. {
  177. std::vector<int> ret;
  178. bool ac[187];
  179. CStack *s = getStack(stackID);
  180. if(s->creature->isDoubleWide())
  181. getAccessibilityMapForTwoHex(ac,s->attackerOwned,stackID);
  182. else
  183. getAccessibilityMap(ac,stackID);
  184. int pr[187], dist[187];
  185. makeBFS(s->position,ac,pr,dist);
  186. for(int i=0;i<187;i++)
  187. if(dist[i] <= s->creature->speed)
  188. ret.push_back(i);
  189. return ret;
  190. }
  191. signed char BattleInfo::mutualPosition(int hex1, int hex2)
  192. {
  193. if(hex2 == hex1 - ( (hex1/17)%2 ? 18 : 17 )) //top left
  194. return 0;
  195. if(hex2 == hex1 - ( (hex1/17)%2 ? 17 : 16 )) //top right
  196. return 1;
  197. if(hex2 == hex1 - 1 && hex1%17 != 0) //left
  198. return 5;
  199. if(hex2 == hex1 + 1 && hex1%17 != 16) //right
  200. return 2;
  201. if(hex2 == hex1 + ( (hex1/17)%2 ? 16 : 17 )) //bottom left
  202. return 4;
  203. if(hex2 == hex1 + ( (hex1/17)%2 ? 17 : 18 )) //bottom right
  204. return 3;
  205. return -1;
  206. }
  207. std::vector<int> BattleInfo::neighbouringTiles(int hex)
  208. {
  209. #define CHECK_AND_PUSH(tile) {int hlp = (tile); if(hlp>=0 && hlp<187 && (hlp%17!=16) && hlp%17) ret.push_back(hlp);}
  210. std::vector<int> ret;
  211. CHECK_AND_PUSH(hex - ( (hex/17)%2 ? 18 : 17 ));
  212. CHECK_AND_PUSH(hex - ( (hex/17)%2 ? 17 : 16 ));
  213. CHECK_AND_PUSH(hex - 1);
  214. CHECK_AND_PUSH(hex + 1);
  215. CHECK_AND_PUSH(hex + ( (hex/17)%2 ? 16 : 17 ));
  216. CHECK_AND_PUSH(hex + ( (hex/17)%2 ? 17 : 18 ));
  217. #undef CHECK_AND_PUSH
  218. return ret;
  219. }
  220. std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
  221. {
  222. int predecessor[187]; //for getting the Path
  223. int dist[187]; //calculated distances
  224. makeBFS(start,accessibility,predecessor,dist);
  225. //making the Path
  226. std::vector<int> path;
  227. int curElem = dest;
  228. while(curElem != start)
  229. {
  230. path.push_back(curElem);
  231. curElem = predecessor[curElem];
  232. }
  233. return path;
  234. }
  235. CStack::CStack(CCreature * C, int A, int O, int I, bool AO)
  236. :creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints)
  237. {
  238. }
  239. void CGameState::applyNL(IPack * pack)
  240. {
  241. switch(pack->getType())
  242. {
  243. case 101://NewTurn
  244. {
  245. NewTurn * n = static_cast<NewTurn*>(pack);
  246. day = n->day;
  247. BOOST_FOREACH(NewTurn::Hero h, n->heroes) //give mana/movement point
  248. {
  249. static_cast<CGHeroInstance*>(map->objects[h.id])->movement = h.move;
  250. static_cast<CGHeroInstance*>(map->objects[h.id])->mana = h.mana;
  251. }
  252. BOOST_FOREACH(SetResources h, n->res) //give resources
  253. applyNL(&h);
  254. BOOST_FOREACH(SetAvailableCreatures h, n->cres) //set available creatures in towns
  255. applyNL(&h);
  256. if(n->resetBuilded) //reset amount of structures set in this turn in towns
  257. BOOST_FOREACH(CGTownInstance* t, map->towns)
  258. t->builded = 0;
  259. break;
  260. }
  261. case 102: //set resource amount
  262. {
  263. SetResource *sr = static_cast<SetResource*>(pack);
  264. players[sr->player].resources[sr->resid] = sr->val;
  265. break;
  266. }
  267. case 104:
  268. {
  269. SetResources *sr = static_cast<SetResources*>(pack);
  270. for(int i=0;i<sr->res.size();i++)
  271. players[sr->player].resources[i] = sr->res[i];
  272. break;
  273. }
  274. case 105:
  275. {
  276. SetPrimSkill *sr = static_cast<SetPrimSkill*>(pack);
  277. CGHeroInstance *hero = getHero(sr->id);
  278. if(sr->which <4)
  279. {
  280. if(sr->abs)
  281. hero->primSkills[sr->which] = sr->val;
  282. else
  283. hero->primSkills[sr->which] += sr->val;
  284. }
  285. else if(sr->which == 4) //XP
  286. {
  287. if(sr->abs)
  288. hero->exp = sr->val;
  289. else
  290. hero->exp += sr->val;
  291. }
  292. break;
  293. }
  294. case 500:
  295. {
  296. RemoveHero *rh = static_cast<RemoveHero*>(pack);
  297. CGHeroInstance *h = static_cast<CGHeroInstance*>(map->objects[rh->id]);
  298. std::vector<CGHeroInstance*>::iterator nitr = std::find(map->heroes.begin(), map->heroes.end(),h);
  299. map->heroes.erase(nitr);
  300. int player = h->tempOwner;
  301. nitr = std::find(players[player].heroes.begin(), players[player].heroes.end(), h);
  302. players[player].heroes.erase(nitr);
  303. map->objects[h->id] = NULL;
  304. break;
  305. }
  306. case 501://hero try-move
  307. {
  308. TryMoveHero * n = static_cast<TryMoveHero*>(pack);
  309. CGHeroInstance *h = static_cast<CGHeroInstance*>(map->objects[n->id]);
  310. h->movement = n->movePoints;
  311. if(n->result)
  312. h->pos = n->end;
  313. else
  314. h->pos = n->start;
  315. BOOST_FOREACH(int3 t, n->fowRevealed)
  316. players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1;
  317. break;
  318. }
  319. case 502:
  320. {
  321. SetGarrisons * n = static_cast<SetGarrisons*>(pack);
  322. for(std::map<ui32,CCreatureSet>::iterator i = n->garrs.begin(); i!=n->garrs.end(); i++)
  323. static_cast<CArmedInstance*>(map->objects[i->first])->army = i->second;
  324. break;
  325. }
  326. case 503:
  327. {
  328. //SetStrInfo *ssi = static_cast<SetStrInfo*>(pack);
  329. //static_cast<CGTownInstance*>(map->objects[ssi->tid])->strInfo.creatures = ssi->cres;
  330. break;
  331. }
  332. case 504:
  333. {
  334. NewStructures *ns = static_cast<NewStructures*>(pack);
  335. CGTownInstance*t = static_cast<CGTownInstance*>(map->objects[ns->tid]);
  336. BOOST_FOREACH(si32 bid,ns->bid)
  337. t->builtBuildings.insert(bid);
  338. t->builded = ns->builded;
  339. break;
  340. }
  341. case 506:
  342. {
  343. SetAvailableCreatures *sac = static_cast<SetAvailableCreatures*>(pack);
  344. static_cast<CGTownInstance*>(map->objects[sac->tid])->strInfo.creatures = sac->creatures;
  345. break;
  346. }
  347. case 1001://set object property
  348. {
  349. SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
  350. int CGObjectInstance::*point;
  351. switch(p->what)
  352. {
  353. case 1:
  354. point = &CGObjectInstance::tempOwner;
  355. break;
  356. case 2:
  357. point = &CGObjectInstance::blockVisit;
  358. break;
  359. }
  360. map->objects[p->id]->*point = p->val;
  361. break;
  362. }
  363. case 3000:
  364. {
  365. BattleStart * bs = static_cast<BattleStart*>(pack);
  366. curB = bs->info;
  367. break;
  368. }
  369. case 3001:
  370. {
  371. BattleNextRound *ns = static_cast<BattleNextRound*>(pack);
  372. curB->round = ns->round;
  373. break;
  374. }
  375. case 3002:
  376. {
  377. BattleSetActiveStack *ns = static_cast<BattleSetActiveStack*>(pack);
  378. curB->activeStack = ns->stack;
  379. break;
  380. }
  381. case 3003:
  382. {
  383. BattleResult *br = static_cast<BattleResult*>(pack);
  384. //TODO: give exp, artifacts to winner, decrease armies (casualties)
  385. for(unsigned i=0;i<curB->stacks.size();i++)
  386. delete curB->stacks[i];
  387. delete curB;
  388. curB = NULL;
  389. break;
  390. }
  391. case 3004:
  392. {
  393. BattleStackMoved *br = static_cast<BattleStackMoved*>(pack);
  394. curB->getStack(br->stack)->position = br->tile;
  395. break;
  396. }
  397. case 3005:
  398. {
  399. BattleStackAttacked *br = static_cast<BattleStackAttacked*>(pack);
  400. CStack * at = curB->getStack(br->stackAttacked);
  401. at->amount = br->newAmount;
  402. at->firstHPleft = br->newHP;
  403. at->alive = !br->killed();
  404. break;
  405. }
  406. case 3006:
  407. {
  408. BattleAttack *br = static_cast<BattleAttack*>(pack);
  409. applyNL(&br->bsa);
  410. break;
  411. }
  412. }
  413. }
  414. void CGameState::apply(IPack * pack)
  415. {
  416. mx->lock();
  417. applyNL(pack);
  418. mx->unlock();
  419. }
  420. int CGameState::pickHero(int owner)
  421. {
  422. int h=-1;
  423. if(map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero
  424. return h;
  425. int f = scenarioOps->getIthPlayersSettings(owner).castle;
  426. int i=0;
  427. do //try to find free hero of our faction
  428. {
  429. i++;
  430. h = scenarioOps->getIthPlayersSettings(owner).castle*HEROES_PER_TYPE*2+(ran()%(HEROES_PER_TYPE*2));//->scenarioOps->playerInfos[pru].hero = VLC->
  431. } while( map->getHero(h) && i<175);
  432. if(i>174) //probably no free heroes - there's no point in further search, we'll take first free
  433. {
  434. std::cout << "Warning: cannot find free hero - trying to get first available..."<<std::endl;
  435. for(int j=0; j<HEROES_PER_TYPE * 2 * F_NUMBER; j++)
  436. if(!map->getHero(j))
  437. h=j;
  438. }
  439. return h;
  440. }
  441. CGHeroInstance *CGameState::getHero(int objid)
  442. {
  443. if(objid<0 || objid>=map->objects.size())
  444. return NULL;
  445. return static_cast<CGHeroInstance *>(map->objects[objid]);
  446. }
  447. std::pair<int,int> CGameState::pickObject(CGObjectInstance *obj)
  448. {
  449. switch(obj->ID)
  450. {
  451. case 65: //random artifact
  452. return std::pair<int,int>(5,(ran()%136)+7); //tylko sensowny zakres - na poczatku sa katapulty itp, na koncu specjalne i blanki
  453. case 66: //random treasure artifact
  454. return std::pair<int,int>(5,VLC->arth->treasures[ran()%VLC->arth->treasures.size()]->id);
  455. case 67: //random minor artifact
  456. return std::pair<int,int>(5,VLC->arth->minors[ran()%VLC->arth->minors.size()]->id);
  457. case 68: //random major artifact
  458. return std::pair<int,int>(5,VLC->arth->majors[ran()%VLC->arth->majors.size()]->id);
  459. case 69: //random relic artifact
  460. return std::pair<int,int>(5,VLC->arth->relics[ran()%VLC->arth->relics.size()]->id);
  461. case 70: //random hero
  462. {
  463. return std::pair<int,int>(34,pickHero(obj->tempOwner));
  464. }
  465. case 71: //random monster
  466. return std::pair<int,int>(54,ran()%(VLC->creh->creatures.size()));
  467. case 72: //random monster lvl1
  468. return std::pair<int,int>(54,VLC->creh->levelCreatures[1][ran()%VLC->creh->levelCreatures[1].size()]->idNumber);
  469. case 73: //random monster lvl2
  470. return std::pair<int,int>(54,VLC->creh->levelCreatures[2][ran()%VLC->creh->levelCreatures[2].size()]->idNumber);
  471. case 74: //random monster lvl3
  472. return std::pair<int,int>(54,VLC->creh->levelCreatures[3][ran()%VLC->creh->levelCreatures[3].size()]->idNumber);
  473. case 75: //random monster lvl4
  474. return std::pair<int,int>(54,VLC->creh->levelCreatures[4][ran()%VLC->creh->levelCreatures[4].size()]->idNumber);
  475. case 76: //random resource
  476. return std::pair<int,int>(79,ran()%7); //now it's OH3 style, use %8 for mithril
  477. case 77: //random town
  478. {
  479. int align = ((CGTownInstance*)obj)->alignment,
  480. f;
  481. if(align>PLAYER_LIMIT-1)//same as owner / random
  482. {
  483. if(obj->tempOwner > PLAYER_LIMIT-1)
  484. f = -1; //random
  485. else
  486. f = scenarioOps->getIthPlayersSettings(obj->tempOwner).castle;
  487. }
  488. else
  489. {
  490. f = scenarioOps->getIthPlayersSettings(align).castle;
  491. }
  492. if(f<0) f = ran()%VLC->townh->towns.size();
  493. return std::pair<int,int>(98,f);
  494. }
  495. case 162: //random monster lvl5
  496. return std::pair<int,int>(54,VLC->creh->levelCreatures[5][ran()%VLC->creh->levelCreatures[5].size()]->idNumber);
  497. case 163: //random monster lvl6
  498. return std::pair<int,int>(54,VLC->creh->levelCreatures[6][ran()%VLC->creh->levelCreatures[6].size()]->idNumber);
  499. case 164: //random monster lvl7
  500. return std::pair<int,int>(54,VLC->creh->levelCreatures[7][ran()%VLC->creh->levelCreatures[7].size()]->idNumber);
  501. case 216: //random dwelling
  502. {
  503. int faction = ran()%F_NUMBER;
  504. CCreGen2ObjInfo* info =(CCreGen2ObjInfo*)obj->info;
  505. if (info->asCastle)
  506. {
  507. for(int i=0;i<map->objects.size();i++)
  508. {
  509. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  510. {
  511. randomizeObject(map->objects[i]); //we have to randomize the castle first
  512. faction = map->objects[i]->subID;
  513. break;
  514. }
  515. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  516. {
  517. faction = map->objects[i]->subID;
  518. break;
  519. }
  520. }
  521. }
  522. else
  523. {
  524. while((!(info->castles[0]&(1<<faction))))
  525. {
  526. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  527. break;
  528. faction = ran()%F_NUMBER;
  529. }
  530. }
  531. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  532. int cid = VLC->townh->towns[faction].basicCreatures[level];
  533. for(int i=0;i<VLC->objh->cregens.size();i++)
  534. if(VLC->objh->cregens[i]==cid)
  535. return std::pair<int,int>(17,i);
  536. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  537. return std::pair<int,int>(17,0);
  538. }
  539. case 217:
  540. {
  541. int faction = ran()%F_NUMBER;
  542. CCreGenObjInfo* info =(CCreGenObjInfo*)obj->info;
  543. if (info->asCastle)
  544. {
  545. for(int i=0;i<map->objects.size();i++)
  546. {
  547. if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  548. {
  549. randomizeObject(map->objects[i]); //we have to randomize the castle first
  550. faction = map->objects[i]->subID;
  551. break;
  552. }
  553. else if(map->objects[i]->ID==98 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
  554. {
  555. faction = map->objects[i]->subID;
  556. break;
  557. }
  558. }
  559. }
  560. else
  561. {
  562. while((!(info->castles[0]&(1<<faction))))
  563. {
  564. if((faction>7) && (info->castles[1]&(1<<(faction-8))))
  565. break;
  566. faction = ran()%F_NUMBER;
  567. }
  568. }
  569. int cid = VLC->townh->towns[faction].basicCreatures[obj->subID];
  570. for(int i=0;i<VLC->objh->cregens.size();i++)
  571. if(VLC->objh->cregens[i]==cid)
  572. return std::pair<int,int>(17,i);
  573. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  574. return std::pair<int,int>(17,0);
  575. }
  576. case 218:
  577. {
  578. CCreGen3ObjInfo* info =(CCreGen3ObjInfo*)obj->info;
  579. int level = ((info->maxLevel-info->minLevel) ? (ran()%(info->maxLevel-info->minLevel)+info->minLevel) : (info->minLevel));
  580. int cid = VLC->townh->towns[obj->subID].basicCreatures[level];
  581. for(int i=0;i<VLC->objh->cregens.size();i++)
  582. if(VLC->objh->cregens[i]==cid)
  583. return std::pair<int,int>(17,i);
  584. std::cout << "Cannot find a dwelling for creature "<<cid <<std::endl;
  585. return std::pair<int,int>(17,0);
  586. }
  587. }
  588. return std::pair<int,int>(-1,-1);
  589. }
  590. void CGameState::randomizeObject(CGObjectInstance *cur)
  591. {
  592. std::pair<int,int> ran = pickObject(cur);
  593. if(ran.first<0 || ran.second<0) //this is not a random object, or we couldn't find anything
  594. {
  595. if(cur->ID==98) //town - set def
  596. {
  597. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  598. if(t->hasCapitol())
  599. t->defInfo = capitols[t->subID];
  600. else if(t->hasFort())
  601. t->defInfo = forts[t->subID];
  602. else
  603. t->defInfo = villages[t->subID];
  604. }
  605. return;
  606. }
  607. else if(ran.first==34)//special code for hero
  608. {
  609. CGHeroInstance *h = dynamic_cast<CGHeroInstance *>(cur);
  610. if(!h) {std::cout<<"Wrong random hero at "<<cur->pos<<std::endl; return;}
  611. cur->ID = ran.first;
  612. h->portrait = cur->subID = ran.second;
  613. h->type = VLC->heroh->heroes[ran.second];
  614. map->heroes.push_back(h);
  615. return; //TODO: maybe we should do something with definfo?
  616. }
  617. else if(ran.first==98)//special code for town
  618. {
  619. CGTownInstance *t = dynamic_cast<CGTownInstance*>(cur);
  620. if(!t) {std::cout<<"Wrong random town at "<<cur->pos<<std::endl; return;}
  621. cur->ID = ran.first;
  622. cur->subID = ran.second;
  623. t->town = &VLC->townh->towns[ran.second];
  624. if(t->hasCapitol())
  625. t->defInfo = capitols[t->subID];
  626. else if(t->hasFort())
  627. t->defInfo = forts[t->subID];
  628. else
  629. t->defInfo = villages[t->subID];
  630. map->towns.push_back(t);
  631. return;
  632. }
  633. //we have to replace normal random object
  634. cur->ID = ran.first;
  635. cur->subID = ran.second;
  636. map->defs.insert(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
  637. if(!cur->defInfo)
  638. {
  639. std::cout<<"Missing def declaration for "<<cur->ID<<" "<<cur->subID<<std::endl;
  640. return;
  641. }
  642. }
  643. int CGameState::getDate(int mode) const
  644. {
  645. int temp;
  646. switch (mode)
  647. {
  648. case 0:
  649. return day;
  650. break;
  651. case 1:
  652. temp = (day)%7;
  653. if (temp)
  654. return temp;
  655. else return 7;
  656. break;
  657. case 2:
  658. temp = ((day-1)/7)+1;
  659. if (!(temp%4))
  660. return 4;
  661. else
  662. return (temp%4);
  663. break;
  664. case 3:
  665. return ((day-1)/28)+1;
  666. break;
  667. }
  668. return 0;
  669. }
  670. CGameState::CGameState()
  671. {
  672. mx = new boost::shared_mutex();
  673. }
  674. CGameState::~CGameState()
  675. {
  676. delete mx;
  677. }
  678. void CGameState::init(StartInfo * si, Mapa * map, int Seed)
  679. {
  680. day = 0;
  681. seed = Seed;
  682. ran.seed((boost::int32_t)seed);
  683. scenarioOps = si;
  684. this->map = map;
  685. for(int i=0;i<F_NUMBER;i++)
  686. {
  687. villages[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  688. forts[i] = VLC->dobjinfo->castles[i];
  689. capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
  690. }
  691. //picking random factions for players
  692. for(int i=0;i<scenarioOps->playerInfos.size();i++)
  693. {
  694. if(scenarioOps->playerInfos[i].castle==-1)
  695. {
  696. int f;
  697. do
  698. {
  699. f = ran()%F_NUMBER;
  700. }while(!(map->players[scenarioOps->playerInfos[i].color].allowedFactions & 1<<f));
  701. scenarioOps->playerInfos[i].castle = f;
  702. }
  703. }
  704. //randomizing objects
  705. for(int no=0; no<map->objects.size(); ++no)
  706. {
  707. randomizeObject(map->objects[no]);
  708. if(map->objects[no]->ID==26)
  709. map->objects[no]->defInfo->handler=NULL;
  710. map->objects[no]->hoverName = VLC->objh->names[map->objects[no]->ID];
  711. }
  712. //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
  713. //giving starting hero
  714. for(int i=0;i<PLAYER_LIMIT;i++)
  715. {
  716. if((map->players[i].generateHeroAtMainTown && map->players[i].hasMainTown) || (map->players[i].hasMainTown && map->version==RoE))
  717. {
  718. int3 hpos = map->players[i].posOfMainTown;
  719. hpos.x+=1;// hpos.y+=1;
  720. int j;
  721. for(j=0; j<scenarioOps->playerInfos.size(); j++)
  722. if(scenarioOps->playerInfos[j].color == i)
  723. break;
  724. if(j == scenarioOps->playerInfos.size())
  725. continue;
  726. int h=pickHero(i);
  727. CGHeroInstance * nnn = static_cast<CGHeroInstance*>(createObject(34,h,hpos,i));
  728. nnn->id = map->objects.size();
  729. //nnn->defInfo->handler = graphics->flags1[0];
  730. map->heroes.push_back(nnn);
  731. map->objects.push_back(nnn);
  732. }
  733. }
  734. //std::cout<<"\tGiving starting heroes: "<<th.getDif()<<std::endl;
  735. /*********creating players entries in gs****************************************/
  736. for (int i=0; i<scenarioOps->playerInfos.size();i++)
  737. {
  738. std::pair<int,PlayerState> ins(scenarioOps->playerInfos[i].color,PlayerState());
  739. ins.second.color=ins.first;
  740. ins.second.serial=i;
  741. players.insert(ins);
  742. }
  743. /******************RESOURCES****************************************************/
  744. //TODO: zeby komputer dostawal inaczej niz gracz
  745. std::vector<int> startres;
  746. std::ifstream tis("config/startres.txt");
  747. int k;
  748. for (int j=0;j<scenarioOps->difficulty;j++)
  749. {
  750. tis >> k;
  751. for (int z=0;z<RESOURCE_QUANTITY;z++)
  752. tis>>k;
  753. }
  754. tis >> k;
  755. for (int i=0;i<RESOURCE_QUANTITY;i++)
  756. {
  757. tis >> k;
  758. startres.push_back(k);
  759. }
  760. tis.close();
  761. for (std::map<ui8,PlayerState>::iterator i = players.begin(); i!=players.end(); i++)
  762. {
  763. (*i).second.resources.resize(RESOURCE_QUANTITY);
  764. for (int x=0;x<RESOURCE_QUANTITY;x++)
  765. (*i).second.resources[x] = startres[x];
  766. }
  767. /*************************HEROES************************************************/
  768. for (int i=0; i<map->heroes.size();i++) //heroes instances
  769. {
  770. if (map->heroes[i]->getOwner()<0)
  771. continue;
  772. CGHeroInstance * vhi = (map->heroes[i]);
  773. if(!vhi->type)
  774. vhi->type = VLC->heroh->heroes[vhi->subID];
  775. //vhi->subID = vhi->type->ID;
  776. if (vhi->level<1)
  777. {
  778. vhi->exp=40+ran()%50;
  779. vhi->level = 1;
  780. }
  781. if (vhi->level>1) ;//TODO dodac um dr, ale potrzebne los
  782. if ((!vhi->primSkills.size()) || (vhi->primSkills[0]<0))
  783. {
  784. if (vhi->primSkills.size()<PRIMARY_SKILLS)
  785. vhi->primSkills.resize(PRIMARY_SKILLS);
  786. vhi->primSkills[0] = vhi->type->heroClass->initialAttack;
  787. vhi->primSkills[1] = vhi->type->heroClass->initialDefence;
  788. vhi->primSkills[2] = vhi->type->heroClass->initialPower;
  789. vhi->primSkills[3] = vhi->type->heroClass->initialKnowledge;
  790. }
  791. vhi->mana = vhi->primSkills[3]*10;
  792. if (!vhi->name.length())
  793. {
  794. vhi->name = vhi->type->name;
  795. }
  796. if (!vhi->biography.length())
  797. {
  798. vhi->biography = vhi->type->biography;
  799. }
  800. if (vhi->portrait < 0)
  801. vhi->portrait = vhi->type->ID;
  802. //initial army
  803. if (!vhi->army.slots.size()) //standard army
  804. {
  805. int pom, pom2=0;
  806. for(int x=0;x<3;x++)
  807. {
  808. pom = (VLC->creh->nameToID[vhi->type->refTypeStack[x]]);
  809. if(pom>=145 && pom<=149) //war machine
  810. {
  811. pom2++;
  812. switch (pom)
  813. {
  814. case 145: //catapult
  815. vhi->artifWorn[16] = 3;
  816. break;
  817. default:
  818. pom-=145;
  819. vhi->artifWorn[13+pom] = 4+pom;
  820. break;
  821. }
  822. continue;
  823. }
  824. vhi->army.slots[x-pom2].first = pom;
  825. if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0)
  826. vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
  827. else
  828. vhi->army.slots[x-pom2].second = +vhi->type->lowStack[x];
  829. }
  830. }
  831. players[vhi->getOwner()].heroes.push_back(vhi);
  832. }
  833. /*************************FOG**OF**WAR******************************************/
  834. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  835. {
  836. k->second.fogOfWarMap.resize(map->width);
  837. for(int g=0; g<map->width; ++g)
  838. k->second.fogOfWarMap[g].resize(map->height);
  839. for(int g=-0; g<map->width; ++g)
  840. for(int h=0; h<map->height; ++h)
  841. k->second.fogOfWarMap[g][h].resize(map->twoLevel+1, 0);
  842. for(int g=0; g<map->width; ++g)
  843. for(int h=0; h<map->height; ++h)
  844. for(int v=0; v<map->twoLevel+1; ++v)
  845. k->second.fogOfWarMap[g][h][v] = 0;
  846. for(int xd=0; xd<map->width; ++xd) //revealing part of map around heroes
  847. {
  848. for(int yd=0; yd<map->height; ++yd)
  849. {
  850. for(int ch=0; ch<k->second.heroes.size(); ++ch)
  851. {
  852. int deltaX = (k->second.heroes[ch]->getPosition(false).x-xd)*(k->second.heroes[ch]->getPosition(false).x-xd);
  853. int deltaY = (k->second.heroes[ch]->getPosition(false).y-yd)*(k->second.heroes[ch]->getPosition(false).y-yd);
  854. if(deltaX+deltaY<k->second.heroes[ch]->getSightDistance()*k->second.heroes[ch]->getSightDistance())
  855. k->second.fogOfWarMap[xd][yd][k->second.heroes[ch]->getPosition(false).z] = 1;
  856. }
  857. }
  858. }
  859. }
  860. /****************************TOWNS************************************************/
  861. for (int i=0;i<map->towns.size();i++)
  862. {
  863. CGTownInstance * vti =(map->towns[i]);
  864. if(!vti->town)
  865. vti->town = &VLC->townh->towns[vti->subID];
  866. if (vti->name.length()==0) // if town hasn't name we draw it
  867. vti->name=vti->town->names[ran()%vti->town->names.size()];
  868. if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
  869. {
  870. vti->builtBuildings.erase(-50);
  871. vti->builtBuildings.insert(10);
  872. vti->builtBuildings.insert(5);
  873. vti->builtBuildings.insert(30);
  874. if(ran()%2)
  875. vti->builtBuildings.insert(31);
  876. }
  877. players[vti->getOwner()].towns.push_back(vti);
  878. }
  879. for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
  880. {
  881. if(k->first==-1 || k->first==255)
  882. continue;
  883. for(int xd=0; xd<map->width; ++xd) //revealing part of map around towns
  884. {
  885. for(int yd=0; yd<map->height; ++yd)
  886. {
  887. for(int ch=0; ch<k->second.towns.size(); ++ch)
  888. {
  889. int deltaX = (k->second.towns[ch]->pos.x-xd)*(k->second.towns[ch]->pos.x-xd);
  890. int deltaY = (k->second.towns[ch]->pos.y-yd)*(k->second.towns[ch]->pos.y-yd);
  891. if(deltaX+deltaY<k->second.towns[ch]->getSightDistance()*k->second.towns[ch]->getSightDistance())
  892. k->second.fogOfWarMap[xd][yd][k->second.towns[ch]->pos.z] = 1;
  893. }
  894. }
  895. }
  896. //init visiting heroes
  897. for(int l=0; l<k->second.heroes.size();l++)
  898. {
  899. for(int m=0; m<k->second.towns.size();m++)
  900. {
  901. int3 vistile = k->second.towns[m]->pos; vistile.x--; //tile next to the entrance
  902. if(vistile == k->second.heroes[l]->pos)
  903. {
  904. k->second.towns[m]->visitingHero = k->second.heroes[l];
  905. break;
  906. }
  907. }
  908. }
  909. }
  910. }
  911. bool CGameState::battleShootCreatureStack(int ID, int dest)
  912. {
  913. return true;
  914. }
  915. int CGameState::battleGetStack(int pos)
  916. {
  917. for(int g=0; g<curB->stacks.size(); ++g)
  918. {
  919. if(curB->stacks[g]->position == pos ||
  920. ( curB->stacks[g]->creature->isDoubleWide() &&
  921. ( (curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos) ||
  922. (!curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos)
  923. )
  924. )
  925. )
  926. return curB->stacks[g]->ID;
  927. }
  928. return -1;
  929. }
  930. int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender)
  931. {
  932. int attackDefenseBonus = attacker->creature->attack - defender->creature->defence;
  933. int damageBase = 0;
  934. if(attacker->creature->damageMax == attacker->creature->damageMin) //constant damage
  935. {
  936. damageBase = attacker->creature->damageMin;
  937. }
  938. else
  939. {
  940. damageBase = rand()%(attacker->creature->damageMax - attacker->creature->damageMin) + attacker->creature->damageMin + 1;
  941. }
  942. float dmgBonusMultiplier = 1.0;
  943. if(attackDefenseBonus < 0) //decreasing dmg
  944. {
  945. if(0.02f * (-attackDefenseBonus) > 0.3f)
  946. {
  947. dmgBonusMultiplier += -0.3f;
  948. }
  949. else
  950. {
  951. dmgBonusMultiplier += 0.02f * attackDefenseBonus;
  952. }
  953. }
  954. else //increasing dmg
  955. {
  956. if(0.05f * attackDefenseBonus > 4.0f)
  957. {
  958. dmgBonusMultiplier += 4.0f;
  959. }
  960. else
  961. {
  962. dmgBonusMultiplier += 0.05f * attackDefenseBonus;
  963. }
  964. }
  965. return (float)damageBase * (float)attacker->amount * dmgBonusMultiplier;
  966. }