CCallback.cpp 29 KB

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