PageRenderTime 156ms CodeModel.GetById 41ms app.highlight 71ms RepoModel.GetById 39ms 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
  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
 10#include <pgimage.h>
 11#include <pgtooltiphelp.h>
 12
 13#include "attackpanel.h"
 14
 15#include "../paradialog.h"
 16#include "../attack.h"
 17#include "../explosivemines.h"
 18#include "../iconrepository.h"
 19
 20#include "../soundList.h"
 21#include "../gamemap.h"
 22#include "../events.h"
 23#include "../gameoptions.h"
 24#include "../windowing.h"
 25#include "../sdl/graphicsqueue.h"
 26
 27#define USE_COLOR_CONSTANTS
 28#include <pgcolors.h>
 29
 30
 31class GetAttackerImage : public FightVisitor {
 32   private:
 33      const SDL_Rect dst;
 34      Surface& surf;
 35
 36      void paint( UnitAttacksSomething& battle )
 37      {
 38         battle.getAttackingUnit()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getAttackingUnit()->getOwningPlayer().getPlayerColor() );
 39      }
 40      
 41   public:
 42      GetAttackerImage( tfight& battle, Surface& surface, const SDL_Rect& dest ) : dst ( dest ), surf( surface )
 43      {
 44         battle.visit( *this );
 45      };
 46      
 47      void visit( tunitattacksobject& battle )  { paint(battle); };
 48      void visit( tunitattacksbuilding& battle )  { paint(battle); };
 49      void visit( tunitattacksunit& battle )  { paint(battle); };
 50      
 51      void visit( tmineattacksunit& battle )
 52      {
 53         Mine* m = battle.getFirstMine();
 54         if ( m )
 55            m->paint( surf, SPoint( dst.x, dst.y ) );
 56      }
 57};
 58
 59class GetTargetImage : public FightVisitor {
 60   private:
 61      const SDL_Rect dst;
 62      Surface& surf;
 63   public:
 64      GetTargetImage( tfight& battle, Surface& surface, const SDL_Rect& dest ) : dst ( dest ), surf( surface )
 65      {
 66         battle.visit( *this );
 67      };
 68
 69      
 70      void visit( tunitattacksobject& battle )
 71      {
 72         battle.getTarget()->typ->display( surf, SPoint( dst.x, dst.y ) );
 73      };
 74      
 75      void visit( tmineattacksunit& battle )
 76      {
 77         battle.getTarget()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getTarget()->getOwningPlayer().getPlayerColor() );
 78      }
 79      
 80      void visit( tunitattacksbuilding& battle )
 81      {
 82         battle.getTarget()->paintSingleField( surf, SPoint(dst.x, dst.y), battle.getTarget()->typ->entry );
 83      };
 84      
 85      void visit( tunitattacksunit& battle )
 86      {
 87         battle.getTarget()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getTarget()->getOwningPlayer().getPlayerColor() );
 88      };
 89};
 90
 91
 92
 93class AttackPanel : public Panel {
 94       tfight& engine;
 95       int attacker_exp;
 96       int defender_exp;
 97   public:
 98      AttackPanel ( tfight& engine_ ) ;
 99      void setBarGraphValue( const ASCString& widgetName, float fraction ) { Panel::setBargraphValue( widgetName, fraction ); };
100      void setLabelText ( const ASCString& widgetName, int i ) { Panel::setLabelText ( widgetName, i ); };
101      void setLabelText ( const ASCString& widgetName, const ASCString& i ) { Panel::setLabelText ( widgetName, i ); };
102      void dispValue ( const ASCString& name, float value, float maxvalue, PG_Color color );
103      void setBarGraphColor( const ASCString& widgetName, PG_Color color ) { Panel::setBarGraphColor( widgetName, color ); };
104      void painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst);
105   private:
106      void registerSpecialDisplay( const ASCString& name );
107};
108
109
110
111AttackPanel::AttackPanel ( tfight& engine_ ) : Panel( PG_Application::GetWidgetById(ASC_PG_App::mainScreenID), PG_Rect(0,0,170,200), "Attack" ), engine( engine_ )
112{
113   registerSpecialDisplay( "attacker_unit_pic" );
114   registerSpecialDisplay( "defender_unit_pic" );
115   registerSpecialDisplay( "attacker_unitexp" );
116   registerSpecialDisplay( "defender_unitexp" );
117   registerSpecialDisplay( "attacker_level" );
118   registerSpecialDisplay( "defender_level" );
119   registerSpecialDisplay( "attacker_weaponsymbol" );
120   registerSpecialDisplay( "defender_weaponsymbol" );
121   attacker_exp = engine.av.experience;
122   defender_exp = engine.dv.experience;
123}
124
125
126void AttackPanel::registerSpecialDisplay( const ASCString& name )
127{
128   SpecialDisplayWidget* sdw = dynamic_cast<SpecialDisplayWidget*>( FindChild( name, true ) );
129   if ( sdw )
130      sdw->display.connect( SigC::slot( *this, &AttackPanel::painter ));
131}
132
133
134void AttackPanel::painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst)
135{
136   Surface s = Surface::Wrap( PG_Application::GetScreen() );
137
138   if ( name  == "attacker_unit_pic" ) {
139      GetAttackerImage( engine, s, dst );
140      return;
141   }
142   if ( name  == "defender_unit_pic" ) {
143      GetTargetImage( engine, s, dst );
144      return;
145   }
146   if ( name  == "attacker_unitexp" ) {
147      s.Blit( IconRepository::getIcon("experience" + ASCString::toString(attacker_exp) + ".png"), SPoint(dst.x, dst.y) );
148      return;
149   }
150   if ( name  == "defender_unitexp" ) {
151      s.Blit( IconRepository::getIcon("experience" + ASCString::toString(defender_exp) + ".png"), SPoint(dst.x, dst.y) );
152      return;
153   }
154   if ( name  == "attacker_level" && engine.av.height ) {
155      s.Blit( IconRepository::getIcon("height-a" + ASCString::toString(getFirstBit(engine.av.height)) + ".png"), SPoint(dst.x, dst.y) );
156      return;
157   }
158   if ( name  == "defender_level" && engine.dv.height ) {
159      s.Blit( IconRepository::getIcon("height-a" + ASCString::toString(getFirstBit(engine.dv.height)) + ".png"), SPoint(dst.x, dst.y) );
160      return;
161   }
162
163   if ( name  == "attacker_weaponsymbol" && engine.av.weapontype >= 0  ) {
164      s.Blit( IconRepository::getIcon(SingleWeapon::getIconFileName( engine.av.weapontype ) + "-small.png"), SPoint(dst.x, dst.y) );
165      return;
166   }
167   if ( name  == "defender_weaponsymbol" && engine.dv.weapontype >= 0  ) {
168      s.Blit( IconRepository::getIcon(SingleWeapon::getIconFileName( engine.dv.weapontype ) + "-small.png"), SPoint(dst.x, dst.y) );
169      return;
170   }
171
172}
173
174
175void AttackPanel::dispValue ( const ASCString& name, float value, float maxvalue, PG_Color color )
176{
177   if ( value > 0 ) {
178      setBarGraphColor( name + "bar", color );
179      if ( value > maxvalue )
180         setBarGraphValue( name + "bar", 1 );
181      else
182         setBarGraphValue( name + "bar", value / maxvalue );
183   } else {
184      setBarGraphColor( name + "bar", PG_Colormap::yellow );
185      if ( value < -maxvalue )
186         setBarGraphValue( name + "bar", 1 );
187      else
188         setBarGraphValue( name + "bar", -value / maxvalue );
189   }
190   ASCString s;
191   s.format ( "%d", int(value * 100) );
192   setLabelText( name, s );
193}
194
195
196
197class BattleSoundPlayer : public FightVisitor {
198   private:
199      bool first;
200      tfight& the_battle;
201            
202      void play( UnitAttacksSomething& battle )
203      {
204         SoundList::getInstance().playSound ( SoundList::shooting,
205                                              battle.getAttackingUnit()->getWeapon(battle.av.weapnum)->getScalarWeaponType(),
206                                              false,
207                                              battle.getAttackingUnit()->getWeapon(battle.av.weapnum)->soundLabel );
208      };
209      
210   public:
211      BattleSoundPlayer( tfight& battle ) : first ( true ), the_battle(battle)
212      {
213         battle.visit( *this );
214      };
215
216      void playEnd()
217      {
218         first = false;
219         the_battle.visit( *this );
220      }
221      
222      void visit( tunitattacksobject& battle )
223      {
224         if ( first )
225            play( battle );
226      };
227      
228      void visit( tunitattacksbuilding& battle )
229      {
230         if ( first )
231            play( battle );
232         else
233            if ( battle.dv.damage >= 100 )
234               SoundList::getInstance().playSound( SoundList::buildingCollapses );
235      };
236      
237      void visit( tunitattacksunit& battle )
238      {
239         if ( first )
240            play( battle );
241         else {
242            if ( battle.av.damage >= 100  )
243               SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getAttackingUnit()->typ->killSoundLabel );
244            
245            if ( battle.dv.damage >= 100 )
246               SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getTarget()->typ->killSoundLabel );
247
248         }
249      };
250      
251      void visit( tmineattacksunit& battle )
252      {
253         if ( first )
254            SoundList::getInstance().playSound( SoundList::shooting , 1 );
255         else
256            if ( battle.dv.damage >= 100 )
257               SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getTarget()->typ->killSoundLabel );
258      }
259      
260};
261
262const int maxdefenseshown = 2;
263const int maxattackshown = 2;
264
265/**
266  Waits the given time, but still updates the screen.
267  These is of no use to the user, but are needed by the video recorder
268*/
269void waitWithUpdate( int millisecs ) 
270{
271   int frameDelay;
272   if ( CGameOptions::Instance()->video.ascframeratelimit  > 0 )
273      frameDelay = 100 / CGameOptions::Instance()->video.ascframeratelimit ;
274   else
275      frameDelay = 10;
276   
277   int t = ticker;
278   do {
279      int t2 = ticker;
280      do {
281         releasetimeslice();
282      } while ( t2 + frameDelay > ticker );
283      postScreenUpdate( PG_Application::GetScreen() );
284   } while ( t + millisecs/20 > ticker ); 
285}
286
287
288void showAttackAnimation( tfight& battle, GameMap* actmap, int ad, int dd )
289{
290
291   BattleSoundPlayer bsp( battle );
292   
293   auto_ptr<AttackPanel> at ( new AttackPanel(battle));
294
295   float avd = float( 100 - battle.av.damage )/100;
296   float dvd = float( 100 - battle.dv.damage )/100;
297
298   PG_Color attackingColor = lighten_Color( actmap->player[battle.getAttackingPlayer()].getColor(), 22 );
299   PG_Color defendingColor = lighten_Color( actmap->player[battle.getDefendingPlayer()].getColor(), 22 );
300
301   at->setBarGraphValue( "attacker_unitstatusbar", avd );
302   at->setBarGraphColor( "attacker_unitstatusbar", attackingColor );
303
304   at->setBarGraphValue( "defender_unitstatusbar", dvd );
305   at->setBarGraphColor( "defender_unitstatusbar", defendingColor );
306
307   at->setLabelText( "attacker_unitstatus", 100 - battle.av.damage );
308   at->setLabelText( "defender_unitstatus", 100 - battle.dv.damage );
309
310
311
312   at->setBarGraphValue( "attacker_hemmingbar", (battle.dv.hemming -1) / 1.4 );
313   at->setBarGraphColor( "attacker_hemmingbar", attackingColor );
314   at->setBarGraphValue( "defender_hemmingbar", (battle.av.hemming -1) / 1.4 );
315   at->setBarGraphColor( "defender_hemmingbar", defendingColor );
316
317   at->setLabelText( "defender_hemming", "-" );
318   at->setLabelText( "attacker_hemming", int((battle.dv.hemming-1) * 100 ));
319
320   at->dispValue( "attacker_attackbonus", battle.strength_attackbonus(battle.av.attackbonus), maxattackshown, attackingColor );
321   at->dispValue( "defender_attackbonus", battle.strength_attackbonus(battle.dv.attackbonus), maxattackshown, defendingColor );
322
323
324   at->dispValue( "attacker_defencebonus", battle.defense_defensebonus(battle.av.defensebonus), maxattackshown, attackingColor );
325   at->dispValue( "defender_defencebonus", battle.defense_defensebonus(battle.dv.defensebonus), maxattackshown, defendingColor );
326
327
328   battle.calc();
329   at->Show();
330
331
332   int time1 = CGameOptions::Instance()->attackspeed1;
333   if ( time1 <= 0 )
334      time1 = 30;
335
336   int time2 = CGameOptions::Instance()->attackspeed2;
337   if ( time2 <= 0 )
338      time2 = 50;
339
340   int time3 = CGameOptions::Instance()->attackspeed3;
341   if ( time3 <= 0 )
342      time3 = 30;
343
344   waitWithUpdate( time1*10 );
345
346
347
348   if ( ad != -1 )
349      battle.av.damage = ad;
350
351   if ( dd != -1 )
352      battle.dv.damage = dd;
353
354
355   float avd2 = float( 100 - battle.av.damage )/100;
356   float dvd2 = float( 100 - battle.dv.damage )/100;
357
358   int starttime = ticker;
359   while ( ticker < starttime + time2 ) {
360      float p = float(ticker - starttime ) / time2;
361
362      at->setBarGraphValue( "attacker_unitstatusbar", avd + (avd2-avd) * p );
363      at->setBarGraphValue( "defender_unitstatusbar", dvd + (dvd2-dvd) * p );
364
365      at->setLabelText( "attacker_unitstatus", int( 100.0 * (avd + (avd2-avd) * p )) );
366      at->setLabelText( "defender_unitstatus", int( 100.0 * (dvd + (dvd2-dvd) * p )) );
367      at->Update();
368
369      releasetimeslice();
370   }
371
372   at->setBarGraphValue( "attacker_unitstatusbar", avd2 );
373   at->setBarGraphValue( "defender_unitstatusbar", dvd2 );
374   at->Update();
375
376   bsp.playEnd();
377   
378   waitWithUpdate( time3*10 );
379}
380