(svn r10280) [0.5] -Backport from trunk (r10109, r10219, r10222, r10230, r10246, r10258): 0.5
authorrubidium
Fri, 22 Jun 2007 20:12:09 +0000
branch0.5
changeset 5513 0d3227e250eb
parent 5512 52869fa67090
child 5514 f122a67b50fb
(svn r10280) [0.5] -Backport from trunk (r10109, r10219, r10222, r10230, r10246, r10258):
- Fix: Do not look in every direction for tunnels when building one, one direction is enough (r10258)
- Fix: Take the age of the front vehicle for station rating (r10246)
- Fix: Terraforming wipes out canals. Now you always have to remove the canal before terraforming, instead of "just" removing the canal [FS#594] (r10240)
- Fix: Only 2 trains could crash at one time as collision checking stopped on the first hit. This could technically cause desyncs in network games as the collision hash order is not guaranteed [FS#892] (r10222)
- Fix: Land under foundations was terraform when it shouldn't be terraformed [FS#882, FS#890] (r10219)
- Fix: Some NewGRFs use the same (unused in the "current" climate) sprite IDs. Normally this gives some artefacts, but when one NewGRF expects it to be a sprite and another NewGRF overwrites it with a non-sprite nasty things happen (drawing a non-sprite crashes OTTD) [FS#838] (r10109)
clear_cmd.c
economy.c
lang/english.txt
spritecache.c
spritecache.h
train_cmd.c
tunnel_map.c
tunnel_map.h
tunnelbridge_cmd.c
water_map.h
--- a/clear_cmd.c	Fri Jun 22 20:08:37 2007 +0000
+++ b/clear_cmd.c	Fri Jun 22 20:12:09 2007 +0000
@@ -17,6 +17,7 @@
 #include "unmovable_map.h"
 #include "genworld.h"
 #include "industry.h"
+#include "water_map.h"
 
 typedef struct TerraformerHeightMod {
 	TileIndex tile;
@@ -111,7 +112,7 @@
 		// basement and then you raise/lower the other corner.
 		tileh = GetTileSlope(tile, &z);
 		if (tileh == unsafe_slope[mode] ||
-				tileh == ComplementSlope(unsafe_slope[mode])) {
+				tileh == (SLOPE_STEEP | ComplementSlope(unsafe_slope[mode]))) {
 			_terraform_err_tile = tile;
 			_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
 			return -1;
@@ -136,6 +137,13 @@
 		}
 	}
 
+	/* Canals can't be terraformed */
+	if (IsClearWaterTile(tile) && IsCanal(tile)) {
+		_terraform_err_tile = tile;
+		_error_message = STR_MUST_DEMOLISH_CANAL_FIRST;
+		return -1;
+	}
+
 	ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
 	if (CmdFailed(ret)) {
--- a/economy.c	Fri Jun 22 20:08:37 2007 +0000
+++ b/economy.c	Fri Jun 22 20:12:09 2007 +0000
@@ -1468,7 +1468,7 @@
 
 		// if last speed is 0, we treat that as if no vehicle has ever visited the station.
 		ge->last_speed = min(t, 255);
-		ge->last_age = _cur_year - v->build_year;
+		ge->last_age = _cur_year - u->build_year;
 
 		// If there's goods waiting at the station, and the vehicle
 		//  has capacity for it, load it on the vehicle.
--- a/lang/english.txt	Fri Jun 22 20:08:37 2007 +0000
+++ b/lang/english.txt	Fri Jun 22 20:12:09 2007 +0000
@@ -1801,6 +1801,7 @@
 STR_3805_COAST_OR_RIVERBANK                                     :Coast or riverbank
 STR_3806_SHIP_DEPOT                                             :Ship depot
 STR_3807_CAN_T_BUILD_ON_WATER                                   :{WHITE}...Can't build on water
+STR_MUST_DEMOLISH_CANAL_FIRST                                   :{WHITE}Must demolish canal first
 
 ##id 0x4000
 STR_4000_SAVE_GAME                                              :{WHITE}Save Game
--- a/spritecache.c	Fri Jun 22 20:08:37 2007 +0000
+++ b/spritecache.c	Fri Jun 22 20:12:09 2007 +0000
@@ -84,7 +84,7 @@
 
 static void* AllocSprite(size_t);
 
-static void* ReadSprite(SpriteID id)
+static void* ReadSprite(SpriteID id, bool real_sprite)
 {
 	uint num;
 	byte type;
@@ -104,7 +104,17 @@
 	num  = FioReadWord();
 	type = FioReadByte();
 	if (type == 0xFF) {
-		byte* dest = AllocSprite(num);
+		byte* dest;
+
+		if (real_sprite) {
+			static byte warning_level = 0;
+			DEBUG(misc, warning_level) ("Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id);
+			warning_level = 6;
+			if (id == SPR_IMG_QUERY) error("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a non- sprite?");
+			return (void*)GetSprite(SPR_IMG_QUERY);
+		}
+
+		dest = AllocSprite(num);
 
 		_sprite_ptr[id] = dest;
 		FioReadBlock(dest, num);
@@ -116,6 +126,12 @@
 		Sprite* sprite;
 		byte* dest;
 
+		if (!real_sprite) {
+			static byte warning_level = 0;
+			DEBUG(misc, warning_level) ("Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
+			warning_level = 6;
+		}
+
 		num = (type & 0x02) ? width * height : num - 8;
 		sprite = AllocSprite(sizeof(*sprite) + num);
 		_sprite_ptr[id] = sprite;
@@ -424,7 +440,7 @@
 }
 #endif
 
-const void *GetRawSprite(SpriteID sprite)
+const void *GetRawSprite(SpriteID sprite, bool real_sprite)
 {
 	void* p;
 
@@ -444,7 +460,7 @@
 
 	p = _sprite_ptr[sprite];
 	// Load the sprite, if it is not loaded, yet
-	if (p == NULL) p = ReadSprite(sprite);
+	if (p == NULL) p = ReadSprite(sprite, real_sprite);
 	return p;
 }
 
--- a/spritecache.h	Fri Jun 22 20:08:37 2007 +0000
+++ b/spritecache.h	Fri Jun 22 20:12:09 2007 +0000
@@ -12,17 +12,17 @@
 	byte data[VARARRAY_SIZE];
 } Sprite;
 
-const void *GetRawSprite(SpriteID sprite);
+const void *GetRawSprite(SpriteID sprite, bool real_sprite);
 bool SpriteExists(SpriteID sprite);
 
 static inline const Sprite *GetSprite(SpriteID sprite)
 {
-	return GetRawSprite(sprite);
+	return GetRawSprite(sprite, true);
 }
 
 static inline const byte *GetNonSprite(SpriteID sprite)
 {
-	return GetRawSprite(sprite);
+	return GetRawSprite(sprite, false);
 }
 
 void GfxInitSpriteMem(void);
--- a/train_cmd.c	Fri Jun 22 20:08:37 2007 +0000
+++ b/train_cmd.c	Fri Jun 22 20:12:09 2007 +0000
@@ -2915,28 +2915,6 @@
 }
 
 
-typedef struct TrainCollideChecker {
-	const Vehicle *v;
-	const Vehicle *v_skip;
-} TrainCollideChecker;
-
-static void *FindTrainCollideEnum(Vehicle *v, void *data)
-{
-	const TrainCollideChecker* tcc = data;
-
-	if (v != tcc->v &&
-			v != tcc->v_skip &&
-			v->type == VEH_Train &&
-			v->u.rail.track != 0x80 &&
-			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
-			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
-			myabs(v->y_pos - tcc->v->y_pos) < 6) {
-		return v;
-	} else {
-		return NULL;
-	}
-}
-
 static void SetVehicleCrashed(Vehicle *v)
 {
 	Vehicle *u;
@@ -2962,6 +2940,47 @@
 	return num;
 }
 
+typedef struct TrainCollideChecker {
+	Vehicle *v;
+	const Vehicle *v_skip;
+	uint num;
+} TrainCollideChecker;
+
+static void *FindTrainCollideEnum(Vehicle *v, void *data)
+{
+	TrainCollideChecker* tcc = (TrainCollideChecker*)data;
+
+	if (v != tcc->v &&
+			v != tcc->v_skip &&
+			v->type == VEH_Train &&
+			v->u.rail.track != 0x80 &&
+			myabs(v->z_pos - tcc->v->z_pos) < 6 &&
+			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
+			myabs(v->y_pos - tcc->v->y_pos) < 6 ) {
+
+		Vehicle *coll = GetFirstVehicleInChain(v);
+
+		/* it can't collide with its own wagons */
+		if (tcc->v == coll ||
+			(tcc->v->u.rail.track == 0x40 && (tcc->v->direction & 2) != (v->direction & 2)))
+			return NULL;
+
+		/* two drivers + passengers killed in train tcc->v (if it was not crashed already) */
+		if (!(tcc->v->vehstatus & VS_CRASHED)) {
+			tcc->num += 2 + CountPassengersInTrain(tcc->v);
+			SetVehicleCrashed(tcc->v);
+		}
+
+		if (!(coll->vehstatus & VS_CRASHED)) {
+			/* two drivers + passengers killed in train coll (if it was not crashed already) */
+			tcc->num += 2 + CountPassengersInTrain(coll);
+			SetVehicleCrashed(coll);
+		}
+	}
+
+	return NULL;
+}
+
 /*
  * Checks whether the specified train has a collision with another vehicle. If
  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
@@ -2971,9 +2990,6 @@
 static void CheckTrainCollision(Vehicle *v)
 {
 	TrainCollideChecker tcc;
-	Vehicle *coll;
-	Vehicle *realcoll;
-	uint num;
 
 	/* can't collide in depot */
 	if (v->u.rail.track == 0x80) return;
@@ -2982,28 +2998,15 @@
 
 	tcc.v = v;
 	tcc.v_skip = v->next;
-
-	/* find colliding vehicle */
-	realcoll = VehicleFromPos(TileVirtXY(v->x_pos, v->y_pos), &tcc, FindTrainCollideEnum);
-	if (realcoll == NULL) return;
-
-	coll = GetFirstVehicleInChain(realcoll);
-
-	/* it can't collide with its own wagons */
-	if (v == coll ||
-			(v->u.rail.track & 0x40 && (v->direction & 2) != (realcoll->direction & 2)))
-		return;
-
-	//two drivers + passangers killed in train v
-	num = 2 + CountPassengersInTrain(v);
-	if (!(coll->vehstatus & VS_CRASHED))
-		//two drivers + passangers killed in train coll (if it was not crashed already)
-		num += 2 + CountPassengersInTrain(coll);
-
-	SetVehicleCrashed(v);
-	if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
-
-	SetDParam(0, num);
+	tcc.num = 0;
+
+	/* find colliding vehicles */
+	VehicleFromPos(v->tile, &tcc, FindTrainCollideEnum);
+
+	/* any dead -> no crash */
+	if (tcc.num == 0) return;
+
+	SetDParam(0, tcc.num);
 	AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
 		v->index,
--- a/tunnel_map.c	Fri Jun 22 20:08:37 2007 +0000
+++ b/tunnel_map.c	Fri Jun 22 20:12:09 2007 +0000
@@ -24,7 +24,7 @@
 }
 
 
-static bool IsTunnelInWayDir(TileIndex tile, uint z, DiagDirection dir)
+bool IsTunnelInWayDir(TileIndex tile, uint z, DiagDirection dir)
 {
 	TileIndexDiff delta = TileOffsByDiagDir(dir);
 	uint height;
--- a/tunnel_map.h	Fri Jun 22 20:08:37 2007 +0000
+++ b/tunnel_map.h	Fri Jun 22 20:12:09 2007 +0000
@@ -38,6 +38,7 @@
 
 TileIndex GetOtherTunnelEnd(TileIndex);
 bool IsTunnelInWay(TileIndex, uint z);
+bool IsTunnelInWayDir(TileIndex tile, uint z, DiagDirection dir);
 
 
 static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d)
--- a/tunnelbridge_cmd.c	Fri Jun 22 20:08:37 2007 +0000
+++ b/tunnelbridge_cmd.c	Fri Jun 22 20:12:09 2007 +0000
@@ -452,6 +452,7 @@
 	uint end_z;
 	int32 cost;
 	int32 ret;
+	DiagDirection tunnel_in_way_dir;
 
 	_build_tunnel_endtile = 0;
 
@@ -476,6 +477,12 @@
 	 * position, because of increased-cost-by-length: 'cost += cost >> 3' */
 	cost = 0;
 	delta = TileOffsByDiagDir(direction);
+	if (OtherAxis(DiagDirToAxis(direction)) == AXIS_X) {
+		tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
+	} else {
+		tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
+	}
+
 	end_tile = start_tile;
 	for (;;) {
 		end_tile += delta;
@@ -483,7 +490,7 @@
 
 		if (start_z == end_z) break;
 
-		if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z)) {
+		if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
 			return_cmd_error(STR_5003_ANOTHER_TUNNEL_IN_THE_WAY);
 		}
 
--- a/water_map.h	Fri Jun 22 20:08:37 2007 +0000
+++ b/water_map.h	Fri Jun 22 20:12:09 2007 +0000
@@ -43,6 +43,11 @@
 	return GetWaterTileType(t) == WATER_COAST;
 }
 
+static inline bool IsCanal(TileIndex t)
+{
+	return GetWaterTileType(t) == WATER_CLEAR && GetTileOwner(t) != OWNER_WATER;
+}
+
 static inline bool IsClearWaterTile(TileIndex t)
 {
 	return IsTileType(t, MP_WATER) && IsWater(t) && GetTileSlope(t, NULL) == SLOPE_FLAT;