00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sstream>
00023 #include <pgimage.h>
00024
00025 #include "admingame.h"
00026 #include "../paradialog.h"
00027 #include "../gamemap.h"
00028 #include "../spfst.h"
00029 #include "../loaders.h"
00030 #include "playersetup.h"
00031 #include "fileselector.h"
00032 #include "pwd_dlg.h"
00033
00034 #include "../widgets/multilistbox.h"
00035
00036
00037
00038
00039 class AdminGameWindow : public ASC_PG_Dialog {
00040 private:
00041 PG_ListBox* playerlistbox;
00042 PG_ListBox* actionlistbox;
00043 vector<PG_ListBoxItem*> players;
00044 GameMap* gamemap;
00045 PG_LineEdit* turn;
00046 PG_LineEdit* currentPlayer;
00047 PG_LineEdit* filename;
00048
00049 typedef Loki::Functor<void, LOKI_TYPELIST_1(int) > PlayerActionFunctor;
00050 typedef PG_ListBoxDataItem<PlayerActionFunctor> ActionItem;
00051
00052 PG_ScrollWidget* scrollwidget;
00053
00054 PlayerSetupWidget* playerSetup;
00055 TurnSkipper* turnSkipper;
00056
00057 bool successfullyClosed;
00058
00059 void updateTurn()
00060 {
00061 if ( turn )
00062 turn->SetText( ASCString::toString( gamemap->time.turn() ));
00063
00064 if ( currentPlayer ) {
00065 if ( gamemap->actplayer >= 0 )
00066 currentPlayer->SetText( gamemap->player[gamemap->actplayer].getName() );
00067 else
00068 currentPlayer->SetText( ASCString::toString( gamemap->actplayer ) );
00069 }
00070 }
00071
00072 bool skipPlayer()
00073 {
00074 if ( turnSkipper ) {
00075 (*turnSkipper)(gamemap);
00076 }
00077
00078 updateTurn();
00079 return true;
00080 }
00081
00082 bool apply()
00083 {
00084 for ( int i = 0; i < playerlistbox->GetWidgetCount(); ++i ) {
00085 PG_ListBoxBaseItem* bi = dynamic_cast<PG_ListBoxBaseItem*>(playerlistbox->FindWidget(i));
00086 if ( bi && bi->IsSelected() )
00087 applyForPlayer( i );
00088 }
00089 repaintMap();
00090 mapChanged( gamemap );
00091 return true;
00092 }
00093
00094 void applyForPlayer( int player )
00095 {
00096 for ( int i = 0; i < actionlistbox->GetWidgetCount(); ++i ) {
00097 ActionItem* bi = dynamic_cast<ActionItem*>(actionlistbox->FindWidget(i));
00098 if ( bi && bi->IsSelected() )
00099 bi->getData()(player);
00100 }
00101 }
00102
00103 void resetView( int player )
00104 {
00105 gamemap->getPlayer(player).resetView();
00106 }
00107 void resetResearch( int player )
00108 {
00109 gamemap->getPlayer(player).resetResearch();
00110 }
00111
00112 void resetTribute( int player )
00113 {
00114 gamemap->getPlayer(player).resetTribute();
00115 }
00116
00117 void resetPassword( int player )
00118 {
00119 gamemap->getPlayer(player).resetPassword();
00120 }
00121
00122 void newPassword( int player )
00123 {
00124 enterpassword( gamemap->player[player].passwordcrc, true, true, false);
00125 }
00126
00127 void newEmail( int player )
00128 {
00129 gamemap->player[player].email = editString2( "Mail Address for " + gamemap->player[player].getName(), gamemap->player[player].email);
00130 }
00131
00132
00133 void resetDiplomacy( int player )
00134 {
00135 for ( int j = 0; j< gamemap->getPlayerCount(); ++j ) {
00136 if ( j != player ) {
00137 gamemap->getPlayer(player).diplomacy.setState( j, WAR );
00138 gamemap->getPlayer(j).diplomacy.setState( player, WAR );
00139 }
00140 }
00141 }
00142
00143 void deleteUnits( int player )
00144 {
00145 while ( gamemap->player[player].vehicleList.begin() != gamemap->player[player].vehicleList.end() )
00146 delete *gamemap->player[player].vehicleList.begin();
00147
00148 }
00149
00150 void deleteMines( int player )
00151 {
00152 for ( int y = 0; y < gamemap->ysize; ++y )
00153 for ( int x = 0; x < gamemap->xsize; ++x ) {
00154 MapField* fld = gamemap->getField(x,y);
00155 for ( MapField::MineContainer::iterator i = fld->mines.begin(); i != fld->mines.end(); )
00156 if ( i->player == player )
00157 i = fld->mines.erase( i );
00158 else
00159 ++i;
00160 }
00161
00162 }
00163
00164 void deleteBuildings( int player )
00165 {
00166 while ( gamemap->player[player].buildingList.begin() != gamemap->player[player].buildingList.end() )
00167 delete *gamemap->player[player].buildingList.begin();
00168
00169 }
00170
00171 void neutralBuildings( int player )
00172 {
00173 while ( gamemap->player[player].buildingList.begin() != gamemap->player[player].buildingList.end() )
00174 gamemap->player[player].buildingList.front()->convert(8);
00175
00176 }
00177
00178
00179 void deleteProduction( int player )
00180 {
00181 for ( Player::BuildingList::iterator i = gamemap->player[player].buildingList.begin(); i != gamemap->player[player].buildingList.end(); ++i )
00182 (*i)->deleteAllProductionLines();
00183
00184 }
00185
00186 void deleteResources( int player )
00187 {
00188 for ( Player::BuildingList::iterator i = gamemap->player[player].buildingList.begin(); i != gamemap->player[player].buildingList.end(); ++i ) {
00189 for ( int j = 0; j < waffenanzahl; ++j )
00190 (*i)->ammo[j] = 0;
00191
00192 (*i)->actstorage = Resources();
00193 }
00194 gamemap->bi_resource[player] = Resources();
00195
00196 resetTribute( player );
00197 }
00198
00199 static const int techID = 0xE1C8;
00200
00201 void exportTechs( int player )
00202 {
00203 ASCString filename = selectFile( "*.asctechs", false );
00204 if ( filename.empty() )
00205 return;
00206
00207 tnfilestream stream( filename, tnstream::writing );
00208 stream.writeInt( techID );
00209 stream.writeInt( 1 );
00210 writeClassContainer( gamemap->player[player].research.developedTechnologies, stream );
00211 }
00212
00213 void importTechs( int player )
00214 {
00215 ASCString filename = selectFile( "*.asctechs", true );
00216 if ( filename.empty() )
00217 return;
00218
00219 tnfilestream stream( filename, tnstream::reading );
00220 if ( stream.readInt() != techID ) {
00221 errorMessage("invalid file contents");
00222 return;
00223 }
00224
00225 if ( stream.readInt() != 1 ) {
00226 errorMessage("invalid file version");
00227 return;
00228 }
00229 vector<int> dt;
00230 readClassContainer( dt, stream );
00231 vector<int>& techs = gamemap->player[player].research.developedTechnologies;
00232 copy( dt.begin(), dt.end(), back_inserter( techs ));
00233 sort( techs.begin(), techs.end() );
00234 techs.erase( unique( techs.begin(), techs.end()), techs.end() );
00235 }
00236
00237
00238 bool saveAsMap()
00239 {
00240 apply();
00241 if ( playerSetup->Apply() ) {
00242 GameTransferMechanism* gtm = gamemap->network;
00243 gamemap->network = NULL;
00244
00245 if ( gamemap->_resourcemode == 1)
00246 warningMessage("This map uses BI resource mode. Saving as map will delete all global resources of all players");
00247
00248 ASCString name = selectFile( mapextension, false);
00249 if ( !name.empty() ) {
00250 StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "saving " + name );
00251 savemap( name, gamemap );
00252 }
00253
00254 gamemap->network = gtm;
00255 QuitModal();
00256 return true;
00257 } else
00258 return false;
00259 return true;
00260 }
00261
00262 bool turnEdited()
00263 {
00264 gamemap->time.set( atoi( turn->GetText() ), 0 );
00265 updateTurn();
00266 return true;
00267 }
00268
00269 bool netSetup()
00270 {
00271 if ( gamemap && gamemap->network )
00272 gamemap->network->setup();
00273 return true;
00274 }
00275
00276
00277 public:
00278 AdminGameWindow( GameMap* actmap, PG_Widget *parent, TurnSkipper* turnSkipper ) : ASC_PG_Dialog( parent, PG_Rect( -1, -1, 600, min(1000, PG_Application::GetScreenHeight()) ), "Admin Game" ), gamemap( actmap ), successfullyClosed(false)
00279 {
00280 this->turnSkipper = turnSkipper;
00281
00282 scrollwidget = new PG_ScrollWidget( this, PG_Rect( 1, GetTitlebarHeight(), Width() - 2, Height() - GetTitlebarHeight() - 2 ));
00283 scrollwidget->SetTransparency(255);
00284
00285 const int selectorHeight = 250;
00286 const int selectorWidth = 200;
00287 const int gap = 20;
00288 int ypos = gap;
00289 playerlistbox = (new MultiListBox( scrollwidget, PG_Rect( gap, ypos, selectorWidth, selectorHeight )))->getListBox();
00290
00291 int lastPlayer = 0;
00292 for ( int i = 0; i < actmap->getPlayerCount(); ++i )
00293 if ( actmap->player[i].exist() )
00294 lastPlayer = i;
00295
00296 for ( int i = 0; i <= lastPlayer; ++i ) {
00297 if ( actmap->player[i].exist() )
00298 players.push_back( new PG_ListBoxItem( playerlistbox, 20, actmap->player[i].getName() ));
00299 else
00300 players.push_back ( new PG_ListBoxItem( playerlistbox, 20, "-" ) );
00301 }
00302
00303 actionlistbox = (new MultiListBox( scrollwidget, PG_Rect( 2*gap + selectorWidth, gap, selectorWidth, selectorHeight )))->getListBox();
00304 new ActionItem( actionlistbox, 20, "reset view", PlayerActionFunctor( this, &AdminGameWindow::resetView) );
00305 new ActionItem( actionlistbox, 20, "reset research", PlayerActionFunctor( this, &AdminGameWindow::resetResearch));
00306 new ActionItem( actionlistbox, 20, "reset tribute", PlayerActionFunctor( this, &AdminGameWindow::resetTribute));
00307 new ActionItem( actionlistbox, 20, "reset diplomacy (->war)", PlayerActionFunctor( this, &AdminGameWindow::resetDiplomacy));
00308 new ActionItem( actionlistbox, 20, "reset password", PlayerActionFunctor( this, &AdminGameWindow::resetPassword));
00309 new ActionItem( actionlistbox, 20, "delete units", PlayerActionFunctor( this, &AdminGameWindow::deleteUnits));
00310 new ActionItem( actionlistbox, 20, "delete buildings", PlayerActionFunctor( this, &AdminGameWindow::deleteBuildings));
00311 new ActionItem( actionlistbox, 20, "delete production", PlayerActionFunctor( this, &AdminGameWindow::deleteProduction));
00312 new ActionItem( actionlistbox, 20, "delete resources + ammo", PlayerActionFunctor( this, &AdminGameWindow::deleteResources));
00313 new ActionItem( actionlistbox, 20, "delete mines", PlayerActionFunctor( this, &AdminGameWindow::deleteMines));
00314 new ActionItem( actionlistbox, 20, "make buildings neutral", PlayerActionFunctor( this, &AdminGameWindow::neutralBuildings));
00315 new ActionItem( actionlistbox, 20, "enter new password", PlayerActionFunctor( this, &AdminGameWindow::newPassword));
00316 new ActionItem( actionlistbox, 20, "edit email", PlayerActionFunctor( this, &AdminGameWindow::newEmail));
00317 new ActionItem( actionlistbox, 20, "export technology", PlayerActionFunctor( this, &AdminGameWindow::exportTechs));
00318 new ActionItem( actionlistbox, 20, "import technology", PlayerActionFunctor( this, &AdminGameWindow::importTechs));
00319
00320 (new PG_Button( scrollwidget, PG_Rect( 3*gap+2*selectorWidth, ypos, 50, selectorHeight ), "Apply" ))->sigClick.connect( SigC::slot( *this, &AdminGameWindow::apply ));
00321
00322 ypos += 270;
00323
00324 new PG_Label( scrollwidget, PG_Rect( 20, ypos, 100, 20 ), "Turn:" );
00325 turn = new PG_LineEdit( scrollwidget, PG_Rect( 130, ypos, 50, 20));
00326 turn->SetEditable( true );
00327 turn->sigEditEnd.connect( SigC::slot( *this, &AdminGameWindow::turnEdited ));
00328 turn->sigEditReturn.connect( SigC::slot( *this, &AdminGameWindow::turnEdited ));
00329
00330 if ( turnSkipper ) {
00331 PG_Button* b = new PG_Button ( scrollwidget, PG_Rect( 200, ypos, 100, 50 ), "skip player" );
00332 b->sigClick.connect( SigC::slot( *this, &AdminGameWindow::skipPlayer ));
00333 }
00334
00335 ypos += 30;
00336 new PG_Label( scrollwidget, PG_Rect( 20, ypos, 100, 20 ), "Player:" );
00337 currentPlayer = new PG_LineEdit( scrollwidget, PG_Rect( 130, ypos, 50, 20));
00338 currentPlayer->SetEditable( false );
00339
00340
00341
00342 if ( actmap->network ) {
00343 ypos += 30;
00344 (new PG_Button( scrollwidget, PG_Rect( 20, ypos, 200, 20 ), "Setup data transfer" ))->sigClick.connect( SigC::slot( *this, &AdminGameWindow::netSetup )) ;
00345 }
00346
00347 ypos += 30;
00348 playerSetup = new PlayerSetupWidget( gamemap, PlayerSetupWidget::AllEditable, scrollwidget, PG_Rect(gap, ypos, Width() - 3*gap, PlayerSetupWidget::guessHeight(gamemap) ) );
00349
00350 ypos += PlayerSetupWidget::guessHeight(gamemap) + gap;
00351
00352
00353 (new PG_Button( scrollwidget, PG_Rect( gap, ypos, Width() - 3* gap, 30), "OK" ))->sigClick.connect( SigC::slot( *this, &AdminGameWindow::ok));
00354 ypos += 40;
00355
00356 if ( actmap->getgameparameter(cgp_superVisorCanSaveMap)) {
00357 (new PG_Button( scrollwidget, PG_Rect( gap, ypos, Width() - 3* gap, 30), "Save as Map" ))->sigClick.connect( SigC::slot( *this, &AdminGameWindow::saveAsMap));
00358 ypos += 40;
00359 }
00360
00361 updateTurn();
00362 }
00363
00364
00365 bool ok()
00366 {
00367 apply();
00368 if ( playerSetup->Apply() ) {
00369 successfullyClosed = true;
00370 QuitModal();
00371 return true;
00372 } else
00373 return false;
00374 }
00375
00376
00377 bool GetStatus()
00378 {
00379 return successfullyClosed;
00380 }
00381 };
00382
00383
00384
00385
00386
00387 bool adminGame( GameMap* actmap, TurnSkipper* turnSkipper )
00388 {
00389 AdminGameWindow agw( actmap, NULL, turnSkipper);
00390 agw.Show();
00391 agw.RunModal();
00392 return agw.GetStatus();
00393 }