(svn r11073) [0.5] -Backport from trunk (r11039, r11029, r11027, r11024, r11021, r11020, r11018): 0.5
authorrubidium
Sun, 09 Sep 2007 20:36:15 +0000
branch0.5
changeset 5541 08e4afe5e927
parent 5540 f96ccea118f5
child 5542 c719509fb0b7
(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)
clear_cmd.c
command.c
depot.h
economy.c
graph_gui.c
main_gui.c
music/win32_m.c
tree_cmd.c
vehicle.c
water_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);
 	}
--- 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;