102 players.c
@@ -721,6 +721,108 @@ int32 CmdPlayerCtrl(int x, int y, uint32 flags, uint32 p1, uint32 p2)
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),
@@ -330,6 +330,11 @@ void SetDifficultyLevel(int mode, GameOptions *gm_opt)

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 *w, WindowEvent *e)
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 *w, WindowEvent *e)
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 *w, WindowEvent *e)
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 *w, WindowEvent *e)
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_widgets[] = {
{ 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)
{
@@ -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,
10 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()
1 ttd.h
@@ -449,6 +449,7 @@ enum {
WC_NETWORK_STATUS_WINDOW = 0x4A,
WC_CUSTOM_CURRENCY = 0x4B,
WC_REPLACE_VEHICLE = 0x4C,
WC_HIGHSCORE_ENDSCREEN = 0x4D,
};


1 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
@@ -340,6 +340,7 @@ VARDEF int _num_screenshot_formats, _cur_screenshot_format;
VARDEF char _savegame_format[8];

VARDEF char *_config_file;
VARDEF char *_highscore_file;
VARDEF char *_log_file;
VARDEF FILE *_log_file_fd;

@@ -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
@@ -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...");
@@ -546,6 +546,8 @@ void HandleButtonClick(Window *w, byte widget);
Window *GetCallbackWnd();
void DeleteNonVitalWindows();
void DeleteAllNonVitalWindows(void);
void HideVitalWindows(void);
void ShowVitalWindows(void);

/* window.c */
VARDEF Window _windows[25];