PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/source/dialogs/attackpanel.cpp

https://bitbucket.org/gcubar/asc
C++ | 380 lines | 283 code | 85 blank | 12 comment | 46 complexity | 3482209104de6171e42175c38d41bf2a MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /***************************************************************************
  2. * *
  3. * This program is free software; you can redistribute it and/or modify *
  4. * it under the terms of the GNU General Public License as published by *
  5. * the Free Software Foundation; either version 2 of the License, or *
  6. * (at your option) any later version. *
  7. * *
  8. ***************************************************************************/
  9. #include <pgimage.h>
  10. #include <pgtooltiphelp.h>
  11. #include "attackpanel.h"
  12. #include "../paradialog.h"
  13. #include "../attack.h"
  14. #include "../explosivemines.h"
  15. #include "../iconrepository.h"
  16. #include "../soundList.h"
  17. #include "../gamemap.h"
  18. #include "../events.h"
  19. #include "../gameoptions.h"
  20. #include "../windowing.h"
  21. #include "../sdl/graphicsqueue.h"
  22. #define USE_COLOR_CONSTANTS
  23. #include <pgcolors.h>
  24. class GetAttackerImage : public FightVisitor {
  25. private:
  26. const SDL_Rect dst;
  27. Surface& surf;
  28. void paint( UnitAttacksSomething& battle )
  29. {
  30. battle.getAttackingUnit()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getAttackingUnit()->getOwningPlayer().getPlayerColor() );
  31. }
  32. public:
  33. GetAttackerImage( tfight& battle, Surface& surface, const SDL_Rect& dest ) : dst ( dest ), surf( surface )
  34. {
  35. battle.visit( *this );
  36. };
  37. void visit( tunitattacksobject& battle ) { paint(battle); };
  38. void visit( tunitattacksbuilding& battle ) { paint(battle); };
  39. void visit( tunitattacksunit& battle ) { paint(battle); };
  40. void visit( tmineattacksunit& battle )
  41. {
  42. Mine* m = battle.getFirstMine();
  43. if ( m )
  44. m->paint( surf, SPoint( dst.x, dst.y ) );
  45. }
  46. };
  47. class GetTargetImage : public FightVisitor {
  48. private:
  49. const SDL_Rect dst;
  50. Surface& surf;
  51. public:
  52. GetTargetImage( tfight& battle, Surface& surface, const SDL_Rect& dest ) : dst ( dest ), surf( surface )
  53. {
  54. battle.visit( *this );
  55. };
  56. void visit( tunitattacksobject& battle )
  57. {
  58. battle.getTarget()->typ->display( surf, SPoint( dst.x, dst.y ) );
  59. };
  60. void visit( tmineattacksunit& battle )
  61. {
  62. battle.getTarget()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getTarget()->getOwningPlayer().getPlayerColor() );
  63. }
  64. void visit( tunitattacksbuilding& battle )
  65. {
  66. battle.getTarget()->paintSingleField( surf, SPoint(dst.x, dst.y), battle.getTarget()->typ->entry );
  67. };
  68. void visit( tunitattacksunit& battle )
  69. {
  70. battle.getTarget()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getTarget()->getOwningPlayer().getPlayerColor() );
  71. };
  72. };
  73. class AttackPanel : public Panel {
  74. tfight& engine;
  75. int attacker_exp;
  76. int defender_exp;
  77. public:
  78. AttackPanel ( tfight& engine_ ) ;
  79. void setBarGraphValue( const ASCString& widgetName, float fraction ) { Panel::setBargraphValue( widgetName, fraction ); };
  80. void setLabelText ( const ASCString& widgetName, int i ) { Panel::setLabelText ( widgetName, i ); };
  81. void setLabelText ( const ASCString& widgetName, const ASCString& i ) { Panel::setLabelText ( widgetName, i ); };
  82. void dispValue ( const ASCString& name, float value, float maxvalue, PG_Color color );
  83. void setBarGraphColor( const ASCString& widgetName, PG_Color color ) { Panel::setBarGraphColor( widgetName, color ); };
  84. void painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst);
  85. private:
  86. void registerSpecialDisplay( const ASCString& name );
  87. };
  88. AttackPanel::AttackPanel ( tfight& engine_ ) : Panel( PG_Application::GetWidgetById(ASC_PG_App::mainScreenID), PG_Rect(0,0,170,200), "Attack" ), engine( engine_ )
  89. {
  90. registerSpecialDisplay( "attacker_unit_pic" );
  91. registerSpecialDisplay( "defender_unit_pic" );
  92. registerSpecialDisplay( "attacker_unitexp" );
  93. registerSpecialDisplay( "defender_unitexp" );
  94. registerSpecialDisplay( "attacker_level" );
  95. registerSpecialDisplay( "defender_level" );
  96. registerSpecialDisplay( "attacker_weaponsymbol" );
  97. registerSpecialDisplay( "defender_weaponsymbol" );
  98. attacker_exp = engine.av.experience;
  99. defender_exp = engine.dv.experience;
  100. }
  101. void AttackPanel::registerSpecialDisplay( const ASCString& name )
  102. {
  103. SpecialDisplayWidget* sdw = dynamic_cast<SpecialDisplayWidget*>( FindChild( name, true ) );
  104. if ( sdw )
  105. sdw->display.connect( SigC::slot( *this, &AttackPanel::painter ));
  106. }
  107. void AttackPanel::painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst)
  108. {
  109. Surface s = Surface::Wrap( PG_Application::GetScreen() );
  110. if ( name == "attacker_unit_pic" ) {
  111. GetAttackerImage( engine, s, dst );
  112. return;
  113. }
  114. if ( name == "defender_unit_pic" ) {
  115. GetTargetImage( engine, s, dst );
  116. return;
  117. }
  118. if ( name == "attacker_unitexp" ) {
  119. s.Blit( IconRepository::getIcon("experience" + ASCString::toString(attacker_exp) + ".png"), SPoint(dst.x, dst.y) );
  120. return;
  121. }
  122. if ( name == "defender_unitexp" ) {
  123. s.Blit( IconRepository::getIcon("experience" + ASCString::toString(defender_exp) + ".png"), SPoint(dst.x, dst.y) );
  124. return;
  125. }
  126. if ( name == "attacker_level" && engine.av.height ) {
  127. s.Blit( IconRepository::getIcon("height-a" + ASCString::toString(getFirstBit(engine.av.height)) + ".png"), SPoint(dst.x, dst.y) );
  128. return;
  129. }
  130. if ( name == "defender_level" && engine.dv.height ) {
  131. s.Blit( IconRepository::getIcon("height-a" + ASCString::toString(getFirstBit(engine.dv.height)) + ".png"), SPoint(dst.x, dst.y) );
  132. return;
  133. }
  134. if ( name == "attacker_weaponsymbol" && engine.av.weapontype >= 0 ) {
  135. s.Blit( IconRepository::getIcon(SingleWeapon::getIconFileName( engine.av.weapontype ) + "-small.png"), SPoint(dst.x, dst.y) );
  136. return;
  137. }
  138. if ( name == "defender_weaponsymbol" && engine.dv.weapontype >= 0 ) {
  139. s.Blit( IconRepository::getIcon(SingleWeapon::getIconFileName( engine.dv.weapontype ) + "-small.png"), SPoint(dst.x, dst.y) );
  140. return;
  141. }
  142. }
  143. void AttackPanel::dispValue ( const ASCString& name, float value, float maxvalue, PG_Color color )
  144. {
  145. if ( value > 0 ) {
  146. setBarGraphColor( name + "bar", color );
  147. if ( value > maxvalue )
  148. setBarGraphValue( name + "bar", 1 );
  149. else
  150. setBarGraphValue( name + "bar", value / maxvalue );
  151. } else {
  152. setBarGraphColor( name + "bar", PG_Colormap::yellow );
  153. if ( value < -maxvalue )
  154. setBarGraphValue( name + "bar", 1 );
  155. else
  156. setBarGraphValue( name + "bar", -value / maxvalue );
  157. }
  158. ASCString s;
  159. s.format ( "%d", int(value * 100) );
  160. setLabelText( name, s );
  161. }
  162. class BattleSoundPlayer : public FightVisitor {
  163. private:
  164. bool first;
  165. tfight& the_battle;
  166. void play( UnitAttacksSomething& battle )
  167. {
  168. SoundList::getInstance().playSound ( SoundList::shooting,
  169. battle.getAttackingUnit()->getWeapon(battle.av.weapnum)->getScalarWeaponType(),
  170. false,
  171. battle.getAttackingUnit()->getWeapon(battle.av.weapnum)->soundLabel );
  172. };
  173. public:
  174. BattleSoundPlayer( tfight& battle ) : first ( true ), the_battle(battle)
  175. {
  176. battle.visit( *this );
  177. };
  178. void playEnd()
  179. {
  180. first = false;
  181. the_battle.visit( *this );
  182. }
  183. void visit( tunitattacksobject& battle )
  184. {
  185. if ( first )
  186. play( battle );
  187. };
  188. void visit( tunitattacksbuilding& battle )
  189. {
  190. if ( first )
  191. play( battle );
  192. else
  193. if ( battle.dv.damage >= 100 )
  194. SoundList::getInstance().playSound( SoundList::buildingCollapses );
  195. };
  196. void visit( tunitattacksunit& battle )
  197. {
  198. if ( first )
  199. play( battle );
  200. else {
  201. if ( battle.av.damage >= 100 )
  202. SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getAttackingUnit()->typ->killSoundLabel );
  203. if ( battle.dv.damage >= 100 )
  204. SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getTarget()->typ->killSoundLabel );
  205. }
  206. };
  207. void visit( tmineattacksunit& battle )
  208. {
  209. if ( first )
  210. SoundList::getInstance().playSound( SoundList::shooting , 1 );
  211. else
  212. if ( battle.dv.damage >= 100 )
  213. SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getTarget()->typ->killSoundLabel );
  214. }
  215. };
  216. const int maxdefenseshown = 2;
  217. const int maxattackshown = 2;
  218. /**
  219. Waits the given time, but still updates the screen.
  220. These is of no use to the user, but are needed by the video recorder
  221. */
  222. void waitWithUpdate( int millisecs )
  223. {
  224. int frameDelay;
  225. if ( CGameOptions::Instance()->video.ascframeratelimit > 0 )
  226. frameDelay = 100 / CGameOptions::Instance()->video.ascframeratelimit ;
  227. else
  228. frameDelay = 10;
  229. int t = ticker;
  230. do {
  231. int t2 = ticker;
  232. do {
  233. releasetimeslice();
  234. } while ( t2 + frameDelay > ticker );
  235. postScreenUpdate( PG_Application::GetScreen() );
  236. } while ( t + millisecs/20 > ticker );
  237. }
  238. void showAttackAnimation( tfight& battle, GameMap* actmap, int ad, int dd )
  239. {
  240. BattleSoundPlayer bsp( battle );
  241. auto_ptr<AttackPanel> at ( new AttackPanel(battle));
  242. float avd = float( 100 - battle.av.damage )/100;
  243. float dvd = float( 100 - battle.dv.damage )/100;
  244. PG_Color attackingColor = lighten_Color( actmap->player[battle.getAttackingPlayer()].getColor(), 22 );
  245. PG_Color defendingColor = lighten_Color( actmap->player[battle.getDefendingPlayer()].getColor(), 22 );
  246. at->setBarGraphValue( "attacker_unitstatusbar", avd );
  247. at->setBarGraphColor( "attacker_unitstatusbar", attackingColor );
  248. at->setBarGraphValue( "defender_unitstatusbar", dvd );
  249. at->setBarGraphColor( "defender_unitstatusbar", defendingColor );
  250. at->setLabelText( "attacker_unitstatus", 100 - battle.av.damage );
  251. at->setLabelText( "defender_unitstatus", 100 - battle.dv.damage );
  252. at->setBarGraphValue( "attacker_hemmingbar", (battle.dv.hemming -1) / 1.4 );
  253. at->setBarGraphColor( "attacker_hemmingbar", attackingColor );
  254. at->setBarGraphValue( "defender_hemmingbar", (battle.av.hemming -1) / 1.4 );
  255. at->setBarGraphColor( "defender_hemmingbar", defendingColor );
  256. at->setLabelText( "defender_hemming", "-" );
  257. at->setLabelText( "attacker_hemming", int((battle.dv.hemming-1) * 100 ));
  258. at->dispValue( "attacker_attackbonus", battle.strength_attackbonus(battle.av.attackbonus), maxattackshown, attackingColor );
  259. at->dispValue( "defender_attackbonus", battle.strength_attackbonus(battle.dv.attackbonus), maxattackshown, defendingColor );
  260. at->dispValue( "attacker_defencebonus", battle.defense_defensebonus(battle.av.defensebonus), maxattackshown, attackingColor );
  261. at->dispValue( "defender_defencebonus", battle.defense_defensebonus(battle.dv.defensebonus), maxattackshown, defendingColor );
  262. battle.calc();
  263. at->Show();
  264. int time1 = CGameOptions::Instance()->attackspeed1;
  265. if ( time1 <= 0 )
  266. time1 = 30;
  267. int time2 = CGameOptions::Instance()->attackspeed2;
  268. if ( time2 <= 0 )
  269. time2 = 50;
  270. int time3 = CGameOptions::Instance()->attackspeed3;
  271. if ( time3 <= 0 )
  272. time3 = 30;
  273. waitWithUpdate( time1*10 );
  274. if ( ad != -1 )
  275. battle.av.damage = ad;
  276. if ( dd != -1 )
  277. battle.dv.damage = dd;
  278. float avd2 = float( 100 - battle.av.damage )/100;
  279. float dvd2 = float( 100 - battle.dv.damage )/100;
  280. int starttime = ticker;
  281. while ( ticker < starttime + time2 ) {
  282. float p = float(ticker - starttime ) / time2;
  283. at->setBarGraphValue( "attacker_unitstatusbar", avd + (avd2-avd) * p );
  284. at->setBarGraphValue( "defender_unitstatusbar", dvd + (dvd2-dvd) * p );
  285. at->setLabelText( "attacker_unitstatus", int( 100.0 * (avd + (avd2-avd) * p )) );
  286. at->setLabelText( "defender_unitstatus", int( 100.0 * (dvd + (dvd2-dvd) * p )) );
  287. at->Update();
  288. releasetimeslice();
  289. }
  290. at->setBarGraphValue( "attacker_unitstatusbar", avd2 );
  291. at->setBarGraphValue( "defender_unitstatusbar", dvd2 );
  292. at->Update();
  293. bsp.playEnd();
  294. waitWithUpdate( time3*10 );
  295. }