(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)
--- 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);
}
--- 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);
--- 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
--- 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;
--- 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;
--- 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
--- 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 = {
--- 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;
--- 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);
--- 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;