CBattleInterface.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. #include "CBattleInterface.h"
  2. #include "CGameInfo.h"
  3. #include "hch\CLodHandler.h"
  4. #include "SDL_Extensions.h"
  5. #include "CAdvmapInterface.h"
  6. #include "AdventureMapButton.h"
  7. #include "hch\CHeroHandler.h"
  8. #include "hch\CDefHandler.h"
  9. #include "CCallback.h"
  10. #include "CGameState.h"
  11. #include <queue>
  12. extern SDL_Surface * screen;
  13. SDL_Surface * CBattleInterface::cellBorder, * CBattleInterface::cellShade;
  14. CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2)
  15. : printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1)
  16. {
  17. //initializing armies
  18. this->army1 = army1;
  19. this->army2 = army2;
  20. std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
  21. for(std::map<int, CStack>::iterator b=stacks.begin(); b!=stacks.end(); ++b)
  22. {
  23. creAnims[b->second.ID] = (new CCreatureAnimation(b->second.creature->animDefName));
  24. creAnims[b->second.ID]->setType(2);
  25. }
  26. //preparing menu background and terrain
  27. std::vector< std::string > & backref = CGI->mh->battleBacks[ LOCPLINT->cb->battleGetBattlefieldType() ];
  28. background = CGI->bitmaph->loadBitmap(backref[ rand() % backref.size()] );
  29. menu = CGI->bitmaph->loadBitmap("CBAR.BMP");
  30. CSDL_Ext::blueToPlayersAdv(menu, hero1->tempOwner);
  31. //blitting menu background and terrain
  32. blitAt(background, 0, 0);
  33. blitAt(menu, 0, 556);
  34. CSDL_Ext::update();
  35. //preparing buttons
  36. bOptions = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bOptionsf, 3, 561, "icm003.def", this, false, NULL, false);
  37. bSurrender = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bSurrenderf, 54, 561, "icm001.def", this, false, NULL, false);
  38. bFlee = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bFleef, 105, 561, "icm002.def", this, false, NULL, false);
  39. bAutofight = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bAutofightf, 157, 561, "icm004.def", this, false, NULL, false);
  40. bSpell = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bSpellf, 645, 561, "icm005.def", this, false, NULL, false);
  41. bWait = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bWaitf, 696, 561, "icm006.def", this, false, NULL, false);
  42. bDefence = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bDefencef, 747, 561, "icm007.def", this, false, NULL, false);
  43. bConsoleUp = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bConsoleUpf, 624, 561, "ComSlide.def", this, false, NULL, false);
  44. bConsoleDown = new AdventureMapButton<CBattleInterface> (std::string(), std::string(), &CBattleInterface::bConsoleDownf, 624, 580, "ComSlide.def", this, false, NULL, false);
  45. bConsoleDown->bitmapOffset = 2;
  46. //loading hero animations
  47. if(hero1) // attacking hero
  48. {
  49. attackingHero = new CBattleHero(CGI->mh->battleHeroes[hero1->type->heroType], 0, 0, false, hero1->tempOwner);
  50. attackingHero->pos = genRect(attackingHero->dh->ourImages[0].bitmap->h, attackingHero->dh->ourImages[0].bitmap->w, -40, 0);
  51. }
  52. else
  53. {
  54. attackingHero = NULL;
  55. }
  56. if(hero2) // defending hero
  57. {
  58. defendingHero = new CBattleHero(CGI->mh->battleHeroes[hero2->type->heroType], 0, 0, true, hero2->tempOwner);
  59. defendingHero->pos = genRect(defendingHero->dh->ourImages[0].bitmap->h, defendingHero->dh->ourImages[0].bitmap->w, 690, 0);
  60. }
  61. else
  62. {
  63. defendingHero = NULL;
  64. }
  65. //preparing cells and hexes
  66. cellBorder = CGI->bitmaph->loadBitmap("CCELLGRD.BMP");
  67. cellBorder = CSDL_Ext::alphaTransform(cellBorder);
  68. cellShade = CGI->bitmaph->loadBitmap("CCELLSHD.BMP");
  69. cellShade = CSDL_Ext::alphaTransform(cellShade);
  70. for(int h=0; h<187; ++h)
  71. {
  72. bfield[h].myNumber = h;
  73. int x = 14 + ((h/17)%2==0 ? 22 : 0) + 44*(h%17);
  74. int y = 86 + 42 * (h/17);
  75. bfield[h].pos = genRect(cellShade->h, cellShade->w, x, y);
  76. bfield[h].accesible = true;
  77. bfield[h].myInterface = this;
  78. }
  79. //locking occupied positions on batlefield
  80. for(std::map<int, CStack>::iterator it = stacks.begin(); it!=stacks.end(); ++it) //stacks gained at top of this function
  81. {
  82. bfield[it->second.position].accesible = false;
  83. }
  84. }
  85. CBattleInterface::~CBattleInterface()
  86. {
  87. SDL_FreeSurface(background);
  88. SDL_FreeSurface(menu);
  89. delete bOptions;
  90. delete bSurrender;
  91. delete bFlee;
  92. delete bAutofight;
  93. delete bSpell;
  94. delete bWait;
  95. delete bDefence;
  96. delete bConsoleUp;
  97. delete bConsoleDown;
  98. delete attackingHero;
  99. delete defendingHero;
  100. SDL_FreeSurface(cellBorder);
  101. SDL_FreeSurface(cellShade);
  102. for(int g=0; g<creAnims.size(); ++g)
  103. delete creAnims[g];
  104. }
  105. void CBattleInterface::activate()
  106. {
  107. bOptions->activate();
  108. bSurrender->activate();
  109. bFlee->activate();
  110. bAutofight->activate();
  111. bSpell->activate();
  112. bWait->activate();
  113. bDefence->activate();
  114. bConsoleUp->activate();
  115. bConsoleDown->activate();
  116. for(int b=0; b<187; ++b)
  117. {
  118. bfield[b].activate();
  119. }
  120. }
  121. void CBattleInterface::deactivate()
  122. {
  123. bOptions->deactivate();
  124. bSurrender->deactivate();
  125. bFlee->deactivate();
  126. bAutofight->deactivate();
  127. bSpell->deactivate();
  128. bWait->deactivate();
  129. bDefence->deactivate();
  130. bConsoleUp->deactivate();
  131. bConsoleDown->deactivate();
  132. for(int b=0; b<187; ++b)
  133. {
  134. bfield[b].deactivate();
  135. }
  136. }
  137. void CBattleInterface::show(SDL_Surface * to)
  138. {
  139. std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks(); //used in a few places
  140. ++animCount;
  141. if(!to) //"evaluating" to
  142. to = screen;
  143. //showing background
  144. blitAt(background, 0, 0, to);
  145. if(printCellBorders) //printing cell borders
  146. {
  147. for(int i=0; i<11; ++i) //rows
  148. {
  149. for(int j=0; j<15; ++j) //columns
  150. {
  151. int x = 58 + (i%2==0 ? 22 : 0) + 44*j;
  152. int y = 86 + 42 * i;
  153. CSDL_Ext::blit8bppAlphaTo24bpp(cellBorder, NULL, to, &genRect(cellBorder->h, cellBorder->w, x, y));
  154. }
  155. }
  156. }
  157. //printing hovered cell
  158. for(int b=0; b<187; ++b)
  159. {
  160. if(bfield[b].strictHovered && bfield[b].hovered)
  161. {
  162. int x = 14 + ((b/17)%2==0 ? 22 : 0) + 44*(b%17);
  163. int y = 86 + 42 * (b/17);
  164. CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &genRect(cellShade->h, cellShade->w, x, y));
  165. }
  166. }
  167. //showing selected unit's range
  168. for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
  169. {
  170. if(j->first == activeStack) //print range of selected unit //TODO: check if it is to be done
  171. {
  172. showRange(to, stacks[j->first].position, LOCPLINT->cb->battleGetCreature(j->first).speed);
  173. break;
  174. }
  175. }
  176. //showing menu background
  177. blitAt(menu, 0, 556, to);
  178. //showing buttons
  179. bOptions->show(to);
  180. bSurrender->show(to);
  181. bFlee->show(to);
  182. bAutofight->show(to);
  183. bSpell->show(to);
  184. bWait->show(to);
  185. bDefence->show(to);
  186. bConsoleUp->show(to);
  187. bConsoleDown->show(to);
  188. //showing hero animations
  189. if(attackingHero)
  190. attackingHero->show(to);
  191. if(defendingHero)
  192. defendingHero->show(to);
  193. //showing units //a lot of work...
  194. for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
  195. {
  196. std::pair <int, int> coords = CBattleHex::getXYUnitAnim(stacks[j->first].position, stacks[j->first].owner == attackingHeroInstance->tempOwner);
  197. j->second->nextFrame(to, coords.first, coords.second, stacks[j->first].owner == attackingHeroInstance->tempOwner, animCount%2==0, j->first==activeStack);
  198. }
  199. //units shown
  200. CSDL_Ext::update();
  201. }
  202. void CBattleInterface::bOptionsf()
  203. {
  204. }
  205. void CBattleInterface::bSurrenderf()
  206. {
  207. }
  208. void CBattleInterface::bFleef()
  209. {
  210. for(int i=0; i<LOCPLINT->objsToBlit.size(); ++i)
  211. {
  212. if( dynamic_cast<CBattleInterface*>( LOCPLINT->objsToBlit[i] ) )
  213. {
  214. LOCPLINT->objsToBlit.erase(LOCPLINT->objsToBlit.begin()+i);
  215. }
  216. }
  217. deactivate();
  218. LOCPLINT->adventureInt->activate();
  219. delete this;
  220. }
  221. void CBattleInterface::bAutofightf()
  222. {
  223. }
  224. void CBattleInterface::bSpellf()
  225. {
  226. }
  227. void CBattleInterface::bWaitf()
  228. {
  229. }
  230. void CBattleInterface::bDefencef()
  231. {
  232. }
  233. void CBattleInterface::bConsoleUpf()
  234. {
  235. }
  236. void CBattleInterface::bConsoleDownf()
  237. {
  238. }
  239. void CBattleInterface::newStack(CStack stack)
  240. {
  241. creAnims[stack.ID] = new CCreatureAnimation(stack.creature->animDefName);
  242. creAnims[stack.ID]->setType(2);
  243. }
  244. void CBattleInterface::stackRemoved(CStack stack)
  245. {
  246. delete creAnims[stack.ID];
  247. creAnims.erase(stack.ID);
  248. }
  249. void CBattleInterface::stackActivated(int number)
  250. {
  251. activeStack = number;
  252. }
  253. void CBattleInterface::stackMoved(int number, int destHex)
  254. {
  255. }
  256. void CBattleInterface::hexLclicked(int whichOne)
  257. {
  258. if((whichOne%17)!=0 && (whichOne%17)!=16)
  259. LOCPLINT->cb->battleMoveCreature(activeStack, whichOne);
  260. }
  261. void CBattleInterface::showRange(SDL_Surface * to, int initialPlace, int radius)
  262. {
  263. int dists[187]; //calculated distances
  264. std::queue<int> hexq; //bfs queue
  265. hexq.push(initialPlace);
  266. for(int g=0; g<187; ++g)
  267. dists[g] = 100000000;
  268. dists[initialPlace] = 0;
  269. int curNext = -1; //for bfs loop only (helper var)
  270. while(!hexq.empty()) //bfs loop
  271. {
  272. int curHex = hexq.front();
  273. hexq.pop();
  274. curNext = curHex - ( (curHex/17)%2 ? 17 : 18 );
  275. if((curNext > 0) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
  276. {
  277. hexq.push(curNext);
  278. dists[curNext] = dists[curHex] + 1;
  279. }
  280. curNext = curHex - ( (curHex/17)%2 ? 16 : 17 );
  281. if((curNext > 0) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
  282. {
  283. hexq.push(curNext);
  284. dists[curNext] = dists[curHex] + 1;
  285. }
  286. curNext = curHex - 1;
  287. if((curNext > 0) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
  288. {
  289. hexq.push(curNext);
  290. dists[curNext] = dists[curHex] + 1;
  291. }
  292. curNext = curHex + 1;
  293. if((curNext < 187) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
  294. {
  295. hexq.push(curNext);
  296. dists[curNext] = dists[curHex] + 1;
  297. }
  298. curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
  299. if((curNext < 187) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
  300. {
  301. hexq.push(curNext);
  302. dists[curNext] = dists[curHex] + 1;
  303. }
  304. curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
  305. if((curNext < 187) && bfield[curNext].accesible && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
  306. {
  307. hexq.push(curNext);
  308. dists[curNext] = dists[curHex] + 1;
  309. }
  310. }
  311. for(int i=0; i<187; ++i)
  312. {
  313. if(dists[i]<=radius)
  314. {
  315. CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[i].pos);
  316. }
  317. }
  318. }
  319. void CBattleHero::show(SDL_Surface *to)
  320. {
  321. int tick=-1;
  322. for(int i=0; i<dh->ourImages.size(); ++i)
  323. {
  324. if(dh->ourImages[i].groupNumber==phase)
  325. ++tick;
  326. if(tick==image)
  327. {
  328. SDL_Rect posb = pos;
  329. CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[i].bitmap, NULL, to, &posb);
  330. ++image;
  331. if(dh->ourImages[i+1].groupNumber!=phase) //back to appropriate frame
  332. {
  333. image = 0;
  334. }
  335. break;
  336. }
  337. }
  338. if(flip)
  339. {
  340. CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 752, 39));
  341. }
  342. else
  343. {
  344. CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 31, 39));
  345. }
  346. {
  347. ++flagAnim;
  348. flagAnim %= flag->ourImages.size();
  349. }
  350. }
  351. CBattleHero::CBattleHero(std::string defName, int phaseG, int imageG, bool flipG, unsigned char player): phase(phaseG), image(imageG), flip(flipG), flagAnim(0)
  352. {
  353. dh = CGI->spriteh->giveDef( defName );
  354. for(int i=0; i<dh->ourImages.size(); ++i) //transforming images
  355. {
  356. if(flip)
  357. dh->ourImages[i].bitmap = CSDL_Ext::rotate01(dh->ourImages[i].bitmap);
  358. dh->ourImages[i].bitmap = CSDL_Ext::alphaTransform(dh->ourImages[i].bitmap);
  359. }
  360. dh->alphaTransformed = true;
  361. if(flip)
  362. flag = CGI->spriteh->giveDef("CMFLAGR.DEF");
  363. else
  364. flag = CGI->spriteh->giveDef("CMFLAGL.DEF");
  365. //coloring flag and adding transparency
  366. for(int i=0; i<flag->ourImages.size(); ++i)
  367. {
  368. flag->ourImages[i].bitmap = CSDL_Ext::alphaTransform(flag->ourImages[i].bitmap);
  369. CSDL_Ext::blueToPlayersAdv(flag->ourImages[i].bitmap, player);
  370. }
  371. }
  372. CBattleHero::~CBattleHero()
  373. {
  374. delete dh;
  375. delete flag;
  376. }
  377. std::pair<int, int> CBattleHex::getXYUnitAnim(int hexNum, bool attacker)
  378. {
  379. std::pair<int, int> ret = std::make_pair(-500, -500); //returned value
  380. ret.second = -139 + 42 * (hexNum/17); //counting y
  381. //counting x
  382. if(attacker)
  383. {
  384. ret.first = -160 + 22 * ( ((hexNum/17) + 1)%2 ) + 44 * (hexNum % 17);
  385. }
  386. else
  387. {
  388. ret.first = -219 + 22 * ( ((hexNum/17) + 1)%2 ) + 44 * (hexNum % 17);
  389. }
  390. //returning
  391. return ret;
  392. }
  393. void CBattleHex::activate()
  394. {
  395. Hoverable::activate();
  396. MotionInterested::activate();
  397. ClickableL::activate();
  398. }
  399. void CBattleHex::deactivate()
  400. {
  401. Hoverable::deactivate();
  402. MotionInterested::deactivate();
  403. ClickableL::deactivate();
  404. }
  405. void CBattleHex::hover(bool on)
  406. {
  407. hovered = on;
  408. Hoverable::hover(on);
  409. }
  410. CBattleHex::CBattleHex() : myNumber(-1), accesible(true), hovered(false), strictHovered(false), myInterface(NULL)
  411. {
  412. }
  413. void CBattleHex::mouseMoved(SDL_MouseMotionEvent &sEvent)
  414. {
  415. if(CBattleInterface::cellShade)
  416. {
  417. if(CSDL_Ext::SDL_GetPixel(CBattleInterface::cellShade, sEvent.x-pos.x, sEvent.y-pos.y) == 0) //hovered pixel is outside hex
  418. {
  419. strictHovered = false;
  420. }
  421. else //hovered pixel is inside hex
  422. {
  423. strictHovered = true;
  424. }
  425. }
  426. }
  427. void CBattleHex::clickLeft(boost::logic::tribool down)
  428. {
  429. if(!down && hovered && strictHovered) //we've been really clicked!
  430. {
  431. myInterface->hexLclicked(myNumber);
  432. }
  433. }