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