00001
00002
00005 #include "stdafx.h"
00006
00007 #define VARDEF
00008 #include "variables.h"
00009 #undef VARDEF
00010
00011 #include "openttd.h"
00012
00013 #include "blitter/factory.hpp"
00014 #include "sound/sound_driver.hpp"
00015 #include "music/music_driver.hpp"
00016 #include "video/video_driver.hpp"
00017
00018 #include "fontcache.h"
00019 #include "gfxinit.h"
00020 #include "gui.h"
00021 #include "mixer.h"
00022 #include "sound_func.h"
00023 #include "window_func.h"
00024
00025 #include "saveload/saveload.h"
00026 #include "landscape.h"
00027 #include "company_func.h"
00028 #include "command_func.h"
00029 #include "news_func.h"
00030 #include "fileio_func.h"
00031 #include "fios.h"
00032 #include "aircraft.h"
00033 #include "console_func.h"
00034 #include "screenshot.h"
00035 #include "network/network.h"
00036 #include "network/network_func.h"
00037 #include "signs_base.h"
00038 #include "ai/ai.hpp"
00039 #include "ai/ai_config.hpp"
00040 #include "settings_func.h"
00041 #include "genworld.h"
00042 #include "group.h"
00043 #include "strings_func.h"
00044 #include "date_func.h"
00045 #include "vehicle_func.h"
00046 #include "gamelog.h"
00047 #include "cheat_type.h"
00048 #include "animated_tile_func.h"
00049 #include "functions.h"
00050 #include "elrail_func.h"
00051 #include "rev.h"
00052 #include "highscore.h"
00053 #include "thread.h"
00054
00055 #include "newgrf_commons.h"
00056
00057 #include "town.h"
00058 #include "industry.h"
00059
00060 #include <stdarg.h>
00061
00062 #include "table/strings.h"
00063
00064 StringID _switch_mode_errorstr;
00065
00066 void CallLandscapeTick();
00067 void IncreaseDate();
00068 void DoPaletteAnimations();
00069 void MusicLoop();
00070 void ResetMusic();
00071 void ProcessAsyncSaveFinish();
00072 void CallWindowTickEvent();
00073
00074 extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt);
00075 extern Company *DoStartupNewCompany(bool is_ai);
00076 extern void ShowOSErrorBox(const char *buf, bool system);
00077 extern void InitializeRailGUI();
00078
00084 void CDECL usererror(const char *s, ...)
00085 {
00086 va_list va;
00087 char buf[512];
00088
00089 va_start(va, s);
00090 vsnprintf(buf, lengthof(buf), s, va);
00091 va_end(va);
00092
00093 ShowOSErrorBox(buf, false);
00094 if (_video_driver != NULL) _video_driver->Stop();
00095
00096 exit(1);
00097 }
00098
00104 void CDECL error(const char *s, ...)
00105 {
00106 va_list va;
00107 char buf[512];
00108
00109 va_start(va, s);
00110 vsnprintf(buf, lengthof(buf), s, va);
00111 va_end(va);
00112
00113 ShowOSErrorBox(buf, true);
00114 if (_video_driver != NULL) _video_driver->Stop();
00115
00116 assert(0);
00117 exit(1);
00118 }
00119
00124 void CDECL ShowInfoF(const char *str, ...)
00125 {
00126 va_list va;
00127 char buf[1024];
00128 va_start(va, str);
00129 vsnprintf(buf, lengthof(buf), str, va);
00130 va_end(va);
00131 ShowInfo(buf);
00132 }
00133
00137 static void ShowHelp()
00138 {
00139 char buf[8192];
00140 char *p = buf;
00141
00142 p += seprintf(p, lastof(buf), "OpenTTD %s\n", _openttd_revision);
00143 p = strecpy(p,
00144 "\n"
00145 "\n"
00146 "Command line options:\n"
00147 " -v drv = Set video driver (see below)\n"
00148 " -s drv = Set sound driver (see below) (param bufsize,hz)\n"
00149 " -m drv = Set music driver (see below)\n"
00150 " -b drv = Set the blitter to use (see below)\n"
00151 " -a ai = Force use of specific AI (see below)\n"
00152 " -r res = Set resolution (for instance 800x600)\n"
00153 " -h = Display this help text\n"
00154 " -t year = Set starting year\n"
00155 " -d [[fac=]lvl[,...]]= Debug mode\n"
00156 " -e = Start Editor\n"
00157 " -g [savegame] = Start new/save game immediately\n"
00158 " -G seed = Set random seed\n"
00159 #if defined(ENABLE_NETWORK)
00160 " -n [ip:port#company]= Start networkgame\n"
00161 " -D [ip][:port] = Start dedicated server\n"
00162 " -l ip[:port] = Redirect DEBUG()\n"
00163 #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
00164 " -f = Fork into the background (dedicated only)\n"
00165 #endif
00166 #endif
00167 " -i palette = Force to use the DOS (0) or Windows (1) palette\n"
00168 " (defines default setting when adding newgrfs)\n"
00169 " Default value (2) lets OpenTTD use the palette\n"
00170 " specified in graphics set file (see below)\n"
00171 " -I graphics_set = Force the graphics set (see below)\n"
00172 " -c config_file = Use 'config_file' instead of 'openttd.cfg'\n"
00173 " -x = Do not automatically save to config file on exit\n"
00174 "\n",
00175 lastof(buf)
00176 );
00177
00178
00179 p = GetGraphicsSetsList(p, lastof(buf));
00180
00181
00182 p = VideoDriverFactoryBase::GetDriversInfo(p, lastof(buf));
00183
00184
00185 p = BlitterFactoryBase::GetBlittersInfo(p, lastof(buf));
00186
00187
00188 AI::Initialize();
00189 p = AI::GetConsoleList(p, lastof(buf));
00190 AI::Uninitialize(true);
00191
00192
00193
00194 #if !defined(WIN32) && !defined(WIN64)
00195 printf("%s\n", buf);
00196 #else
00197 ShowInfo(buf);
00198 #endif
00199 }
00200
00201
00202 struct MyGetOptData {
00203 char *opt;
00204 int numleft;
00205 char **argv;
00206 const char *options;
00207 const char *cont;
00208
00209 MyGetOptData(int argc, char **argv, const char *options)
00210 {
00211 opt = NULL;
00212 numleft = argc;
00213 this->argv = argv;
00214 this->options = options;
00215 cont = NULL;
00216 }
00217 };
00218
00219 static int MyGetOpt(MyGetOptData *md)
00220 {
00221 const char *s, *r, *t;
00222
00223 s = md->cont;
00224 if (s != NULL)
00225 goto md_continue_here;
00226
00227 for (;;) {
00228 if (--md->numleft < 0) return -1;
00229
00230 s = *md->argv++;
00231 if (*s == '-') {
00232 md_continue_here:;
00233 s++;
00234 if (*s != 0) {
00235
00236 if (*s == ':' || (r = strchr(md->options, *s)) == NULL) {
00237
00238 return -2;
00239 }
00240 if (r[1] == ':') {
00241
00242 if (!*(t = s + 1)) {
00243
00244 if (--md->numleft < 0 || *(t = *md->argv) == '-') {
00245
00246 if (r[2] != ':')
00247 return -2;
00248 md->numleft++;
00249 t = NULL;
00250 } else {
00251 md->argv++;
00252 }
00253 }
00254 md->opt = (char*)t;
00255 md->cont = NULL;
00256 return *s;
00257 }
00258 md->opt = NULL;
00259 md->cont = s;
00260 return *s;
00261 }
00262 } else {
00263
00264 return -2;
00265 }
00266 }
00267 }
00268
00275 static void ParseResolution(Dimension *res, const char *s)
00276 {
00277 const char *t = strchr(s, 'x');
00278 if (t == NULL) {
00279 ShowInfoF("Invalid resolution '%s'", s);
00280 return;
00281 }
00282
00283 res->width = max(strtoul(s, NULL, 0), 64UL);
00284 res->height = max(strtoul(t + 1, NULL, 0), 64UL);
00285 }
00286
00287 static void InitializeDynamicVariables()
00288 {
00289
00290 _engine_mngr.ResetToDefaultMapping();
00291 _house_mngr.ResetMapping();
00292 _industry_mngr.ResetMapping();
00293 _industile_mngr.ResetMapping();
00294 _Company_pool.AddBlockToPool();
00295 }
00296
00297
00301 static void ShutdownGame()
00302 {
00303
00304 AI::Uninitialize(false);
00305
00306 IConsoleFree();
00307
00308 if (_network_available) NetworkShutDown();
00309
00310 DriverFactoryBase::ShutdownDrivers();
00311
00312 UnInitWindowSystem();
00313
00314
00315 UnInitializeAirports();
00316
00317
00318 GamelogReset();
00319 _Town_pool.CleanPool();
00320 _Industry_pool.CleanPool();
00321 _Station_pool.CleanPool();
00322 _Vehicle_pool.CleanPool();
00323 _Sign_pool.CleanPool();
00324 _Order_pool.CleanPool();
00325 _Group_pool.CleanPool();
00326 _CargoPacket_pool.CleanPool();
00327 _Engine_pool.CleanPool();
00328 _Company_pool.CleanPool();
00329
00330 free(_config_file);
00331
00332
00333 FioCloseAll();
00334 }
00335
00336 static void LoadIntroGame()
00337 {
00338 _game_mode = GM_MENU;
00339
00340 ResetGRFConfig(false);
00341
00342
00343 ResetWindowSystem();
00344 SetupColoursAndInitialWindow();
00345
00346
00347 if (SaveOrLoad("opntitle.dat", SL_LOAD, DATA_DIR) != SL_OK) {
00348 GenerateWorld(GW_EMPTY, 64, 64);
00349 WaitTillGeneratedWorld();
00350 SetLocalCompany(COMPANY_SPECTATOR);
00351 } else {
00352 SetLocalCompany(COMPANY_FIRST);
00353 }
00354
00355 _pause_game = 0;
00356 _cursor.fix_at = false;
00357
00358 CheckForMissingGlyphsInLoadedLanguagePack();
00359
00360
00361 if (_music_driver->IsSongPlaying()) ResetMusic();
00362 }
00363
00364 void MakeNewgameSettingsLive()
00365 {
00366 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00367 if (_settings_game.ai_config[c] != NULL) {
00368 delete _settings_game.ai_config[c];
00369 }
00370 }
00371
00372 _settings_game = _settings_newgame;
00373
00374 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00375 _settings_game.ai_config[c] = NULL;
00376 if (_settings_newgame.ai_config[c] != NULL) {
00377 _settings_game.ai_config[c] = new AIConfig(_settings_newgame.ai_config[c]);
00378 }
00379 }
00380 }
00381
00382 byte _savegame_sort_order;
00383 #if defined(UNIX) && !defined(__MORPHOS__)
00384 extern void DedicatedFork();
00385 #endif
00386
00387 int ttd_main(int argc, char *argv[])
00388 {
00389 int i;
00390 const char *optformat;
00391 char *musicdriver = NULL;
00392 char *sounddriver = NULL;
00393 char *videodriver = NULL;
00394 char *blitter = NULL;
00395 char *graphics_set = NULL;
00396 Dimension resolution = {0, 0};
00397 Year startyear = INVALID_YEAR;
00398 uint generation_seed = GENERATE_NEW_SEED;
00399 bool save_config = true;
00400 #if defined(ENABLE_NETWORK)
00401 bool dedicated = false;
00402 bool network = false;
00403 char *network_conn = NULL;
00404 char *debuglog_conn = NULL;
00405 char *dedicated_host = NULL;
00406 uint16 dedicated_port = 0;
00407 #endif
00408
00409 _game_mode = GM_MENU;
00410 _switch_mode = SM_MENU;
00411 _switch_mode_errorstr = INVALID_STRING_ID;
00412 _dedicated_forks = false;
00413 _config_file = NULL;
00414
00415
00416
00417
00418
00419 optformat = "m:s:v:b:hD::n::ei::I:t:d::r:g::G:c:xl:"
00420 #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32)
00421 "f"
00422 #endif
00423 ;
00424
00425 MyGetOptData mgo(argc - 1, argv + 1, optformat);
00426
00427 while ((i = MyGetOpt(&mgo)) != -1) {
00428 switch (i) {
00429 case 'I': free(graphics_set); graphics_set = strdup(mgo.opt); break;
00430 case 'm': free(musicdriver); musicdriver = strdup(mgo.opt); break;
00431 case 's': free(sounddriver); sounddriver = strdup(mgo.opt); break;
00432 case 'v': free(videodriver); videodriver = strdup(mgo.opt); break;
00433 case 'b': free(blitter); blitter = strdup(mgo.opt); break;
00434 #if defined(ENABLE_NETWORK)
00435 case 'D':
00436 free(musicdriver);
00437 free(sounddriver);
00438 free(videodriver);
00439 free(blitter);
00440 musicdriver = strdup("null");
00441 sounddriver = strdup("null");
00442 videodriver = strdup("dedicated");
00443 blitter = strdup("null");
00444 dedicated = true;
00445 SetDebugString("net=6");
00446 if (mgo.opt != NULL) {
00447
00448
00449 const char *temp = NULL;
00450 const char *port = NULL;
00451 ParseConnectionString(&temp, &port, mgo.opt);
00452 if (!StrEmpty(mgo.opt)) dedicated_host = mgo.opt;
00453 if (port != NULL) dedicated_port = atoi(port);
00454 }
00455 break;
00456 case 'f': _dedicated_forks = true; break;
00457 case 'n':
00458 network = true;
00459 network_conn = mgo.opt;
00460 break;
00461 case 'l':
00462 debuglog_conn = mgo.opt;
00463 break;
00464 #endif
00465 case 'r': ParseResolution(&resolution, mgo.opt); break;
00466 case 't': startyear = atoi(mgo.opt); break;
00467 case 'd': {
00468 #if defined(WIN32)
00469 CreateConsole();
00470 #endif
00471 if (mgo.opt != NULL) SetDebugString(mgo.opt);
00472 } break;
00473 case 'e': _switch_mode = SM_EDITOR; break;
00474 case 'i':
00475
00476 if (!StrEmpty(mgo.opt) && mgo.opt[1] == '\0') {
00477 _use_palette = (PaletteType)(mgo.opt[0] - '0');
00478 if (_use_palette <= MAX_PAL) break;
00479 }
00480 usererror("Valid value for '-i' is 0, 1 or 2");
00481 case 'g':
00482 if (mgo.opt != NULL) {
00483 strecpy(_file_to_saveload.name, mgo.opt, lastof(_file_to_saveload.name));
00484 _switch_mode = SM_LOAD;
00485 _file_to_saveload.mode = SL_LOAD;
00486
00487
00488 const char *t = strrchr(_file_to_saveload.name, '.');
00489 if (t != NULL) {
00490 FiosType ft = FiosGetSavegameListCallback(SLD_LOAD_GAME, _file_to_saveload.name, t, NULL, NULL);
00491 if (ft != FIOS_TYPE_INVALID) SetFiosType(ft);
00492 }
00493
00494 break;
00495 }
00496
00497 _switch_mode = SM_NEWGAME;
00498
00499 if (generation_seed == GENERATE_NEW_SEED) {
00500 generation_seed = InteractiveRandom();
00501 }
00502 break;
00503 case 'G': generation_seed = atoi(mgo.opt); break;
00504 case 'c': _config_file = strdup(mgo.opt); break;
00505 case 'x': save_config = false; break;
00506 case -2:
00507 case 'h':
00508
00509
00510
00511 DeterminePaths(argv[0]);
00512 FindGraphicsSets();
00513 ShowHelp();
00514 return 0;
00515 }
00516 }
00517
00518 #if defined(WINCE) && defined(_DEBUG)
00519
00520 SetDebugString("4");
00521 #endif
00522
00523 DeterminePaths(argv[0]);
00524 FindGraphicsSets();
00525
00526 #if defined(UNIX) && !defined(__MORPHOS__)
00527
00528 if (_dedicated_forks)
00529 DedicatedFork();
00530 #endif
00531
00532 AI::Initialize();
00533 LoadFromConfig();
00534 AI::Uninitialize(true);
00535 CheckConfig();
00536 LoadFromHighScore();
00537
00538 if (resolution.width != 0) { _cur_resolution = resolution; }
00539 if (startyear != INVALID_YEAR) _settings_newgame.game_creation.starting_year = startyear;
00540 if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed;
00541
00542
00543
00544 if (_cur_resolution.width <= 0) _cur_resolution.width = 1;
00545 if (_cur_resolution.height <= 0) _cur_resolution.height = 1;
00546
00547 #if defined(ENABLE_NETWORK)
00548 if (dedicated_host) snprintf(_settings_client.network.server_bind_ip, sizeof(_settings_client.network.server_bind_ip), "%s", dedicated_host);
00549 if (dedicated_port) _settings_client.network.server_port = dedicated_port;
00550 if (_dedicated_forks && !dedicated) _dedicated_forks = false;
00551 #endif
00552
00553
00554 InitializeLanguagePacks();
00555
00556
00557 InitializeScreenshotFormats();
00558
00559
00560 InitializeAirports();
00561
00562
00563 InitializeDynamicVariables();
00564
00565
00566 DEBUG(misc, 1, "Loading sound effects...");
00567 MxInitialize(11025);
00568 SoundInitialize("sample.cat");
00569
00570
00571 InitFreeType();
00572
00573
00574 InitWindowSystem();
00575
00576 if (graphics_set == NULL) graphics_set = _ini_graphics_set;
00577 if (!SetGraphicsSet(graphics_set)) {
00578 StrEmpty(graphics_set) ?
00579 usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD.") :
00580 usererror("Failed to select requested graphics set '%s'", graphics_set);
00581 }
00582
00583
00584 GfxInitPalettes();
00585
00586 DEBUG(misc, 1, "Loading blitter...");
00587 if (blitter == NULL) blitter = _ini_blitter;
00588 if (BlitterFactoryBase::SelectBlitter(blitter) == NULL)
00589 StrEmpty(blitter) ?
00590 usererror("Failed to autoprobe blitter") :
00591 usererror("Failed to select requested blitter '%s'; does it exist?", blitter);
00592
00593 DEBUG(driver, 1, "Loading drivers...");
00594
00595 if (sounddriver == NULL) sounddriver = _ini_sounddriver;
00596 _sound_driver = (SoundDriver*)SoundDriverFactoryBase::SelectDriver(sounddriver, Driver::DT_SOUND);
00597 if (_sound_driver == NULL) {
00598 StrEmpty(sounddriver) ?
00599 usererror("Failed to autoprobe sound driver") :
00600 usererror("Failed to select requested sound driver '%s'", sounddriver);
00601 }
00602
00603 if (musicdriver == NULL) musicdriver = _ini_musicdriver;
00604 _music_driver = (MusicDriver*)MusicDriverFactoryBase::SelectDriver(musicdriver, Driver::DT_MUSIC);
00605 if (_music_driver == NULL) {
00606 StrEmpty(musicdriver) ?
00607 usererror("Failed to autoprobe music driver") :
00608 usererror("Failed to select requested music driver '%s'", musicdriver);
00609 }
00610
00611 if (videodriver == NULL) videodriver = _ini_videodriver;
00612 _video_driver = (VideoDriver*)VideoDriverFactoryBase::SelectDriver(videodriver, Driver::DT_VIDEO);
00613 if (_video_driver == NULL) {
00614 StrEmpty(videodriver) ?
00615 usererror("Failed to autoprobe video driver") :
00616 usererror("Failed to select requested video driver '%s'", videodriver);
00617 }
00618
00619 _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
00620
00621 _screen.zoom = ZOOM_LVL_NORMAL;
00622
00623
00624 _music_driver->SetVolume(msf.music_vol);
00625
00626 NetworkStartUp();
00627
00628 #if defined(ENABLE_NETWORK)
00629 if (debuglog_conn != NULL && _network_available) {
00630 const char *not_used = NULL;
00631 const char *port = NULL;
00632 uint16 rport;
00633
00634 rport = NETWORK_DEFAULT_DEBUGLOG_PORT;
00635
00636 ParseConnectionString(¬_used, &port, debuglog_conn);
00637 if (port != NULL) rport = atoi(port);
00638
00639 NetworkStartDebugLog(NetworkAddress(debuglog_conn, rport));
00640 }
00641 #endif
00642
00643 ScanNewGRFFiles();
00644
00645 ResetGRFConfig(false);
00646
00647
00648 if (_switch_mode != SM_NONE) MakeNewgameSettingsLive();
00649
00650
00651 IConsoleInit();
00652 _cursor.in_window = true;
00653 InitializeGUI();
00654 IConsoleCmdExec("exec scripts/autoexec.scr 0");
00655
00656
00657 _genworld_paint_mutex->BeginCritical();
00658 _genworld_mapgen_mutex->BeginCritical();
00659
00660 GenerateWorld(GW_EMPTY, 64, 64);
00661 WaitTillGeneratedWorld();
00662
00663 CheckForMissingGlyphsInLoadedLanguagePack();
00664
00665 #ifdef ENABLE_NETWORK
00666 if (network && _network_available) {
00667 if (network_conn != NULL) {
00668 const char *port = NULL;
00669 const char *company = NULL;
00670 uint16 rport;
00671
00672 rport = NETWORK_DEFAULT_PORT;
00673 _network_playas = COMPANY_NEW_COMPANY;
00674
00675 ParseConnectionString(&company, &port, network_conn);
00676
00677 if (company != NULL) {
00678 _network_playas = (CompanyID)atoi(company);
00679
00680 if (_network_playas != COMPANY_SPECTATOR) {
00681 _network_playas--;
00682 if (_network_playas >= MAX_COMPANIES) return false;
00683 }
00684 }
00685 if (port != NULL) rport = atoi(port);
00686
00687 LoadIntroGame();
00688 _switch_mode = SM_NONE;
00689 NetworkClientConnectGame(NetworkAddress(network_conn, rport));
00690 }
00691 }
00692 #endif
00693
00694 _video_driver->MainLoop();
00695
00696 WaitTillSaved();
00697
00698
00699 if (save_config) {
00700 SaveToConfig();
00701 SaveToHighScore();
00702 }
00703
00704
00705 ShutdownGame();
00706
00707 return 0;
00708 }
00709
00710 void HandleExitGameRequest()
00711 {
00712 if (_game_mode == GM_MENU) {
00713 _exit_game = true;
00714 } else if (_settings_client.gui.autosave_on_exit) {
00715 DoExitSave();
00716 _exit_game = true;
00717 } else {
00718 AskExitGame();
00719 }
00720 }
00721
00722 static void ShowScreenshotResult(bool b)
00723 {
00724 if (b) {
00725 extern char _screenshot_name[];
00726 SetDParamStr(0, _screenshot_name);
00727 ShowErrorMessage(INVALID_STRING_ID, STR_031B_SCREENSHOT_SUCCESSFULLY, 0, 0);
00728 } else {
00729 ShowErrorMessage(INVALID_STRING_ID, STR_031C_SCREENSHOT_FAILED, 0, 0);
00730 }
00731
00732 }
00733
00734 static void MakeNewGameDone()
00735 {
00736 SettingsDisableElrail(_settings_game.vehicle.disable_elrails);
00737
00738
00739 if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 0) {
00740 SetLocalCompany(COMPANY_SPECTATOR);
00741 IConsoleCmdExec("exec scripts/game_start.scr 0");
00742 return;
00743 }
00744
00745
00746 DoStartupNewCompany(false);
00747
00748 IConsoleCmdExec("exec scripts/game_start.scr 0");
00749
00750 SetLocalCompany(COMPANY_FIRST);
00751 _current_company = _local_company;
00752 DoCommandP(0, (_settings_client.gui.autorenew << 15 ) | (_settings_client.gui.autorenew_months << 16) | 4, _settings_client.gui.autorenew_money, CMD_SET_AUTOREPLACE);
00753
00754 InitializeRailGUI();
00755
00756 #ifdef ENABLE_NETWORK
00757
00758
00759 if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) {
00760 char *password = _settings_client.network.default_company_pass;
00761 NetworkChangeCompanyPassword(1, &password);
00762 }
00763 #endif
00764
00765 MarkWholeScreenDirty();
00766 }
00767
00768 static void MakeNewGame(bool from_heightmap)
00769 {
00770 _game_mode = GM_NORMAL;
00771
00772 ResetGRFConfig(true);
00773 _engine_mngr.ResetToDefaultMapping();
00774 _house_mngr.ResetMapping();
00775 _industile_mngr.ResetMapping();
00776 _industry_mngr.ResetMapping();
00777
00778 GenerateWorldSetCallback(&MakeNewGameDone);
00779 GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00780 }
00781
00782 static void MakeNewEditorWorldDone()
00783 {
00784 SetLocalCompany(OWNER_NONE);
00785 }
00786
00787 static void MakeNewEditorWorld()
00788 {
00789 _game_mode = GM_EDITOR;
00790
00791 ResetGRFConfig(true);
00792
00793 GenerateWorldSetCallback(&MakeNewEditorWorldDone);
00794 GenerateWorld(GW_EMPTY, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00795 }
00796
00797 void StartupCompanies();
00798 void StartupDisasters();
00799 extern void StartupEconomy();
00800
00806 static void StartScenario()
00807 {
00808 _game_mode = GM_NORMAL;
00809
00810
00811 if (_file_to_saveload.mode == SL_INVALID) {
00812 DEBUG(sl, 0, "Savegame is obsolete or invalid format: '%s'", _file_to_saveload.name);
00813 SetDParamStr(0, GetSaveLoadErrorString());
00814 ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, 0, 0);
00815 _game_mode = GM_MENU;
00816 return;
00817 }
00818
00819
00820 ResetWindowSystem();
00821
00822 SetupColoursAndInitialWindow();
00823
00824 ResetGRFConfig(true);
00825
00826
00827 if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, SCENARIO_DIR) != SL_OK) {
00828 LoadIntroGame();
00829 SetDParamStr(0, GetSaveLoadErrorString());
00830 ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, 0, 0);
00831 }
00832
00833 _settings_game.difficulty = _settings_newgame.difficulty;
00834
00835
00836 StartupEconomy();
00837 StartupCompanies();
00838 StartupEngines();
00839 StartupDisasters();
00840
00841 SetLocalCompany(COMPANY_FIRST);
00842 _current_company = _local_company;
00843 DoCommandP(0, (_settings_client.gui.autorenew << 15 ) | (_settings_client.gui.autorenew_months << 16) | 4, _settings_client.gui.autorenew_money, CMD_SET_AUTOREPLACE);
00844
00845 MarkWholeScreenDirty();
00846 }
00847
00856 bool SafeSaveOrLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir)
00857 {
00858 GameMode ogm = _game_mode;
00859
00860 _game_mode = newgm;
00861 assert(mode == SL_LOAD || mode == SL_OLD_LOAD);
00862 switch (SaveOrLoad(filename, mode, subdir)) {
00863 case SL_OK: return true;
00864
00865 case SL_REINIT:
00866 switch (ogm) {
00867 default:
00868 case GM_MENU: LoadIntroGame(); break;
00869 case GM_EDITOR: MakeNewEditorWorld(); break;
00870 }
00871 return false;
00872
00873 default:
00874 _game_mode = ogm;
00875 return false;
00876 }
00877 }
00878
00879 void SwitchToMode(SwitchMode new_mode)
00880 {
00881 #ifdef ENABLE_NETWORK
00882
00883 if (new_mode != SM_SAVE) {
00884
00885 if (_networking) {
00886 if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) {
00887 NetworkReboot();
00888 } else {
00889 NetworkDisconnect();
00890 }
00891 }
00892
00893
00894 if (_is_network_server) {
00895
00896 if (new_mode != SM_MENU) {
00897
00898 if (_settings_client.network.reload_cfg) {
00899 LoadFromConfig();
00900 MakeNewgameSettingsLive();
00901 ResetGRFConfig(false);
00902 }
00903 NetworkServerStart();
00904 } else {
00905
00906 _is_network_server = false;
00907 }
00908 }
00909 }
00910 #endif
00911
00912 if (new_mode != SM_SAVE) AI::KillAll();
00913
00914 switch (new_mode) {
00915 case SM_EDITOR:
00916 MakeNewEditorWorld();
00917 break;
00918
00919 case SM_NEWGAME:
00920 #ifdef ENABLE_NETWORK
00921 if (_network_server) {
00922 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "Random Map");
00923 }
00924 #endif
00925 MakeNewGame(false);
00926 break;
00927
00928 case SM_START_SCENARIO:
00929 #ifdef ENABLE_NETWORK
00930 if (_network_server) {
00931 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Loaded scenario)", _file_to_saveload.title);
00932 }
00933 #endif
00934 StartScenario();
00935 break;
00936
00937 case SM_LOAD: {
00938 ResetGRFConfig(true);
00939 ResetWindowSystem();
00940
00941 if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL, NO_DIRECTORY)) {
00942 LoadIntroGame();
00943 SetDParamStr(0, GetSaveLoadErrorString());
00944 ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, 0, 0);
00945 } else {
00946 if (_saveload_mode == SLD_LOAD_SCENARIO) {
00947 StartupEngines();
00948 }
00949
00950
00951 SetLocalCompany(_network_dedicated ? COMPANY_SPECTATOR : COMPANY_FIRST);
00952
00953 IConsoleCmdExec("exec scripts/game_start.scr 0");
00954
00955 DoCommandP(0, 0, 0, CMD_PAUSE);
00956 #ifdef ENABLE_NETWORK
00957 if (_network_server) {
00958 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Loaded game)", _file_to_saveload.title);
00959 }
00960 #endif
00961 }
00962 break;
00963 }
00964
00965 case SM_START_HEIGHTMAP:
00966 #ifdef ENABLE_NETWORK
00967 if (_network_server) {
00968 snprintf(_network_game_info.map_name, lengthof(_network_game_info.map_name), "%s (Heightmap)", _file_to_saveload.title);
00969 }
00970 #endif
00971 MakeNewGame(true);
00972 break;
00973
00974 case SM_LOAD_HEIGHTMAP:
00975 SetLocalCompany(OWNER_NONE);
00976
00977 GenerateWorld(GW_HEIGHTMAP, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
00978 MarkWholeScreenDirty();
00979 break;
00980
00981 case SM_LOAD_SCENARIO: {
00982 if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR, NO_DIRECTORY)) {
00983 SetLocalCompany(OWNER_NONE);
00984 _settings_newgame.game_creation.starting_year = _cur_year;
00985 } else {
00986 SetDParamStr(0, GetSaveLoadErrorString());
00987 ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, 0, 0);
00988 }
00989 break;
00990 }
00991
00992 case SM_MENU:
00993 LoadIntroGame();
00994 break;
00995
00996 case SM_SAVE:
00997
00998 if (_networking && _pause_game == 1) _pause_game = 2;
00999 if (SaveOrLoad(_file_to_saveload.name, SL_SAVE, NO_DIRECTORY) != SL_OK) {
01000 SetDParamStr(0, GetSaveLoadErrorString());
01001 ShowErrorMessage(INVALID_STRING_ID, STR_JUST_RAW_STRING, 0, 0);
01002 } else {
01003 DeleteWindowById(WC_SAVELOAD, 0);
01004 }
01005 if (_networking && _pause_game == 2) _pause_game = 1;
01006 break;
01007
01008 case SM_GENRANDLAND:
01009 SetLocalCompany(OWNER_NONE);
01010 GenerateWorld(GW_RANDOM, 1 << _settings_game.game_creation.map_x, 1 << _settings_game.game_creation.map_y);
01011
01012 MarkWholeScreenDirty();
01013 break;
01014
01015 default: NOT_REACHED();
01016 }
01017
01018 if (_switch_mode_errorstr != INVALID_STRING_ID) {
01019 ShowErrorMessage(INVALID_STRING_ID, _switch_mode_errorstr, 0, 0);
01020 }
01021 }
01022
01023
01029 void StateGameLoop()
01030 {
01031
01032 if (_pause_game) {
01033 CallWindowTickEvent();
01034 return;
01035 }
01036 if (IsGeneratingWorld()) return;
01037
01038 ClearStorageChanges(false);
01039
01040 if (_game_mode == GM_EDITOR) {
01041 RunTileLoop();
01042 CallVehicleTicks();
01043 CallLandscapeTick();
01044 ClearStorageChanges(true);
01045
01046 CallWindowTickEvent();
01047 NewsLoop();
01048 } else {
01049 if (_debug_desync_level > 1) {
01050 Vehicle *v;
01051 FOR_ALL_VEHICLES(v) {
01052 if (v != v->First()) continue;
01053
01054 switch (v->type) {
01055 case VEH_ROAD: {
01056 extern byte GetRoadVehLength(const Vehicle *v);
01057 if (GetRoadVehLength(v) != v->u.road.cached_veh_length) {
01058 DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
01059 }
01060 } break;
01061
01062 case VEH_TRAIN: {
01063 uint length = 0;
01064 for (Vehicle *u = v; u != NULL; u = u->Next()) length++;
01065
01066 VehicleRail *wagons = MallocT<VehicleRail>(length);
01067 length = 0;
01068 for (Vehicle *u = v; u != NULL; u = u->Next()) wagons[length++] = u->u.rail;
01069
01070 TrainConsistChanged(v, true);
01071
01072 length = 0;
01073 for (Vehicle *u = v; u != NULL; u = u->Next()) {
01074 if (memcmp(&wagons[length], &u->u.rail, sizeof(VehicleRail)) != 0) {
01075 DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i, wagon %i\n", v->index, (int)v->owner, v->unitnumber, length);
01076 }
01077 length++;
01078 }
01079
01080 free(wagons);
01081 } break;
01082
01083 case VEH_AIRCRAFT: {
01084 uint speed = v->u.air.cached_max_speed;
01085 UpdateAircraftCache(v);
01086 if (speed != v->u.air.cached_max_speed) {
01087 DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
01088 }
01089 } break;
01090
01091 default:
01092 break;
01093 }
01094 }
01095 }
01096
01097
01098
01099 CompanyID old_company = _current_company;
01100 _current_company = OWNER_NONE;
01101
01102 AnimateAnimatedTiles();
01103 IncreaseDate();
01104 RunTileLoop();
01105 CallVehicleTicks();
01106 CallLandscapeTick();
01107 ClearStorageChanges(true);
01108
01109 AI::GameLoop();
01110
01111 CallWindowTickEvent();
01112 NewsLoop();
01113 _current_company = old_company;
01114 }
01115 }
01116
01119 static void DoAutosave()
01120 {
01121 char buf[MAX_PATH];
01122
01123 #if defined(PSP)
01124
01125 if (_networking) return;
01126 #endif
01127
01128 if (_settings_client.gui.keep_all_autosave) {
01129 GenerateDefaultSaveName(buf, lastof(buf));
01130 strecat(buf, ".sav", lastof(buf));
01131 } else {
01132
01133 snprintf(buf, sizeof(buf), "autosave%d.sav", _autosave_ctr);
01134
01135 if (++_autosave_ctr >= _settings_client.gui.max_num_autosaves) _autosave_ctr = 0;
01136 }
01137
01138 DEBUG(sl, 2, "Autosaving to '%s'", buf);
01139 if (SaveOrLoad(buf, SL_SAVE, AUTOSAVE_DIR) != SL_OK) {
01140 ShowErrorMessage(INVALID_STRING_ID, STR_AUTOSAVE_FAILED, 0, 0);
01141 }
01142 }
01143
01144 void GameLoop()
01145 {
01146 ProcessAsyncSaveFinish();
01147
01148
01149 if (_do_autosave) {
01150 _do_autosave = false;
01151 DoAutosave();
01152 RedrawAutosave();
01153 }
01154
01155
01156 if (IsScreenshotRequested()) ShowScreenshotResult(MakeScreenshot());
01157
01158
01159 if (_switch_mode != SM_NONE) {
01160 SwitchToMode(_switch_mode);
01161 _switch_mode = SM_NONE;
01162 }
01163
01164 IncreaseSpriteLRU();
01165 InteractiveRandom();
01166
01167 extern int _caret_timer;
01168 _caret_timer += 3;
01169 _palette_animation_counter += 8;
01170 CursorTick();
01171
01172 #ifdef ENABLE_NETWORK
01173
01174 if (_network_available) NetworkUDPGameLoop();
01175
01176 if (_networking && !IsGeneratingWorld()) {
01177
01178 NetworkGameLoop();
01179 } else {
01180 if (_network_reconnect > 0 && --_network_reconnect == 0) {
01181
01182
01183 _network_playas = COMPANY_SPECTATOR;
01184 NetworkClientConnectGame(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
01185 }
01186
01187 StateGameLoop();
01188 }
01189 #else
01190 StateGameLoop();
01191 #endif
01192
01193 if (!_pause_game && HasBit(_display_opt, DO_FULL_ANIMATION)) DoPaletteAnimations();
01194
01195 if (!_pause_game || _cheats.build_in_pause.value) MoveAllTextEffects();
01196
01197 InputLoop();
01198
01199 _sound_driver->MainLoop();
01200 MusicLoop();
01201 }