00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <pgimage.h>
00011 #include <pgtooltiphelp.h>
00012
00013 #include "attackpanel.h"
00014
00015 #include "../paradialog.h"
00016 #include "../attack.h"
00017 #include "../explosivemines.h"
00018 #include "../iconrepository.h"
00019
00020 #include "../soundList.h"
00021 #include "../gamemap.h"
00022 #include "../events.h"
00023 #include "../gameoptions.h"
00024 #include "../windowing.h"
00025
00026 #define USE_COLOR_CONSTANTS
00027 #include <pgcolors.h>
00028
00029
00030 class GetAttackerImage : public FightVisitor {
00031 private:
00032 const SDL_Rect dst;
00033 Surface& surf;
00034
00035 void paint( UnitAttacksSomething& battle )
00036 {
00037 battle.getAttackingUnit()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getAttackingUnit()->getOwningPlayer().getPlayerColor() );
00038 }
00039
00040 public:
00041 GetAttackerImage( tfight& battle, Surface& surface, const SDL_Rect& dest ) : dst ( dest ), surf( surface )
00042 {
00043 battle.visit( *this );
00044 };
00045
00046 void visit( tunitattacksobject& battle ) { paint(battle); };
00047 void visit( tunitattacksbuilding& battle ) { paint(battle); };
00048 void visit( tunitattacksunit& battle ) { paint(battle); };
00049
00050 void visit( tmineattacksunit& battle )
00051 {
00052 Mine* m = battle.getFirstMine();
00053 if ( m )
00054 m->paint( surf, SPoint( dst.x, dst.y ) );
00055 }
00056 };
00057
00058 class GetTargetImage : public FightVisitor {
00059 private:
00060 const SDL_Rect dst;
00061 Surface& surf;
00062 public:
00063 GetTargetImage( tfight& battle, Surface& surface, const SDL_Rect& dest ) : dst ( dest ), surf( surface )
00064 {
00065 battle.visit( *this );
00066 };
00067
00068
00069 void visit( tunitattacksobject& battle )
00070 {
00071 battle.getTarget()->typ->display( surf, SPoint( dst.x, dst.y ) );
00072 };
00073
00074 void visit( tmineattacksunit& battle )
00075 {
00076 battle.getTarget()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getTarget()->getOwningPlayer().getPlayerColor() );
00077 }
00078
00079 void visit( tunitattacksbuilding& battle )
00080 {
00081 battle.getTarget()->paintSingleField( surf, SPoint(dst.x, dst.y), battle.getTarget()->typ->entry );
00082 };
00083
00084 void visit( tunitattacksunit& battle )
00085 {
00086 battle.getTarget()->typ->paint( surf, SPoint( dst.x, dst.y ), battle.getTarget()->getOwningPlayer().getPlayerColor() );
00087 };
00088 };
00089
00090
00091
00092 class AttackPanel : public Panel {
00093 tfight& engine;
00094 int attacker_exp;
00095 int defender_exp;
00096 public:
00097 AttackPanel ( tfight& engine_ ) ;
00098 void setBarGraphValue( const ASCString& widgetName, float fraction ) { Panel::setBargraphValue( widgetName, fraction ); };
00099 void setLabelText ( const ASCString& widgetName, int i ) { Panel::setLabelText ( widgetName, i ); };
00100 void setLabelText ( const ASCString& widgetName, const ASCString& i ) { Panel::setLabelText ( widgetName, i ); };
00101 void dispValue ( const ASCString& name, float value, float maxvalue, PG_Color color );
00102 void setBarGraphColor( const ASCString& widgetName, PG_Color color ) { Panel::setBarGraphColor( widgetName, color ); };
00103 void painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst);
00104 private:
00105 void registerSpecialDisplay( const ASCString& name );
00106 };
00107
00108
00109
00110 AttackPanel::AttackPanel ( tfight& engine_ ) : Panel( PG_Application::GetWidgetById(ASC_PG_App::mainScreenID), PG_Rect(0,0,170,200), "Attack" ), engine( engine_ )
00111 {
00112 registerSpecialDisplay( "attacker_unit_pic" );
00113 registerSpecialDisplay( "defender_unit_pic" );
00114 registerSpecialDisplay( "attacker_unitexp" );
00115 registerSpecialDisplay( "defender_unitexp" );
00116 registerSpecialDisplay( "attacker_level" );
00117 registerSpecialDisplay( "defender_level" );
00118 registerSpecialDisplay( "attacker_weaponsymbol" );
00119 registerSpecialDisplay( "defender_weaponsymbol" );
00120 attacker_exp = engine.av.experience;
00121 defender_exp = engine.dv.experience;
00122 }
00123
00124
00125 void AttackPanel::registerSpecialDisplay( const ASCString& name )
00126 {
00127 SpecialDisplayWidget* sdw = dynamic_cast<SpecialDisplayWidget*>( FindChild( name, true ) );
00128 if ( sdw )
00129 sdw->display.connect( SigC::slot( *this, &AttackPanel::painter ));
00130 }
00131
00132
00133 void AttackPanel::painter ( const PG_Rect &src, const ASCString& name, const PG_Rect &dst)
00134 {
00135 Surface s = Surface::Wrap( PG_Application::GetScreen() );
00136
00137 if ( name == "attacker_unit_pic" ) {
00138 GetAttackerImage( engine, s, dst );
00139 return;
00140 }
00141 if ( name == "defender_unit_pic" ) {
00142 GetTargetImage( engine, s, dst );
00143 return;
00144 }
00145 if ( name == "attacker_unitexp" ) {
00146 s.Blit( IconRepository::getIcon("experience" + ASCString::toString(attacker_exp) + ".png"), SPoint(dst.x, dst.y) );
00147 return;
00148 }
00149 if ( name == "defender_unitexp" ) {
00150 s.Blit( IconRepository::getIcon("experience" + ASCString::toString(defender_exp) + ".png"), SPoint(dst.x, dst.y) );
00151 return;
00152 }
00153 if ( name == "attacker_level" && engine.av.height ) {
00154 s.Blit( IconRepository::getIcon("height-a" + ASCString::toString(log2(engine.av.height)) + ".png"), SPoint(dst.x, dst.y) );
00155 return;
00156 }
00157 if ( name == "defender_level" && engine.dv.height ) {
00158 s.Blit( IconRepository::getIcon("height-a" + ASCString::toString(log2(engine.dv.height)) + ".png"), SPoint(dst.x, dst.y) );
00159 return;
00160 }
00161
00162 if ( name == "attacker_weaponsymbol" && engine.av.weapontype >= 0 ) {
00163 s.Blit( IconRepository::getIcon(SingleWeapon::getIconFileName( engine.av.weapontype ) + "-small.png"), SPoint(dst.x, dst.y) );
00164 return;
00165 }
00166 if ( name == "defender_weaponsymbol" && engine.dv.weapontype >= 0 ) {
00167 s.Blit( IconRepository::getIcon(SingleWeapon::getIconFileName( engine.dv.weapontype ) + "-small.png"), SPoint(dst.x, dst.y) );
00168 return;
00169 }
00170
00171 }
00172
00173
00174 void AttackPanel::dispValue ( const ASCString& name, float value, float maxvalue, PG_Color color )
00175 {
00176 if ( value > 0 ) {
00177 setBarGraphColor( name + "bar", color );
00178 if ( value > maxvalue )
00179 setBarGraphValue( name + "bar", 1 );
00180 else
00181 setBarGraphValue( name + "bar", value / maxvalue );
00182 } else {
00183 setBarGraphColor( name + "bar", PG_Colormap::yellow );
00184 if ( value < -maxvalue )
00185 setBarGraphValue( name + "bar", 1 );
00186 else
00187 setBarGraphValue( name + "bar", -value / maxvalue );
00188 }
00189 ASCString s;
00190 s.format ( "%d", int(value * 100) );
00191 setLabelText( name, s );
00192 }
00193
00194
00195
00196 class BattleSoundPlayer : public FightVisitor {
00197 private:
00198 bool first;
00199 tfight& the_battle;
00200
00201 void play( UnitAttacksSomething& battle )
00202 {
00203 SoundList::getInstance().playSound ( SoundList::shooting,
00204 battle.getAttackingUnit()->getWeapon(battle.av.weapnum)->getScalarWeaponType(),
00205 false,
00206 battle.getAttackingUnit()->getWeapon(battle.av.weapnum)->soundLabel );
00207 };
00208
00209 public:
00210 BattleSoundPlayer( tfight& battle ) : first ( true ), the_battle(battle)
00211 {
00212 battle.visit( *this );
00213 };
00214
00215 void playEnd()
00216 {
00217 first = false;
00218 the_battle.visit( *this );
00219 }
00220
00221 void visit( tunitattacksobject& battle )
00222 {
00223 if ( first )
00224 play( battle );
00225 };
00226
00227 void visit( tunitattacksbuilding& battle )
00228 {
00229 if ( first )
00230 play( battle );
00231 else
00232 if ( battle.dv.damage >= 100 )
00233 SoundList::getInstance().playSound( SoundList::buildingCollapses );
00234 };
00235
00236 void visit( tunitattacksunit& battle )
00237 {
00238 if ( first )
00239 play( battle );
00240 else {
00241 if ( battle.av.damage >= 100 )
00242 SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getAttackingUnit()->typ->killSoundLabel );
00243
00244 if ( battle.dv.damage >= 100 )
00245 SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getTarget()->typ->killSoundLabel );
00246
00247 }
00248 };
00249
00250 void visit( tmineattacksunit& battle )
00251 {
00252 if ( first )
00253 SoundList::getInstance().playSound( SoundList::shooting , 1 );
00254 else
00255 if ( battle.dv.damage >= 100 )
00256 SoundList::getInstance().playSound( SoundList::unitExplodes , 0, false, battle.getTarget()->typ->killSoundLabel );
00257 }
00258
00259 };
00260
00261 const int maxdefenseshown = 2;
00262 const int maxattackshown = 2;
00263
00264
00265 void showAttackAnimation( tfight& battle, GameMap* actmap, int ad, int dd )
00266 {
00267
00268 BattleSoundPlayer bsp( battle );
00269
00270 auto_ptr<AttackPanel> at ( new AttackPanel(battle));
00271
00272 float avd = float( 100 - battle.av.damage )/100;
00273 float dvd = float( 100 - battle.dv.damage )/100;
00274
00275 PG_Color attackingColor = lighten_Color( actmap->player[battle.getAttackingPlayer()].getColor(), 22 );
00276 PG_Color defendingColor = lighten_Color( actmap->player[battle.getDefendingPlayer()].getColor(), 22 );
00277
00278 at->setBarGraphValue( "attacker_unitstatusbar", avd );
00279 at->setBarGraphColor( "attacker_unitstatusbar", attackingColor );
00280
00281 at->setBarGraphValue( "defender_unitstatusbar", dvd );
00282 at->setBarGraphColor( "defender_unitstatusbar", defendingColor );
00283
00284 at->setLabelText( "attacker_unitstatus", 100 - battle.av.damage );
00285 at->setLabelText( "defender_unitstatus", 100 - battle.dv.damage );
00286
00287
00288
00289 at->setBarGraphValue( "attacker_hemmingbar", (battle.dv.hemming -1) / 1.4 );
00290 at->setBarGraphColor( "attacker_hemmingbar", attackingColor );
00291 at->setBarGraphValue( "defender_hemmingbar", (battle.av.hemming -1) / 1.4 );
00292 at->setBarGraphColor( "defender_hemmingbar", defendingColor );
00293
00294 at->setLabelText( "defender_hemming", "-" );
00295 at->setLabelText( "attacker_hemming", int((battle.dv.hemming-1) * 100 ));
00296
00297 at->dispValue( "attacker_attackbonus", battle.strength_attackbonus(battle.av.attackbonus), maxattackshown, attackingColor );
00298 at->dispValue( "defender_attackbonus", battle.strength_attackbonus(battle.dv.attackbonus), maxattackshown, defendingColor );
00299
00300
00301 at->dispValue( "attacker_defencebonus", battle.defense_defensebonus(battle.av.defensebonus), maxattackshown, attackingColor );
00302 at->dispValue( "defender_defencebonus", battle.defense_defensebonus(battle.dv.defensebonus), maxattackshown, defendingColor );
00303
00304
00305 int t = ticker;
00306 battle.calc();
00307 at->Show();
00308
00309
00310 int time1 = CGameOptions::Instance()->attackspeed1;
00311 if ( time1 <= 0 )
00312 time1 = 30;
00313
00314 int time2 = CGameOptions::Instance()->attackspeed2;
00315 if ( time2 <= 0 )
00316 time2 = 50;
00317
00318 int time3 = CGameOptions::Instance()->attackspeed3;
00319 if ( time3 <= 0 )
00320 time3 = 30;
00321
00322 do {
00323 releasetimeslice();
00324 } while ( t + time1 > ticker );
00325
00326
00327
00328 if ( ad != -1 )
00329 battle.av.damage = ad;
00330
00331 if ( dd != -1 )
00332 battle.dv.damage = dd;
00333
00334
00335 float avd2 = float( 100 - battle.av.damage )/100;
00336 float dvd2 = float( 100 - battle.dv.damage )/100;
00337
00338 int starttime = ticker;
00339 while ( ticker < starttime + time2 ) {
00340 float p = float(ticker - starttime ) / time2;
00341
00342 at->setBarGraphValue( "attacker_unitstatusbar", avd + (avd2-avd) * p );
00343 at->setBarGraphValue( "defender_unitstatusbar", dvd + (dvd2-dvd) * p );
00344
00345 at->setLabelText( "attacker_unitstatus", int( 100.0 * (avd + (avd2-avd) * p )) );
00346 at->setLabelText( "defender_unitstatus", int( 100.0 * (dvd + (dvd2-dvd) * p )) );
00347 at->Update();
00348
00349 releasetimeslice();
00350 }
00351
00352 at->setBarGraphValue( "attacker_unitstatusbar", avd2 );
00353 at->setBarGraphValue( "defender_unitstatusbar", dvd2 );
00354 at->Update();
00355
00356 bsp.playEnd();
00357
00358 t = ticker;
00359 do {
00360 releasetimeslice();
00361 } while ( t + time3 > ticker );
00362 }
00363