internalAmmoTransferDialog.cpp

Go to the documentation of this file.
00001 /*
00002      This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003      Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00004  
00005      This program is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published by
00007      the Free Software Foundation; either version 2 of the License, or
00008      (at your option) any later version.
00009  
00010      This program is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013      GNU General Public License for more details.
00014  
00015      You should have received a copy of the GNU General Public License
00016      along with this program; see the file COPYING. If not, write to the 
00017      Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00018      Boston, MA  02111-1307  USA
00019 */
00020 
00021 #include <sigc++/sigc++.h>
00022 #include <sstream>
00023 
00024 #include "internalAmmoTransferDialog.h"
00025 
00026 // #include "../unitctrl.h"
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 ]; // weapon ammo when done; might need to have *AmmoInTransfer added
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 //std::cout << "weaponAmmoTransferable: " << i << ", " << j << endl;
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         // zuerst die munition von speziellen waffentypen verteilen, die noch in transfer ist
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         // dann die munition in transfer auf servicewaffen aufteilen
00224         for( int i=0; i<weaponTypeNum; i++ )
00225         {
00226                 if( serviceWeaponAmmoInTransfer[ i ] > 0 )
00227                 {
00228                         // zuerst den servicewaffen zuweisen
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                         // ... dann den anderen waffen zuteilen
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         // munition sollte jetzt im "legalen" bereich sein, 
00274         // und alles was im transfer war den echten waffen zugewiesen,
00275         // also jetzt dem fahrzeug zuweisen
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       //ContainerBase* second;
00377       //TransferHandler handler;
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 )//, second( destination ), handler( source, destination )
00408 {
00409         int ypos = 30;
00410         int border = 10;
00411         
00412         img1 = IconRepository::getIcon( "container.png" );//source->getImage();
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 }

Generated on Mon May 21 01:26:34 2012 for Advanced Strategic Command by  doxygen 1.5.1