# HG changeset patch # User darkvater # Date 2005-01-11 00:54:06 # Node ID 9c58202c20d15ea8743482da8bdbf9feb8c1d38f # Parent ae84d40035917f3d78d8dca09fb221451b04fb38 (svn r1479) -Added highscore chart (accessible from the difficulty window) with top5 companies for a given difficulty (select the difficulty in the menu) -Added endgame score on 1 jan 2051 where you are added to the highscore if sufficiently large points have been accumulated. Game is paused while -These values are saved in hs.dat; added read/write functions for it -Added code to delete all windows to show charts. There is one issue left: somehow a news-gui pops up in front of the the chart at the end of the game. diff --git a/functions.h b/functions.h --- a/functions.h +++ b/functions.h @@ -235,7 +235,8 @@ void ShowNetworkNeedCompanyPassword(); void ShowRenameSignWindow(SignStruct *ss); void ShowRenameWaypointWindow(Waypoint *cp); int FindFirstBit(uint32 x); -void ShowHighscoreTable(int tbl); +void ShowHighscoreTable(int difficulty, int rank); +void ShowEndGameChart(void); TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng); enum SaveOrLoadResult { diff --git a/graph_gui.c b/graph_gui.c --- a/graph_gui.c +++ b/graph_gui.c @@ -1026,9 +1026,9 @@ static const StringID _performance_title STR_706E_TYCOON, }; -static StringID GetPerformanceTitleFromValue(uint v) +static inline StringID GetPerformanceTitleFromValue(uint value) { - return _performance_titles[minu(v, 1000) >> 6]; + return _performance_titles[minu(value, 1000) >> 6]; } static int CDECL _perf_hist_comp(const void *elem1, const void *elem2 ) { diff --git a/lang/english.txt b/lang/english.txt --- a/lang/english.txt +++ b/lang/english.txt @@ -573,9 +573,10 @@ STR_0216_CAPITALIST :Capitalist STR_0217_MAGNATE :Magnate STR_0218_MOGUL :Mogul STR_0219_TYCOON_OF_THE_CENTURY :Tycoon of the Century -STR_021A :{BIGFONT}'{STRING}' ({COMMA16}) -STR_021B_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} achieves '{STRING}' status! -STR_021C_OF_ACHIEVES_STATUS :{BIGFONT}{STRING}{STRING} of {STRING} achieves '{STRING}' status! +STR_HIGHSCORE_NAME :{BIGFONT}{STRING}, {STRING} +STR_HIGHSCORE_STATS :{BIGFONT}'{STRING}' ({COMMA16}) +STR_021B_ACHIEVES_STATUS :{BLACK}{BIGFONT}{STRING} achieves '{STRING}' status! +STR_021C_OF_ACHIEVES_STATUS :{WHITE}{BIGFONT}{STRING} of {STRING} achieves '{STRING}' status! STR_021D :{BLACK} STR_021E :{WHITE} STR_021F :{BLUE}{COMMA16} diff --git a/main_gui.c b/main_gui.c --- a/main_gui.c +++ b/main_gui.c @@ -2402,24 +2402,7 @@ void SetupColorsAndInitialWindow() w = AllocateWindow(0, 0, width, height, MainWindowWndProc, 0, NULL); AssignWindowViewport(w, 0, 0, width, height, 0x8080, 0); - w = AllocateWindowDesc(&_toolb_normal_desc); - w->disabled_state = 1 << 17; // disable zoon-in button (by default game is zoomed in) - - if (_networking) { // if networking, disable fast-forward button - w->disabled_state |= (1 << 1); - if (!_network_server) // if not server, disable pause button - w->disabled_state |= (1 << 0); - } - - w->flags4 &= ~WF_WHITE_BORDER_MASK; - - PositionMainToolbar(w); // already WC_MAIN_TOOLBAR passed (&_toolb_normal_desc) - - _main_status_desc.top = height - 12; - w = AllocateWindowDesc(&_main_status_desc); - w->flags4 &= ~WF_WHITE_BORDER_MASK; - - WP(w,def_d).data_1 = -1280; + ShowVitalWindows(); /* Bring joining GUI to front till the client is really joined */ if (_networking && !_network_server) @@ -2432,7 +2415,7 @@ void SetupColorsAndInitialWindow() w = AllocateWindowDesc(&_toolb_scen_desc); w->disabled_state = 1 << 9; - w->flags4 &= ~WF_WHITE_BORDER_MASK; + CLRBITS(w->flags4, WF_WHITE_BORDER_MASK); PositionMainToolbar(w); // already WC_MAIN_TOOLBAR passed (&_toolb_scen_desc) break; @@ -2441,6 +2424,29 @@ void SetupColorsAndInitialWindow() } } +void ShowVitalWindows(void) +{ + Window *w; + + w = AllocateWindowDesc(&_toolb_normal_desc); + w->disabled_state = 1 << 17; // disable zoom-in button (by default game is zoomed in) + CLRBITS(w->flags4, WF_WHITE_BORDER_MASK); + + if (_networking) { // if networking, disable fast-forward button + SETBIT(w->disabled_state, 1); + if (!_network_server) // if not server, disable pause button + SETBIT(w->disabled_state, 0); + } + + PositionMainToolbar(w); // already WC_MAIN_TOOLBAR passed (&_toolb_normal_desc) + + _main_status_desc.top = _screen.height - 12; + w = AllocateWindowDesc(&_main_status_desc); + CLRBITS(w->flags4, WF_WHITE_BORDER_MASK); + + WP(w,def_d).data_1 = -1280; +} + void GameSizeChanged() { RelocateAllWindows(_screen.width, _screen.height); diff --git a/misc.c b/misc.c --- a/misc.c +++ b/misc.c @@ -700,8 +700,11 @@ void IncreaseDate() NetworkServerYearlyLoop(); #endif /* ENABLE_NETWORK */ + /* check if we reached 2090, that's the maximum year. */ + if (_cur_year == 131) { // end of game on 31 dec 2050 + ShowEndGameChart(); /* check if we reached 2090 (MAX_YEAR_END_REAL), that's the maximum year. */ - if (_cur_year == (MAX_YEAR_END + 1)) { + } else if (_cur_year == (MAX_YEAR_END + 1)) { Vehicle *v; _cur_year = MAX_YEAR_END; _date = 62093; diff --git a/player.h b/player.h --- a/player.h +++ b/player.h @@ -201,4 +201,15 @@ VARDEF Player _players[MAX_PLAYERS]; #define IS_HUMAN_PLAYER(p) (!DEREF_PLAYER((byte)(p))->is_ai) #define IS_INTERACTIVE_PLAYER(p) (((byte)p) == _local_player) +typedef struct HighScore { + char company[100]; + StringID title; + uint16 score; +} HighScore; + +VARDEF HighScore _highscore_table[4][5]; // 4 difficulty-settings; top 5 +void SaveToHighScore(void); +void LoadFromHighScore(void); +int SaveHighScoreValue(const Player *p); + #endif /* PLAYER_H */ diff --git a/player_gui.c b/player_gui.c --- a/player_gui.c +++ b/player_gui.c @@ -744,3 +744,166 @@ void ShowBuyCompanyDialog(uint player) { AllocateWindowDescFront(&_buy_company_desc, player); } + +/********** HIGHSCORE and ENDGAME windows */ + +/* Always draw a maximized window and within there the centered background */ +static void SetupHighScoreEndWindow(Window *w, uint *x, uint *y) +{ + uint i; + // resize window to "full-screen" + w->width = _screen.width; + w->height = _screen.height; + w->widget[0].right = w->width - 1; + w->widget[0].bottom = w->height - 1; + + DrawWindowWidgets(w); + + /* Center Highscore/Endscreen background */ + *x = max(0, (_screen.width / 2) - (640 / 2)); + *y = max(0, (_screen.height / 2) - (480 / 2)); + for (i = 0; i < 10; i++) // the image is split into 10 50px high parts + DrawSprite(WP(w, general_d).i + i, *x, *y + (i * 50)); +} + +extern StringID EndGameGetPerformanceTitleFromValue(uint value); + +/* End game window shown at the end of the game */ +static void EndGameWndProc(Window *w, WindowEvent *e) +{ + switch (e->event) { + case WE_PAINT: { + const Player *p = DEREF_PLAYER(_local_player); + uint x, y; + + SetupHighScoreEndWindow(w, &x, &y); + + /* We need to get performance from last year because the image is shown + * at the start of the new year when these things have already been copied */ + if (WP(w, general_d).i == SPR_TYCOON_IMG2_BEGIN) { // Tycoon of the century \o/ + SetDParam(0, p->president_name_1); + SetDParam(1, p->president_name_2); + SetDParam(2, p->name_1); + SetDParam(3, p->name_2); + SetDParam(4, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history)); + DrawStringMultiCenter(x + (640 / 2), y + 107, STR_021C_OF_ACHIEVES_STATUS, 640); + } else { + SetDParam(0, p->name_1); + SetDParam(1, p->name_2); + SetDParam(2, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history)); + DrawStringMultiCenter(x + (640 / 2), y + 157, STR_021B_ACHIEVES_STATUS, 640); + } + } break; + case WE_CLICK: /* OnClick show the highscore chart */ + DoCommandP(0, 0, 0, NULL, CMD_PAUSE); + ShowHighscoreTable(w->window_number, WP(w, general_d).j); + DeleteWindow(w); + } +} + +static void HighScoreWndProc(Window *w, WindowEvent *e) +{ + switch (e->event) { + case WE_PAINT: { + const HighScore *hs = _highscore_table[w->window_number]; + uint i, x, y; + + SetupHighScoreEndWindow(w, &x, &y); + + SetDParam(0, w->window_number + STR_6801_EASY); + DrawStringMultiCenter(x + (640 / 2), y + 62, STR_0211_TOP_COMPANIES_WHO_REACHED, 640); + + /* Draw Highscore peepz */ + for (i = 0; i < lengthof(_highscore_table[0]); i++) { + SetDParam(0, i + 1); + DrawString(x + 40, y + 140 + (i * 55), STR_0212, 0x10); + + if (hs[i].company[0] != '\0') { + uint16 colour = (WP(w, general_d).j == i) ? 0x3 : 0x10; // draw new highscore in red + + DoDrawString(hs[i].company, x + 71, y + 140 + (i * 55), colour); + SetDParam(0, hs[i].title); + SetDParam(1, hs[i].score); + DrawString(x + 71, y + 160 + (i * 55), STR_HIGHSCORE_STATS, colour); + } + } + } break; + + case WE_CLICK: /* Onclick get back all hidden windows */ + if (_game_mode != GM_MENU) + ShowVitalWindows(); + + DoCommandP(0, 0, 0, NULL, CMD_PAUSE); + DeleteWindow(w); + break; + } +} + +static const Widget _highscore_widgets[] = { +{ WWT_PANEL, RESIZE_NONE, 16, 0, 640, 0, 480, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; + +static const WindowDesc _highscore_desc = { + 0, 0, 641, 481, + WC_HIGHSCORE_ENDSCREEN,0, + 0, + _highscore_widgets, + HighScoreWndProc +}; + +static const WindowDesc _endgame_desc = { + 0, 0, 641, 481, + WC_HIGHSCORE_ENDSCREEN,0, + 0, + _highscore_widgets, + EndGameWndProc +}; + +/* Show the highscore table for a given difficulty. When called from + * endgame ranking is set to the top5 element that was newly added + * and is thus highlighted */ +void ShowHighscoreTable(int difficulty, int ranking) +{ + Window *w; + + /* Close all always on-top windows to get a clean screen */ + if (_game_mode != GM_MENU) + HideVitalWindows(); + + if (!_networking) // pause game to show chart + DoCommandP(0, 1, 0, NULL, CMD_PAUSE); + + DeleteWindowById(WC_HIGHSCORE_ENDSCREEN, 0); + w = AllocateWindowDesc(&_highscore_desc); + + if (w != NULL) { + MarkWholeScreenDirty(); + w->window_number = difficulty; // show highscore chart for difficulty... + WP(w, general_d).i = SPR_HIGHSCORE_CHART_BEGIN; // which background to show + WP(w, general_d).j = ranking; + } +} + +/* Show the endgame victory screen in 2050. Update the new highscore + * if it was high enough */ +void ShowEndGameChart(void) +{ + Window *w; + const Player *p = DEREF_PLAYER(_local_player); + + if (!_networking) { // pause the game and hide all windows to show end-chart + DoCommandP(0, 1, 0, NULL, CMD_PAUSE); + HideVitalWindows(); + } + + DeleteWindowById(WC_HIGHSCORE_ENDSCREEN, 0); + w = AllocateWindowDesc(&_endgame_desc); + + if (w != NULL) { + MarkWholeScreenDirty(); + w->window_number = _opt.diff_level; // show highscore chart for difficulty... + WP(w, general_d).i = (p->old_economy[0].performance_history == SCORE_MAX) ? SPR_TYCOON_IMG2_BEGIN : SPR_TYCOON_IMG1_BEGIN; // which background to show + WP(w, general_d).j = SaveHighScoreValue(p); + } +} diff --git a/players.c b/players.c --- a/players.c +++ b/players.c @@ -721,6 +721,108 @@ int32 CmdPlayerCtrl(int x, int y, uint32 return 0; } +static const StringID _endgame_performance_titles[16] = { + STR_0213_BUSINESSMAN, + STR_0213_BUSINESSMAN, + STR_0213_BUSINESSMAN, + STR_0213_BUSINESSMAN, + STR_0213_BUSINESSMAN, + STR_0214_ENTREPRENEUR, + STR_0214_ENTREPRENEUR, + STR_0215_INDUSTRIALIST, + STR_0215_INDUSTRIALIST, + STR_0216_CAPITALIST, + STR_0216_CAPITALIST, + STR_0217_MAGNATE, + STR_0217_MAGNATE, + STR_0218_MOGUL, + STR_0218_MOGUL, + STR_0219_TYCOON_OF_THE_CENTURY, +}; + +inline StringID EndGameGetPerformanceTitleFromValue(uint value) +{ + return _endgame_performance_titles[minu(value, 1000) >> 6]; +} + +/* Save the highscore for the player */ +int SaveHighScoreValue(const Player *p) +{ + HighScore *hs = _highscore_table[_opt.diff_level]; + uint i; + uint16 score = p->old_economy[0].performance_history; + + for (i = 0; i < lengthof(_highscore_table[0]); i++) { + /* You are in the TOP5. Move all values one down and save us there */ + if (hs[i].score <= score) { + byte buf[sizeof(hs[i].company)]; + + // move all elements one down starting from the replaced one + memmove(&hs[i + 1], &hs[i], sizeof(HighScore) * (lengthof(_highscore_table[0]) - i - 1)); + SetDParam(0, p->president_name_1); + SetDParam(1, p->president_name_2); + SetDParam(2, p->name_1); + SetDParam(3, p->name_1); + GetString(buf, STR_HIGHSCORE_NAME); // get manager/company name string + ttd_strlcpy(hs[i].company, buf, sizeof(buf)); + hs[i].score = score; + hs[i].title = EndGameGetPerformanceTitleFromValue(score); + return i; + } + } + + return -1; // too bad; we did not make it into the top5 +} + +/* Save HighScore table to file */ +void SaveToHighScore(void) +{ + FILE *fp = fopen(_highscore_file, "w"); + + if (fp != NULL) { + uint i; + HighScore *hs; + + for (i = 0; i < lengthof(_highscore_table); i++) { + for (hs = _highscore_table[i]; hs != endof(_highscore_table[i]); hs++) { + /* First character is a command character, so strlen will fail on that */ + byte length = min(sizeof(hs->company), (hs->company[0] == '\0') ? 0 : strlen(&hs->company[1]) + 1); + + fwrite(&length, sizeof(length), 1, fp); // write away string length + fwrite(hs->company, length, 1, fp); + fwrite(&hs->score, sizeof(hs->score), 1, fp); + fwrite(&hs->title, sizeof(hs->title), 1, fp); + } + } + fclose(fp); + } +} + +/* Initialize the highscore table to 0 and if any file exists, load in values */ +void LoadFromHighScore(void) +{ + FILE *fp = fopen(_highscore_file, "r"); + + memset(_highscore_table, 0, sizeof(_highscore_table)); + + if (fp != NULL) { + uint i; + HighScore *hs; + + for (i = 0; i < lengthof(_highscore_table); i++) { + for (hs = _highscore_table[i]; hs != endof(_highscore_table[i]); hs++) { + byte length; + fread(&length, sizeof(length), 1, fp); + + fread(hs->company, 1, length, fp); + fread(&hs->score, sizeof(hs->score), 1, fp); + fread(&hs->title, sizeof(hs->title), 1, fp); + } + } + fclose(fp); + } +} + // Save/load of players static const byte _player_desc[] = { SLE_VAR(Player,name_2, SLE_UINT32), diff --git a/settings_gui.c b/settings_gui.c --- a/settings_gui.c +++ b/settings_gui.c @@ -330,6 +330,11 @@ void SetDifficultyLevel(int mode, GameOp extern void StartupEconomy(); +enum { + GAMEDIFF_WND_TOP_OFFSET = 45, + GAMEDIFF_WND_ROWSIZE = 9 +}; + static void GameDifficultyWndProc(Window *w, WindowEvent *e) { switch(e->event) { @@ -338,11 +343,11 @@ static void GameDifficultyWndProc(Window int i; int x,y,value; - w->click_state = (1 << 4) << _opt_mod_temp.diff_level; - w->disabled_state = (_game_mode != GM_NORMAL) ? 0 : (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); + w->click_state = (1 << 3) << _opt_mod_temp.diff_level; + w->disabled_state = (_game_mode != GM_NORMAL) ? 0 : (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); // Disable save-button in multiplayer (and if client) if (_networking && !_network_server) - w->disabled_state |= (1 << 10); + SETBIT(w->disabled_state, 10); DrawWindowWidgets(w); click_a = _difficulty_click_a; @@ -358,32 +363,32 @@ static void GameDifficultyWndProc(Window disabled = _game_mode == GM_NORMAL ? 0x383E : 0; x = 0; - y = 32; + y = GAMEDIFF_WND_TOP_OFFSET; for (i = 0; i != GAME_DIFFICULTY_NUM; i++) { - DrawFrameRect(x+5, y+1, x+5+9, y+9, 3, GetBitAndShift(&click_a)?0x20:0); - DrawFrameRect(x+15, y+1, x+15+9, y+9, 3, GetBitAndShift(&click_b)?0x20:0); + DrawFrameRect(x+5, y, x+5+8, y+8, 3, GetBitAndShift(&click_a)?0x20:0); + DrawFrameRect(x+15, y, x+15+8, y+8, 3, GetBitAndShift(&click_b)?0x20:0); if (GetBitAndShift(&disabled) || (_networking && !_network_server)) { int color = 0x8000 | _color_list[3].unk2; - GfxFillRect(x+6, y+2, x+6+8, y+9, color); - GfxFillRect(x+16, y+2, x+16+8, y+9, color); + GfxFillRect(x+6, y+1, x+6+8, y+8, color); + GfxFillRect(x+16, y+1, x+16+8, y+8, color); } - DrawStringCentered(x+10, y+1, STR_6819, 0); - DrawStringCentered(x+20, y+1, STR_681A, 0); + DrawStringCentered(x+10, y, STR_6819, 0); + DrawStringCentered(x+20, y, STR_681A, 0); value = _game_setting_info[i].str + ((int*)&_opt_mod_temp.diff)[i]; if (i == 4) value *= 1000; // handle currency option SetDParam(0, value); - DrawString(x+30, y+1, STR_6805_MAXIMUM_NO_COMPETITORS + i, 0); + DrawString(x+30, y, STR_6805_MAXIMUM_NO_COMPETITORS + i, 0); - y += 11; + y += GAMEDIFF_WND_ROWSIZE + 2; // space items apart a bit } } break; case WE_CLICK: switch(e->click.widget) { - case 3: { + case 8: { int x,y; uint btn, dis; int val; @@ -397,19 +402,18 @@ static void GameDifficultyWndProc(Window if (!IS_INT_INSIDE(x, 0, 21)) return; - y = e->click.pt.y - 33; + y = e->click.pt.y - GAMEDIFF_WND_TOP_OFFSET; if (y < 0) return; // Get button from Y coord. - btn = y / 11; - if (btn >= GAME_DIFFICULTY_NUM || y % 11 > 9) + btn = y / (GAMEDIFF_WND_ROWSIZE + 2); + if (btn >= GAME_DIFFICULTY_NUM || y % (GAMEDIFF_WND_ROWSIZE + 2) >= 9) return; // Clicked disabled button? - dis = 0; - if (_game_mode == GM_NORMAL) - dis |= 0x383E; + dis = (_game_mode == GM_NORMAL) ? 0x383E : 0; + if (HASBIT(dis, btn)) return; @@ -434,15 +438,15 @@ static void GameDifficultyWndProc(Window SetWindowDirty(w); break; } - case 4: case 5: case 6: case 7: // easy/medium/hard/custom + case 3: case 4: case 5: case 6: /* Easy / Medium / Hard / Custom */ // temporarily change difficulty level - SetDifficultyLevel(e->click.widget - 4, &_opt_mod_temp); + SetDifficultyLevel(e->click.widget - 3, &_opt_mod_temp); SetWindowDirty(w); break; - case 8: - ShowHighscoreTable(_opt_mod_ptr->diff_level); + case 7: /* Highscore Table */ + ShowHighscoreTable(_opt_mod_temp.diff_level, -1); break; - case 10: { // Save button - save changes + case 10: { /* Save button - save changes */ int btn, val; for (btn = 0; btn != GAME_DIFFICULTY_NUM; btn++) { val = ((int*)&_opt_mod_temp.diff)[btn]; @@ -479,13 +483,12 @@ static const Widget _game_difficulty_wid { WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, RESIZE_NONE, 10, 11, 369, 0, 13, STR_6800_DIFFICULTY_LEVEL, STR_018C_WINDOW_TITLE_DRAG_THIS}, { WWT_PANEL, RESIZE_NONE, 10, 0, 369, 14, 29, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 30, 276, 0x0, STR_NULL}, { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 10, 96, 16, 27, STR_6801_EASY, STR_NULL}, { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 97, 183, 16, 27, STR_6802_MEDIUM, STR_NULL}, { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 184, 270, 16, 27, STR_6803_HARD, STR_NULL}, { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 271, 357, 16, 27, STR_6804_CUSTOM, STR_NULL}, -{ WWT_EMPTY, RESIZE_NONE, 10, 0, 369, 251, 262, 0x0, STR_NULL}, -//{ WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 369, 251, 262, STR_6838_SHOW_HI_SCORE_CHART,STR_NULL}, +{ WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 369, 30, 41, STR_6838_SHOW_HI_SCORE_CHART,STR_NULL}, +{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 262, 0x0, STR_NULL}, { WWT_PANEL, RESIZE_NONE, 10, 0, 369, 263, 278, 0x0, STR_NULL}, { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 105, 185, 265, 276, STR_OPTIONS_SAVE_CHANGES, STR_NULL}, { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 186, 266, 265, 276, STR_012E_CANCEL, STR_NULL}, @@ -510,11 +513,6 @@ void ShowGameDifficulty() AllocateWindowDesc(&_game_difficulty_desc); } -void ShowHighscoreTable(int tbl) -{ - ShowInfoF("ShowHighscoreTable(%d) not implemented", tbl); -} - // virtual PositionMainToolbar function, calls the right one. int32 v_PositionMainToolbar(int32 p1) { diff --git a/table/sprites.h b/table/sprites.h --- a/table/sprites.h +++ b/table/sprites.h @@ -722,6 +722,10 @@ enum Sprites { SPR_OTTD_Y = 4843, SPR_OTTD_C = 4844, + SPR_HIGHSCORE_CHART_BEGIN = 4804, + SPR_TYCOON_IMG1_BEGIN = 4814, + SPR_TYCOON_IMG2_BEGIN = 4824, + /* road_gui.c */ SPR_IMG_ROAD_NW = 1309, SPR_IMG_ROAD_NE = 1310, diff --git a/ttd.c b/ttd.c --- a/ttd.c +++ b/ttd.c @@ -648,6 +648,7 @@ int ttd_main(int argc, char* argv[]) #endif LoadFromConfig(); + LoadFromHighScore(); // override config? if (musicdriver[0]) ttd_strlcpy(_ini_musicdriver, musicdriver, sizeof(_ini_musicdriver)); @@ -748,6 +749,7 @@ int ttd_main(int argc, char* argv[]) _sound_driver->stop(); SaveToConfig(); + SaveToHighScore(); // uninitialize airport state machines UnInitializeAirports(); @@ -1176,9 +1178,11 @@ void BeforeSaveGame() { Window *w = FindWindowById(WC_MAIN_WINDOW, 0); - _saved_scrollpos_x = WP(w,vp_d).scrollpos_x; - _saved_scrollpos_y = WP(w,vp_d).scrollpos_y; - _saved_scrollpos_zoom = w->viewport->zoom; + if (w != NULL) { + _saved_scrollpos_x = WP(w,vp_d).scrollpos_x; + _saved_scrollpos_y = WP(w,vp_d).scrollpos_y; + _saved_scrollpos_zoom = w->viewport->zoom; + } } void ConvertTownOwner() diff --git a/ttd.h b/ttd.h --- a/ttd.h +++ b/ttd.h @@ -449,6 +449,7 @@ enum { WC_NETWORK_STATUS_WINDOW = 0x4A, WC_CUSTOM_CURRENCY = 0x4B, WC_REPLACE_VEHICLE = 0x4C, + WC_HIGHSCORE_ENDSCREEN = 0x4D, }; diff --git a/unix.c b/unix.c --- a/unix.c +++ b/unix.c @@ -505,6 +505,7 @@ void DeterminePaths() _path.gm_dir = str_fmt("%sgm/", _path.game_data_dir); _path.data_dir = str_fmt("%sdata/", _path.game_data_dir); _config_file = str_fmt("%sopenttd.cfg", _path.personal_dir); + _highscore_file = str_fmt("%shs.dat", _path.personal_dir); _log_file = str_fmt("%sopenttd.log", _path.personal_dir); #if defined CUSTOM_LANG_DIR diff --git a/variables.h b/variables.h --- a/variables.h +++ b/variables.h @@ -340,6 +340,7 @@ VARDEF int _num_screenshot_formats, _cur VARDEF char _savegame_format[8]; VARDEF char *_config_file; +VARDEF char *_highscore_file; VARDEF char *_log_file; VARDEF FILE *_log_file_fd; diff --git a/win32.c b/win32.c --- a/win32.c +++ b/win32.c @@ -2065,6 +2065,7 @@ void DeterminePaths() _path.lang_dir = str_fmt("%slang\\", cfg); _config_file = str_fmt("%sopenttd.cfg", _path.personal_dir); + _highscore_file = str_fmt("%shs.dat", _path.personal_dir); _log_file = str_fmt("%sopenttd.log", _path.personal_dir); // make (auto)save and scenario folder diff --git a/window.c b/window.c --- a/window.c +++ b/window.c @@ -1520,6 +1520,13 @@ void DeleteAllNonVitalWindows(void) } } +/* Delete all always on-top windows to get an empty screen */ +void HideVitalWindows(void) +{ + DeleteWindowById(WC_MAIN_TOOLBAR, 0); + DeleteWindowById(WC_STATUS_BAR, 0); +} + int PositionMainToolbar(Window *w) { DEBUG(misc, 1) ("Repositioning Main Toolbar..."); diff --git a/window.h b/window.h --- a/window.h +++ b/window.h @@ -546,6 +546,8 @@ void HandleButtonClick(Window *w, byte w Window *GetCallbackWnd(); void DeleteNonVitalWindows(); void DeleteAllNonVitalWindows(void); +void HideVitalWindows(void); +void ShowVitalWindows(void); /* window.c */ VARDEF Window _windows[25];