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, 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 bool skipPlayer()
00072 {
00073 if ( turnSkipper ) {
00074 GameMap* temp = actmap;
00075 actmap = gamemap;
00076 (*turnSkipper)(gamemap);
00077 actmap = temp;
00078 }
00079
00080 updateTurn();
00081 return true;
00082 }
00083
00084 bool apply()
00085 {
00086 for ( int i = 0; i < playerlistbox->GetWidgetCount(); ++i ) {
00087 PG_ListBoxBaseItem* bi = dynamic_cast<PG_ListBoxBaseItem*>(playerlistbox->FindWidget(i));
00088 if ( bi && bi->IsSelected() )
00089 applyForPlayer( i );
00090 }
00091 repaintMap();
00092 mapChanged( gamemap );
00093 return true;
00094 }
00095
00096 void applyForPlayer( int player )
00097 {
00098 for ( int i = 0; i < actionlistbox->GetWidgetCount(); ++i ) {
00099 ActionItem* bi = dynamic_cast<ActionItem*>(actionlistbox->FindWidget(i));
00100 if ( bi && bi->IsSelected() )
00101 bi->getData()(player);
00102 }
00103 }
00104
00105 void resetView( int player )
00106 {
00107 gamemap->getPlayer(player).resetView();
00108 }
00109 void resetResearch( int player )
00110 {
00111 gamemap->getPlayer(player).resetResearch();
00112 }
00113
00114 void resetTribute( int player )
00115 {
00116 gamemap->getPlayer(player).resetTribute();
00117 }
00118
00119 void resetPassword( int player )
00120 {
00121 gamemap->getPlayer(player).resetPassword();
00122 }
00123
00124 void newPassword( int player )
00125 {
00126 enterpassword( gamemap->player[player].passwordcrc, true, true, false);
00127 }
00128
00129 void newEmail( int player )
00130 {
00131 gamemap->player[player].email = editString2( "Mail Address for " + gamemap->player[player].getName(), gamemap->player[player].email);
00132 }
00133
00134
00135 void resetDiplomacy( int player )
00136 {
00137 for ( int j = 0; j< gamemap->getPlayerCount(); ++j ) {
00138 if ( j != player ) {
00139 gamemap->getPlayer(player).diplomacy.setState( j, WAR, false );
00140 gamemap->getPlayer(j).diplomacy.setState( player, WAR, false );
00141 }
00142 }
00143 }
00144
00145 void deleteUnits( int player )
00146 {
00147 while ( gamemap->player[player].vehicleList.begin() != gamemap->player[player].vehicleList.end() )
00148 delete *gamemap->player[player].vehicleList.begin();
00149
00150 }
00151
00152 void deleteMines( int player )
00153 {
00154 for ( int y = 0; y < gamemap->ysize; ++y )
00155 for ( int x = 0; x < gamemap->xsize; ++x ) {
00156 tfield* fld = gamemap->getField(x,y);
00157 for ( tfield::MineContainer::iterator i = fld->mines.begin(); i != fld->mines.end(); )
00158 if ( i->player == player )
00159 i = fld->mines.erase( i );
00160 else
00161 ++i;
00162 }
00163
00164 }
00165
00166 void deleteBuildings( int player )
00167 {
00168 while ( gamemap->player[player].buildingList.begin() != gamemap->player[player].buildingList.end() )
00169 delete *gamemap->player[player].buildingList.begin();
00170
00171 }
00172
00173 void neutralBuildings( int player )
00174 {
00175 while ( gamemap->player[player].buildingList.begin() != gamemap->player[player].buildingList.end() )
00176 gamemap->player[player].buildingList.front()->convert(8);
00177
00178 }
00179
00180
00181 void deleteProduction( int player )
00182 {
00183 for ( Player::BuildingList::iterator i = gamemap->player[player].buildingList.begin(); i != gamemap->player[player].buildingList.end(); ++i )
00184 (*i)->deleteAllProductionLines();
00185
00186 }
00187
00188 void deleteResources( int player )
00189 {
00190 for ( Player::BuildingList::iterator i = gamemap->player[player].buildingList.begin(); i != gamemap->player[player].buildingList.end(); ++i ) {
00191 for ( int j = 0; j < waffenanzahl; ++j )
00192 (*i)->ammo[j] = 0;
00193
00194 (*i)->actstorage = Resources();
00195 }
00196 gamemap->bi_resource[player] = Resources();
00197
00198 resetTribute( player );
00199 }
00200
00201 static const int techID = 0xE1C8;
00202
00203 void exportTechs( int player )
00204 {
00205 ASCString filename = selectFile( "*.asctechs", false );
00206 if ( filename.empty() )
00207 return;
00208
00209 tnfilestream stream( filename, tnstream::writing );
00210 stream.writeInt( techID );
00211 stream.writeInt( 1 );
00212 writeClassContainer( gamemap->player[player].research.developedTechnologies, stream );
00213 }
00214
00215 void importTechs( int player )
00216 {
00217 ASCString filename = selectFile( "*.asctechs", true );
00218 if ( filename.empty() )
00219 return;
00220
00221 tnfilestream stream( filename, tnstream::reading );
00222 if ( stream.readInt() != techID ) {
00223 errorMessage("invalid file contents");
00224 return;
00225 }
00226
00227 if ( stream.readInt() != 1 ) {
00228 errorMessage("invalid file version");
00229 return;
00230 }
00231 vector<int> dt;
00232 readClassContainer( dt, stream );
00233 vector<int>& techs = gamemap->player[player].research.developedTechnologies;
00234 copy( dt.begin(), dt.end(), back_inserter( techs ));
00235 sort( techs.begin(), techs.end() );
00236 techs.erase( unique( techs.begin(), techs.end()), techs.end() );
00237 }
00238
00239
00240 bool saveAsMap()
00241 {
00242 apply();
00243 if ( playerSetup->Apply() ) {
00244 gamemap->network = NULL;
00245
00246 if ( gamemap->_resourcemode == 1)
00247 warning("This map uses BI resource mode. Saving as map will delete all global resources of all players");
00248
00249 ASCString name = selectFile( mapextension, false);
00250 if ( !name.empty() ) {
00251 StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "saving " + name );
00252 savemap( name.c_str(), gamemap );
00253 }
00254
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 (->truce)", 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 }