CCallback.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. #include "stdafx.h"
  2. #include "CCallback.h"
  3. #include "CPathfinder.h"
  4. #include "hch\CHeroHandler.h"
  5. #include "hch\CTownHandler.h"
  6. #include "CGameInfo.h"
  7. #include "hch\CAmbarCendamo.h"
  8. #include "mapHandler.h"
  9. #include "CGameState.h"
  10. #include "CPlayerInterface.h"
  11. #include "CLua.h"
  12. #include "hch/CGeneralTextHandler.h"
  13. #include "CAdvmapInterface.h"
  14. #include "CPlayerInterface.h"
  15. #include "hch/CBuildingHandler.h"
  16. LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
  17. int CCallback::lowestSpeed(CGHeroInstance * chi)
  18. {
  19. int min = 150;
  20. for ( std::map<int,std::pair<CCreature*,int> >::iterator i = chi->army.slots.begin();
  21. i!=chi->army.slots.end(); i++ )
  22. {
  23. if (min>(*i).second.first->speed)
  24. min = (*i).second.first->speed;
  25. }
  26. return min;
  27. }
  28. int CCallback::valMovePoints(CGHeroInstance * chi)
  29. {
  30. int ret = 1270+70*lowestSpeed(chi);
  31. if (ret>2000)
  32. ret=2000;
  33. //TODO: additional bonuses (but they aren't currently stored in chi)
  34. return ret;
  35. }
  36. void CCallback::newTurn()
  37. {
  38. //std::map<int, PlayerState>::iterator i = gs->players.begin() ;
  39. gs->day++;
  40. for (std::set<CCPPObjectScript *>::iterator i=gs->cppscripts.begin();i!=gs->cppscripts.end();i++)
  41. {
  42. (*i)->newTurn();
  43. }
  44. for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  45. {
  46. //handle heroes/////////////////////////////
  47. for (int j=0;j<(*i).second.heroes.size();j++)
  48. {
  49. (*i).second.heroes[j]->movement = valMovePoints((*i).second.heroes[j]);
  50. }
  51. //handle towns/////////////////////////////
  52. for(int j=0;j<i->second.towns.size();j++)
  53. {
  54. i->second.towns[j]->builded=0;
  55. if(getDate(1)==1) //first day of week
  56. {
  57. for(int k=0;k<CREATURES_PER_TOWN;k++)
  58. {
  59. if(i->second.towns[j]->creatureDwelling(k))//there is dwelling
  60. i->second.towns[j]->strInfo.creatures[k]+=i->second.towns[j]->creatureGrowth(k);
  61. }
  62. }
  63. if((gs->day>1) && i->first<PLAYER_LIMIT)
  64. i->second.resources[6]+=i->second.towns[j]->dailyIncome();
  65. }
  66. }
  67. }
  68. bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
  69. {
  70. CGHeroInstance * hero = NULL;
  71. if (idtype==0)
  72. {
  73. if (player==-1)
  74. hero=gs->players[player+1].heroes[ID];
  75. else
  76. hero=gs->players[player].heroes[ID];
  77. }
  78. else if (idtype==1 && player>=0) //looking for it in local area
  79. {
  80. for (int i=0; i<gs->players[player].heroes.size();i++)
  81. {
  82. if (gs->players[player].heroes[i]->type->ID == ID)
  83. hero = gs->players[player].heroes[i];
  84. }
  85. }
  86. else //idtype==1; player<0
  87. {
  88. for(std::map<int, PlayerState>::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j)
  89. {
  90. for (int i=0; i<(*j).second.heroes.size();i++)
  91. {
  92. if ((*j).second.heroes[i]->type->ID == ID)
  93. {
  94. hero = (*j).second.heroes[i];
  95. }
  96. }
  97. }
  98. }
  99. if (!hero)
  100. return false; //can't find hero
  101. if(!verifyPath(path,!hero->canWalkOnSea()))//TODO: not check sea, if hero has flying or walking on water
  102. return false; //invalid path
  103. //check path format
  104. if (pathType==0)
  105. CPathfinder::convertPath(path,pathType);
  106. if (pathType>1)
  107. throw std::exception("Unknown path format");
  108. CPath * ourPath = path;
  109. if(!ourPath)
  110. return false;
  111. for(int i=ourPath->nodes.size()-1; i>0; i--)
  112. {
  113. int3 stpos, endpos;
  114. stpos = int3(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, hero->pos.z);
  115. endpos = int3(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, hero->pos.z);
  116. HeroMoveDetails curd;
  117. curd.src = stpos;
  118. curd.dst = endpos;
  119. curd.ho = hero;
  120. curd.owner = hero->getOwner();
  121. /*if(player!=-1)
  122. {
  123. hero->pos = endpos;
  124. }*/
  125. if((hero->movement>=CGI->mh->getCost(stpos, endpos, hero)) || player==-1)
  126. { //performing move
  127. hero->movement-=CGI->mh->getCost(stpos, endpos, hero);
  128. std::vector< CGObjectInstance * > vis = CGI->mh->getVisitableObjs(CGHeroInstance::convertPosition(curd.dst,false));
  129. bool blockvis = false;
  130. for (int pit = 0; pit<vis.size();pit++)
  131. if (vis[pit]->blockVisit)
  132. blockvis = true;
  133. if (!blockvis)
  134. {
  135. curd.successful = true;
  136. hero->pos = curd.dst;
  137. //inform leaved objects
  138. std::vector< CGObjectInstance * > leave = CGI->mh->getVisitableObjs(CGHeroInstance::convertPosition(curd.src,false));
  139. for (int iii=0; iii<leave.size(); iii++) //if object is visitable we call onHeroVisit
  140. {
  141. //TODO: allow to handle this in LUA
  142. if(leave[iii]->state) //hard-coded function
  143. leave[iii]->state->onHeroLeave(leave[iii],curd.ho->subID);
  144. }
  145. //reveal fog of war
  146. int heroSight = hero->getSightDistance();
  147. int xbeg = stpos.x - heroSight - 2;
  148. if(xbeg < 0)
  149. xbeg = 0;
  150. int xend = stpos.x + heroSight + 2;
  151. if(xend >= CGI->ac->map.width)
  152. xend = CGI->ac->map.width;
  153. int ybeg = stpos.y - heroSight - 2;
  154. if(ybeg < 0)
  155. ybeg = 0;
  156. int yend = stpos.y + heroSight + 2;
  157. if(yend >= CGI->ac->map.height)
  158. yend = CGI->ac->map.height;
  159. for(int xd=xbeg; xd<xend; ++xd) //revealing part of map around heroes
  160. {
  161. for(int yd=ybeg; yd<yend; ++yd)
  162. {
  163. int deltaX = (hero->getPosition(false).x-xd)*(hero->getPosition(false).x-xd);
  164. int deltaY = (hero->getPosition(false).y-yd)*(hero->getPosition(false).y-yd);
  165. if(deltaX+deltaY<hero->getSightDistance()*hero->getSightDistance())
  166. {
  167. if(gs->players[player].fogOfWarMap[xd][yd][hero->getPosition(false).z] == 0)
  168. {
  169. CGI->playerint[gs->players[player].serial]->tileRevealed(int3(xd, yd, hero->getPosition(false).z));
  170. }
  171. gs->players[player].fogOfWarMap[xd][yd][hero->getPosition(false).z] = 1;
  172. }
  173. }
  174. }
  175. //notify interfacesabout move
  176. int nn=0; //number of interfece of currently browsed player
  177. for(std::map<int, PlayerState>::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j)//CGI->state->players.size(); ++j) //for testing
  178. {
  179. if (j->first > PLAYER_LIMIT)
  180. break;
  181. if(j->second.fogOfWarMap[stpos.x-1][stpos.y][stpos.z] || j->second.fogOfWarMap[endpos.x-1][endpos.y][endpos.z])
  182. { //player should be notified
  183. CGI->playerint[j->second.serial]->heroMoved(curd);
  184. }
  185. ++nn;
  186. }
  187. //call objects if they arevisited
  188. for (int iii=0; iii<vis.size(); iii++) //if object is visitable we call onHeroVisit
  189. {
  190. if(gs->checkFunc(vis[iii]->ID,"heroVisit")) //script function
  191. gs->objscr[vis[iii]->ID]["heroVisit"]->onHeroVisit(vis[iii],curd.ho->subID);
  192. if(vis[iii]->state) //hard-coded function
  193. vis[iii]->state->onHeroVisit(vis[iii],curd.ho->subID);
  194. }
  195. }
  196. else //interaction with blocking object (like resources)
  197. {
  198. curd.successful = false;
  199. CGI->playerint[gs->players[hero->getOwner()].serial]->heroMoved(curd);
  200. for (int iii=0; iii<vis.size(); iii++) //if object is visitable we call onHeroVisit
  201. {
  202. if (vis[iii]->blockVisit)
  203. {
  204. if(gs->checkFunc(vis[iii]->ID,"heroVisit")) //script function
  205. gs->objscr[vis[iii]->ID]["heroVisit"]->onHeroVisit(vis[iii],curd.ho->subID);
  206. if(vis[iii]->state) //hard-coded function
  207. vis[iii]->state->onHeroVisit(vis[iii],curd.ho->subID);
  208. }
  209. }
  210. return false;
  211. }
  212. }
  213. else
  214. return true; //move ended - no more movement points
  215. }
  216. return true;
  217. }
  218. void CCallback::selectionMade(int selection, int asker)
  219. {
  220. //todo - jak bedzie multiplayer po sieci, to moze wymagac przerobek zaleznych od obranego modelu
  221. IChosen * ask = (IChosen *)asker;
  222. ask->chosen(selection);
  223. }
  224. void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount)
  225. {
  226. if(amount<=0) return;
  227. if(obj->ID==98)
  228. {
  229. int ser=-1;
  230. CGTownInstance *t = const_cast<CGTownInstance*>(static_cast<const CGTownInstance*>(obj));
  231. //verify
  232. bool found = false;
  233. typedef std::pair<const int,int> Parka;
  234. for(std::map<int,int>::iterator av=t->strInfo.creatures.begin();av!=t->strInfo.creatures.end();av++)
  235. {
  236. if( ( found = (ID == t->town->basicCreatures[av->first]) )
  237. || (found = (ID == t->town->upgradedCreatures[av->first])) )
  238. {
  239. amount = std::min(amount,av->second);
  240. ser = av->first;
  241. break;
  242. }
  243. }
  244. if(!found) //no such creature
  245. return;
  246. if(amount > CGI->creh->creatures[ID].maxAmount(gs->players[player].resources))
  247. return; //not enough resources
  248. for(int i=0;i<RESOURCE_QUANTITY;i++)
  249. if (gs->players[player].resources[i] < (CGI->creh->creatures[ID].cost[i] * amount))
  250. return; //not enough resources
  251. if(amount<=0) return;
  252. //recruit
  253. int slot = -1;
  254. std::pair<int,std::pair<CCreature*,int> > parb;
  255. for(int i=0;i<7;i++)
  256. {
  257. if(!t->army.slots[i].first)
  258. {
  259. slot = i;
  260. break;
  261. }
  262. }
  263. if(slot<0) //no free slot
  264. return;
  265. for(int i=0;i<RESOURCE_QUANTITY;i++)
  266. gs->players[player].resources[i] -= (CGI->creh->creatures[ID].cost[i] * amount);
  267. t->strInfo.creatures[ser] -= amount;
  268. t->army.slots[slot].first = &CGI->creh->creatures[ID];
  269. t->army.slots[slot].second = amount;
  270. CGI->playerint[gs->players[player].serial]->garrisonChanged(obj);
  271. }
  272. }
  273. bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos)
  274. {
  275. return false;
  276. }
  277. bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos)
  278. {
  279. return false;
  280. }
  281. UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
  282. {
  283. return UpgradeInfo();
  284. }
  285. int CCallback::howManyTowns()
  286. {
  287. return gs->players[gs->currentPlayer].towns.size();
  288. }
  289. const CGTownInstance * CCallback::getTownInfo(int val, bool mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
  290. {
  291. if (!mode)
  292. return gs->players[gs->currentPlayer].towns[val];
  293. else
  294. {
  295. //TODO: add some smart ID to the CTownInstance
  296. //for (int i=0; i<gs->players[gs->currentPlayer].towns.size();i++)
  297. //{
  298. // if (gs->players[gs->currentPlayer].towns[i]->someID==val)
  299. // return gs->players[gs->currentPlayer].towns[i];
  300. //}
  301. return NULL;
  302. }
  303. return NULL;
  304. }
  305. int CCallback::howManyHeroes()
  306. {
  307. return gs->players[player].heroes.size();
  308. }
  309. const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
  310. {
  311. if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info
  312. return NULL;
  313. if (!mode)
  314. if(val<gs->players[player].heroes.size())
  315. return gs->players[player].heroes[val];
  316. else return NULL;
  317. else
  318. {
  319. for (int i=0; i<gs->players[player].heroes.size();i++)
  320. {
  321. if (gs->players[player].heroes[i]->type->ID==val)
  322. return gs->players[player].heroes[i];
  323. }
  324. }
  325. return NULL;
  326. }
  327. int CCallback::getResourceAmount(int type)
  328. {
  329. return gs->players[player].resources[type];
  330. }
  331. std::vector<int> CCallback::getResourceAmount()
  332. {
  333. return gs->players[player].resources;
  334. }
  335. int CCallback::getDate(int mode)
  336. {
  337. int temp;
  338. switch (mode)
  339. {
  340. case 0:
  341. return gs->day;
  342. break;
  343. case 1:
  344. temp = (gs->day)%7;
  345. if (temp)
  346. return temp;
  347. else return 7;
  348. break;
  349. case 2:
  350. temp = ((gs->day-1)/7)+1;
  351. if (!(temp%4))
  352. return 4;
  353. else
  354. return (temp%4);
  355. break;
  356. case 3:
  357. return ((gs->day-1)/28)+1;
  358. break;
  359. }
  360. return 0;
  361. }
  362. bool CCallback::verifyPath(CPath * path, bool blockSea)
  363. {
  364. for (int i=0;i<path->nodes.size();i++)
  365. {
  366. if ( CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].blocked
  367. && (! (CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].visitable)))
  368. return false; //path is wrong - one of the tiles is blocked
  369. if (blockSea)
  370. {
  371. if (i==0)
  372. continue;
  373. if (
  374. ((CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].terType==EterrainType::water)
  375. &&
  376. (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].terType!=EterrainType::water))
  377. ||
  378. ((CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].terType!=EterrainType::water)
  379. &&
  380. (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].terType==EterrainType::water))
  381. ||
  382. (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].terType==EterrainType::rock)
  383. )
  384. return false;
  385. }
  386. }
  387. return true;
  388. }
  389. std::vector < std::string > CCallback::getObjDescriptions(int3 pos)
  390. {
  391. if(gs->players[player].fogOfWarMap[pos.x][pos.y][pos.z])
  392. return CGI->mh->getObjDescriptions(pos);
  393. else return std::vector< std::string > ();
  394. }
  395. PseudoV< PseudoV< PseudoV<unsigned char> > > & CCallback::getVisibilityMap()
  396. {
  397. return gs->players[player].fogOfWarMap;
  398. }
  399. bool CCallback::isVisible(int3 pos, int Player)
  400. {
  401. return gs->players[Player].fogOfWarMap[pos.x][pos.y][pos.z];
  402. }
  403. std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur)
  404. {
  405. std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
  406. for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  407. {
  408. for (int j=0;j<(*i).second.towns.size();j++)
  409. {
  410. if ( ( isVisible((*i).second.towns[j]->pos,player) ) || (*i).first==player)
  411. {
  412. ret.push_back((*i).second.towns[j]);
  413. }
  414. }
  415. } // for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  416. return ret;
  417. }
  418. std::vector < const CGHeroInstance *> CCallback::getHeroesInfo(bool onlyOur)
  419. {
  420. std::vector < const CGHeroInstance *> ret = std::vector < const CGHeroInstance *>();
  421. for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  422. {
  423. for (int j=0;j<(*i).second.heroes.size();j++)
  424. {
  425. if ( ( isVisible((*i).second.heroes[j]->getPosition(false),player) ) || (*i).first==player)
  426. {
  427. ret.push_back((*i).second.heroes[j]);
  428. }
  429. }
  430. } // for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  431. return ret;
  432. }
  433. bool CCallback::isVisible(int3 pos)
  434. {
  435. return isVisible(pos,player);
  436. }
  437. int CCallback::getMyColor()
  438. {
  439. return player;
  440. }
  441. int CCallback::getHeroSerial(const CGHeroInstance * hero)
  442. {
  443. for (int i=0; i<gs->players[player].heroes.size();i++)
  444. {
  445. if (gs->players[player].heroes[i]==hero)
  446. return i;
  447. }
  448. return -1;
  449. }
  450. const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj)
  451. {
  452. if(!obj)
  453. return NULL;
  454. if(obj->ID == 34)
  455. return &(dynamic_cast<const CGHeroInstance*>(obj))->army;
  456. else if(obj->ID == 98)
  457. return &(dynamic_cast<const CGTownInstance*>(obj)->army);
  458. else return NULL;
  459. }
  460. int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
  461. {
  462. CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
  463. if (false)
  464. {
  465. //TODO: check if we are allowed to swap these creatures
  466. return -1;
  467. }
  468. CCreature * pom = S2->slots[p2].first;
  469. S2->slots[p2].first = S1->slots[p1].first;
  470. S1->slots[p1].first = pom;
  471. int pom2 = S2->slots[p2].second;
  472. S2->slots[p2].second = S1->slots[p1].second;
  473. S1->slots[p1].second = pom2;
  474. if(!S1->slots[p1].first)
  475. S1->slots.erase(p1);
  476. if(!S2->slots[p2].first)
  477. S2->slots.erase(p2);
  478. if(s1->tempOwner<PLAYER_LIMIT)
  479. {
  480. for(int b=0; b<CGI->playerint.size(); ++b)
  481. {
  482. if(CGI->playerint[b]->playerID == s1->tempOwner)
  483. {
  484. CGI->playerint[b]->garrisonChanged(s1);
  485. break;
  486. }
  487. }
  488. }
  489. if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1))
  490. {
  491. for(int b=0; b<CGI->playerint.size(); ++b)
  492. {
  493. if(CGI->playerint[b]->playerID == s2->tempOwner)
  494. {
  495. CGI->playerint[b]->garrisonChanged(s2);
  496. break;
  497. }
  498. }
  499. }
  500. return 0;
  501. }
  502. int CCallback::mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
  503. {
  504. CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
  505. if ((S1->slots[p1].first != S2->slots[p2].first) && (true /*we are allowed to*/))
  506. {
  507. return -1;
  508. }
  509. S2->slots[p2].second += S1->slots[p1].second;
  510. S1->slots[p1].first = NULL;
  511. S1->slots[p1].second = 0;
  512. S1->slots.erase(p1);
  513. if(s1->tempOwner<PLAYER_LIMIT)
  514. {
  515. for(int b=0; b<CGI->playerint.size(); ++b)
  516. {
  517. if(CGI->playerint[b]->playerID == s1->tempOwner)
  518. {
  519. CGI->playerint[b]->garrisonChanged(s1);
  520. break;
  521. }
  522. }
  523. }
  524. if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1))
  525. {
  526. for(int b=0; b<CGI->playerint.size(); ++b)
  527. {
  528. if(CGI->playerint[b]->playerID == s2->tempOwner)
  529. {
  530. CGI->playerint[b]->garrisonChanged(s2);
  531. break;
  532. }
  533. }
  534. }
  535. return 0;
  536. }
  537. int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)
  538. {
  539. if(!val)
  540. return -1;
  541. CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
  542. if ((S1->slots[p1].second<=val) && (true /*we are allowed to*/))
  543. {
  544. return -1;
  545. }
  546. S2->slots[p2].first = S1->slots[p1].first;
  547. S2->slots[p2].second = val;
  548. S1->slots[p1].second -= val;
  549. if(s1->tempOwner<PLAYER_LIMIT)
  550. {
  551. for(int b=0; b<CGI->playerint.size(); ++b)
  552. {
  553. if(CGI->playerint[b]->playerID == s1->tempOwner)
  554. {
  555. CGI->playerint[b]->garrisonChanged(s1);
  556. break;
  557. }
  558. }
  559. }
  560. if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1))
  561. {
  562. for(int b=0; b<CGI->playerint.size(); ++b)
  563. {
  564. if(CGI->playerint[b]->playerID == s2->tempOwner)
  565. {
  566. CGI->playerint[b]->garrisonChanged(s2);
  567. break;
  568. }
  569. }
  570. }
  571. return 0;
  572. }
  573. bool CCallback::dismissHero(const CGHeroInstance *hero)
  574. {
  575. CGHeroInstance * Vhero = const_cast<CGHeroInstance *>(hero);
  576. CGI->mh->removeObject(Vhero);
  577. std::vector<CGHeroInstance*>::iterator nitr = find(CGI->state->players[player].heroes.begin(), CGI->state->players[player].heroes.end(), Vhero);
  578. CGI->state->players[player].heroes.erase(nitr);
  579. LOCPLINT->adventureInt->heroList.updateHList();
  580. return false;
  581. }
  582. int CCallback::getMySerial()
  583. {
  584. return gs->players[player].serial;
  585. }
  586. bool CCallback::swapArifacts(const CGHeroInstance * hero1, bool worn1, int pos1, const CGHeroInstance * hero2, bool worn2, int pos2)
  587. {
  588. if(!hero1 || !hero2) //incorrect data
  589. return false;
  590. CGHeroInstance * Uhero1 = const_cast<CGHeroInstance *>(hero1);
  591. CGHeroInstance * Uhero2 = const_cast<CGHeroInstance *>(hero2);
  592. if(worn1 && worn2)
  593. {
  594. std::swap(Uhero1->artifWorn[pos1], Uhero2->artifWorn[pos2]);
  595. }
  596. else if(worn1 && !worn2)
  597. {
  598. std::swap(Uhero1->artifWorn[pos1], Uhero2->artifacts[pos2]);
  599. }
  600. else if(!worn1 && worn2)
  601. {
  602. std::swap(Uhero1->artifacts[pos1], Uhero2->artifWorn[pos2]);
  603. }
  604. else
  605. {
  606. std::swap(Uhero1->artifacts[pos1], Uhero2->artifacts[pos2]);
  607. }
  608. return true;
  609. }
  610. bool CCallback::buildBuilding(const CGTownInstance *town, int buildingID)
  611. {
  612. CGTownInstance * t = const_cast<CGTownInstance *>(town);
  613. CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
  614. if(0/*not allowed*/)//TODO: check if we are allowed to build
  615. return false;
  616. if(buildingID>36) //upg dwelling
  617. {
  618. if(t->getHordeLevel(0) == (buildingID-37))
  619. t->builtBuildings.insert(19);
  620. else if(t->getHordeLevel(1) == (buildingID-37))
  621. t->builtBuildings.insert(25);
  622. }
  623. else if(buildingID >= 30) //bas. dwelling
  624. {
  625. t->strInfo.creatures[buildingID-30] = CGI->creh->creatures[t->town->basicCreatures[buildingID-30]].growth;
  626. }
  627. t->builtBuildings.insert(buildingID);
  628. for(int i=0;i<7;i++)
  629. gs->players[player].resources[i]-=b->resources[i];
  630. t->builded++;
  631. CGI->playerint[CGI->state->players[player].serial]->buildChanged(town,buildingID,1);
  632. return true;
  633. }
  634. int CCallback::battleGetBattlefieldType()
  635. {
  636. return CGI->mh->ttiles[CGI->state->curB->tile.x][CGI->state->curB->tile.y][CGI->state->curB->tile.z].terType;
  637. }
  638. int CCallback::battleGetObstaclesAtTile(int tile) //returns bitfield
  639. {
  640. //TODO - write
  641. return -1;
  642. }
  643. int CCallback::battleGetStack(int pos)
  644. {
  645. for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
  646. {
  647. if(CGI->state->curB->stacks[g]->position == pos)
  648. return CGI->state->curB->stacks[g]->ID;
  649. }
  650. return -1;
  651. }
  652. CStack CCallback::battleGetStackByID(int ID)
  653. {
  654. for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
  655. {
  656. if(CGI->state->curB->stacks[g]->ID == ID)
  657. return *(CGI->state->curB->stacks[g]);
  658. }
  659. return CStack();
  660. }
  661. int CCallback::battleGetPos(int stack)
  662. {
  663. for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
  664. {
  665. if(CGI->state->curB->stacks[g]->ID == stack)
  666. return CGI->state->curB->stacks[g]->position;
  667. }
  668. return -1;
  669. }
  670. std::map<int, CStack> CCallback::battleGetStacks()
  671. {
  672. std::map<int, CStack> ret;
  673. for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
  674. {
  675. ret[CGI->state->curB->stacks[g]->ID] = *(CGI->state->curB->stacks[g]);
  676. }
  677. return ret;
  678. }
  679. CCreature CCallback::battleGetCreature(int number)
  680. {
  681. for(int h=0; h<CGI->state->curB->stacks.size(); ++h)
  682. {
  683. if(CGI->state->curB->stacks[h]->ID == number) //creature found
  684. return *(CGI->state->curB->stacks[h]->creature);
  685. }
  686. throw new std::exception("Cannot find the creature");
  687. }
  688. std::vector<int> CCallback::battleGetAvailableHexes(int ID)
  689. {
  690. return CGI->state->battleGetRange(ID);
  691. }
  692. bool CCallback::battleIsStackMine(int ID)
  693. {
  694. for(int h=0; h<CGI->state->curB->stacks.size(); ++h)
  695. {
  696. if(CGI->state->curB->stacks[h]->ID == ID) //creature found
  697. return CGI->state->curB->stacks[h]->owner == player;
  698. }
  699. return false;
  700. }
  701. int3 CScriptCallback::getPos(CGObjectInstance * ob)
  702. {
  703. return ob->pos;
  704. }
  705. void CScriptCallback::changePrimSkill(int ID, int which, int val)
  706. {
  707. CGHeroInstance * hero = CGI->state->getHero(ID,0);
  708. if (which<PRIMARY_SKILLS)
  709. {
  710. hero->primSkills[which]+=val;
  711. for (int i=0; i<CGI->playerint.size(); i++)
  712. {
  713. if (CGI->playerint[i]->playerID == hero->getOwner())
  714. {
  715. CGI->playerint[i]->heroPrimarySkillChanged(hero, which, val);
  716. break;
  717. }
  718. }
  719. }
  720. else if (which==4)
  721. {
  722. hero->exp+=val;
  723. if(hero->exp >= CGI->heroh->reqExp(hero->level+1)) //new level
  724. {
  725. hero->level++;
  726. std::cout << hero->name <<" got level "<<hero->level<<std::endl;
  727. int r = rand()%100, pom=0, x=0;
  728. int std::pair<int,int>::*g = (hero->level>9) ? (&std::pair<int,int>::second) : (&std::pair<int,int>::first);
  729. for(;x<PRIMARY_SKILLS;x++)
  730. {
  731. pom += hero->type->heroClass->primChance[x].*g;
  732. if(r<pom)
  733. break;
  734. }
  735. std::cout << "Bohater dostaje umiejetnosc pierwszorzedna " << x << " (wynik losowania "<<r<<")"<<std::endl;
  736. hero->primSkills[x]++;
  737. //TODO: dac dwie umiejetnosci 2-rzedne to wyboru
  738. }
  739. //TODO - powiadomic interfejsy, sprawdzic czy nie ma awansu itp
  740. }
  741. }
  742. int CScriptCallback::getHeroOwner(int heroID)
  743. {
  744. CGHeroInstance * hero = CGI->state->getHero(heroID,0);
  745. return hero->getOwner();
  746. }
  747. void CScriptCallback::showInfoDialog(int player, std::string text, std::vector<SComponent*> * components)
  748. {
  749. //TODO: upewniac sie ze mozemy to zrzutowac (przy customowych interfejsach cos moze sie kopnac)
  750. if (player>=0)
  751. {
  752. CGameInterface * temp = CGI->playerint[CGI->state->players[player].serial];
  753. if (temp->human)
  754. ((CPlayerInterface*)(temp))->showInfoDialog(text,*components);
  755. return;
  756. }
  757. else
  758. {
  759. for (int i=0; i<CGI->playerint.size();i++)
  760. {
  761. if (CGI->playerint[i]->human)
  762. ((CPlayerInterface*)(CGI->playerint[i]))->showInfoDialog(text,*components);
  763. }
  764. }
  765. }
  766. void CScriptCallback::showSelDialog(int player, std::string text, std::vector<CSelectableComponent*>*components, IChosen * asker)
  767. {
  768. CGameInterface * temp = CGI->playerint[CGI->state->players[player].serial];
  769. if (temp->human)
  770. ((CPlayerInterface*)(temp))->showSelDialog(text,*components,(int)asker);
  771. return;
  772. }
  773. int CScriptCallback::getSelectedHero()
  774. {
  775. int ret;
  776. if (LOCPLINT->adventureInt->selection.type == HEROI_TYPE)
  777. ret = ((CGHeroInstance*)(LOCPLINT->adventureInt->selection.selected))->subID;
  778. else
  779. ret = -1;;
  780. return ret;
  781. }
  782. int CScriptCallback::getDate(int mode)
  783. {
  784. int temp;
  785. switch (mode)
  786. {
  787. case 0:
  788. return gs->day;
  789. break;
  790. case 1:
  791. temp = (gs->day)%7;
  792. if (temp)
  793. return temp;
  794. else return 7;
  795. break;
  796. case 2:
  797. temp = ((gs->day-1)/7)+1;
  798. if (!(temp%4))
  799. return 4;
  800. else
  801. return (temp%4);
  802. break;
  803. case 3:
  804. return ((gs->day-1)/28)+1;
  805. break;
  806. }
  807. return 0;
  808. }
  809. void CScriptCallback::giveResource(int player, int which, int val)
  810. {
  811. gs->players[player].resources[which]+=val;
  812. CGI->playerint[gs->players[player].serial]->receivedResource(which,val);
  813. }
  814. void CScriptCallback::showCompInfo(int player, SComponent * comp)
  815. {
  816. CPlayerInterface * i = dynamic_cast<CPlayerInterface*>(CGI->playerint[gs->players[player].serial]);
  817. if(i)
  818. i->showComp(*comp);
  819. }
  820. void CScriptCallback::heroVisitCastle(CGObjectInstance * ob, int heroID)
  821. {
  822. CGTownInstance * n;
  823. if(n = dynamic_cast<CGTownInstance*>(ob))
  824. {
  825. n->visitingHero = CGI->state->getHero(heroID,0);
  826. for(int b=0; b<CGI->playerint.size(); ++b)
  827. {
  828. if(CGI->playerint[b]->playerID == getHeroOwner(heroID))
  829. {
  830. CGI->playerint[b]->heroVisitsTown(CGI->state->getHero(heroID,0),n);
  831. break;
  832. }
  833. }
  834. }
  835. else
  836. return;
  837. }
  838. void CScriptCallback::stopHeroVisitCastle(CGObjectInstance * ob, int heroID)
  839. {
  840. CGTownInstance * n;
  841. if(n = dynamic_cast<CGTownInstance*>(ob))
  842. {
  843. if(n->visitingHero && n->visitingHero->type->ID == heroID)
  844. n->visitingHero = NULL;
  845. return;
  846. }
  847. else
  848. return;
  849. }
  850. void CScriptCallback::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack
  851. {
  852. CGHeroInstance* h = gs->getHero(hid,0);
  853. if(position<0)
  854. {
  855. for(int i=0;i<h->artifacts.size();i++)
  856. {
  857. if(!h->artifacts[i])
  858. {
  859. h->artifacts[i] = &CGI->arth->artifacts[artid];
  860. return;
  861. }
  862. }
  863. h->artifacts.push_back(&CGI->arth->artifacts[artid]);
  864. return;
  865. }
  866. else
  867. {
  868. if(h->artifWorn[position]) //slot is occupied
  869. {
  870. giveHeroArtifact(h->artifWorn[position]->id,hid,-1);
  871. }
  872. h->artifWorn[position] = &CGI->arth->artifacts[artid];
  873. }
  874. }
  875. void CScriptCallback::startBattle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2) //use hero=NULL for no hero
  876. {
  877. gs->battle(army1,army2,tile,hero1,hero2);
  878. }
  879. void CScriptCallback::startBattle(int heroID, CCreatureSet * army, int3 tile) //for hero<=>neutral army
  880. {
  881. CGHeroInstance* h = gs->getHero(heroID,0);
  882. gs->battle(&h->army,army,tile,h,NULL);
  883. }
  884. void CLuaCallback::registerFuncs(lua_State * L)
  885. {
  886. lua_newtable(L);
  887. #define REGISTER_C_FUNC(x) \
  888. lua_pushstring(L, #x); \
  889. lua_pushcfunction(L, x); \
  890. lua_rawset(L, -3)
  891. REGISTER_C_FUNC(getPos);
  892. REGISTER_C_FUNC(changePrimSkill);
  893. REGISTER_C_FUNC(getGnrlText);
  894. REGISTER_C_FUNC(getSelectedHero);
  895. /*
  896. REGISTER_C_FUNC(changePrimSkill);
  897. REGISTER_C_FUNC(getGnrlText);
  898. REGISTER_C_FUNC(changePrimSkill);
  899. REGISTER_C_FUNC(getGnrlText);
  900. REGISTER_C_FUNC(changePrimSkill);
  901. REGISTER_C_FUNC(getGnrlText);*/
  902. lua_setglobal(L, "vcmi");
  903. #undef REGISTER_C_FUNC
  904. }
  905. int CLuaCallback::getPos(lua_State * L)//(CGObjectInstance * object);
  906. {
  907. const int args = lua_gettop(L); // number of arguments
  908. if ((args < 1) || !lua_isnumber(L, 1) )
  909. luaL_error(L,
  910. "Incorrect arguments to getPos([Object address])");
  911. CGObjectInstance * object = (CGObjectInstance *)(lua_tointeger(L, 1));
  912. lua_pushinteger(L,object->pos.x);
  913. lua_pushinteger(L,object->pos.y);
  914. lua_pushinteger(L,object->pos.z);
  915. return 3;
  916. }
  917. int CLuaCallback::changePrimSkill(lua_State * L)//(int ID, int which, int val);
  918. {
  919. const int args = lua_gettop(L); // number of arguments
  920. if ((args < 1) || !lua_isnumber(L, 1) ||
  921. ((args >= 2) && !lua_isnumber(L, 2)) ||
  922. ((args >= 3) && !lua_isnumber(L, 3)) )
  923. {
  924. luaL_error(L,
  925. "Incorrect arguments to changePrimSkill([Hero ID], [Which Primary skill], [Change by])");
  926. }
  927. int ID = lua_tointeger(L, 1),
  928. which = lua_tointeger(L, 2),
  929. val = lua_tointeger(L, 3);
  930. CScriptCallback::changePrimSkill(ID,which,val);
  931. return 0;
  932. }
  933. int CLuaCallback::getGnrlText(lua_State * L) //(int which),returns string
  934. {
  935. const int args = lua_gettop(L); // number of arguments
  936. if ((args < 1) || !lua_isnumber(L, 1) )
  937. luaL_error(L,
  938. "Incorrect arguments to getGnrlText([Text ID])");
  939. int which = lua_tointeger(L,1);
  940. lua_pushstring(L,CGI->generaltexth->allTexts[which].c_str());
  941. return 1;
  942. }
  943. int CLuaCallback::getSelectedHero(lua_State * L) //(),returns int (ID of hero, -1 if no hero is seleceted)
  944. {
  945. int ret;
  946. if (LOCPLINT->adventureInt->selection.type == HEROI_TYPE)
  947. ret = ((CGHeroInstance*)(LOCPLINT->adventureInt->selection.selected))->subID;
  948. else
  949. ret = -1;
  950. lua_pushinteger(L,ret);
  951. return 1;
  952. }