# HG changeset patch # User rubidium # Date 1189370175 0 # Node ID 08e4afe5e927f3f3c5b81e62a76ba581b6a77b09 # Parent f96ccea118f505c2963b70b1c1b7275501c3a4ce (svn r11073) [0.5] -Backport from trunk (r11039, r11029, r11027, r11024, r11021, r11020, r11018): - Fix: Underflow that caused overflows in the performance rating [FS#1179] (r11039) - Fix [Windows]: MIDI does not stop when closing openttd [FS#1164] (r11029) - Fix: Do not unconditionally assume that a tile has a depot (r11027) - Fix: Give a more correct error when building some things on tile 0 [FS#1173] (r11024) - Fix: Do not display income/expenses when they do not belong to a "valid" tile, like the money cheat and giving money [FS#1175] (r11021) - Fix: One could not give money when (s)he had too much money [FS#1174] (r11020) - Fix: Disallow buying/selling shares in your own company or a bankrupt company [FS#1169] (r11018) diff -r f96ccea118f5 -r 08e4afe5e927 clear_cmd.c --- a/clear_cmd.c Sun Sep 09 16:59:56 2007 +0000 +++ b/clear_cmd.c Sun Sep 09 20:36:15 2007 +0000 @@ -414,8 +414,6 @@ SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); - if (!EnsureNoVehicle(tile)) return CMD_ERROR; - if (IsOwnedLandTile(tile) && IsTileOwner(tile, _current_player)) { return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT); } diff -r f96ccea118f5 -r 08e4afe5e927 command.c --- a/command.c Sun Sep 09 16:59:56 2007 +0000 +++ b/command.c Sun Sep 09 20:36:15 2007 +0000 @@ -537,7 +537,7 @@ SubtractMoneyFromPlayer(res2); if (IsLocalPlayer() && _game_mode != GM_EDITOR) { - if (res2 != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2); + if (res2 != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2); if (_additional_cash_required) { SetDParam(0, _additional_cash_required); ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x,y); diff -r f96ccea118f5 -r 08e4afe5e927 depot.h --- a/depot.h Sun Sep 09 16:59:56 2007 +0000 +++ b/depot.h Sun Sep 09 20:36:15 2007 +0000 @@ -10,6 +10,7 @@ #include "oldpool.h" #include "tile.h" #include "variables.h" +#include "station_map.h" struct Depot { TileIndex xy; @@ -82,6 +83,21 @@ } } +/** + * Is the given tile a tile with a depot on it? + * @param tile the tile to check + * @return true if and only if there is a depot on the tile. + */ +static inline bool IsDepotTile(TileIndex tile) +{ + switch (GetTileType(tile)) { + case MP_STREET: return (_m[tile].m5 & 0xF0) == 0x20; + case MP_WATER: return (_m[tile].m5 & ~3) == 0x80; + case MP_RAILWAY: return (_m[tile].m5 & 0xFC) == 0xC0; + case MP_STATION: return IsHangar(tile); + default: return false; + } +} /** * Find out if the slope of the tile is suitable to build a depot of given direction diff -r f96ccea118f5 -r 08e4afe5e927 economy.c --- a/economy.c Sun Sep 09 16:59:56 2007 +0000 +++ b/economy.c Sun Sep 09 20:36:15 2007 +0000 @@ -217,10 +217,7 @@ // Skip the total if (i == SCORE_TOTAL) continue; // Check the score - s = (_score_part[owner][i] >= _score_info[i].needed) ? - _score_info[i].score : - _score_part[owner][i] * _score_info[i].score / _score_info[i].needed; - if (s < 0) s = 0; + s = clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed; score += s; total_score += _score_info[i].score; } @@ -649,6 +646,8 @@ int i; int32 inf = _economy.infl_amount * 54; + if ((_cur_year - _patches.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return; + for (i = 0; i != NUM_PRICES; i++) { AddSingleInflation((int32*)&_price + i, _price_frac + i, inf); } @@ -1633,11 +1632,16 @@ Player *p; int64 cost; - /* Check if buying shares is allowed (protection against modified clients */ - if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares) return CMD_ERROR; + /* Check if buying shares is allowed (protection against modified clients) */ + /* Cannot buy own shares */ + if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; + + p = GetPlayer((PlayerID)p1); + + /* Cannot buy shares of non-existent nor bankrupted company */ + if (!p->is_active) return CMD_ERROR; SET_EXPENSES_TYPE(EXPENSES_OTHER); - p = GetPlayer(p1); /* Protect new companies from hostile takeovers */ if (_cur_year - p->inaugurated_year < 6) return_cmd_error(STR_7080_PROTECTED); @@ -1678,11 +1682,16 @@ Player *p; int64 cost; - /* Check if buying shares is allowed (protection against modified clients */ - if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares) return CMD_ERROR; + /* Check if selling shares is allowed (protection against modified clients) */ + /* Cannot sell own shares */ + if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; + + p = GetPlayer((PlayerID)p1); + + /* Cannot sell shares of non-existent nor bankrupted company */ + if (!p->is_active) return CMD_ERROR; SET_EXPENSES_TYPE(EXPENSES_OTHER); - p = GetPlayer(p1); /* Those lines are here for network-protection (clients can be slow) */ if (GetAmountOwnedBy(p, _current_player) == 0) return 0; diff -r f96ccea118f5 -r 08e4afe5e927 graph_gui.c --- a/graph_gui.c Sun Sep 09 16:59:56 2007 +0000 +++ b/graph_gui.c Sun Sep 09 20:36:15 2007 +0000 @@ -997,13 +997,7 @@ DrawStringRightAligned(107, y, SET_PERFORMANCE_DETAIL_INT, 0); // Calculate the %-bar - if (val > needed) { - x = 50; - } else if (val == 0) { - x = 0; - } else { - x = val * 50 / needed; - } + x = clamp(val, 0, needed) * 50 / needed; // SCORE_LOAN is inversed if (val < 0 && i == SCORE_LOAN) x = 0; @@ -1013,7 +1007,7 @@ if (x != 50) GfxFillRect(112 + x, y - 2, 112 + 50, y + 10, color_notdone); // Calculate the % - x = (val <= needed) ? val * 100 / needed : 100; + x = clamp(val, 0, needed) * 100 / needed; // SCORE_LOAN is inversed if (val < 0 && i == SCORE_LOAN) x = 0; diff -r f96ccea118f5 -r 08e4afe5e927 main_gui.c --- a/main_gui.c Sun Sep 09 16:59:56 2007 +0000 +++ b/main_gui.c Sun Sep 09 20:36:15 2007 +0000 @@ -88,7 +88,7 @@ #ifdef ENABLE_NETWORK case 3: { /* Give money, you can only give money in excess of loan */ const Player *p = GetPlayer(_current_player); - int32 money = min(p->money64 - p->current_loan, atoi(e->we.edittext.str) / _currency->rate); + int32 money = min(p->money64 - p->current_loan, (int64)(atoi(e->we.edittext.str) / _currency->rate)); money = clamp(money, 0, 20000000); // Clamp between 20 million and 0 diff -r f96ccea118f5 -r 08e4afe5e927 music/win32_m.c --- a/music/win32_m.c Sun Sep 09 16:59:56 2007 +0000 +++ b/music/win32_m.c Sun Sep 09 20:36:15 2007 +0000 @@ -12,6 +12,7 @@ bool playing; int new_vol; HANDLE wait_obj; + HANDLE thread; UINT_PTR devid; char start_song[260]; } _midi; @@ -86,8 +87,6 @@ static DWORD WINAPI MidiThread(LPVOID arg) { - _midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL); - do { char *s; int vol; @@ -104,9 +103,7 @@ s[0] = '\0'; // Delay somewhat in case we don't manage to play. - if (!_midi.playing) { - Sleep(5000); - } + if (!_midi.playing) WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 5000); } if (_midi.stop_song && _midi.playing) { @@ -121,14 +118,13 @@ WaitForMultipleObjects(1, &_midi.wait_obj, FALSE, 1000); } while (!_midi.terminate); - DeleteObject(_midi.wait_obj); + MidiIntStopSong(); return 0; } static const char *Win32MidiStart(const char * const *parm) { MIDIOUTCAPS midicaps; - DWORD threadId; UINT nbdev; UINT_PTR dev; char buf[16]; @@ -148,8 +144,8 @@ } } - if (CreateThread(NULL, 8192, MidiThread, 0, 0, &threadId) == NULL) - return "Failed to create thread"; + if (NULL == (_midi.wait_obj = CreateEvent(NULL, FALSE, FALSE, NULL))) return "Failed to create event"; + if (NULL == (_midi.thread = CreateThread(NULL, 8192, MidiThread, 0, 0, NULL))) return "Failed to create thread"; return NULL; } @@ -158,6 +154,9 @@ { _midi.terminate = true; SetEvent(_midi.wait_obj); + WaitForMultipleObjects(1, &_midi.thread, true, INFINITE); + CloseHandle(_midi.wait_obj); + CloseHandle(_midi.thread); } const HalMusicDriver _win32_music_driver = { diff -r f96ccea118f5 -r 08e4afe5e927 tree_cmd.c --- a/tree_cmd.c Sun Sep 09 16:59:56 2007 +0000 +++ b/tree_cmd.c Sun Sep 09 20:36:15 2007 +0000 @@ -249,6 +249,11 @@ cost += _price.build_trees * 2; break; + case MP_WATER: + msg = STR_3807_CAN_T_BUILD_ON_WATER; + continue; + break; + case MP_CLEAR: if (!IsTileOwner(tile, OWNER_NONE)) { msg = STR_2804_SITE_UNSUITABLE; diff -r f96ccea118f5 -r 08e4afe5e927 vehicle.c --- a/vehicle.c Sun Sep 09 16:59:56 2007 +0000 +++ b/vehicle.c Sun Sep 09 20:36:15 2007 +0000 @@ -1740,7 +1740,7 @@ byte vehicle_type = GB(p1, 0, 8); - if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; + if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR; /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, NULL, NULL, NULL); diff -r f96ccea118f5 -r 08e4afe5e927 water_cmd.c --- a/water_cmd.c Sun Sep 09 16:59:56 2007 +0000 +++ b/water_cmd.c Sun Sep 09 20:36:15 2007 +0000 @@ -61,10 +61,7 @@ if (p1 > 1) return CMD_ERROR; - if (!EnsureNoVehicle(tile)) return CMD_ERROR; - tile2 = tile + (p1 ? TileDiffXY(0, 1) : TileDiffXY(1, 0)); - if (!EnsureNoVehicle(tile2)) return CMD_ERROR; if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2)) return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER); @@ -294,15 +291,15 @@ case WATER_CLEAR: if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); - // Make sure no vehicle is on the tile - if (!EnsureNoVehicle(tile)) return CMD_ERROR; - // Make sure it's not an edge tile. if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) || !IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) { return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); } + /* Make sure no vehicle is on the tile */ + if (!EnsureNoVehicle(tile)) return CMD_ERROR; + if (GetTileOwner(tile) != OWNER_WATER && GetTileOwner(tile) != OWNER_NONE && !CheckTileOwnership(tile)) return CMD_ERROR; if (flags & DC_EXEC) DoClearSquare(tile); @@ -314,12 +311,6 @@ // Make sure no vehicle is on the tile if (!EnsureNoVehicle(tile)) return CMD_ERROR; - // Make sure it's not an edge tile. - if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) || - !IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) { - return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); - } - if (flags & DC_EXEC) DoClearSquare(tile); if (slope == SLOPE_N || slope == SLOPE_E || slope == SLOPE_S || slope == SLOPE_W) { return _price.clear_water;