00001
00002
00003
00004
00005
00006
00007
00008
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00070 #include "global.h"
00071
00072 #include <stdio.h>
00073 #include <stdlib.h>
00074 #include <new>
00075 #include <cstdlib>
00076 #include <ctype.h>
00077 #include <algorithm>
00078 #include <memory>
00079
00080 #include <boost/regex.hpp>
00081
00082 #include "paradialog.h"
00083
00084 #include "vehicletype.h"
00085 #include "buildingtype.h"
00086 #include "ai/ai.h"
00087 #include "misc.h"
00088 #include "events.h"
00089 #include "typen.h"
00090 #include "spfst.h"
00091 #include "loaders.h"
00092 #include "dlg_box.h"
00093 #include "controls.h"
00094 #include "dlg_box.h"
00095 #include "dialog.h"
00096 #include "strtmesg.h"
00097 #include "gamedlg.h"
00098 #include "sg.h"
00099 #include "gameoptions.h"
00100 #include "loadimage.h"
00101 #include "astar2.h"
00102 #include "errors.h"
00103 #include "dialogs/pwd_dlg.h"
00104 #include "viewcalculation.h"
00105 #include "replay.h"
00106 #include "graphicset.h"
00107 #include "loadbi3.h"
00108 #include "itemrepository.h"
00109 #include "music.h"
00110 #include "messagedlg.h"
00111 #include "statisticdialog.h"
00112 #include "clipboard.h"
00113 #include "guifunctions.h"
00114 #include "iconrepository.h"
00115 #include "dashboard.h"
00116 #include "gamedialog.h"
00117 #include "unitset.h"
00118
00119 #ifdef WEATHERGENERATOR
00120 # include "weathercast.h"
00121 #endif
00122
00123 #include "asc-mainscreen.h"
00124 #include "dialogs/unitinfodialog.h"
00125 #include "messaginghub.h"
00126 #include "cannedmessages.h"
00127 #include "memorycheck.cpp"
00128 #include "networkinterface.h"
00129 #include "resourcenet.h"
00130 #include "mapimageexport.h"
00131 #include "loadpcx.h"
00132 #include "gameeventsystem.h"
00133 #include "sdl/sound.h"
00134 #include "soundList.h"
00135 #include "turncontrol.h"
00136 #include "networksupervisor.h"
00137
00138 #include "dialogs/newgame.h"
00139 #include "dialogs/soundsettings.h"
00140 #include "dialogs/alliancesetup.h"
00141 #include "dialogs/unitcounting.h"
00142 #include "dialogs/editgameoptions.h"
00143 #include "dialogs/nextcampaignmap.h"
00144 #include "dialogs/terraininfo.h"
00145 #include "dialogs/editplayerdata.h"
00146 #include "dialogs/locatefile.h"
00147 #include "stdio-errorhandler.h"
00148 #include "widgets/textrenderer.h"
00149 #include "dialogs/productionanalysis.h"
00150 #include "dialogs/fileselector.h"
00151 #include "containerbase-functions.h"
00152 #include "memory-measurement.h"
00153 #include "dialogs/mailoptionseditor.h"
00154
00155 #ifdef WIN32
00156 # include "win32/win32-errormsg.h"
00157 # include "win32/msvc/mdump.h"
00158 MiniDumper miniDumper( "main" );
00159 # include <direct.h>
00160 # include <stdlib.h>
00161 # include <stdio.h>
00162 #endif
00163
00164 tfield* getSelectedField(void)
00165 {
00166 return actmap->getField( actmap->getCursor() );
00167 }
00168
00169
00170 #define mmaintainence
00171
00172 bool maintainencecheck( void )
00173 {
00174 int res = 0;
00175 if ( res )
00176 return true;
00177
00178 #ifdef maintainence
00179 int num = 0;
00180
00181 for ( int i = 0; i < 8; i++ )
00182 if ( actmap->player[i].stat == Player::human && actmap->player[i].exist())
00183 num++;
00184
00185 if ( actmap->campaign )
00186 num++;
00187
00188 if ( actmap->network )
00189 num++;
00190
00191 if ( num <= 1 )
00192 return 1;
00193 else
00194 return 0;
00195
00196 #else
00197 return false;
00198 #endif
00199 }
00200
00201 void positionCursor( Player& player )
00202 {
00203 getDefaultMapDisplay().displayPosition( player.getParentMap()->getCursor() );
00204 }
00205
00206 void viewcomp( Player& player )
00207 {
00208 computeview( player.getParentMap() );
00209 }
00210
00211 void hookGuiToMap( GameMap* map )
00212 {
00213 if ( !map->getGuiHooked() ) {
00214
00215 map->sigPlayerUserInteractionBegins.connect( SigC::slot( &viewcomp ) );
00216 map->sigPlayerUserInteractionBegins.connect( SigC::hide<Player&>( repaintMap.slot() ));
00217
00218 map->sigPlayerUserInteractionBegins.connect( SigC::slot( &positionCursor ));
00219 map->sigPlayerUserInteractionBegins.connect( SigC::hide<Player&>( SigC::slot( &checkforreplay )));
00220 map->sigPlayerUserInteractionBegins.connect( SigC::slot( &researchCheck ));
00221 map->sigPlayerUserInteractionBegins.connect( SigC::slot( &viewunreadmessages ));
00222 map->sigPlayerUserInteractionBegins.connect( SigC::slot( &checkJournal ));
00223 map->sigPlayerUserInteractionBegins.connect( SigC::slot( &checkUsedASCVersions ));
00224 map->sigPlayerUserInteractionBegins.connect( SigC::hide<Player&>( updateFieldInfo.slot() ));
00225
00226 map->sigPlayerTurnHasEnded.connect( SigC::slot( viewOwnReplay));
00227
00228
00229 map->guiHooked();
00230 }
00231 }
00232
00233
00234 bool loadGame( const ASCString& filename )
00235 {
00236 GameMap* m = mapLoadingExceptionChecker( filename, MapLoadingFunction( tsavegameloaders::loadGameFromFile ));
00237 if ( !m )
00238 return false;
00239
00240 delete actmap;
00241 actmap = m;
00242 actmap->levelfinished = false;
00243
00244 if ( actmap->replayinfo ) {
00245 if ( actmap->replayinfo->actmemstream )
00246 displaymessage2( "actmemstream already open at begin of turn ",2 );
00247
00248 if ( actmap->replayinfo->guidata[actmap->actplayer] )
00249 actmap->replayinfo->actmemstream = new tmemorystream ( actmap->replayinfo->guidata[actmap->actplayer], tnstream::appending );
00250 else {
00251 actmap->replayinfo->guidata[actmap->actplayer] = new tmemorystreambuf;
00252 actmap->replayinfo->actmemstream = new tmemorystream ( actmap->replayinfo->guidata[actmap->actplayer], tnstream::writing );
00253 }
00254 }
00255
00256 computeview( actmap );
00257 hookGuiToMap ( actmap );
00258 return true;
00259 }
00260
00261
00262 bool loadGame( bool mostRecent )
00263 {
00264 ASCString s1;
00265 if ( mostRecent ) {
00266 int datefound = 0;
00267
00268 tfindfile ff ( savegameextension );
00269 tfindfile::FileInfo fi;
00270 while ( ff.getnextname( fi ))
00271 if ( fi.date > datefound ) {
00272 datefound = fi.date;
00273 s1 = fi.name;
00274 }
00275 } else {
00276 s1 = selectFile( savegameextension, true );
00277 }
00278
00279 if ( !s1.empty() ) {
00280 StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "loading " + s1 );
00281
00282 loadGame( s1 );
00283
00284 updateFieldInfo();
00285 positionCursor( actmap->getCurrentPlayer() );
00286 getDefaultMapDisplay().displayPosition( actmap->getCursor() );
00287 displaymap();
00288
00289 moveparams.movestatus = 0;
00290 return true;
00291 } else
00292 return false;
00293 }
00294
00295
00296 void saveGame( bool as )
00297 {
00298 if ( !actmap )
00299 return;
00300
00301 ASCString s1;
00302
00303 int nameavail = 0;
00304 if ( !actmap->preferredFileNames.savegame[actmap->actplayer].empty() )
00305 nameavail = 1;
00306
00307 if ( as || !nameavail ) {
00308 s1 = selectFile( savegameextension, false);
00309 } else
00310 s1 = actmap->preferredFileNames.savegame[actmap->actplayer];
00311
00312 if ( !s1.empty() ) {
00313 actmap->preferredFileNames.savegame[actmap->actplayer] = s1;
00314
00315 StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "saving " + s1 );
00316 savegame( s1 );
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325 void loadmap( const ASCString& name, bool campaign )
00326 {
00327 GameMap* m = mapLoadingExceptionChecker( name, MapLoadingFunction( tmaploaders::loadmap ));
00328 delete actmap;
00329 actmap = m;
00330 computeview( actmap );
00331 hookGuiToMap( actmap );
00332 if ( !campaign )
00333 actmap->campaign.avail = false;
00334 }
00335
00336
00337 enum MapTypeLoaded { None, Map, Savegame, Mailfile };
00338
00339 MapTypeLoaded loadStartupMap ( const char *gameToLoad=NULL )
00340 {
00341 if ( gameToLoad && gameToLoad[0] ) {
00342 try {
00343 if ( patimat ( ASCString("*")+tournamentextension, gameToLoad )) {
00344
00345 if( validateemlfile( gameToLoad ) == 0 )
00346 fatalError( "Email gamefile %s is invalid. Aborting.", gameToLoad );
00347
00348 try {
00349
00350 if ( continuenetworkgame( ASCString(gameToLoad) ))
00351 hookGuiToMap(actmap);
00352
00353 return Mailfile;
00354 } catch ( tfileerror ) {
00355 fatalError ( "%s is not a legal email game.", gameToLoad );
00356 }
00357 } else if( patimat ( savegameextension, gameToLoad )) {
00358 if( validatesavfile( gameToLoad ) == 0 )
00359 fatalError ( "The savegame %s is invalid. Aborting.", gameToLoad );
00360
00361 try {
00362 loadGame( gameToLoad );
00363 computeview( actmap );
00364 return Savegame;
00365 } catch ( tfileerror ) {
00366 fatalError ( "%s is not a legal savegame. ", gameToLoad );
00367 }
00368
00369 } else if( patimat ( mapextension, gameToLoad )) {
00370 if( validatemapfile( gameToLoad ) == 0 )
00371 fatalError ( "Mapfile %s is invalid. Aborting.", gameToLoad );
00372
00373 try {
00374 loadmap( gameToLoad, false );
00375 } catch ( tfileerror ) {
00376 fatalError ( "%s is not a legal map. ", gameToLoad );
00377 }
00378 } else
00379 fatalError ( "Don't know how to handle the file %s ", gameToLoad );
00380
00381 }
00382 catch ( InvalidID err ) {
00383 displaymessage( err.getMessage(), 2 );
00384 }
00385 catch ( tinvalidversion err ) {
00386 if ( err.expected < err.found )
00387 displaymessage( "File/module %s has invalid version.\nExpected version %d\nFound version %d\nPlease install the latest version from www.asc-hq.org", 2, err.getFileName().c_str(), err.expected, err.found );
00388 else
00389 displaymessage( "File/module %s has invalid version.\nExpected version %d\nFound version %d\nThis is a bug, please report it!", 2, err.getFileName().c_str(), err.expected, err.found );
00390 }
00391 } else {
00392
00393 ASCString s = CGameOptions::Instance()->startupMap;
00394
00395 if ( s.empty() )
00396 s = "asc001.map";
00397
00398
00399 int maploadable;
00400 {
00401 tfindfile ff ( s );
00402 string filename = ff.getnextname();
00403 maploadable = validatemapfile ( filename );
00404 }
00405
00406 if ( !maploadable ) {
00407
00408 tfindfile ff ( mapextension );
00409 string filename = ff.getnextname();
00410
00411 if ( filename.empty() )
00412 displaymessage( "unable to load startup-map",2);
00413
00414 while ( !validatemapfile ( filename ) ) {
00415 filename = ff.getnextname();
00416 if ( filename.empty() )
00417 displaymessage( "unable to load startup-map",2);
00418
00419 }
00420 s = filename;
00421 }
00422
00423 loadmap( s, true );
00424 return Map;
00425 displayLogMessage ( 6, "done\n" );
00426 }
00427
00428 return None;
00429 }
00430
00431
00432 void startnextcampaignmap( int id)
00433 {
00434 GameMap* map = nextCampaignMap( id );
00435 delete actmap;
00436 actmap = map;
00437
00438 if ( actmap ) {
00439 computeview( actmap );
00440 hookGuiToMap( actmap );
00441 repaintMap();
00442 }
00443 }
00444
00445
00446 void benchgame ( bool withViewCalc )
00447 {
00448 int t2;
00449 int t = ticker;
00450 int n = 0;
00451 do {
00452 if ( withViewCalc )
00453 computeview( actmap );
00454
00455 repaintMap();
00456
00457 n++;
00458 t2 = ticker;
00459 } while ( t + 1000 > t2 );
00460 double d = 100 * n;
00461 d /= (t2-t);
00462 char buf[100];
00463 sprintf ( buf, "%3.1f fps", d );
00464 infoMessage ( buf );
00465 }
00466
00467
00468 void showSearchPath()
00469 {
00470
00471 ASCString s = "#fontsize=17#ASC search path#fontsize=13#\n";
00472 for ( int i = 0; i < getSearchPathNum(); ++i )
00473 s += getSearchPath ( i ) + "\n";
00474
00475 s += "\n";
00476 s += "Configuration file used: \n";
00477 s += getConfigFileName();
00478
00479 #ifdef WIN32
00480 char buffer[_MAX_PATH];
00481
00482 if( _getcwd( buffer, _MAX_PATH ) ) {
00483 s += "\n#fontsize=17#Current working directory#fontsize=13#\n";
00484 s += buffer;
00485 }
00486 #endif
00487
00488 s += "\n\n#fontsize=17#Mounted archive files#fontsize=13#\n";
00489 s += listContainer();
00490
00491
00492 ViewFormattedText vft("ASC directories", s, PG_Rect( -1, -1, 400, 400 ));
00493 vft.Show();
00494 vft.RunModal();
00495 }
00496
00497
00498
00499 void changePassword( GameMap* gamemap )
00500 {
00501 if ( Player::getHumanPlayerNum( gamemap) < 2 ) {
00502 infoMessage ("Passwords are only used for multiplayer games");
00503 return;
00504 }
00505
00506 bool success;
00507 do {
00508 Password oldpwd = gamemap->player[gamemap->actplayer].passwordcrc;
00509 gamemap->player[gamemap->actplayer].passwordcrc.reset();
00510 success = enterpassword ( gamemap->player[gamemap->actplayer].passwordcrc, true, true );
00511 if ( !success )
00512 gamemap->player[gamemap->actplayer].passwordcrc = oldpwd;
00513 } while ( gamemap->player[gamemap->actplayer].passwordcrc.empty() && success && viewtextquery ( 910, "warning", "~e~nter password", "~c~ontinue without password" ) == 0 );
00514 }
00515
00516 void showSDLInfo()
00517 {
00518 #ifdef _SDL_
00519 ASCString s;
00520 s += "#fontsize=18#SDL versions#fontsize=14#\n";
00521 char buf[1000];
00522 SDL_version compiled;
00523 SDL_VERSION(&compiled);
00524 sprintf(buf, "\nCompiled with SDL version: %d.%d.%d\n", compiled.major, compiled.minor, compiled.patch);
00525 s += buf;
00526
00527 sprintf(buf, "Linked with SDL version: %d.%d.%d\n", SDL_Linked_Version()->major, SDL_Linked_Version()->minor, SDL_Linked_Version()->patch);
00528 s += buf;
00529
00530 s += "Byte order is ";
00531 #if SDL_BYTEORDER==SDL_LIL_ENDIAN
00532 s += "little endian\n";
00533 #else
00534 #if SDL_BYTEORDER==SDL_BIG_ENDIAN
00535 s += "big endian\n";
00536 #else
00537 s += "undefined\n";
00538 #endif
00539 #endif
00540
00541 s += "Graphics backend: ";
00542 s += SDL_VideoDriverName( buf, 1000 );
00543 s += "\n";
00544
00545
00546 const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
00547 s += "VideoInfo: \n";
00548
00549 s += "Hardware surfaces available: ";
00550 s += videoInfo->hw_available ? "yes" : "no";
00551
00552
00553 s += "\nScreen uses hardware surface: ";
00554 s += PG_Application::GetScreen()->flags & SDL_HWSURFACE ? "yes" : "no";
00555
00556 s += "\nWindow manager available: ";
00557 s += videoInfo->wm_available ? "yes" : "no";
00558
00559 s += "\nhardware to hardware blits accelerated: ";
00560 s += videoInfo->blit_hw ? "yes" : "no";
00561
00562 s += "\nhardware to hardware colorkey blits accelerated: ";
00563 s += videoInfo->blit_hw_CC ? "yes" : "no";
00564
00565 s += "\nhardware to hardware alpha blits accelerated: ";
00566 s += videoInfo->blit_hw_A ? "yes" : "no";
00567
00568 s += "\nsoftware to hardware blits accelerated: ";
00569 s += videoInfo->blit_sw ? "yes" : "no";
00570
00571 s += "\nsoftware to hardware colorkey blits accelerated: ";
00572 s += videoInfo->blit_sw_CC ? "yes" : "no";
00573
00574 s += "\nsoftware to hardware alpha blits accelerated: ";
00575 s += videoInfo->blit_sw_A ? "yes" : "no";
00576
00577 s += "\ncolor fills accelerated: ";
00578 s += videoInfo->blit_fill ? "yes" : "no";
00579
00580 s += "\nVideo memory: ";
00581 s += ASCString::toString( int(videoInfo->video_mem ));
00582
00583 ViewFormattedText vft( "SDL Settings", s, PG_Rect(-1,-1,450,550));
00584 vft.Show();
00585 vft.RunModal();
00586 #endif
00587 }
00588
00589 void helpAbout()
00590 {
00591 ASCString s = "#fontsize=22#Advanced Strategic Command#fontsize=14#\n";
00592 s += getVersionAndCompilation();
00593
00594 s += "\n#fontsize=18#Credits#fontsize=14#\n";
00595
00596 s += readtextmessage( 30 );
00597
00598 ViewFormattedText vft( "About", s, PG_Rect(-1,-1,450,550));
00599 vft.Show();
00600 vft.RunModal();
00601 }
00602
00603
00604
00605 void execuseraction ( tuseractions action )
00606 {
00607 switch ( action ) {
00608 case ua_repainthard :
00609 case ua_repaint :
00610 repaintDisplay();
00611 break;
00612
00613 case ua_help :
00614 help(20);
00615 break;
00616
00617 case ua_howtostartpbem :
00618 help(21);
00619 break;
00620
00621 case ua_howtocontinuepbem :
00622 help(22);
00623 break;
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 case ua_changeresourceview:
00673 if ( mainScreenWidget )
00674 mainScreenWidget->toggleMapLayer( "resources");
00675 displaymap();
00676 break;
00677
00678 case ua_visibilityInfo:
00679 if ( mainScreenWidget )
00680 mainScreenWidget->toggleMapLayer( "visibilityvalue");
00681 displaymap();
00682 break;
00683
00684 case ua_showCargoLayer:
00685 if ( mainScreenWidget )
00686 mainScreenWidget->toggleMapLayer( "container");
00687 displaymap();
00688 break;
00689
00690 case ua_benchgamewov:
00691 benchgame( false );
00692 break;
00693
00694 case ua_benchgamewv :
00695 benchgame( true );
00696 break;
00697
00698 case ua_writescreentopcx:
00699 {
00700 ASCString name = getnextfilenumname ( "screen", "pcx", 0 );
00701 Surface s ( PG_Application::GetScreen() );
00702 writepcx ( name, s);
00703 displaymessage2( "screen saved to %s", name.c_str() );
00704 }
00705 break;
00706
00707 case ua_bi3preferences:
00708 bi3preferences();
00709 break;
00710
00711 case ua_settribute :
00712 settributepayments ();
00713 break;
00714
00715 case ua_giveunitaway:
00716 if ( actmap && actmap->getgameparameter( cgp_disableUnitTransfer ) == 0 )
00717 giveunitaway ( actmap->getField( actmap->getCursor() ));
00718 else
00719 infoMessage("Sorry, this function has been disabled when starting the map!");
00720 break;
00721
00722 case ua_newmessage:
00723 newmessage();
00724 break;
00725
00726 case ua_viewqueuedmessages:
00727 viewmessages( "queued messages", actmap->unsentmessage, 1 );
00728 break;
00729
00730 case ua_viewsentmessages:
00731 viewmessages( "sent messages", actmap->player[ actmap->actplayer ].sentmessage, 0);
00732 break;
00733
00734 case ua_viewreceivedmessages:
00735 viewmessages( "received messages", actmap->player[ actmap->actplayer ].oldmessage, 0 );
00736 break;
00737
00738 case ua_viewjournal:
00739 viewjournal( true );
00740 break;
00741
00742 case ua_editjournal:
00743 editjournal();
00744 break;
00745
00746 case ua_viewaboutmessage:
00747 helpAbout();
00748 break;
00749
00750 case ua_viewlayerhelp:
00751 help(49);
00752 break;
00753
00754 case ua_SDLinfo:
00755 showSDLInfo();
00756 break;
00757
00758 case ua_toggleunitshading:
00759 {
00760 CGameOptions::Instance()->units_gray_after_move = !CGameOptions::Instance()->units_gray_after_move;
00761 CGameOptions::Instance()->setChanged();
00762 displaymap();
00763 while ( mouseparams.taste )
00764 releasetimeslice();
00765
00766 ASCString condition;
00767 if ( CGameOptions::Instance()->units_gray_after_move )
00768 condition = "- thay can't move";
00769 else
00770 condition = "- thay can't move AND\n- thay can't shoot";
00771
00772 infoMessage ("units that now displayed shaded when:\n" + condition);
00773 }
00774
00775 break;
00776
00777 case ua_computerturn:
00778 if ( maintainencecheck() ) {
00779 displaymessage("This function is under development and for programmers only\n"
00780 "unpredictable things may happen ...",3 ) ;
00781
00782 if (choice_dlg("do you really want to start the AI?","~y~es","~n~o") == 1) {
00783
00784 if ( !actmap->player[ actmap->actplayer ].ai )
00785 actmap->player[ actmap->actplayer ].ai = new AI ( actmap, actmap->actplayer );
00786
00787 savegame ( "aistart.sav" );
00788 actmap->player[ actmap->actplayer ].ai->run();
00789 }
00790 }
00791 break;
00792 case ua_setupnetwork:
00793
00794
00795
00796
00797
00798
00799 displaymessage("Not implemented yet",3 );
00800 break;
00801 case ua_UnitSetInfo:
00802 viewUnitSetinfo();
00803 break;
00804 case ua_GameParameterInfo:
00805 showGameParameters();
00806 break;
00807 case ua_viewunitweaponrange:
00808 mainScreenWidget->showWeaponRange( actmap, actmap->getCursor() );
00809 break;
00810
00811 case ua_viewunitmovementrange:
00812 mainScreenWidget->showMovementRange( actmap, actmap->getCursor() );
00813 break;
00814
00815 case ua_aibench:
00816 if ( maintainencecheck() && 0 ) {
00817 if ( !actmap->player[ actmap->actplayer ].ai )
00818 actmap->player[ actmap->actplayer ].ai = new AI ( actmap, actmap->actplayer );
00819
00820 if ( AI* ai = dynamic_cast<AI*>( actmap->player[ actmap->actplayer ].ai )) {
00821 savegame ( "ai-bench-start.sav" );
00822 ai->run( true );
00823 }
00824 }
00825 break;
00826
00827 case ua_selectPlayList:
00828 selectPlayList();
00829 break;
00830 case ua_statisticdialog:
00831 statisticDialog();
00832 break;
00833
00834 case ua_togglesound:
00835 if ( !SoundSystem::getInstance()->isOff() ) {
00836 bool on = !SoundSystem::getInstance()->areEffectsMuted();
00837 SoundSystem::getInstance()->setEffectsMute( on );
00838 if ( on )
00839 SoundSystem::getInstance()->pauseMusic();
00840 else
00841 SoundSystem::getInstance()->resumeMusic();
00842 }
00843 break;
00844 case ua_showPlayerSpeed:
00845 showPlayerTime();
00846 break;
00847 case ua_cancelResearch:
00848 if ( actmap->player[actmap->actplayer].research.activetechnology ) {
00849 ASCString s = "do you really want to cancel the current research project ?\n";
00850
00851
00852 if (choice_dlg(s.c_str(),"~y~es","~n~o") == 1) {
00853 actmap->player[actmap->actplayer].research.cancel();
00854 logtoreplayinfo( rpl_cancelResearch );
00855 }
00856
00857 } else
00858 displaymessage("you are not researching anything", 3);
00859 break;
00860 case ua_showResearchStatus: {
00861 ASCString s;
00862 s += "Current technology:\n";
00863 if ( actmap->player[actmap->actplayer].research.activetechnology )
00864 s += actmap->player[actmap->actplayer].research.activetechnology->name;
00865 else
00866 s += " - none - ";
00867 s += "\n\n";
00868
00869 s += "Research Points: \n";
00870 s += strrr( actmap->player[actmap->actplayer].research.progress );
00871 if ( actmap->player[actmap->actplayer].research.activetechnology )
00872 s += ASCString(" / ") + strrr ( actmap->player[actmap->actplayer].research.activetechnology->researchpoints );
00873 s += "\n\n";
00874
00875 s+= "Research Points Plus \n";
00876
00877 s += strrr ( actmap->player[actmap->actplayer].research.getResearchPerTurn() );
00878
00879 s += "\n\n";
00880
00881 s+= "Developed Technologies: \n";
00882 for ( vector<int>::iterator i = actmap->player[actmap->actplayer].research.developedTechnologies.begin(); i != actmap->player[actmap->actplayer].research.developedTechnologies.end(); ++i ) {
00883 Technology* t = technologyRepository.getObject_byID( *i );
00884 if ( t )
00885 s += t->name + "\n";
00886 }
00887
00888 tviewanytext vat ;
00889 vat.init ( "Research Status", s.c_str(), 20, -1 , 450, 480 );
00890 vat.run();
00891 vat.done();
00892 }
00893 break;
00894 case ua_exportUnitToFile:
00895 if ( getSelectedField()->vehicle && getSelectedField()->vehicle->getOwner() == actmap->actplayer ){
00896 if (choice_dlg( "do you really want to cut this unit from the game?", "~y~es","~n~o") == 1) {
00897 Vehicle* veh = getSelectedField()->vehicle;
00898 ClipBoard::Instance().clear();
00899 ClipBoard::Instance().addUnit( veh );
00900
00901 ASCString filename = selectFile( clipboardFileExtension, false );
00902 if ( !filename.empty() ) {
00903 tnfilestream stream ( filename, tnstream::writing );
00904 ClipBoard::Instance().write( stream );
00905 logtoreplayinfo ( rpl_cutFromGame, veh->networkid );
00906 veh->prepareForCleanRemove();
00907 delete veh;
00908 computeview( actmap );
00909 displaymap();
00910 }
00911 }
00912 }
00913 break;
00914
00915 default:;
00916 };
00917 }
00918
00919 bool continueAndStartMultiplayerGame( bool mostRecent = false )
00920 {
00921 if ( continuenetworkgame( mostRecent )) {
00922 hookGuiToMap(actmap);
00923 actmap->sigPlayerUserInteractionBegins( actmap->player[actmap->actplayer] );
00924 displaymap();
00925 return true;
00926 } else
00927 return false;
00928 }
00929
00930
00931 void ammoCounter( const ContainerBase* c, map<int,int>& amount )
00932 {
00933 for ( int i = 0; i < cwaffentypennum; ++i )
00934 if ( weaponAmmo[i] )
00935 amount[i] += c->getAmmo(i,maxint );
00936
00937 for ( int i = 1000; i < 1003; ++i )
00938 amount[i] += c->getAvailableResource( maxint, i-1000, 0 );
00939
00940 for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00941 if ( *i )
00942 ammoCounter( *i, amount );
00943 }
00944
00945
00946 void showCargoSummary( tfield* fld )
00947 {
00948 if ( !fld->vehicle ) {
00949 infoMessage( "Please select a unit");
00950 return;
00951 }
00952
00953 if ( actmap->getCurrentPlayer().diplomacy.isAllied( fld->vehicle )) {
00954 showUnitCargoSummary( fld->vehicle );
00955 map<int,int> ammo;
00956 ammoCounter( fld->vehicle, ammo );
00957 ASCString s;
00958 for ( int i = 0; i < cwaffentypennum; ++i )
00959 if ( weaponAmmo[i] )
00960 s += ASCString(cwaffentypen[i]) + ": " + ASCString::toString( ammo[i] ) + "\n";
00961
00962 s += "\n";
00963 for ( int i = 1000; i < 1003; ++i )
00964 s += ASCString(Resources::name(i-1000)) + ": " + ASCString::toString( ammo[i] ) + "\n";
00965
00966 ViewFormattedText vft("Ammo summary", s, PG_Rect( -1, -1, 300, 300 ));
00967 vft.Show();
00968 vft.RunModal();
00969 } else
00970 infoMessage( "The unit is not yours");
00971
00972 }
00973
00974
00975 class GotoPosition: public ASC_PG_Dialog {
00976 PG_LineEdit* xfield;
00977 PG_LineEdit* yfield;
00978 GameMap* gamemap;
00979
00980
00981
00982 bool ok()
00983 {
00984 static boost::regex numercial("\\d+");
00985
00986 if( boost::regex_match( xfield->GetText(), numercial) &&
00987 boost::regex_match( yfield->GetText(), numercial)) {
00988 int xx = atoi( xfield->GetText() );
00989 int yy = atoi( yfield->GetText() );
00990 if ( xx >= 0 && yy >= 0 && xx < gamemap->xsize && yy < gamemap->ysize ) {
00991 Hide();
00992 MapDisplayPG* md = getMainScreenWidget()->getMapDisplay();
00993 md->cursor.goTo( MapCoordinate( xx, yy) );
00994 QuitModal();
00995 return true;
00996 }
00997 }
00998 return false;
00999 }
01000
01001 bool cancel()
01002 {
01003 QuitModal();
01004 return true;
01005 }
01006
01007 static const int border = 20;
01008
01009 bool line1completed()
01010 {
01011 if ( yfield ) {
01012 yfield->EditBegin();
01013 return true;
01014 } else
01015 return false;
01016 }
01017
01018 public:
01019 GotoPosition ( GameMap* gamemap ) : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 300, 120), "Enter Coordinates")
01020 {
01021 this->gamemap = gamemap;
01022 int fieldwidth = (Width()-3*border)/2;
01023 xfield = new PG_LineEdit( this, PG_Rect( border, 40, fieldwidth, 20));
01024
01025 xfield->sigEditReturn.connect( SigC::slot( *this, &GotoPosition::line1completed ));
01026
01027 yfield = new PG_LineEdit( this, PG_Rect( (Width()+border)/2, 40, fieldwidth, 20));
01028
01029 yfield->sigEditReturn.connect( SigC::slot( *this, &GotoPosition::ok ));
01030
01031 AddStandardButton( "~O~k" )->sigClick.connect( SigC::slot( *this, &GotoPosition::ok ));
01032 };
01033
01034 int RunModal()
01035 {
01036 xfield->EditBegin();
01037 return ASC_PG_Dialog::RunModal();
01038 }
01039 };
01040
01041
01042
01043 class FontViewer : public ASC_PG_Dialog {
01044 static const int spacing = 30;
01045 public:
01046 FontViewer() : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 18 * spacing, 19 * spacing ), "view character set" )
01047 {
01048 for ( int i = 32; i < 255; ++i ) {
01049 ASCString s;
01050 s += char(i);
01051 new PG_Label ( this, PG_Rect( (i % 16 + 1) * spacing, (i / 16 + 2) * spacing, spacing, spacing ), s );
01052 }
01053 };
01054 };
01055
01056 void viewFont()
01057 {
01058 FontViewer fv;
01059 fv.Show();
01060 fv.RunModal();
01061 }
01062
01063
01064 void resourceAnalysis()
01065 {
01066 ASCString s;
01067 Resources total;
01068 for ( Player::BuildingList::iterator j = actmap->player[actmap->actplayer].buildingList.begin(); j != actmap->player[actmap->actplayer].buildingList.end() ; j++ ) {
01069 Resources res = (*j)->getResource( Resources(maxint,maxint,maxint), true, 0 );
01070 MapCoordinate pos = (*j)->getPosition();
01071 s += (*j)->getName() + " #pos150#(" + ASCString::toString( pos.x ) + "/" + ASCString::toString( pos.y) + pos.toString() + ") : #pos300#" + ASCString::toString(res.energy) + "#pos400#" + ASCString::toString(res.material) + "#pos500#" + ASCString::toString(res.fuel) + "\n";
01072 total += res;
01073 }
01074 s += "\nTotal:\n";
01075
01076 for ( int r = 0; r < 3; ++r)
01077 if ( actmap->isResourceGlobal(r))
01078 total.resource(r) = actmap->bi_resource[actmap->actplayer].resource(r);
01079 s += total.toString();
01080
01081 ViewFormattedText vft("Resource Analysis", s, PG_Rect( -1, -1, 600, 550 ));
01082 vft.Show();
01083 vft.RunModal();
01084 }
01085
01086 void showUnitEndurance()
01087 {
01088
01089 vector<Vehicletype*> units;
01090 for ( int i = 0; i < vehicleTypeRepository.getNum(); ++i ) {
01091 Vehicletype* vt = vehicleTypeRepository.getObject_byPos(i);
01092 if ( vt && (vt->movemalustyp == MoveMalusType::medium_aircraft ||
01093 vt->movemalustyp == MoveMalusType::light_aircraft ||
01094 vt->movemalustyp == MoveMalusType::heavy_aircraft ||
01095 vt->movemalustyp == MoveMalusType::helicopter))
01096 units.push_back( vt );
01097 }
01098 sort( units.begin(), units.end(), vehicleComp );
01099
01100 ASCString s;
01101 for ( vector<Vehicletype*>::iterator i = units.begin(); i != units.end(); ++i )
01102 {
01103 ASCString u;
01104 ASCString range;
01105 if ( (*i)->fuelConsumption )
01106 range = ASCString::toString( (*i)->getStorageCapacity(0).fuel / (*i)->fuelConsumption);
01107 else
01108 range = "-";
01109
01110 u.format( "#vehicletype=%d# %s : %d fuel ; %s fields range ; %d turns endurance \n", (*i)->id, (*i)->getName().c_str(), (*i)->getStorageCapacity(0).fuel, range.c_str(), UnitHooveringLogic::getEndurance(*i) );
01111 s += u;
01112 }
01113
01114 ViewFormattedText vft("Unit Endurance", s, PG_Rect( -1, -1, 650, 550 ));
01115 vft.Show();
01116 vft.RunModal();
01117 }
01118
01119
01120 void showMemoryFootprint()
01121 {
01122 MemoryMeasurement mm;
01123 mm.measureTypes();
01124 mm.measure( actmap );
01125 mm.measureIcons();
01126
01127 ViewFormattedText vft("Memory Usage", mm.getResult(), PG_Rect( -1, -1, 750, 550 ));
01128 vft.Show();
01129 vft.RunModal();
01130 }
01131
01132
01133 void viewMiningPower()
01134 {
01135 typedef map<const ContainerBaseType*,ASCString> InfoMap;
01136 InfoMap info;
01137
01138 for ( Player::BuildingList::iterator i = actmap->getCurrentPlayer().buildingList.begin(); i != actmap->getCurrentPlayer().buildingList.end(); ++i )
01139 if ( (*i)->baseType->hasFunction( ContainerBaseType::MiningStation )) {
01140 int power;
01141 int output;
01142 MiningStation miningStation ( *i, true );
01143 for ( int r = 0; r < 3; ++r )
01144 if ( (*i)->maxplus.resource(r) ) {
01145 power = 100 * (*i)->plus.resource(r) / (*i)->maxplus.resource(r) ;
01146 break;
01147 }
01148
01149 for ( int r = 0; r < 3; ++r )
01150 if ( miningStation.getPlus().resource(r) ) {
01151 output = miningStation.getPlus().resource(r);
01152 break;
01153 }
01154
01155 ASCString txt = ASCString::toString(output) + " (" + ASCString::toString(power) + "%) " + (*i)->getPosition().toString() + " " + (*i)->baseType->name + "\n";
01156 info[(*i)->baseType] += txt;
01157 }
01158
01159 ASCString fullText = "Mining Station Statistics\n\n";
01160 for ( InfoMap::iterator i = info.begin(); i != info.end(); ++i )
01161 fullText += i->second;
01162
01163
01164 ViewFormattedText vft("Mining Stations", fullText, PG_Rect( -1, -1, 750, 550 ));
01165 vft.Show();
01166 vft.RunModal();
01167
01168 }
01169
01170
01171
01172
01173
01174 void execuseraction2 ( tuseractions action )
01175 {
01176 switch ( action ) {
01177
01178 case ua_unitweightinfo:
01179 if ( fieldvisiblenow ( getSelectedField() )) {
01180 Vehicle* eht = getSelectedField()->vehicle;
01181 if ( eht && actmap->player[actmap->actplayer].diplomacy.getState( eht->getOwner()) >= PEACE_SV )
01182 infoMessage(" weight of unit: \n basic: " + ASCString::toString(eht->typ->weight) + "\n+cargo: " + ASCString::toString(eht->cargoWeight()) + "\n= " + ASCString::toString( eht->weight() ));
01183 }
01184 break;
01185 case ua_GameStatus:
01186 infoMessage ( "Current game time is:\n turn " + ASCString::toString( actmap->time.turn() ) + " , move " + ASCString::toString( actmap->time.move() ));
01187 break;
01188 case ua_soundDialog:
01189 soundSettings( NULL );
01190 break;
01191 case ua_reloadDlgTheme:
01192 getPGApplication().reloadTheme();
01193 MessagingHub::Instance().message( MessagingHubBase::InfoMessage, "Theme reloaded" );
01194
01195 break;
01196 case ua_viewButtonPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::ButtonPanel );
01197 break;
01198 case ua_viewWindPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::WindInfo );
01199 break;
01200 case ua_clearImageCache: IconRepository::clear();
01201 break;
01202 case ua_viewUnitInfoPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::UnitInfo );
01203 break;
01204 case ua_viewOverviewMapPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::OverviewMap );
01205 break;
01206 case ua_viewMapControlPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::MapControl );
01207 break;
01208 case ua_vehicleinfo: unitInfoDialog();
01209 break;
01210 #ifdef WEATHERGENERATOR
01211 case ua_weathercast: weathercast();
01212 break;
01213 #endif
01214 case ua_newGame:
01215 startMultiplayerGame();
01216 break;
01217
01218 case ua_continuerecentnetworkgame:
01219 continueAndStartMultiplayerGame( true );
01220 break;
01221
01222 case ua_continuenetworkgame:
01223 continueAndStartMultiplayerGame();
01224 break;
01225 case ua_loadgame: loadGame( false);
01226 break;
01227 case ua_loadrecentgame: loadGame ( true );
01228 break;
01229 case ua_savegame: saveGame( true );
01230 break;
01231 case ua_setupalliances:
01232 if ( setupalliances( actmap, actmap->getCurrentPlayer().stat == Player::supervisor ) ) {
01233 if ( computeview( actmap ))
01234 displaymap();
01235 }
01236 updateFieldInfo();
01237 break;
01238 case ua_mainmenu:
01239
01240
01241
01242
01243
01244
01245
01246 GameDialog::gameDialog();
01247 break;
01248 case ua_viewterraininfo:
01249 if ( fieldvisiblenow( actmap->getField( actmap->getCursor())))
01250 viewterraininfo( actmap, actmap->getCursor(), fieldVisibility( actmap->getField( actmap->getCursor())) == visible_all );
01251 break;
01252 case ua_testMessages:
01253 MessagingHub::Instance().message( MessagingHubBase::InfoMessage, "This is an informational message" );
01254 MessagingHub::Instance().message( MessagingHubBase::Warning, "This is an warning message" );
01255 MessagingHub::Instance().message( MessagingHubBase::Error, "This is an error message" );
01256 MessagingHub::Instance().message( MessagingHubBase::FatalError, "This is an fatal error message. Game will be exited." );
01257 break;
01258 case ua_writemaptopcx :
01259 writemaptopcx ( actmap, choice_dlg("Include View ?","~y~es","~n~o")==1 );
01260 break;
01261 case ua_exitgame:
01262 if (choice_dlg("do you really want to quit ?","~y~es","~n~o") == 1)
01263 getPGApplication().Quit();
01264 break;
01265 case ua_cargosummary:
01266 showCargoSummary( getSelectedField() );
01267 break;
01268 case ua_unitsummary: showUnitSummary( actmap );
01269 break;
01270 case ua_gamepreferences:
01271 editGameOptions();
01272 break;
01273 case ua_increase_zoom:
01274 if ( mainScreenWidget && mainScreenWidget->getMapDisplay() ) {
01275 mainScreenWidget->getMapDisplay()->changeZoom( 10 );
01276 viewChanged();
01277 repaintMap();
01278 }
01279 break;
01280 case ua_decrease_zoom:
01281 if ( mainScreenWidget && mainScreenWidget->getMapDisplay() ) {
01282 mainScreenWidget->getMapDisplay()->changeZoom( -10 );
01283 viewChanged();
01284 repaintMap();
01285 }
01286 break;
01287 case ua_selectgraphicset:
01288 selectgraphicset();
01289 break;
01290 case ua_networksupervisor:
01291 networksupervisor();
01292 displaymap();
01293 break;
01294 case ua_researchinfo:
01295 researchinfo ();
01296 break;
01297 case ua_viewPipeNet:
01298 mainScreenWidget->getMapDisplay()->toggleMapLayer("pipes");
01299 repaintMap();
01300 break;
01301 case ua_showsearchdirs: showSearchPath();
01302 break;
01303 case ua_changepassword:
01304 changePassword( actmap );
01305 break;
01306 case ua_editPlayerData:
01307 editPlayerData( actmap );
01308 break;
01309 case ua_locatefile:
01310 locateFile();
01311 break;
01312 case ua_viewfont:
01313 viewFont();
01314 break;
01315 case ua_resourceAnalysis:
01316 resourceAnalysis();
01317 break;
01318 case ua_unitproductionanalysis:
01319 unitProductionAnalysis( actmap );
01320 break;
01321 case ua_gotoPosition: {
01322 GotoPosition gp( actmap );
01323 gp.Show();
01324 gp.RunModal();
01325 break;
01326 };
01327 case ua_showTechAdapter: {
01328 ViewFormattedText vft("TechAdapter", actmap->getCurrentPlayer().research.listTriggeredTechAdapter(), PG_Rect( -1,-1,300,500));
01329 vft.Show();
01330 vft.RunModal();
01331 };
01332 break;
01333 case ua_showUnitEndurance: showUnitEndurance();
01334 break;
01335
01336 case ua_getMemoryFootprint: showMemoryFootprint();
01337 break;
01338
01339 case ua_showMiningPower: viewMiningPower();
01340 break;
01341
01342 case ua_emailOptions: editEmailOptions();
01343 break;
01344
01345 case ua_createReminder: newreminder();
01346 break;
01347
01348 default:
01349 break;
01350 }
01351
01352 }
01353
01354
01355
01356
01357 void execUserAction_ev( tuseractions action )
01358 {
01359 execuseraction( action );
01360 execuseraction2( action );
01361 }
01362
01363
01364
01365
01366 bool mainloopidle( PG_MessageObject* msgObj )
01367 {
01368 if ( msgObj != PG_Application::GetApp())
01369 return false;
01370
01371 if ( actmap ) {
01372 while ( actmap->player[ actmap->actplayer ].queuedEvents )
01373 if ( !checkevents( &getDefaultMapDisplay() ))
01374 return false;
01375
01376 checktimedevents( &getDefaultMapDisplay() );
01377
01378 checkforvictory( true );
01379 }
01380 return false;
01381 }
01382
01383
01384
01385 pfont load_font ( const char* name )
01386 {
01387 tnfilestream stream ( name , tnstream::reading );
01388 return loadfont ( &stream );
01389 }
01390
01391
01392 void resetActions( GameMap& map )
01393 {
01394 moveparams.reset();
01395 pendingVehicleActions.reset();
01396 }
01397
01398
01399 void