00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <sigc++/sigc++.h>
00022 #include <sstream>
00023
00024 #include "internalAmmoTransferDialog.h"
00025
00026
00027 #include "../containercontrols.h"
00028 #include "../gameoptions.h"
00029 #include "../actions/servicing.h"
00030 #include "../iconrepository.h"
00031 #include "../replay.h"
00032 #include "../actions/internalammotransfercommand.h"
00033 #include "../sg.h"
00034 #include "../dialog.h"
00035
00036
00040 class InternalAmmoTransferWidget;
00041 class InternalAmmoTransferHandler
00042 {
00043
00044 int serviceWeaponAmmoInTransfer[ weaponTypeNum ];
00045 int weaponAmmo[ 16 ];
00046 int weaponAmmoInTransfer[ 16 ];
00047 int weaponAmmoTransferSlot[ 16 ];
00048 std::vector<InternalAmmoTransferWidget*> widgets;
00049
00050 bool weaponAmmoTransferable[ 16 ];
00051 bool serviceweaponAmmoTransferable[ weaponTypeNum ];
00052 int equalWeaponsTypeCounter;
00053
00054 Vehicle* _vehicle;
00055
00056 public:
00057 InternalAmmoTransferHandler( Vehicle* vehicle );
00058 bool isAmmoTransferable( int weaponID );
00059 int* weaponAmmoTransferSource( int weaponID );
00060 int* weaponAmmoTransferBuffer( int weaponID );
00061 int getMaxAmmo( int weaponID );
00062 std::string getName( int weaponID );
00063
00064 void addWidget( InternalAmmoTransferWidget* widget );
00065 void updateBufferTexts();
00066
00067 void performTransfer();
00068 };
00069
00070 class InternalAmmoTransferWidget : public PG_Widget
00071 {
00072 PG_Slider* slider;
00073 InternalAmmoTransferHandler* _handler;
00074 int _weaponID;
00075 int* amount;
00076 int* buffer;
00077 PG_Label* bufferAmount;
00078 PG_Label* weaponAmount;
00079
00080 std::string bufferLabel;
00081 std::string unitLabel;
00082
00083 public:
00084 InternalAmmoTransferWidget( PG_Widget* parent, const PG_Rect& pos, InternalAmmoTransferHandler* handler, int weaponID );
00085
00086 bool slide( long amount );
00087 bool slideEnd( long amount );
00088 void updateTexts();
00089 };
00090
00091 InternalAmmoTransferHandler::InternalAmmoTransferHandler( Vehicle* vehicle )
00092 {
00093 _vehicle = vehicle;
00094 equalWeaponsTypeCounter = 0;
00095
00096 for( int i=0; i<16; i++ )
00097 {
00098 weaponAmmo[ i ] = vehicle->ammo[ i ];
00099 weaponAmmoInTransfer[ i ] = 0;
00100 weaponAmmoTransferSlot[ i ] = -1;
00101 weaponAmmoTransferable[ i ] = false;
00102 }
00103
00104 for( int i=0; i<weaponTypeNum; i++ )
00105 {
00106 serviceWeaponAmmoInTransfer[ i ] = 0;
00107 serviceweaponAmmoTransferable[ i ] = false;
00108 }
00109
00110 for( int i=0; i<vehicle->typ->weapons.count; i++ )
00111 {
00112 const SingleWeapon* weapon = vehicle->getWeapon( i );
00113 if( weapon->canRefuel() )
00114 {
00115 serviceweaponAmmoTransferable[ weapon->getScalarWeaponType() ] = true;
00116 weaponAmmoTransferable[ i ] = true;
00117 }
00118 }
00119
00120 for( int i=0; i<vehicle->typ->weapons.count; i++ )
00121 {
00122 const SingleWeapon* weapon = vehicle->getWeapon( i );
00123 if( ! weapon->canRefuel() )
00124 {
00125 if( serviceweaponAmmoTransferable[ weapon->getScalarWeaponType() ] )
00126 {
00127 weaponAmmoTransferable[ i ] = true;
00128 }else
00129 {
00130 for( int j=0; j<i; j++ )
00131 {
00132 if( weapon->equals( vehicle->getWeapon( j ) ) )
00133 {
00134 weaponAmmoTransferable[ i ] = true;
00135 weaponAmmoTransferable[ j ] = true;
00136
00137
00138 if( weaponAmmoTransferSlot[ j ] == -1 )
00139 {
00140 weaponAmmoTransferSlot[ j ] = equalWeaponsTypeCounter;
00141 equalWeaponsTypeCounter++;
00142 }
00143 weaponAmmoTransferSlot[ i ] = weaponAmmoTransferSlot[ j ];
00144 }
00145 }
00146 }
00147 }
00148 }
00149 }
00150
00151 void InternalAmmoTransferHandler::addWidget( InternalAmmoTransferWidget* widget )
00152 {
00153 widgets.push_back( widget );
00154 }
00155
00156 void InternalAmmoTransferHandler::updateBufferTexts()
00157 {
00158 for( int i=0; i<widgets.size(); i++ )
00159 {
00160 widgets.at( i ) -> updateTexts();
00161 }
00162 }
00163
00164
00165 bool InternalAmmoTransferHandler::isAmmoTransferable( int weaponID )
00166 {
00167 return weaponAmmoTransferable[ weaponID ];
00168 }
00169
00170 int* InternalAmmoTransferHandler::weaponAmmoTransferSource( int weaponID )
00171 {
00172 return &weaponAmmo[ weaponID ];
00173 }
00174
00175 int InternalAmmoTransferHandler::getMaxAmmo( int weaponID )
00176 {
00177 return _vehicle->getWeapon( weaponID )->count;
00178 }
00179
00180 std::string InternalAmmoTransferHandler::getName( int weaponID )
00181 {
00182 return _vehicle->getWeapon( weaponID )->getName();
00183 }
00184
00185 int* InternalAmmoTransferHandler::weaponAmmoTransferBuffer( int weaponID )
00186 {
00187 if( weaponAmmoTransferSlot[ weaponID ] >= 0 )
00188 {
00189 return &weaponAmmoInTransfer[ weaponAmmoTransferSlot[ weaponID ] ];
00190 }else
00191 {
00192 return &serviceWeaponAmmoInTransfer[ _vehicle->getWeapon( weaponID )->getScalarWeaponType() ];
00193 }
00194 }
00195
00196 void InternalAmmoTransferHandler::performTransfer()
00197 {
00198
00199 for( int i=0; i<16; i++ )
00200 {
00201 if( weaponAmmoInTransfer[ i ] > 0 )
00202 {
00203 for( int j=0;j<16; j++ )
00204 {
00205 if( weaponAmmoTransferSlot[ j ] == i )
00206 {
00207 const SingleWeapon* weapon = _vehicle->getWeapon( j );
00208 if( weaponAmmo[ j ] < weapon->count )
00209 {
00210 int ammoTransfer = weapon->count - weaponAmmo[ j ];
00211 if( weaponAmmoInTransfer[ i ] < ammoTransfer )
00212 {
00213 ammoTransfer = weaponAmmoInTransfer[ i ];
00214 }
00215 weaponAmmo[ j ] += ammoTransfer;
00216 weaponAmmoInTransfer[ i ] -= ammoTransfer;
00217 }
00218 }
00219 }
00220 }
00221 }
00222
00223
00224 for( int i=0; i<weaponTypeNum; i++ )
00225 {
00226 if( serviceWeaponAmmoInTransfer[ i ] > 0 )
00227 {
00228
00229 for( int j=0; j<_vehicle->typ->weapons.count; j++ )
00230 {
00231 const SingleWeapon* weapon = _vehicle->getWeapon( j );
00232 if( weapon->getScalarWeaponType() == i )
00233 {
00234 if( weapon->canRefuel() )
00235 {
00236 if( weaponAmmo[ j ] < weapon->count )
00237 {
00238 int ammoTransfer = weapon->count - weaponAmmo[ j ];
00239 if( serviceWeaponAmmoInTransfer[ i ] < ammoTransfer )
00240 {
00241 ammoTransfer = serviceWeaponAmmoInTransfer[ i ];
00242 }
00243 weaponAmmo[ j ] += ammoTransfer;
00244 serviceWeaponAmmoInTransfer[ i ] -= ammoTransfer;
00245 }
00246 }
00247 }
00248 }
00249
00250 for( int j=0; j<_vehicle->typ->weapons.count; j++ )
00251 {
00252 const SingleWeapon* weapon = _vehicle->getWeapon( j );
00253 if( weapon->getScalarWeaponType() == i )
00254 {
00255 if( ! weapon->canRefuel() )
00256 {
00257 if( weaponAmmo[ j ] < weapon->count )
00258 {
00259 int ammoTransfer = weapon->count - weaponAmmo[ j ];
00260 if( serviceWeaponAmmoInTransfer[ i ] < ammoTransfer )
00261 {
00262 ammoTransfer = serviceWeaponAmmoInTransfer[ i ];
00263 }
00264 weaponAmmo[ j ] += ammoTransfer;
00265 serviceWeaponAmmoInTransfer[ i ] -= ammoTransfer;
00266 }
00267 }
00268 }
00269 }
00270 }
00271 }
00272
00273
00274
00275
00276 vector<int> am;
00277 for( int i=0; i<16; i++ )
00278 am.push_back( weaponAmmo[i] );
00279
00280 auto_ptr<InternalAmmoTransferCommand> iatc ( new InternalAmmoTransferCommand( _vehicle));
00281 iatc->setAmmounts( am );
00282 ActionResult res = iatc->execute( createContext( _vehicle->getMap() ));
00283 if ( res.successful() )
00284 iatc.release();
00285 else
00286 displayActionError( res );
00287
00288 }
00289
00290
00291
00292 InternalAmmoTransferWidget::InternalAmmoTransferWidget( PG_Widget* parent, const PG_Rect& pos, InternalAmmoTransferHandler* handler, int weaponID ) : PG_Widget( parent,pos ), slider(NULL), _weaponID( weaponID )
00293 {
00294 _handler = handler;
00295 _handler->addWidget( this );
00296 amount = _handler->weaponAmmoTransferSource( _weaponID );
00297 buffer = _handler->weaponAmmoTransferBuffer( _weaponID );
00298 bufferLabel = "Buffer ";
00299 unitLabel = "Unit ";
00300
00301 slider = new PG_Slider( this, PG_Rect( 0, 25, pos.w, 15 ), PG_ScrollBar::HORIZONTAL );
00302 slider->SetRange( 0, _handler->getMaxAmmo( weaponID ) );
00303 slider->SetPosition( *amount );
00304
00305 slider->sigSlide.connect( SigC::slot( *this, &InternalAmmoTransferWidget::slide ));
00306 slider->sigSlideEnd.connect( SigC::slot( *this, &InternalAmmoTransferWidget::slideEnd));
00307
00308 PG_Rect labels = PG_Rect( 0, 0, pos.w, 20 );
00309 std::stringstream nameStream;
00310 nameStream << handler->getName( weaponID ) << " (" << weaponID << ")";
00311 PG_Label* l = new PG_Label ( this, labels, nameStream.str() );
00312 l->SetAlignment( PG_Label::CENTER );
00313
00314 bufferAmount = new PG_Label ( this, labels );
00315 bufferAmount->SetAlignment( PG_Label::LEFT );
00316
00317 weaponAmount = new PG_Label ( this, labels );
00318 weaponAmount->SetAlignment( PG_Label::RIGHT );
00319
00320 updateTexts();
00321 }
00322
00323
00324 bool InternalAmmoTransferWidget::slide( long newAmount )
00325 {
00326 int difference = newAmount - (*amount);
00327 if( difference > (*buffer) )
00328 {
00329 difference = (*buffer);
00330 }
00331 (*amount) += difference;
00332 (*buffer) -= difference;
00333
00334 if( difference != 0 )
00335 {
00336 _handler->updateBufferTexts();
00337 return true;
00338 }
00339 return false;
00340 }
00341
00342 void InternalAmmoTransferWidget::updateTexts()
00343 {
00344 std::stringstream ssStream;
00345 ssStream << bufferLabel << (*buffer);
00346 bufferAmount->SetText( ssStream.str() );
00347
00348 std::stringstream ssStream2;
00349 ssStream2 << unitLabel << (*amount);
00350 weaponAmount->SetText( ssStream2.str() );
00351 }
00352
00353 bool InternalAmmoTransferWidget::slideEnd( long newAmount )
00354 {
00355 int difference = newAmount - (*amount);
00356 if( difference > (*buffer) )
00357 {
00358 difference = (*buffer);
00359 }
00360 (*amount) += difference;
00361 (*buffer) -= difference;
00362
00363 if( difference != 0 )
00364 {
00365 _handler->updateBufferTexts();
00366 return true;
00367 }
00368 return false;
00369 }
00370
00371
00372 class InternalAmmoTransferWindow : public ASC_PG_Dialog {
00373 private:
00374 Vehicle* vehicle;
00375 InternalAmmoTransferHandler handler;
00376
00377
00378
00379
00380 Surface img1,img2;
00381
00382 bool ok()
00383 {
00384 handler.performTransfer();
00385 QuitModal();
00386 return true;
00387 }
00388
00389 public:
00390 InternalAmmoTransferWindow ( Vehicle* source, PG_Widget* parent );
00391
00392 bool somethingToTransfer() { return InternalAmmoTransferCommand::avail( vehicle ); };
00393
00394 bool eventKeyDown(const SDL_KeyboardEvent* key)
00395 {
00396 if ( key->keysym.sym == SDLK_ESCAPE ) {
00397 QuitModal();
00398 return true;
00399 }
00400 return false;
00401 }
00402
00403
00404 };
00405
00406
00407 InternalAmmoTransferWindow :: InternalAmmoTransferWindow ( Vehicle* source, PG_Widget* parent ) : ASC_PG_Dialog( NULL, PG_Rect( 30, 30, 400, 400 ), "Transfer" ), vehicle( source ), handler( source )
00408 {
00409 int ypos = 30;
00410 int border = 10;
00411
00412 img1 = IconRepository::getIcon( "container.png" );
00413 img2 = source->getImage();
00414
00415 const int singleTransferHeight = 60;
00416
00417 int transferableWeaponsCounter = 0;
00418
00419 for( int i=0; i<16; i++ )
00420 {
00421 if( handler.isAmmoTransferable( i ) ) transferableWeaponsCounter++;
00422 }
00423
00424 int expectedHeight = transferableWeaponsCounter * singleTransferHeight;
00425
00426 int newHeight = min( PG_Application::GetScreen()->h - 60, expectedHeight + 130 );
00427 SizeWidget( w, newHeight );
00428
00429 PG_ScrollWidget* area = new PG_ScrollWidget ( this, PG_Rect( border, ypos, w - border, h - 80 ));
00430 area->SetTransparency( 255 );
00431
00432 (new PG_ThemeWidget( area, PG_Rect( 5,3, fieldsizex, fieldsizey)))->SetBackground( img1.getBaseSurface(), PG_Draw::STRETCH );
00433 (new PG_ThemeWidget( area, PG_Rect( area->Width() - 5 - fieldsizex, 3, fieldsizex, fieldsizey)))->SetBackground( img2.getBaseSurface(), PG_Draw::STRETCH );
00434
00435 ypos = fieldsizex + 5;
00436
00437 for( int i=0; i<16; i++ )
00438 {
00439 if( handler.isAmmoTransferable( i ) )
00440 {
00441 new InternalAmmoTransferWidget( area, PG_Rect( 0, ypos, area->w - 30, 50 ), &handler, i );
00442 ypos += singleTransferHeight;
00443 }
00444 }
00445
00446 int buttonWidth = 150;
00447 PG_Button* b = new PG_Button( this, PG_Rect( w - buttonWidth - border, h - 30 - border, buttonWidth, 30), "OK" );
00448 b->sigClick.connect( SigC::slot( *this, &InternalAmmoTransferWindow::ok ));
00449 }
00450
00451 void internalAmmoTransferWindow ( Vehicle* vehicle )
00452 {
00453 InternalAmmoTransferWindow iatw( vehicle, NULL );
00454 if ( iatw.somethingToTransfer() ) {
00455 iatw.Show();
00456 iatw.RunModal();
00457 }
00458 }