CBattleInterface.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084
  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 "hch\CGeneralTextHandler.h"
  12. #include <queue>
  13. #include <sstream>
  14. extern SDL_Surface * screen;
  15. extern TTF_Font * GEOR13;
  16. extern SDL_Color zwykly;
  17. SDL_Surface * CBattleInterface::cellBorder, * CBattleInterface::cellShade;
  18. CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2)
  19. : printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), givenCommand(NULL), attackingInfo(NULL)
  20. {
  21. //initializing armies
  22. this->army1 = army1;
  23. this->army2 = army2;
  24. std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
  25. for(std::map<int, CStack>::iterator b=stacks.begin(); b!=stacks.end(); ++b)
  26. {
  27. std::pair <int, int> coords = CBattleHex::getXYUnitAnim(b->second.position, b->second.owner == attackingHeroInstance->tempOwner, b->second.creature);
  28. creAnims[b->second.ID] = (new CCreatureAnimation(b->second.creature->animDefName));
  29. creAnims[b->second.ID]->setType(2);
  30. creAnims[b->second.ID]->pos = genRect(creAnims[b->second.ID]->fullHeight, creAnims[b->second.ID]->fullWidth, coords.first, coords.second);
  31. creDir[b->second.ID] = b->second.owner==attackingHeroInstance->tempOwner;
  32. }
  33. //preparing menu background and terrain
  34. std::vector< std::string > & backref = CGI->mh->battleBacks[ LOCPLINT->cb->battleGetBattlefieldType() ];
  35. background = CGI->bitmaph->loadBitmap(backref[ rand() % backref.size()] );
  36. menu = CGI->bitmaph->loadBitmap("CBAR.BMP");
  37. CSDL_Ext::blueToPlayersAdv(menu, hero1->tempOwner);
  38. //preparing graphics for displaying amounts of creatures
  39. amountBasic = CGI->bitmaph->loadBitmap("CMNUMWIN.BMP");
  40. amountNormal = CGI->bitmaph->loadBitmap("CMNUMWIN.BMP");
  41. CSDL_Ext::alphaTransform(amountNormal);
  42. for(int g=0; g<amountNormal->format->palette->ncolors; ++g)
  43. {
  44. if((amountNormal->format->palette->colors+g)->b != 132 &&
  45. (amountNormal->format->palette->colors+g)->g != 231 &&
  46. (amountNormal->format->palette->colors+g)->r != 255) //it's not yellow border
  47. {
  48. (amountNormal->format->palette->colors+g)->r = (float)((amountNormal->format->palette->colors+g)->r) * 0.54f;
  49. (amountNormal->format->palette->colors+g)->g = (float)((amountNormal->format->palette->colors+g)->g) * 0.19f;
  50. (amountNormal->format->palette->colors+g)->b = (float)((amountNormal->format->palette->colors+g)->b) * 0.93f;
  51. }
  52. }
  53. ////blitting menu background and terrain
  54. blitAt(background, 0, 0);
  55. blitAt(menu, 0, 556);
  56. CSDL_Ext::update();
  57. //preparing buttons and console
  58. bOptions = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bOptionsf,this), 3, 561, "icm003.def", false, NULL, false);
  59. bSurrender = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bSurrenderf,this), 54, 561, "icm001.def", false, NULL, false);
  60. bFlee = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bFleef,this), 105, 561, "icm002.def", false, NULL, false);
  61. bAutofight = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bAutofightf,this), 157, 561, "icm004.def", false, NULL, false);
  62. bSpell = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bSpellf,this), 645, 561, "icm005.def", false, NULL, false);
  63. bWait = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bWaitf,this), 696, 561, "icm006.def", false, NULL, false);
  64. bDefence = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bDefencef,this), 747, 561, "icm007.def", false, NULL, false);
  65. bConsoleUp = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bConsoleUpf,this), 624, 561, "ComSlide.def", false, NULL, false);
  66. bConsoleDown = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleInterface::bConsoleDownf,this), 624, 580, "ComSlide.def", false, NULL, false);
  67. bConsoleDown->bitmapOffset = 2;
  68. console = new CBattleConsole();
  69. console->pos.x = 211;
  70. console->pos.y = 560;
  71. console->pos.w = 406;
  72. console->pos.h = 38;
  73. //loading hero animations
  74. if(hero1) // attacking hero
  75. {
  76. attackingHero = new CBattleHero(CGI->mh->battleHeroes[hero1->type->heroType], 0, 0, false, hero1->tempOwner);
  77. attackingHero->pos = genRect(attackingHero->dh->ourImages[0].bitmap->h, attackingHero->dh->ourImages[0].bitmap->w, -40, 0);
  78. }
  79. else
  80. {
  81. attackingHero = NULL;
  82. }
  83. if(hero2) // defending hero
  84. {
  85. defendingHero = new CBattleHero(CGI->mh->battleHeroes[hero2->type->heroType], 0, 0, true, hero2->tempOwner);
  86. defendingHero->pos = genRect(defendingHero->dh->ourImages[0].bitmap->h, defendingHero->dh->ourImages[0].bitmap->w, 690, 0);
  87. }
  88. else
  89. {
  90. defendingHero = NULL;
  91. }
  92. //preparing cells and hexes
  93. cellBorder = CGI->bitmaph->loadBitmap("CCELLGRD.BMP");
  94. CSDL_Ext::alphaTransform(cellBorder);
  95. cellShade = CGI->bitmaph->loadBitmap("CCELLSHD.BMP");
  96. CSDL_Ext::alphaTransform(cellShade);
  97. for(int h=0; h<187; ++h)
  98. {
  99. bfield[h].myNumber = h;
  100. int x = 14 + ((h/17)%2==0 ? 22 : 0) + 44*(h%17);
  101. int y = 86 + 42 * (h/17);
  102. bfield[h].pos = genRect(cellShade->h, cellShade->w, x, y);
  103. bfield[h].accesible = true;
  104. bfield[h].myInterface = this;
  105. }
  106. //locking occupied positions on batlefield
  107. for(std::map<int, CStack>::iterator it = stacks.begin(); it!=stacks.end(); ++it) //stacks gained at top of this function
  108. {
  109. bfield[it->second.position].accesible = false;
  110. }
  111. }
  112. CBattleInterface::~CBattleInterface()
  113. {
  114. SDL_FreeSurface(background);
  115. SDL_FreeSurface(menu);
  116. SDL_FreeSurface(amountBasic);
  117. SDL_FreeSurface(amountNormal);
  118. delete bOptions;
  119. delete bSurrender;
  120. delete bFlee;
  121. delete bAutofight;
  122. delete bSpell;
  123. delete bWait;
  124. delete bDefence;
  125. delete bConsoleUp;
  126. delete bConsoleDown;
  127. delete console;
  128. delete attackingHero;
  129. delete defendingHero;
  130. SDL_FreeSurface(cellBorder);
  131. SDL_FreeSurface(cellShade);
  132. for(std::map< int, CCreatureAnimation * >::iterator g=creAnims.begin(); g!=creAnims.end(); ++g)
  133. delete g->second;
  134. }
  135. void CBattleInterface::activate()
  136. {
  137. bOptions->activate();
  138. bSurrender->activate();
  139. bFlee->activate();
  140. bAutofight->activate();
  141. bSpell->activate();
  142. bWait->activate();
  143. bDefence->activate();
  144. bConsoleUp->activate();
  145. bConsoleDown->activate();
  146. for(int b=0; b<187; ++b)
  147. {
  148. bfield[b].activate();
  149. }
  150. }
  151. void CBattleInterface::deactivate()
  152. {
  153. bOptions->deactivate();
  154. bSurrender->deactivate();
  155. bFlee->deactivate();
  156. bAutofight->deactivate();
  157. bSpell->deactivate();
  158. bWait->deactivate();
  159. bDefence->deactivate();
  160. bConsoleUp->deactivate();
  161. bConsoleDown->deactivate();
  162. for(int b=0; b<187; ++b)
  163. {
  164. bfield[b].deactivate();
  165. }
  166. }
  167. void CBattleInterface::show(SDL_Surface * to)
  168. {
  169. std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks(); //used in a few places
  170. ++animCount;
  171. if(!to) //"evaluating" to
  172. to = screen;
  173. //showing background
  174. blitAt(background, 0, 0, to);
  175. if(printCellBorders) //printing cell borders
  176. {
  177. for(int i=0; i<11; ++i) //rows
  178. {
  179. for(int j=0; j<15; ++j) //columns
  180. {
  181. int x = 58 + (i%2==0 ? 22 : 0) + 44*j;
  182. int y = 86 + 42 * i;
  183. CSDL_Ext::blit8bppAlphaTo24bpp(cellBorder, NULL, to, &genRect(cellBorder->h, cellBorder->w, x, y));
  184. }
  185. }
  186. }
  187. //printing hovered cell
  188. for(int b=0; b<187; ++b)
  189. {
  190. if(bfield[b].strictHovered && bfield[b].hovered)
  191. {
  192. int x = 14 + ((b/17)%2==0 ? 22 : 0) + 44*(b%17);
  193. int y = 86 + 42 * (b/17);
  194. CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &genRect(cellShade->h, cellShade->w, x, y));
  195. }
  196. }
  197. //showing selected unit's range
  198. if(creAnims[activeStack]->getType() != 0) //don't show if unit is moving
  199. {
  200. showRange(to, activeStack);
  201. }
  202. //showing menu background and console
  203. blitAt(menu, 0, 556, to);
  204. console->show(to);
  205. //showing buttons
  206. bOptions->show(to);
  207. bSurrender->show(to);
  208. bFlee->show(to);
  209. bAutofight->show(to);
  210. bSpell->show(to);
  211. bWait->show(to);
  212. bDefence->show(to);
  213. bConsoleUp->show(to);
  214. bConsoleDown->show(to);
  215. //showing hero animations
  216. if(attackingHero)
  217. attackingHero->show(to);
  218. if(defendingHero)
  219. defendingHero->show(to);
  220. //showing units //a lot of work...
  221. int stackByHex[187];
  222. for(int b=0; b<187; ++b)
  223. stackByHex[b] = -1;
  224. for(std::map<int, CStack>::iterator j=stacks.begin(); j!=stacks.end(); ++j)
  225. {
  226. stackByHex[j->second.position] = j->second.ID;
  227. }
  228. attackingShowHelper(); // handle attack animation
  229. for(int b=0; b<187; ++b)
  230. {
  231. if(stackByHex[b]!=-1)
  232. {
  233. creAnims[stackByHex[b]]->nextFrame(to, creAnims[stackByHex[b]]->pos.x, creAnims[stackByHex[b]]->pos.y, creDir[stackByHex[b]], (animCount%2==0 || creAnims[stackByHex[b]]->getType()!=2) && stacks[stackByHex[b]].alive, stackByHex[b]==activeStack); //increment always when moving, never if stack died
  234. //printing amount
  235. if(stacks[stackByHex[b]].amount > 0) //don't print if stack is not alive
  236. {
  237. if(stacks[stackByHex[b]].attackerOwned)
  238. {
  239. CSDL_Ext::blit8bppAlphaTo24bpp(amountNormal, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[stackByHex[b]]->pos.x + 220, creAnims[stackByHex[b]]->pos.y + 260));
  240. std::stringstream ss;
  241. ss<<stacks[stackByHex[b]].amount;
  242. CSDL_Ext::printAtMiddleWB(ss.str(), creAnims[stackByHex[b]]->pos.x + 220 + 14, creAnims[stackByHex[b]]->pos.y + 260 + 4, GEOR13, 20, zwykly, to);
  243. }
  244. else
  245. {
  246. CSDL_Ext::blit8bppAlphaTo24bpp(amountNormal, NULL, to, &genRect(amountNormal->h, amountNormal->w, creAnims[stackByHex[b]]->pos.x + 202, creAnims[stackByHex[b]]->pos.y + 260));
  247. std::stringstream ss;
  248. ss<<stacks[stackByHex[b]].amount;
  249. CSDL_Ext::printAtMiddleWB(ss.str(), creAnims[stackByHex[b]]->pos.x + 202 + 14, creAnims[stackByHex[b]]->pos.y + 260 + 4, GEOR13, 20, zwykly, to);
  250. }
  251. }
  252. }
  253. }
  254. //units shown
  255. }
  256. bool CBattleInterface::reverseCreature(int number, int hex, bool wideTrick)
  257. {
  258. if(creAnims[number]==NULL)
  259. return false; //there is no such creature
  260. creAnims[number]->setType(8);
  261. for(int g=0; g<creAnims[number]->framesInGroup(8); ++g)
  262. {
  263. show();
  264. CSDL_Ext::update();
  265. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  266. }
  267. creDir[number] = !creDir[number];
  268. CStack curs = LOCPLINT->cb->battleGetStackByID(number);
  269. std::pair <int, int> coords = CBattleHex::getXYUnitAnim(hex, creDir[number], curs.creature);
  270. creAnims[number]->pos.x = coords.first;
  271. //creAnims[number]->pos.y = coords.second;
  272. if(wideTrick && curs.creature->isDoubleWide())
  273. {
  274. creAnims[number]->pos.x -= 44;
  275. }
  276. creAnims[number]->setType(7);
  277. for(int g=0; g<creAnims[number]->framesInGroup(7); ++g)
  278. {
  279. show();
  280. CSDL_Ext::update();
  281. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  282. }
  283. creAnims[number]->setType(2);
  284. return true;
  285. }
  286. void CBattleInterface::bOptionsf()
  287. {
  288. }
  289. void CBattleInterface::bSurrenderf()
  290. {
  291. }
  292. void CBattleInterface::bFleef()
  293. {
  294. BattleAction * ba = new BattleAction;
  295. ba->actionType = 4;
  296. givenCommand = ba;
  297. }
  298. void CBattleInterface::bAutofightf()
  299. {
  300. }
  301. void CBattleInterface::bSpellf()
  302. {
  303. }
  304. void CBattleInterface::bWaitf()
  305. {
  306. }
  307. void CBattleInterface::bDefencef()
  308. {
  309. BattleAction * ba = new BattleAction;
  310. ba->actionType = 3;
  311. ba->stackNumber = activeStack;
  312. givenCommand = ba;
  313. }
  314. void CBattleInterface::bConsoleUpf()
  315. {
  316. console->scrollUp();
  317. }
  318. void CBattleInterface::bConsoleDownf()
  319. {
  320. console->scrollDown();
  321. }
  322. void CBattleInterface::newStack(CStack stack)
  323. {
  324. creAnims[stack.ID] = new CCreatureAnimation(stack.creature->animDefName);
  325. creAnims[stack.ID]->setType(2);
  326. creDir[stack.ID] = stack.owner==attackingHeroInstance->tempOwner;
  327. }
  328. void CBattleInterface::stackRemoved(CStack stack)
  329. {
  330. delete creAnims[stack.ID];
  331. creAnims.erase(stack.ID);
  332. }
  333. void CBattleInterface::stackKilled(int ID)
  334. {
  335. creAnims[ID]->setType(5); //death
  336. for(int i=0; i<creAnims[ID]->framesInGroup(5)-1; ++i)
  337. {
  338. show();
  339. CSDL_Ext::update();
  340. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  341. }
  342. }
  343. void CBattleInterface::stackActivated(int number)
  344. {
  345. givenCommand = NULL;
  346. activeStack = number;
  347. }
  348. void CBattleInterface::stackMoved(int number, int destHex, bool startMoving, bool endMoving)
  349. {
  350. //a few useful variables
  351. int curStackPos = LOCPLINT->cb->battleGetPos(number);
  352. int steps = creAnims[number]->framesInGroup(0);
  353. int hexWbase = 44, hexHbase = 42;
  354. if(startMoving) //animation of starting move
  355. {
  356. for(int i=0; i<creAnims[number]->framesInGroup(20); ++i)
  357. {
  358. show();
  359. CSDL_Ext::update();
  360. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  361. }
  362. }
  363. int mutPos = CBattleHex::mutualPosition(curStackPos, destHex);
  364. if(LOCPLINT->cb->battleGetCreature(number).isDoubleWide() &&
  365. ((creDir[number] && mutPos == 5) || (creDir[number] && mutPos == 0) || (creDir[number] && mutPos == 4))) //for special cases
  366. {
  367. switch(CBattleHex::mutualPosition(curStackPos, destHex)) //reverse unit if necessary
  368. {
  369. case 0:
  370. if(creDir[number] == true)
  371. reverseCreature(number, curStackPos, true);
  372. break;
  373. case 1:
  374. if(creDir[number] == false)
  375. reverseCreature(number, curStackPos, true);
  376. break;
  377. case 2:
  378. if(creDir[number] == false)
  379. reverseCreature(number, curStackPos, true);
  380. break;
  381. case 3:
  382. if(creDir[number] == false)
  383. reverseCreature(number, curStackPos, true);
  384. break;
  385. case 4:
  386. if(creDir[number] == true)
  387. reverseCreature(number, curStackPos, true);
  388. break;
  389. case 5:
  390. if(creDir[number] == true)
  391. reverseCreature(number, curStackPos, true);
  392. break;
  393. }
  394. //moving instructions
  395. creAnims[number]->setType(0);
  396. for(int i=0; i<steps; ++i)
  397. {
  398. switch(CBattleHex::mutualPosition(curStackPos, destHex))
  399. {
  400. case 0:
  401. creAnims[number]->pos.x -= hexWbase/(2*steps);
  402. creAnims[number]->pos.y -= hexHbase/steps;
  403. break;
  404. case 1:
  405. creAnims[number]->pos.x += hexWbase/(2*steps);
  406. creAnims[number]->pos.y -= hexHbase/steps;
  407. break;
  408. case 2:
  409. creAnims[number]->pos.x += hexWbase/steps;
  410. break;
  411. case 3:
  412. creAnims[number]->pos.x += hexWbase/(2*steps);
  413. creAnims[number]->pos.y += hexHbase/steps;
  414. break;
  415. case 4:
  416. creAnims[number]->pos.x -= hexWbase/(2*steps);
  417. creAnims[number]->pos.y += hexHbase/steps;
  418. break;
  419. case 5:
  420. creAnims[number]->pos.x -= hexWbase/steps;
  421. break;
  422. }
  423. show();
  424. CSDL_Ext::update();
  425. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  426. }
  427. if( (LOCPLINT->cb->battleGetStackByID(number).owner == attackingHeroInstance->tempOwner ) != creDir[number])
  428. {
  429. reverseCreature(number, curStackPos, true);
  430. }
  431. }
  432. else //normal move instructions
  433. {
  434. switch(CBattleHex::mutualPosition(curStackPos, destHex)) //reverse unit if necessary
  435. {
  436. case 0:
  437. if(creDir[number] == true)
  438. reverseCreature(number, curStackPos);
  439. break;
  440. case 1:
  441. if(creDir[number] == false)
  442. reverseCreature(number, curStackPos);
  443. break;
  444. case 2:
  445. if(creDir[number] == false)
  446. reverseCreature(number, curStackPos);
  447. break;
  448. case 3:
  449. if(creDir[number] == false)
  450. reverseCreature(number, curStackPos);
  451. break;
  452. case 4:
  453. if(creDir[number] == true)
  454. reverseCreature(number, curStackPos);
  455. break;
  456. case 5:
  457. if(creDir[number] == true)
  458. reverseCreature(number, curStackPos);
  459. break;
  460. }
  461. //moving instructions
  462. creAnims[number]->setType(0);
  463. for(int i=0; i<steps; ++i)
  464. {
  465. switch(CBattleHex::mutualPosition(curStackPos, destHex))
  466. {
  467. case 0:
  468. creAnims[number]->pos.x -= hexWbase/(2*steps);
  469. creAnims[number]->pos.y -= hexHbase/steps;
  470. break;
  471. case 1:
  472. creAnims[number]->pos.x += hexWbase/(2*steps);
  473. creAnims[number]->pos.y -= hexHbase/steps;
  474. break;
  475. case 2:
  476. creAnims[number]->pos.x += hexWbase/steps;
  477. break;
  478. case 3:
  479. creAnims[number]->pos.x += hexWbase/(2*steps);
  480. creAnims[number]->pos.y += hexHbase/steps;
  481. break;
  482. case 4:
  483. creAnims[number]->pos.x -= hexWbase/(2*steps);
  484. creAnims[number]->pos.y += hexHbase/steps;
  485. break;
  486. case 5:
  487. creAnims[number]->pos.x -= hexWbase/steps;
  488. break;
  489. }
  490. show();
  491. CSDL_Ext::update();
  492. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  493. }
  494. }
  495. if(endMoving) //animation of ending move
  496. {
  497. for(int i=0; i<creAnims[number]->framesInGroup(21); ++i)
  498. {
  499. show();
  500. CSDL_Ext::update();
  501. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  502. }
  503. }
  504. creAnims[number]->setType(2); //resetting to default
  505. CStack curs = LOCPLINT->cb->battleGetStackByID(number);
  506. if(endMoving) //resetting to default
  507. {
  508. if(creDir[number] != (curs.owner == attackingHeroInstance->tempOwner))
  509. reverseCreature(number, destHex);
  510. //creDir[number] = (curs.owner == attackingHeroInstance->tempOwner);
  511. }
  512. std::pair <int, int> coords = CBattleHex::getXYUnitAnim(destHex, creDir[number], curs.creature);
  513. creAnims[number]->pos.x = coords.first;
  514. creAnims[number]->pos.y = coords.second;
  515. }
  516. void CBattleInterface::stackIsAttacked(int ID)
  517. {
  518. creAnims[ID]->setType(3); //getting hit
  519. for(int i=0; i<creAnims[ID]->framesInGroup(3); ++i)
  520. {
  521. show();
  522. CSDL_Ext::update();
  523. SDL_framerateDelay(LOCPLINT->mainFPSmng);
  524. }
  525. creAnims[ID]->setType(2);
  526. }
  527. void CBattleInterface::stackAttacking(int ID, int dest)
  528. {
  529. CStack aStack = LOCPLINT->cb->battleGetStackByID(ID); //attacking stack
  530. if(aStack.creature->isDoubleWide())
  531. {
  532. switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
  533. {
  534. case 0:
  535. //reverseCreature(ID, aStack.position, true);
  536. break;
  537. case 1:
  538. break;
  539. case 2:
  540. break;
  541. case 3:
  542. break;
  543. case 4:
  544. //reverseCreature(ID, aStack.position, true);
  545. break;
  546. case 5:
  547. reverseCreature(ID, aStack.position, true);
  548. break;
  549. }
  550. }
  551. else //else for if(aStack.creature->isDoubleWide())
  552. {
  553. switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
  554. {
  555. case 0:
  556. reverseCreature(ID, aStack.position, true);
  557. break;
  558. case 1:
  559. break;
  560. case 2:
  561. break;
  562. case 3:
  563. break;
  564. case 4:
  565. reverseCreature(ID, aStack.position, true);
  566. break;
  567. case 5:
  568. reverseCreature(ID, aStack.position, true);
  569. break;
  570. }
  571. }
  572. attackingInfo = new CAttHelper;
  573. attackingInfo->dest = dest;
  574. attackingInfo->frame = 0;
  575. attackingInfo->ID = ID;
  576. attackingInfo->reversing = false;
  577. if(aStack.creature->isDoubleWide())
  578. {
  579. switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
  580. {
  581. case 0:
  582. attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
  583. break;
  584. case 1:
  585. attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
  586. break;
  587. case 2:
  588. attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
  589. break;
  590. case 3:
  591. attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
  592. break;
  593. case 4:
  594. attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
  595. break;
  596. case 5:
  597. attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
  598. break;
  599. }
  600. }
  601. else //else for if(aStack.creature->isDoubleWide())
  602. {
  603. switch(CBattleHex::mutualPosition(aStack.position, dest)) //attack direction
  604. {
  605. case 0:
  606. attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
  607. break;
  608. case 1:
  609. attackingInfo->maxframe = creAnims[ID]->framesInGroup(10);
  610. break;
  611. case 2:
  612. attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
  613. break;
  614. case 3:
  615. attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
  616. break;
  617. case 4:
  618. attackingInfo->maxframe = creAnims[ID]->framesInGroup(12);
  619. break;
  620. case 5:
  621. attackingInfo->maxframe = creAnims[ID]->framesInGroup(11);
  622. break;
  623. }
  624. }
  625. }
  626. void CBattleInterface::newRound(int number)
  627. {
  628. console->addText(CGI->generaltexth->allTexts[412]);
  629. }
  630. void CBattleInterface::hexLclicked(int whichOne)
  631. {
  632. if((whichOne%17)!=0 && (whichOne%17)!=16) //if player is trying to attack enemey unit or move creature stack
  633. {
  634. int atCre = LOCPLINT->cb->battleGetStack(whichOne); //creature at destination tile; -1 if there is no one
  635. //LOCPLINT->cb->battleGetCreature();
  636. if(atCre==-1) //normal move action
  637. {
  638. BattleAction * ba = new BattleAction(); //to be deleted by engine
  639. ba->actionType = 2;
  640. ba->destinationTile = whichOne;
  641. ba->stackNumber = activeStack;
  642. givenCommand = ba;
  643. }
  644. else if(LOCPLINT->cb->battleGetStackByID(atCre).owner != attackingHeroInstance->tempOwner) //attacking
  645. {
  646. BattleAction * ba = new BattleAction(); //to be deleted by engine
  647. ba->actionType = 6;
  648. ba->destinationTile = whichOne;
  649. ba->stackNumber = activeStack;
  650. givenCommand = ba;
  651. }
  652. }
  653. }
  654. void CBattleInterface::showRange(SDL_Surface * to, int ID)
  655. {
  656. std::vector<int> shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(ID);
  657. for(int i=0; i<shadedHexes.size(); ++i)
  658. {
  659. CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[shadedHexes[i]].pos);
  660. }
  661. }
  662. void CBattleInterface::attackingShowHelper()
  663. {
  664. if(attackingInfo && !attackingInfo->reversing)
  665. {
  666. if(attackingInfo->frame == 0)
  667. {
  668. CStack aStack = LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
  669. if(aStack.creature->isDoubleWide())
  670. {
  671. switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
  672. {
  673. case 0:
  674. creAnims[attackingInfo->ID]->setType(10);
  675. break;
  676. case 1:
  677. creAnims[attackingInfo->ID]->setType(10);
  678. break;
  679. case 2:
  680. creAnims[attackingInfo->ID]->setType(11);
  681. break;
  682. case 3:
  683. creAnims[attackingInfo->ID]->setType(12);
  684. break;
  685. case 4:
  686. creAnims[attackingInfo->ID]->setType(12);
  687. break;
  688. case 5:
  689. creAnims[attackingInfo->ID]->setType(11);
  690. break;
  691. }
  692. }
  693. else //else for if(aStack.creature->isDoubleWide())
  694. {
  695. switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
  696. {
  697. case 0:
  698. creAnims[attackingInfo->ID]->setType(10);
  699. break;
  700. case 1:
  701. creAnims[attackingInfo->ID]->setType(10);
  702. break;
  703. case 2:
  704. creAnims[attackingInfo->ID]->setType(11);
  705. break;
  706. case 3:
  707. creAnims[attackingInfo->ID]->setType(12);
  708. break;
  709. case 4:
  710. creAnims[attackingInfo->ID]->setType(12);
  711. break;
  712. case 5:
  713. creAnims[attackingInfo->ID]->setType(11);
  714. break;
  715. }
  716. }
  717. }
  718. else if(attackingInfo->frame == (attackingInfo->maxframe - 1))
  719. {
  720. attackingInfo->reversing = true;
  721. CStack aStack = LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
  722. if(aStack.creature->isDoubleWide())
  723. {
  724. switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
  725. {
  726. case 0:
  727. //reverseCreature(ID, aStack.position, true);
  728. break;
  729. case 1:
  730. break;
  731. case 2:
  732. break;
  733. case 3:
  734. break;
  735. case 4:
  736. //reverseCreature(ID, aStack.position, true);
  737. break;
  738. case 5:
  739. reverseCreature(attackingInfo->ID, aStack.position, true);
  740. break;
  741. }
  742. }
  743. else //else for if(aStack.creature->isDoubleWide())
  744. {
  745. switch(CBattleHex::mutualPosition(aStack.position, attackingInfo->dest)) //attack direction
  746. {
  747. case 0:
  748. reverseCreature(attackingInfo->ID, aStack.position, true);
  749. break;
  750. case 1:
  751. break;
  752. case 2:
  753. break;
  754. case 3:
  755. break;
  756. case 4:
  757. reverseCreature(attackingInfo->ID, aStack.position, true);
  758. break;
  759. case 5:
  760. reverseCreature(attackingInfo->ID, aStack.position, true);
  761. break;
  762. }
  763. }
  764. attackingInfo->reversing = false;
  765. creAnims[attackingInfo->ID]->setType(2);
  766. delete attackingInfo;
  767. attackingInfo = NULL;
  768. }
  769. if(attackingInfo)
  770. {
  771. attackingInfo->frame++;
  772. }
  773. }
  774. }
  775. void CBattleHero::show(SDL_Surface *to)
  776. {
  777. //animation of flag
  778. if(flip)
  779. {
  780. CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 752, 39));
  781. }
  782. else
  783. {
  784. CSDL_Ext::blit8bppAlphaTo24bpp(flag->ourImages[flagAnim].bitmap, NULL, screen, &genRect(flag->ourImages[flagAnim].bitmap->h, flag->ourImages[flagAnim].bitmap->w, 31, 39));
  785. }
  786. {
  787. ++flagAnim;
  788. flagAnim %= flag->ourImages.size();
  789. }
  790. //animation of hero
  791. int tick=-1;
  792. for(int i=0; i<dh->ourImages.size(); ++i)
  793. {
  794. if(dh->ourImages[i].groupNumber==phase)
  795. ++tick;
  796. if(tick==image)
  797. {
  798. SDL_Rect posb = pos;
  799. CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[i].bitmap, NULL, to, &posb);
  800. ++image;
  801. if(dh->ourImages[i+1].groupNumber!=phase) //back to appropriate frame
  802. {
  803. image = 0;
  804. }
  805. break;
  806. }
  807. }
  808. }
  809. CBattleHero::CBattleHero(std::string defName, int phaseG, int imageG, bool flipG, unsigned char player): phase(phaseG), image(imageG), flip(flipG), flagAnim(0)
  810. {
  811. dh = CGI->spriteh->giveDef( defName );
  812. for(int i=0; i<dh->ourImages.size(); ++i) //transforming images
  813. {
  814. if(flip)
  815. {
  816. SDL_Surface * hlp = CSDL_Ext::rotate01(dh->ourImages[i].bitmap);
  817. SDL_FreeSurface(dh->ourImages[i].bitmap);
  818. dh->ourImages[i].bitmap = hlp;
  819. }
  820. dh->ourImages[i].bitmap = CSDL_Ext::alphaTransform(dh->ourImages[i].bitmap);
  821. }
  822. dh->alphaTransformed = true;
  823. if(flip)
  824. flag = CGI->spriteh->giveDef("CMFLAGR.DEF");
  825. else
  826. flag = CGI->spriteh->giveDef("CMFLAGL.DEF");
  827. //coloring flag and adding transparency
  828. for(int i=0; i<flag->ourImages.size(); ++i)
  829. {
  830. flag->ourImages[i].bitmap = CSDL_Ext::alphaTransform(flag->ourImages[i].bitmap);
  831. CSDL_Ext::blueToPlayersAdv(flag->ourImages[i].bitmap, player);
  832. }
  833. }
  834. CBattleHero::~CBattleHero()
  835. {
  836. delete dh;
  837. delete flag;
  838. }
  839. std::pair<int, int> CBattleHex::getXYUnitAnim(int hexNum, bool attacker, CCreature * creature)
  840. {
  841. std::pair<int, int> ret = std::make_pair(-500, -500); //returned value
  842. ret.second = -139 + 42 * (hexNum/17); //counting y
  843. //counting x
  844. if(attacker)
  845. {
  846. ret.first = -160 + 22 * ( ((hexNum/17) + 1)%2 ) + 44 * (hexNum % 17);
  847. }
  848. else
  849. {
  850. ret.first = -219 + 22 * ( ((hexNum/17) + 1)%2 ) + 44 * (hexNum % 17);
  851. }
  852. //shifting position for double - hex creatures
  853. if(creature->isDoubleWide())
  854. {
  855. if(attacker)
  856. {
  857. ret.first -= 42;
  858. }
  859. else
  860. {
  861. ret.first += 42;
  862. }
  863. }
  864. //returning
  865. return ret;
  866. }
  867. signed char CBattleHex::mutualPosition(int hex1, int hex2)
  868. {
  869. if(hex2 == hex1 - ( (hex1/17)%2 ? 18 : 17 )) //top left
  870. return 0;
  871. if(hex2 == hex1 - ( (hex1/17)%2 ? 17 : 16 )) //top right
  872. return 1;
  873. if(hex2 == hex1 - 1 && hex1%17 != 0) //left
  874. return 5;
  875. if(hex2 == hex1 + 1 && hex1%17 != 16) //right
  876. return 2;
  877. if(hex2 == hex1 + ( (hex1/17)%2 ? 16 : 17 )) //bottom left
  878. return 4;
  879. if(hex2 == hex1 + ( (hex1/17)%2 ? 17 : 18 )) //bottom right
  880. return 3;
  881. return -1;
  882. }
  883. void CBattleHex::activate()
  884. {
  885. Hoverable::activate();
  886. MotionInterested::activate();
  887. ClickableL::activate();
  888. ClickableR::activate();
  889. }
  890. void CBattleHex::deactivate()
  891. {
  892. Hoverable::deactivate();
  893. MotionInterested::deactivate();
  894. ClickableL::deactivate();
  895. ClickableR::deactivate();
  896. }
  897. void CBattleHex::hover(bool on)
  898. {
  899. hovered = on;
  900. Hoverable::hover(on);
  901. }
  902. CBattleHex::CBattleHex() : myNumber(-1), accesible(true), hovered(false), strictHovered(false), myInterface(NULL)
  903. {
  904. }
  905. void CBattleHex::mouseMoved(SDL_MouseMotionEvent &sEvent)
  906. {
  907. if(CBattleInterface::cellShade)
  908. {
  909. if(CSDL_Ext::SDL_GetPixel(CBattleInterface::cellShade, sEvent.x-pos.x, sEvent.y-pos.y) == 0) //hovered pixel is outside hex
  910. {
  911. strictHovered = false;
  912. }
  913. else //hovered pixel is inside hex
  914. {
  915. strictHovered = true;
  916. }
  917. }
  918. }
  919. void CBattleHex::clickLeft(boost::logic::tribool down)
  920. {
  921. if(!down && hovered && strictHovered) //we've been really clicked!
  922. {
  923. myInterface->hexLclicked(myNumber);
  924. }
  925. }
  926. void CBattleHex::clickRight(boost::logic::tribool down)
  927. {
  928. int stID = LOCPLINT->cb->battleGetStack(myNumber); //id of stack being on this tile
  929. if(hovered && strictHovered && stID!=-1)
  930. {
  931. CStack myst = LOCPLINT->cb->battleGetStackByID(stID); //stack info
  932. StackState *pom = NULL;
  933. if(down)
  934. {
  935. pom = new StackState();
  936. const CGHeroInstance *h = myst.owner == myInterface->attackingHeroInstance->tempOwner ? myInterface->attackingHeroInstance : myInterface->defendingHeroInstance;
  937. if(h)
  938. {
  939. pom->attackBonus = h->primSkills[0];
  940. pom->defenseBonus = h->primSkills[1];
  941. pom->luck = h->getCurrentLuck();
  942. pom->morale = h->getCurrentMorale();
  943. }
  944. (new CCreInfoWindow(myst.creature->idNumber,0,pom,boost::function<void()>(),boost::function<void()>()))
  945. ->activate();
  946. }
  947. delete pom;
  948. }
  949. }
  950. CBattleConsole::CBattleConsole() : lastShown(-1)
  951. {
  952. }
  953. CBattleConsole::~CBattleConsole()
  954. {
  955. texts.clear();
  956. }
  957. void CBattleConsole::show(SDL_Surface * to)
  958. {
  959. if(texts.size())
  960. {
  961. if(texts.size()==1)
  962. {
  963. CSDL_Ext::printAtMiddleWB(texts[0], pos.x + pos.w/2, pos.y + 10, GEOR13, 80, zwykly, to);
  964. }
  965. else
  966. {
  967. CSDL_Ext::printAtMiddleWB(texts[lastShown-1], pos.x + pos.w/2, pos.y + 10, GEOR13, 80, zwykly, to);
  968. CSDL_Ext::printAtMiddleWB(texts[lastShown], pos.x + pos.w/2, pos.y + 26, GEOR13, 80, zwykly, to);
  969. }
  970. }
  971. }
  972. bool CBattleConsole::addText(std::string text)
  973. {
  974. if(text.size()>70)
  975. return false; //text too long!
  976. texts.push_back(text);
  977. lastShown++;
  978. return true;
  979. }
  980. void CBattleConsole::eraseText(unsigned int pos)
  981. {
  982. if(pos < texts.size())
  983. {
  984. texts.erase(texts.begin() + pos);
  985. if(lastShown == texts.size())
  986. --lastShown;
  987. }
  988. }
  989. void CBattleConsole::changeTextAt(std::string text, unsigned int pos)
  990. {
  991. if(pos >= texts.size()) //no such pos
  992. return;
  993. texts[pos] = text;
  994. }
  995. void CBattleConsole::scrollUp(unsigned int by)
  996. {
  997. if(lastShown > by)
  998. lastShown -= by;
  999. }
  1000. void CBattleConsole::scrollDown(unsigned int by)
  1001. {
  1002. if(lastShown + by < texts.size())
  1003. lastShown += by;
  1004. }