diff -r 0fd0e4612711 src/aircraft.h
--- a/src/aircraft.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/aircraft.h	Fri Jul 22 00:25:33 2011 +0000
@@ -59,6 +59,7 @@
 	ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_INC : EXPENSES_AIRCRAFT_RUN; }
 	bool IsPrimaryVehicle() const                  { return this->IsNormalAircraft(); }
 	SpriteID GetImage(Direction direction) const;
+	SpriteID GetIcon(Direction direction) const;
 	int GetDisplaySpeed() const    { return this->cur_speed; }
 	int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
 	int GetSpeedOldUnits() const   { return this->vcache.cached_max_speed * 10 / 128; }
diff -r 0fd0e4612711 src/aircraft_cmd.cpp
--- a/src/aircraft_cmd.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/aircraft_cmd.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -157,6 +157,20 @@
 	return direction + _aircraft_sprite[spritenum];
 }
 
+SpriteID Aircraft::GetIcon(Direction direction) const
+{
+	uint8 spritenum = this->spritenum;
+
+	if (is_custom_sprite(spritenum)) {
+		SpriteID sprite = GetCustomVehicleGUISprite(this, direction);
+		if (sprite != 0) return sprite;
+
+		spritenum = Engine::Get(this->engine_type)->original_image_index;
+	}
+
+	return direction + _aircraft_sprite[spritenum];
+}
+
 SpriteID GetRotorImage(const Aircraft *v)
 {
 	assert(v->subtype == AIR_HELICOPTER);
diff -r 0fd0e4612711 src/aircraft_gui.cpp
--- a/src/aircraft_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/aircraft_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -80,7 +80,7 @@
 {
 	bool rtl = _current_text_dir == TD_RTL;
 
-	SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W);
+	SpriteID sprite = v->GetIcon(rtl ? DIR_E : DIR_W);
 	const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
 
 	int x = rtl ? right - real_sprite->width - real_sprite->x_offs : left - real_sprite->x_offs;
diff -r 0fd0e4612711 src/depot_gui.cpp
--- a/src/depot_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/depot_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -295,7 +295,7 @@
 			case VEH_ROAD:     DrawRoadVehImage( v, image_left, image_right, sprite_y, this->sel); break;
 			case VEH_SHIP:     DrawShipImage(    v, image_left, image_right, sprite_y, this->sel); break;
 			case VEH_AIRCRAFT: {
-				const Sprite *spr = GetSprite(v->GetImage(DIR_W), ST_NORMAL);
+				const Sprite *spr = GetSprite(v->GetIcon(DIR_W), ST_NORMAL);
 				DrawAircraftImage(v, image_left, image_right,
 									y + max(spr->height + spr->y_offs - 14, 0), // tall sprites needs an y offset
 									this->sel);
@@ -501,7 +501,7 @@
 					this->sel = INVALID_VEHICLE;
 					TrainDepotMoveVehicle(v, sel, gdvp.head);
 				} else if (v != NULL) {
-					int image = v->GetImage(_current_text_dir == TD_RTL ? DIR_E : DIR_W);
+					int image = v->GetIcon(_current_text_dir == TD_RTL ? DIR_E : DIR_W);
 					SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this);
 
 					this->sel = v->index;
diff -r 0fd0e4612711 src/group_gui.cpp
--- a/src/group_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/group_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -457,7 +457,7 @@
 
 				this->vehicle_sel = v->index;
 
-				int image = v->GetImage(_current_text_dir == TD_RTL ? DIR_E : DIR_W);
+				int image = v->GetIcon(_current_text_dir == TD_RTL ? DIR_E : DIR_W);
 				SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this);
 				_cursor.vehchain = true;
 
diff -r 0fd0e4612711 src/newgrf_engine.cpp
--- a/src/newgrf_engine.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/newgrf_engine.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -659,6 +659,63 @@
 				return count;
 			}
 
+		// get vars for n-th vehicle in chain [signed number relative to vehicle]
+		case 0x61: // DirDifference
+			if (v->type != VEH_TRAIN && v->type != VEH_ROAD) return 0;
+
+			{
+				const Vehicle* u = v->Next((int8)parameter);
+				if (u == NULL) return 0;
+
+				DirDiff d = (int8)parameter < 0 ? DirDifference(u->direction, v->direction) : DirDifference(v->direction, u->direction);
+				if (d > DIRDIFF_REVERSE) return d | 0xFFFFFFF8;
+				return d;
+			}
+
+		case 0x62: // height difference
+			if (v->type != VEH_TRAIN && v->type != VEH_ROAD) return 0;
+
+			{
+				const Vehicle* u = v->Next((int8)parameter);
+				if (u == NULL) return 0;
+				return (int8)parameter < 0 ? u->z_pos - v->z_pos : v->z_pos - u->z_pos;
+			}
+
+		case 0x63: // vehstatus
+			if (v->type != VEH_TRAIN && v->type != VEH_ROAD) return 0;
+
+			{
+				const Vehicle* u = v->Next((int8)parameter);
+				if (u == NULL) return 0;
+				return u->vehstatus;
+			}
+
+		case 0x64: // bitstuffed variant xxyyzzhd
+			if (v->type != VEH_TRAIN && v->type != VEH_ROAD) return 0;
+
+			{
+				const Vehicle* u = v->Next((int8)parameter);
+				if (u == NULL) return 0;
+
+				uint32 ret = (int8)parameter < 0 ? DirDifference(u->direction, v->direction) : DirDifference(v->direction, u->direction);
+				if (ret > DIRDIFF_REVERSE) ret |= 0x08;
+				if (u->vehstatus & VS_HIDDEN) ret |= 0x80;
+				ret |= (((int8)parameter < 0 ? u->z_pos - v->z_pos : v->z_pos - u->z_pos) & 0xFF) << 8;
+				ret |= (((int8)parameter < 0 ? u->y_pos - v->y_pos : v->y_pos - u->y_pos) & 0xFF) << 16;
+				ret |= (((int8)parameter < 0 ? u->x_pos - v->x_pos : v->x_pos - u->x_pos) & 0xFF) << 24;
+				return ret;
+			}
+
+		case 0x65: // engine-id
+			if (v->type != VEH_TRAIN && v->type != VEH_ROAD) return 0;
+
+			{
+				const Vehicle* u = v->Next((int8)parameter);
+				if (u == NULL) return 0xFFFFFFFF;
+				return Engine::Get(u->engine_type)->grf_prop.local_id;
+			}
+
+
 		case 0xFE:
 		case 0xFF: {
 			uint16 modflags = 0;
@@ -928,13 +985,15 @@
 }
 
 
-SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction)
+SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, bool gui)
 {
 	const SpriteGroup *group;
 	ResolverObject object;
 
 	NewVehicleResolver(&object, engine, v);
 
+	object.callback_param1 = gui?1:0;
+
 	group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), &object);
 	if (group == NULL || group->GetNumResults() == 0) return 0;
 
diff -r 0fd0e4612711 src/newgrf_engine.h
--- a/src/newgrf_engine.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/newgrf_engine.h	Fri Jul 22 00:25:33 2011 +0000
@@ -26,7 +26,7 @@
 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const struct SpriteGroup *group, EngineID *train_id, uint trains);
 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine);
 void SetCustomEngineSprites(EngineID engine, byte cargo, const struct SpriteGroup *group);
-SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction);
+SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, bool gui);
 SpriteID GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view);
 #define GetCustomRotorSprite(v, i) GetRotorOverrideSprite(v->engine_type, v, i)
 #define GetCustomRotorIcon(et) GetRotorOverrideSprite(et, NULL, true)
@@ -42,8 +42,9 @@
 uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v);
 uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent);
 bool UsesWagonOverride(const Vehicle *v);
-#define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction)
-#define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction)
+#define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction, false)
+#define GetCustomVehicleGUISprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction, true)
+#define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction, true)
 
 /* Handler to Evaluate callback 36. If the callback fails (i.e. most of the
  * time) orig_value is returned */
diff -r 0fd0e4612711 src/rail_map.h
--- a/src/rail_map.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/rail_map.h	Fri Jul 22 00:25:33 2011 +0000
@@ -552,4 +552,27 @@
 	_me[t].m7 = 0;
 }
 
+
+static inline void IncreaseStuckCounter(TileIndex t)
+{
+	if (!IsTileType(t, MP_RAILWAY)) return;
+	if (_me[t].m7 == 255) return;
+	_me[t].m7++;
+}
+
+
+static inline void ReduceStuckCounter(TileIndex t)
+{
+	if (!IsTileType(t, MP_RAILWAY)) return;
+	_me[t].m7 -= _me[t].m7/4;
+}
+
+
+static inline byte GetStuckCounter(TileIndex t)
+{
+	if (!IsTileType(t, MP_RAILWAY)) return 0;
+	return _me[t].m7;
+
+}
+
 #endif /* RAIL_MAP_H */
diff -r 0fd0e4612711 src/roadveh.h
--- a/src/roadveh.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/roadveh.h	Fri Jul 22 00:25:33 2011 +0000
@@ -108,6 +108,7 @@
 	ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_ROADVEH_INC : EXPENSES_ROADVEH_RUN; }
 	bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
 	SpriteID GetImage(Direction direction) const;
+	SpriteID GetIcon(Direction direction) const;
 	int GetDisplaySpeed() const { return this->gcache.last_speed / 2; }
 	int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
 	Money GetRunningCost() const;
diff -r 0fd0e4612711 src/roadveh_cmd.cpp
--- a/src/roadveh_cmd.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/roadveh_cmd.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -137,6 +137,25 @@
 	return sprite;
 }
 
+SpriteID RoadVehicle::GetIcon(Direction direction) const
+{
+	uint8 spritenum = this->spritenum;
+	SpriteID sprite;
+
+	if (is_custom_sprite(spritenum)) {
+		sprite = GetCustomVehicleGUISprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)));
+		if (sprite != 0) return sprite;
+
+		spritenum = Engine::Get(this->engine_type)->original_image_index;
+	}
+
+	sprite = direction + _roadveh_images[spritenum];
+
+	if (this->cargo.Count() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
+
+	return sprite;
+}
+
 /**
  * Draw a road vehicle engine.
  * @param left Left edge to draw within.
diff -r 0fd0e4612711 src/roadveh_gui.cpp
--- a/src/roadveh_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/roadveh_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -149,7 +149,7 @@
 
 		if (rtl ? px + width > 0 : px - width < max_width) {
 			PaletteID pal = (u->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(u);
-			DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), 6 + offset.y);
+			DrawSprite(u->GetIcon(dir), pal, px + (rtl ? -offset.x : offset.x), 6 + offset.y);
 		}
 
 		px += rtl ? -width : width;
diff -r 0fd0e4612711 src/ship.h
--- a/src/ship.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/ship.h	Fri Jul 22 00:25:33 2011 +0000
@@ -33,6 +33,7 @@
 	void PlayLeaveStationSound() const;
 	bool IsPrimaryVehicle() const { return true; }
 	SpriteID GetImage(Direction direction) const;
+	SpriteID GetIcon(Direction direction) const;
 	int GetDisplaySpeed() const { return this->cur_speed / 2; }
 	int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
 	Money GetRunningCost() const;
diff -r 0fd0e4612711 src/ship_cmd.cpp
--- a/src/ship_cmd.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/ship_cmd.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -113,6 +113,20 @@
 	return _ship_sprites[spritenum] + direction;
 }
 
+SpriteID Ship::GetIcon(Direction direction) const
+{
+	uint8 spritenum = this->spritenum;
+
+	if (is_custom_sprite(spritenum)) {
+		SpriteID sprite = GetCustomVehicleGUISprite(this, direction);
+		if (sprite != 0) return sprite;
+
+		spritenum = Engine::Get(this->engine_type)->original_image_index;
+	}
+
+	return _ship_sprites[spritenum] + direction;
+}
+
 static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
 {
 	/* Find the closest depot */
diff -r 0fd0e4612711 src/ship_gui.cpp
--- a/src/ship_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/ship_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -32,7 +32,7 @@
 {
 	bool rtl = _current_text_dir == TD_RTL;
 
-	SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W);
+	SpriteID sprite = v->GetIcon(rtl ? DIR_E : DIR_W);
 	const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
 
 	int x = rtl ? right - real_sprite->width - real_sprite->x_offs : left - real_sprite->x_offs;
diff -r 0fd0e4612711 src/train.h
--- a/src/train.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/train.h	Fri Jul 22 00:25:33 2011 +0000
@@ -97,6 +97,7 @@
 	void PlayLeaveStationSound() const;
 	bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
 	SpriteID GetImage(Direction direction) const;
+	SpriteID GetIcon(Direction direction) const;
 	int GetDisplaySpeed() const { return this->gcache.last_speed; }
 	int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
 	Money GetRunningCost() const;
diff -r 0fd0e4612711 src/train_cmd.cpp
--- a/src/train_cmd.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/train_cmd.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -493,6 +493,27 @@
 	return sprite;
 }
 
+SpriteID Train::GetIcon(Direction direction) const
+{
+	uint8 spritenum = this->spritenum;
+	SpriteID sprite;
+
+	if (HasBit(this->flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
+
+	if (is_custom_sprite(spritenum)) {
+		sprite = GetCustomVehicleGUISprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)));
+		if (sprite != 0) return sprite;
+
+		spritenum = Engine::Get(this->engine_type)->original_image_index;
+	}
+
+	sprite = GetDefaultTrainSprite(spritenum, direction);
+
+	if (this->cargo.Count() >= this->cargo_cap / 2U) sprite += _wagon_full_adder[spritenum];
+
+	return sprite;
+}
+
 static SpriteID GetRailIcon(EngineID engine, bool rear_head, int &y)
 {
 	const Engine *e = Engine::Get(engine);
diff -r 0fd0e4612711 src/train_gui.cpp
--- a/src/train_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/train_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -122,7 +122,7 @@
 
 		if (rtl ? px + width > 0 : px - width < max_width) {
 			PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
-			DrawSprite(v->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), 7 + offset.y);
+			DrawSprite(v->GetIcon(dir), pal, px + (rtl ? -offset.x : offset.x), 7 + offset.y);
 		}
 
 		if (!v->IsArticulatedPart()) sel_articulated = false;
@@ -359,7 +359,7 @@
 				int width = u->GetDisplayImageWidth(&offset);
 				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
 					PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
-					DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
+					DrawSprite(u->GetIcon(dir), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
 				}
 				px += rtl ? -width : width;
 				dx += width;
diff -r 0fd0e4612711 src/vehicle_base.h
--- a/src/vehicle_base.h	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/vehicle_base.h	Fri Jul 22 00:25:33 2011 +0000
@@ -344,6 +344,13 @@
 	virtual SpriteID GetImage(Direction direction) const { return 0; }
 
 	/**
+	 * Gets the sprite to show for the given direction, for GUI use
+	 * @param direction the direction the vehicle is facing
+	 * @return the sprite for the given vehicle in the given direction
+	 */
+	virtual SpriteID GetIcon(Direction direction) const { return 0; }
+
+	/**
 	 * Invalidates cached NewGRF variables
 	 * @see InvalidateNewGRFCacheOfChain
 	 */
@@ -460,6 +467,12 @@
 	 * @return the next vehicle or NULL when there isn't a next vehicle.
 	 */
 	inline Vehicle *Next() const { return this->next; }
+	inline Vehicle *Next(int8 n) {
+		if (n < 0) return this->Previous(-n);
+		Vehicle *v = this;
+		for (int i = 0; i != n && v != NULL; i++) v = v->Next();
+		return v;
+	}
 
 	/**
 	 * Get the previous vehicle of this vehicle.
@@ -467,6 +480,12 @@
 	 * @return the previous vehicle or NULL when there isn't a previous vehicle.
 	 */
 	inline Vehicle *Previous() const { return this->previous; }
+	inline Vehicle *Previous(int8 n) {
+		if (n < 0) return this->Next(-n);
+		Vehicle *v = this;
+		for (int i = 0; i != n && v != NULL; i++) v = v->Previous();
+		return v;
+	}
 
 	/**
 	 * Get the first vehicle of this vehicle chain.
diff -r 0fd0e4612711 src/vehicle_gui.cpp
--- a/src/vehicle_gui.cpp	Thu Jul 21 17:45:22 2011 +0000
+++ b/src/vehicle_gui.cpp	Fri Jul 22 00:25:33 2011 +0000
@@ -1996,7 +1996,7 @@
 			case VLD_WIDGET_MIDDLE_DETAILS: {
 				/* For other vehicles, at the place of the matrix. */
 				bool rtl = _current_text_dir == TD_RTL;
-				uint sprite_width = max<uint>(GetSprite(v->GetImage(rtl ? DIR_E : DIR_W), ST_NORMAL)->width, 70U) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
+				uint sprite_width = max<uint>(GetSprite(v->GetIcon(rtl ? DIR_E : DIR_W), ST_NORMAL)->width, 70U) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
 
 				uint text_left  = r.left  + (rtl ? 0 : sprite_width);
 				uint text_right = r.right - (rtl ? sprite_width : 0);
@@ -2705,7 +2705,7 @@
 
 		default:
 			bool rtl = _current_text_dir == TD_RTL;
-			SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W);
+			SpriteID sprite = v->GetIcon(rtl ? DIR_E : DIR_W);
 			const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
 			vehicle_width = real_sprite->width;
 
