(svn r10120) [NoAI] -Sync with trunk r10096:r10119 noai
authorglx
Tue, 12 Jun 2007 19:52:26 +0000
branchnoai
changeset 9627 6a7c8ead2328
parent 9626 79f2b5a0cdd7
child 9628 b5c2449616b5
(svn r10120) [NoAI] -Sync with trunk r10096:r10119
bin/data/flags.grf
projects/openttd.vcproj
projects/openttd_vs80.vcproj
source.list
src/ai/api/ai_vehiclelist.cpp
src/articulated_vehicles.cpp
src/articulated_vehicles.h
src/blitter/8bpp_debug.cpp
src/blitter/8bpp_debug.hpp
src/blitter/8bpp_optimized.cpp
src/blitter/8bpp_optimized.hpp
src/blitter/8bpp_simple.cpp
src/blitter/8bpp_simple.hpp
src/blitter/8bpp_slow.cpp
src/blitter/8bpp_slow.hpp
src/depot_gui.cpp
src/economy.cpp
src/fileio.cpp
src/fileio.h
src/industry_cmd.cpp
src/industry_map.h
src/lang/bulgarian.txt
src/lang/catalan.txt
src/lang/czech.txt
src/lang/danish.txt
src/lang/dutch.txt
src/lang/english.txt
src/lang/estonian.txt
src/lang/french.txt
src/lang/hungarian.txt
src/lang/italian.txt
src/lang/korean.txt
src/lang/romanian.txt
src/lang/swedish.txt
src/lang/ukrainian.txt
src/main_gui.cpp
src/misc_gui.cpp
src/newgrf.cpp
src/newgrf_config.cpp
src/newgrf_config.h
src/newgrf_engine.cpp
src/newgrf_gui.cpp
src/newgrf_industries.cpp
src/newgrf_industries.h
src/newgrf_text.cpp
src/newgrf_text.h
src/openttd.cpp
src/player_gui.cpp
src/rail_gui.cpp
src/road_cmd.cpp
src/roadveh.h
src/roadveh_cmd.cpp
src/roadveh_gui.cpp
src/screenshot.cpp
src/spritecache.cpp
src/spritecache.h
src/spriteloader/grf.cpp
src/station_cmd.cpp
src/table/ai_rail.h
src/train_cmd.cpp
src/tunnelbridge_cmd.cpp
src/vehicle.cpp
src/vehicle.h
src/vehicle_gui.h
src/viewport.cpp
src/water_cmd.cpp
Binary file bin/data/flags.grf has changed
--- a/projects/openttd.vcproj	Tue Jun 12 18:02:11 2007 +0000
+++ b/projects/openttd.vcproj	Tue Jun 12 19:52:26 2007 +0000
@@ -1235,10 +1235,10 @@
 				RelativePath=".\..\src\blitter\8bpp_optimized.hpp">
 			</File>
 			<File
-				RelativePath=".\..\src\blitter\8bpp_slow.cpp">
+				RelativePath=".\..\src\blitter\8bpp_simple.cpp">
 			</File>
 			<File
-				RelativePath=".\..\src\blitter\8bpp_slow.hpp">
+				RelativePath=".\..\src\blitter\8bpp_simple.hpp">
 			</File>
 			<File
 				RelativePath=".\..\src\blitter\blitter.hpp">
--- a/projects/openttd_vs80.vcproj	Tue Jun 12 18:02:11 2007 +0000
+++ b/projects/openttd_vs80.vcproj	Tue Jun 12 19:52:26 2007 +0000
@@ -1862,11 +1862,11 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\blitter\8bpp_slow.cpp"
+				RelativePath=".\..\src\blitter\8bpp_simple.cpp"
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\blitter\8bpp_slow.hpp"
+				RelativePath=".\..\src\blitter\8bpp_simple.hpp"
 				>
 			</File>
 			<File
--- a/source.list	Tue Jun 12 18:02:11 2007 +0000
+++ b/source.list	Tue Jun 12 19:52:26 2007 +0000
@@ -386,8 +386,8 @@
 blitter/8bpp_debug.hpp
 blitter/8bpp_optimized.cpp
 blitter/8bpp_optimized.hpp
-blitter/8bpp_slow.cpp
-blitter/8bpp_slow.hpp
+blitter/8bpp_simple.cpp
+blitter/8bpp_simple.hpp
 blitter/blitter.hpp
 
 # Sprite loaders
--- a/src/ai/api/ai_vehiclelist.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/ai/api/ai_vehiclelist.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -6,7 +6,7 @@
 {
 	Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
-		if (v->owner == _current_player && v->first == NULL)
+		if (v->owner == _current_player && v->IsPrimaryVehicle())
 			this->AddItem(v->index);
 	}
 }
--- a/src/articulated_vehicles.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/articulated_vehicles.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -4,16 +4,17 @@
 
 #include "stdafx.h"
 #include "openttd.h"
-#include "debug.h"
 #include "functions.h"
 #include "command.h"
 #include "vehicle.h"
 #include "articulated_vehicles.h"
 #include "engine.h"
 #include "train.h"
+#include "roadveh.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_engine.h"
 
+
 uint CountArticulatedParts(EngineID engine_type)
 {
 	if (!HASBIT(EngInfo(engine_type)->callbackmask, CBM_ARTIC_ENGINE)) return 0;
@@ -27,7 +28,7 @@
 	return i - 1;
 }
 
-void AddArticulatedParts(Vehicle **vl)
+void AddArticulatedParts(Vehicle **vl, VehicleType type)
 {
 	const Vehicle *v = vl[0];
 	Vehicle *u = vl[0];
@@ -46,9 +47,8 @@
 
 		u = u->next;
 
-		EngineID engine_type = GB(callback, 0, 7);
+		EngineID engine_type = GetFirstEngineOfType(type) + GB(callback, 0, 7);
 		bool flip_image = HASBIT(callback, 7);
-		const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
 
 		/* get common values from first engine */
 		u->direction = v->direction;
@@ -57,28 +57,57 @@
 		u->x_pos = v->x_pos;
 		u->y_pos = v->y_pos;
 		u->z_pos = v->z_pos;
-		u->u.rail.track = v->u.rail.track;
-		u->u.rail.railtype = v->u.rail.railtype;
 		u->build_year = v->build_year;
 		u->vehstatus = v->vehstatus & ~VS_STOPPED;
-		u->u.rail.first_engine = v->engine_type;
 
-		/* get more settings from rail vehicle info */
-		u->spritenum = rvi_artic->image_index;
-		if (flip_image) u->spritenum++;
-		u->cargo_type = rvi_artic->cargo_type;
 		u->cargo_subtype = 0;
-		u->cargo_cap = rvi_artic->capacity;
 		u->max_speed = 0;
 		u->max_age = 0;
 		u->engine_type = engine_type;
 		u->value = 0;
-		u = new (u) Train();
 		u->subtype = 0;
-		SetArticulatedPart(u);
 		u->cur_image = 0xAC2;
 		u->random_bits = VehicleRandomBits();
 
+		switch (type) {
+			default: NOT_REACHED();
+
+			case VEH_TRAIN: {
+				const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
+
+				u = new (u) Train();
+				u->u.rail.track = v->u.rail.track;
+				u->u.rail.railtype = v->u.rail.railtype;
+				u->u.rail.first_engine = v->engine_type;
+
+				u->spritenum = rvi_artic->image_index;
+				u->cargo_type = rvi_artic->cargo_type;
+				u->cargo_cap = rvi_artic->capacity;
+
+				SetArticulatedPart(u);
+			} break;
+
+			case VEH_ROAD: {
+				const RoadVehicleInfo *rvi_artic = RoadVehInfo(engine_type);
+
+				u = new (u) RoadVehicle();
+				u->u.road.first_engine = v->engine_type;
+				u->u.road.cached_veh_length = GetRoadVehLength(u);
+				u->u.road.state = RVSB_IN_DEPOT;
+
+				u->u.road.roadtype = v->u.road.roadtype;
+				u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes;
+
+				u->spritenum = rvi_artic->image_index;
+				u->cargo_type = rvi_artic->cargo_type;
+				u->cargo_cap = rvi_artic->capacity;
+
+				SetRoadVehArticPart(u);
+			} break;
+		}
+
+		if (flip_image) u->spritenum++;
+
 		VehiclePositionChanged(u);
 	}
 }
--- a/src/articulated_vehicles.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/articulated_vehicles.h	Tue Jun 12 19:52:26 2007 +0000
@@ -6,6 +6,6 @@
 #define ARTICULATED_VEHICLES_H
 
 uint CountArticulatedParts(EngineID engine_type);
-void AddArticulatedParts(Vehicle **vl);
+void AddArticulatedParts(Vehicle **vl, VehicleType type);
 
 #endif /* ARTICULATED_VEHICLES_H */
--- a/src/blitter/8bpp_debug.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/blitter/8bpp_debug.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1,3 +1,7 @@
+/* $Id$ */
+
+/** @file 8bpp_debug.cpp */
+
 #include "../stdafx.h"
 #include "../zoom.hpp"
 #include "../gfx.h"
--- a/src/blitter/8bpp_debug.hpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/blitter/8bpp_debug.hpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1,6 +1,6 @@
 /* $Id$ */
 
-/** @file debug.hpp */
+/** @file 8bpp_debug.hpp */
 
 #ifndef BLITTER_8BPP_DEBUG_HPP
 #define BLITTER_8BPP_DEBUG_HPP
--- a/src/blitter/8bpp_optimized.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/blitter/8bpp_optimized.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1,3 +1,7 @@
+/* $Id$ */
+
+/** @file 8bpp_optimized.cpp */
+
 #include "../stdafx.h"
 #include "../zoom.hpp"
 #include "../gfx.h"
@@ -137,18 +141,15 @@
 
 			for (int x = 0; x < UnScaleByZoom(sprite->width, (ZoomLevel)i); x++) {
 				uint color = 0;
-				int count = 0;
 
 				/* Get the color keeping in mind the zoom-level */
 				for (int j = 0; j < ScaleByZoom(1, (ZoomLevel)i); j++) {
-					if (src->m != 0) { color = src->m; count++; }
+					if (src->m != 0) color = src->m;
 					src++;
 					rx++;
 					/* Because of the scaling it might happen we read outside the buffer. Avoid that. */
 					if (rx == sprite->width) break;
 				}
-				/* If more than 12.5% of the pixels are non-transparent, make thisone non-transparent too */
-				if (count < ScaleByZoom(1, (ZoomLevel)i) / 8) color = 0;
 
 				if (last_color == 0 || color == 0) {
 					if (count_index != 0) {
--- a/src/blitter/8bpp_optimized.hpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/blitter/8bpp_optimized.hpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1,6 +1,6 @@
 /* $Id$ */
 
-/** @file 8bpp_nice.hpp */
+/** @file 8bpp_optimized.hpp */
 
 #ifndef BLITTER_8BPP_OPTIMIZED_HPP
 #define BLITTER_8BPP_OPTIMIZED_HPP
@@ -20,7 +20,7 @@
 
 class FBlitter_8bppOptimized: public BlitterFactory<FBlitter_8bppOptimized> {
 public:
-	/* virtual */ const char *GetName() { return "8bpp-optimzed"; }
+	/* virtual */ const char *GetName() { return "8bpp-optimized"; }
 
 	/* virtual */ const char *GetDescription() { return "8bpp Optimized Blitter (compression + all-ZoomLevel cache)"; }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/blitter/8bpp_simple.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -0,0 +1,67 @@
+/* $Id$ */
+
+/** @file 8bpp_simple.cpp */
+
+#include "../stdafx.h"
+#include "../zoom.hpp"
+#include "../gfx.h"
+#include "8bpp_simple.hpp"
+
+static FBlitter_8bppSimple iFBlitter_8bppSimple;
+
+void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
+{
+	const byte *src, *src_line;
+	Pixel8 *dst, *dst_line;
+
+	/* Find where to start reading in the source sprite */
+	src_line = (const byte *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
+	dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
+
+	for (int y = 0; y < bp->height; y++) {
+		dst = dst_line;
+		dst_line += bp->pitch;
+
+		src = src_line;
+		src_line += bp->sprite_width * ScaleByZoom(1, zoom);
+
+		for (int x = 0; x < bp->width; x++) {
+			uint color = 0;
+
+			switch (mode) {
+				case BM_COLOUR_REMAP:
+					color = bp->remap[*src];
+					break;
+
+				case BM_TRANSPARENT:
+					if (*src != 0) color = bp->remap[*dst];
+					break;
+
+				default:
+					color = *src;
+					break;
+			}
+			if (color != 0) *dst = color;
+			dst++;
+			src += ScaleByZoom(1, zoom);
+		}
+	}
+}
+
+Sprite *Blitter_8bppSimple::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
+{
+	Sprite *dest_sprite;
+	dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sprite->height * sprite->width);;
+
+	dest_sprite->height = sprite->height;
+	dest_sprite->width  = sprite->width;
+	dest_sprite->x_offs = sprite->x_offs;
+	dest_sprite->y_offs = sprite->y_offs;
+
+	/* Copy over only the 'remap' channel, as that is what we care about in 8bpp */
+	for (int i = 0; i < sprite->height * sprite->width; i++) {
+		dest_sprite->data[i] = sprite->data[i].m;
+	}
+
+	return dest_sprite;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/blitter/8bpp_simple.hpp	Tue Jun 12 19:52:26 2007 +0000
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/** @file 8bpp_simple.hpp */
+
+#ifndef BLITTER_8BPP_SIMPLE_HPP
+#define BLITTER_8BPP_SIMPLE_HPP
+
+#include "blitter.hpp"
+
+typedef Pixel Pixel8;
+
+class Blitter_8bppSimple : public Blitter {
+public:
+	uint8 GetScreenDepth() { return 8; }
+
+	void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+
+	Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+};
+
+class FBlitter_8bppSimple: public BlitterFactory<FBlitter_8bppSimple> {
+public:
+	/* virtual */ const char *GetName() { return "8bpp-simple"; }
+
+	/* virtual */ const char *GetDescription() { return "8bpp Simple Blitter (relative slow, but never wrong)"; }
+
+	/* virtual */ Blitter *CreateInstance() { return new Blitter_8bppSimple(); }
+};
+
+#endif /* BLITTER_8BPP_SIMPLE_HPP */
--- a/src/blitter/8bpp_slow.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#include "../stdafx.h"
-#include "../zoom.hpp"
-#include "../gfx.h"
-#include "8bpp_slow.hpp"
-
-static FBlitter_8bppSimple iFBlitter_8bppSimple;
-
-void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
-{
-	const byte *src, *src_line;
-	Pixel8 *dst, *dst_line;
-
-	/* Find where to start reading in the source sprite */
-	src_line = (const byte *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
-	dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
-
-	for (int y = 0; y < bp->height; y++) {
-		dst = dst_line;
-		dst_line += bp->pitch;
-
-		src = src_line;
-		src_line += bp->sprite_width * ScaleByZoom(1, zoom);
-
-		for (int x = 0; x < bp->width; x++) {
-			uint color = 0;
-
-			switch (mode) {
-				case BM_COLOUR_REMAP:
-					color = bp->remap[*src];
-					break;
-
-				case BM_TRANSPARENT:
-					if (*src != 0) color = bp->remap[*dst];
-					break;
-
-				default:
-					color = *src;
-					break;
-			}
-			if (color != 0) *dst = color;
-			dst++;
-			src += ScaleByZoom(1, zoom);
-		}
-	}
-}
-
-Sprite *Blitter_8bppSimple::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
-{
-	Sprite *dest_sprite;
-	dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sprite->height * sprite->width);;
-
-	dest_sprite->height = sprite->height;
-	dest_sprite->width  = sprite->width;
-	dest_sprite->x_offs = sprite->x_offs;
-	dest_sprite->y_offs = sprite->y_offs;
-
-	/* Copy over only the 'remap' channel, as that is what we care about in 8bpp */
-	for (int i = 0; i < sprite->height * sprite->width; i++) {
-		dest_sprite->data[i] = sprite->data[i].m;
-	}
-
-	return dest_sprite;
-}
--- a/src/blitter/8bpp_slow.hpp	Tue Jun 12 18:02:11 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/* $Id$ */
-
-/** @file 8bpp.hpp */
-
-#ifndef BLITTER_8BPP_SIMPLE_HPP
-#define BLITTER_8BPP_SIMPLE_HPP
-
-#include "blitter.hpp"
-
-typedef Pixel Pixel8;
-
-class Blitter_8bppSimple : public Blitter {
-public:
-	uint8 GetScreenDepth() { return 8; }
-
-	void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
-
-	Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
-};
-
-class FBlitter_8bppSimple: public BlitterFactory<FBlitter_8bppSimple> {
-public:
-	/* virtual */ const char *GetName() { return "8bpp-simple"; }
-
-	/* virtual */ const char *GetDescription() { return "8bpp Simple Blitter (relative slow, but never wrong)"; }
-
-	/* virtual */ Blitter *CreateInstance() { return new Blitter_8bppSimple(); }
-};
-
-#endif /* BLITTER_8BPP_SIMPLE_HPP */
--- a/src/depot_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/depot_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -184,7 +184,7 @@
 			DrawStringRightAligned(w->widget[DEPOT_WIDGET_MATRIX].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter
 			break;
 
-		case VEH_ROAD:     DrawRoadVehImage( v, x + 24, sprite_y, WP(w, depot_d).sel); break;
+		case VEH_ROAD:     DrawRoadVehImage( v, x + 24, sprite_y, 1, WP(w, depot_d).sel); break;
 		case VEH_SHIP:     DrawShipImage(    v, x + 19, sprite_y - 1, WP(w, depot_d).sel); break;
 		case VEH_AIRCRAFT: {
 			const Sprite *spr = GetSprite(GetAircraftImage(v, DIR_W));
--- a/src/economy.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/economy.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -30,6 +30,7 @@
 #include "vehicle_gui.h"
 #include "ai/ai.h"
 #include "train.h"
+#include "roadveh.h"
 #include "aircraft.h"
 #include "newgrf_engine.h"
 #include "newgrf_sound.h"
@@ -340,7 +341,7 @@
 			if (v->owner == new_player) {
 				switch (v->type) {
 					case VEH_TRAIN:    if (IsFrontEngine(v)) num_train++; break;
-					case VEH_ROAD:     num_road++; break;
+					case VEH_ROAD:     if (IsRoadVehFront(v)) num_road++; break;
 					case VEH_SHIP:     num_ship++; break;
 					case VEH_AIRCRAFT: if (IsNormalAircraft(v)) num_aircraft++; break;
 					default: break;
@@ -354,14 +355,37 @@
 					DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 					DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
 					DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
-					DeleteVehicle(v);
+
+					if (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && IsFreeWagon(v))) {
+						switch (v->type) {
+							default: NOT_REACHED();
+
+							case VEH_TRAIN: {
+								Vehicle *u = v;
+								do {
+									Vehicle *next = GetNextVehicle(u);
+									DeleteVehicle(u);
+									u = next;
+								} while (u != NULL);
+							} break;
+
+							case VEH_ROAD:
+							case VEH_SHIP:
+								DeleteVehicle(v);
+								break;
+
+							case VEH_AIRCRAFT:
+								DeleteVehicleChain(v);
+								break;
+						}
+					}
 				} else {
 					v->owner = new_player;
 					v->group_id = DEFAULT_GROUP;
 					if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++;
 					switch (v->type) {
 						case VEH_TRAIN:    if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
-						case VEH_ROAD:     v->unitnumber = ++num_road; break;
+						case VEH_ROAD:     if (IsRoadVehFront(v)) v->unitnumber = ++num_road; break;
 						case VEH_SHIP:     v->unitnumber = ++num_ship; break;
 						case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
 						default: NOT_REACHED();
--- a/src/fileio.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/fileio.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -394,3 +394,20 @@
 	FioCreateDirectory(_paths.scenario_dir);
 	FioCreateDirectory(_paths.heightmap_dir);
 }
+
+/**
+ * Sanitizes a filename, i.e. removes all illegal characters from it.
+ * @param filename the "\0" terminated filename
+ */
+void SanitizeFilename(char *filename)
+{
+	for (; *filename != '\0'; filename++) {
+		switch (*filename) {
+			/* The following characters are not allowed in filenames
+			 * on at least one of the supported operating systems: */
+			case ':': case '\\': case '*': case '?': case '/':
+				*filename = '_';
+				break;
+		}
+	}
+}
--- a/src/fileio.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/fileio.h	Tue Jun 12 19:52:26 2007 +0000
@@ -20,6 +20,7 @@
 bool FioCheckFileExists(const char *filename);
 void FioCreateDirectory(const char *filename);
 
+void SanitizeFilename(char *filename);
 void AppendPathSeparator(char *buf, size_t buflen);
 void DeterminePaths(const char *exe);
 
--- a/src/industry_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/industry_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1308,7 +1308,7 @@
 		/* check if an industry that accepts the same goods is nearby */
 		if (DistanceMax(tile, i->xy) <= 14 &&
 				indspec->accepts_cargo[0] != CT_INVALID &&
-				indspec->accepts_cargo[0] == indspec->accepts_cargo[0] && (
+				indspec->accepts_cargo[0] == GetIndustrySpec(i->type)->accepts_cargo[0] && (
 					_game_mode != GM_EDITOR ||
 					!_patches.same_industry_close ||
 					!_patches.multiple_industry_per_town
--- a/src/industry_map.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/industry_map.h	Tue Jun 12 19:52:26 2007 +0000
@@ -160,7 +160,7 @@
 	_m[t].m2 = index;
 	_m[t].m3 = 0;
 	_m[t].m4 = 0;
-	_m[t].m5 = gfx;
+	SetIndustryGfx(t, gfx);
 }
 
 /**
@@ -246,4 +246,45 @@
 	_m[tile].m3 = state;
 }
 
+/**
+ * Get the random bits for this tile.
+ * Used for grf callbacks
+ * @param tile TileIndex of the tile to query
+ * @pre IsTileType(tile, MP_INDUSTRY)
+ * @return requested bits
+ * @todo implement the storage in map array
+ */
+static inline byte GetIndustryRandomBits(TileIndex tile)
+{
+	assert(IsTileType(tile, MP_INDUSTRY));
+	return 0;
+}
+
+/**
+ * Get the activated triggers bits for this industry tile
+ * Used for grf callbacks
+ * @param tile TileIndex of the tile to query
+ * @pre IsTileType(tile, MP_INDUSTRY)
+ * @return requested triggers
+ * @todo implement the storage in map array
+ */
+static inline byte GetIndustryTriggers(TileIndex tile)
+{
+	assert(IsTileType(tile, MP_INDUSTRY));
+	return 0;
+}
+
+
+/**
+ * Set the activated triggers bits for this industry tile
+ * Used for grf callbacks
+ * @param tile TileIndex of the tile to query
+ * @pre IsTileType(tile, MP_INDUSTRY)
+ * @todo implement the storage in map array
+ */
+static inline void SetIndustryTriggers(TileIndex tile, byte triggers)
+{
+	assert(IsTileType(tile, MP_INDUSTRY));
+}
+
 #endif /* INDUSTRY_MAP_H */
--- a/src/lang/bulgarian.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/bulgarian.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2688,6 +2688,7 @@
 STR_8851_SHOW_CAPACITIES_OF_EACH                                :{BLACK}Капацитет на влаковата композиция
 STR_8852_SHOW_TOTAL_CARGO                                       :{BLACK}Общ капацитет на влака, разбит по типове товар
 STR_8852_ORDERS_LIST_CLICK_ON_ORDER                             :{BLACK}Пътен лист - натиснете върху назначение за маркиране. CTRL + натискане - центрира върху станцията
+STR_8853_SKIP_THE_CURRENT_ORDER                                 :
 STR_8854_DELETE_THE_HIGHLIGHTED                                 :{BLACK}Изтриване на избраното назначение
 STR_8855_MAKE_THE_HIGHLIGHTED_ORDER                             :{BLACK}Преминавай през избраното назначение без спиране
 STR_8856_INSERT_A_NEW_ORDER_BEFORE                              :{BLACK}Добавяне на назначение преди избраната или в края на списъка
@@ -2766,6 +2767,7 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Списък с избор на МПС-та - натисни върху МПС за информация
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Купи посоченото МПС
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Цена: {CURRENCY}{}Скорост: {VELOCITY}{}Оперативен разход: {CURRENCY}/год{}Вместимост: {CARGO}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Преименувай МПС-то
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Не може да преименуваш МПС-то...
--- a/src/lang/catalan.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/catalan.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -922,7 +922,7 @@
 STR_CURR_NLG                                                    :Florins Holandesos (NLG)
 STR_CURR_NOK                                                    :Corones Noruegues (NOK)
 STR_CURR_PLN                                                    :Zloty Polac (PLN)
-STR_CURR_ROL                                                    :Leu RomanÚs (ROL)
+STR_CURR_ROL                                                    :Leu Romanès (ROL)
 STR_CURR_RUR                                                    :Rubles Russos (RUR)
 STR_CURR_SIT                                                    :Eslovè Tolar (SIT)
 STR_CURR_SEK                                                    :Corones Sueques (SEK)
@@ -2624,8 +2624,8 @@
 STR_881A_TRAINS_CAN_ONLY_BE_ALTERED                             :{WHITE}Els trens només es poden modificar quan estan parats dins d'una cotxera
 STR_881B_TRAINS                                                 :{WHITE}{COMPANY} - {COMMA} Trens
 
-STR_881C_NEW_RAIL_VEHICLES                                      :{WHITE}Nous Vehicles
-STR_NEW_ELRAIL_VEHICLES                                         :{WHITE}Nous vehicles de Via Electrificada
+STR_881C_NEW_RAIL_VEHICLES                                      :{WHITE}Nous Trens
+STR_NEW_ELRAIL_VEHICLES                                         :{WHITE}Nous Trens de Via Electrificada
 STR_881D_NEW_MONORAIL_VEHICLES                                  :{WHITE}Nous Trens Monorail
 STR_881E_NEW_MAGLEV_VEHICLES                                    :{WHITE}Nous Trens Maglev
 STR_ALL_AVAIL_RAIL_VEHICLES                                     :{WHITE}Vehicles amb Vies
@@ -2733,7 +2733,7 @@
 
 STR_NEW_VEHICLE_NOW_AVAILABLE                                   :{BLACK}{BIGFONT}Nou {STRING} disponible!
 STR_NEW_VEHICLE_TYPE                                            :{BLACK}{BIGFONT}{STRING}
-STR_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE                         :{BLACK}Nou {STRING} disponible!  -  {STRING}
+STR_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE                         :{BLACK}Nou/Nova {STRING} disponible!  -  {STRING}
 
 ##id 0x9000
 STR_9000_ROAD_VEHICLE_IN_THE_WAY                                :{WHITE}Automòbil en camí
--- a/src/lang/czech.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/czech.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -1127,7 +1127,7 @@
 STR_CONFIG_PATCHES_LAND_GENERATOR                               :{LTBLUE}Tvůrce krajiny: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL                      :původní
 STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
-STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Maximální vzdálenost ropných rafinerií od okraje mapy {ORANGE}{STRING}
+STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Maximální vzdálenost ropných rafinerií od okraje mapy: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_SNOWLINE_HEIGHT                              :{LTBLUE}Výška sněhové čáry: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Členitost krajiny (jen TerraGenesis): {ORANGE}{STRING}
 STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :velmi rovná
@@ -2727,6 +2727,7 @@
 STR_8833_CAN_T_INSERT_NEW_ORDER                                 :{WHITE}Nemohu přidat nový příkaz
 STR_8834_CAN_T_DELETE_THIS_ORDER                                :{WHITE}Nemohu tento příkaz smazat...
 STR_8835_CAN_T_MODIFY_THIS_ORDER                                :{WHITE}Nemohu tento příkaz změnit...
+STR_CAN_T_MOVE_THIS_ORDER                                       :{WHITE}Nelze přesunout tento příkaz...
 STR_CAN_T_SKIP_ORDER                                            :{WHITE}Nelze přeskočit současný příkaz...
 STR_CAN_T_SKIP_TO_ORDER                                         :{WHITE}Nelze přeskočit na označený příkaz...
 STR_8837_CAN_T_MOVE_VEHICLE                                     :{WHITE}Nemohu přesunout vozidlo...
@@ -2839,6 +2840,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Seznam silničních vozidel - klepni na vozidlo pro informace
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Koupit označené vozidlo
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Cena: {CURRENCY}{}Rychlost: {VELOCITY}{}Cena provozu: {CURRENCY} ročně{}Kapacita: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Kapacita: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Přejmenovat silniční vozidlo
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Nelze přejmenovat silniční vozidlo...
--- a/src/lang/danish.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/danish.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2776,6 +2776,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Liste over køretøjstyper - klik på køretøj for information
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Byg det markerede køretøj
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Pris: {CURRENCY}{}Hastighed: {VELOCITY}{}Driftsomkostninger: {CURRENCY}/år{}Kapacitet: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Kapacitet: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Giv køretøjet et navn
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Kan ikke give køretøjet et navn...
--- a/src/lang/dutch.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/dutch.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2663,6 +2663,7 @@
 STR_8833_CAN_T_INSERT_NEW_ORDER                                 :{WHITE}Kan nieuwe order niet invoegen...
 STR_8834_CAN_T_DELETE_THIS_ORDER                                :{WHITE}Kan deze order niet verwijderen...
 STR_8835_CAN_T_MODIFY_THIS_ORDER                                :{WHITE}Kan deze order niet aanpassen...
+STR_CAN_T_MOVE_THIS_ORDER                                       :{WHITE}Kan deze order niet verplaatsen...
 STR_CAN_T_SKIP_ORDER                                            :{WHITE}Kan huidige order niet overslaan...
 STR_CAN_T_SKIP_TO_ORDER                                         :{WHITE}Kan geselecteerde order niet overslaan...
 STR_8837_CAN_T_MOVE_VEHICLE                                     :{WHITE}Kan voertuig niet verplaatsen...
--- a/src/lang/english.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/english.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2776,6 +2776,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Road vehicle selection list - click on vehicle for information
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Build the highlighted road vehicle
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Cost: {CURRENCY}{}Speed: {VELOCITY}{}Running Cost: {CURRENCY}/yr{}Capacity: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Capacity: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Name road vehicle
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Can't name road vehicle...
--- a/src/lang/estonian.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/estonian.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -450,12 +450,12 @@
 ############ range for menu starts
 STR_0154_OPERATING_PROFIT_GRAPH                                 :Opereerimiskasumi graafik
 STR_0155_INCOME_GRAPH                                           :Tulugraafik
-STR_0156_DELIVERED_CARGO_GRAPH                                  :Transporditud kauba graafik
+STR_0156_DELIVERED_CARGO_GRAPH                                  :Kohaleviidud kauba graafik
 STR_0157_PERFORMANCE_HISTORY_GRAPH                              :Tegevustulemuste graafik
 STR_0158_COMPANY_VALUE_GRAPH                                    :Firmaväärtuse graafik
 STR_0159_CARGO_PAYMENT_RATES                                    :Veotasude määrad
 STR_015A_COMPANY_LEAGUE_TABLE                                   :Ettevõtete edetabel
-STR_PERFORMANCE_DETAIL_MENU                                     :Üksikasjalik tulemusreiting
+STR_PERFORMANCE_DETAIL_MENU                                     :Üksikasjalik tulemushinnang
 ############ range for menu ends
 
 STR_015B_OPENTTD                                                :{WHITE}OpenTTD lisainfo
@@ -472,7 +472,7 @@
 STR_SORT_BY_POPULATION                                          :{BLACK}Rahvastik
 STR_SORT_BY_PRODUCTION                                          :{BLACK}Toodang
 STR_SORT_BY_TYPE                                                :{BLACK}Tüüp
-STR_SORT_BY_TRANSPORTED                                         :{BLACK}Transporditud
+STR_SORT_BY_TRANSPORTED                                         :{BLACK}Veetud
 STR_SORT_BY_NAME                                                :{BLACK}Nimi
 STR_SORT_BY_DROPDOWN_NAME                                       :Nimi
 STR_SORT_BY_DATE                                                :{BLACK}Daatum
@@ -561,7 +561,7 @@
 STR_STICKY_BUTTON                                               :{BLACK}Keela selle akna sulgemine 'Sulge kõik aknad' nupu klõpsamisel
 STR_RESIZE_BUTTON                                               :{BLACK}Kliki ja venita, et akna suurust muuta
 STR_SAVELOAD_HOME_BUTTON                                        :{BLACK}Vajuta siia, et minna praegusesse vaikimisi valitud salvestamise/laadimise kausta
-STR_018D_DEMOLISH_BUILDINGS_ETC                                 :{BLACK}Ehitiste jms. hävitamine
+STR_018D_DEMOLISH_BUILDINGS_ETC                                 :{BLACK}Rajatiste lammutamine
 STR_018E_LOWER_A_CORNER_OF_LAND                                 :{BLACK}Maapinna madaldamine
 STR_018F_RAISE_A_CORNER_OF_LAND                                 :{BLACK}Maapinna kõrgendamine
 STR_0190_SCROLL_BAR_SCROLLS_LIST                                :{BLACK}Kerimisriba - kerib nimistut üles/alla
@@ -864,12 +864,12 @@
 STR_FULL                                                        :Täielik
 STR_02BA                                                        :{SILVER}- -  {COMPANY}  - -
 STR_02BB_TOWN_DIRECTORY                                         :Linnanimistu
-STR_02BC_VEHICLE_DESIGN_NAMES                                   :{BLACK}Sõidukite disaini nimed
+STR_02BC_VEHICLE_DESIGN_NAMES                                   :{BLACK}Sõidukidisanide nimed
 STR_02BD                                                        :{BLACK}{STRING}
 STR_02BE_DEFAULT                                                :Vaikimisi valitud
 STR_02BF_CUSTOM                                                 :Omatehtud
 STR_02C0_SAVE_CUSTOM_NAMES                                      :{BLACK}Salvesta oma nimega
-STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION                         :{BLACK}Sõidukite disaininimede valik
+STR_02C1_VEHICLE_DESIGN_NAMES_SELECTION                         :{BLACK}Sõidukidisainide nimevalik
 STR_02C2_SAVE_CUSTOMIZED_VEHICLE                                :{BLACK}Salvesta omatehtud disaininimed
 
 STR_CHECKMARK                                                   :{CHECKMARK}
@@ -929,7 +929,7 @@
 STR_02EC                                                        :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 STR_02ED_SELECT_STYLE_OF_TOWN_NAMES                             :{BLACK}Vali linnanimede stiil
 
-STR_02F4_AUTOSAVE                                               :{BLACK}Automaatsalvestus
+STR_02F4_AUTOSAVE                                               :{BLACK}Isesalvestus
 STR_02F5                                                        :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 STR_02F6_SELECT_INTERVAL_BETWEEN                                :{BLACK}Vali intervall, mille järel isesalvestus toimub
 STR_02F7_OFF                                                    :Väljas
@@ -1048,7 +1048,7 @@
 STR_OPTIONS_SCREENSHOT_FORMAT_TIP                               :{BLACK}Valik, millises formaadis salvestatakse ekraanitõmmis
 
 STR_AUTOSAVE_1_MONTH                                            :Iga kuu
-STR_AUTOSAVE_FAILED                                             :{WHITE}Automaatsalvestus ebaõnnestus
+STR_AUTOSAVE_FAILED                                             :{WHITE}Isesalvestus ebaõnnestus
 
 STR_MONTH_JAN                                                   :Jaanuar
 STR_MONTH_FEB                                                   :Veebruar
@@ -1169,7 +1169,7 @@
 STR_CONFIG_PATCHES_LAND_GENERATOR                               :{LTBLUE}Maaala Generaator: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_LAND_GENERATOR_ORIGINAL                      :Algupärane
 STR_CONFIG_PATCHES_LAND_GENERATOR_TERRA_GENESIS                 :TerraGenesis
-STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Suurim kaugus kaardi äärest nafta puuraukudeni {ORANGE}{STRING}
+STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE                        :{LTBLUE}Suurim kaugus kaardiservast naftapuuraukudeni {ORANGE}{STRING}
 STR_CONFIG_PATCHES_SNOWLINE_HEIGHT                              :{LTBLUE}Lumepiiri kõrgus: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN                         :{LTBLUE}Maa mägisus (TerraGenesis ainult) : {ORANGE}{STRING}
 STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH             :Väga sile
@@ -1201,7 +1201,7 @@
 STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLL                           :Keri kaarti
 STR_CONFIG_PATCHES_SCROLLWHEEL_OFF                              :Väljas
 STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER                       :{LTBLUE}Kaardi kerimisrulliku kiirus: {ORANGE}{STRING}
-STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Automaatne mängu peatamine uue mängu alustamisel: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME                            :{LTBLUE}Mängu isepeatamine uue mängu alustamisel: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS                       :{LTBLUE}Kasuta laiendatud sõidukinimekirja: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_MAX_TRAINS                                   :{LTBLUE}Enim ronge mängija kohta: {ORANGE}{STRING}
@@ -1235,7 +1235,7 @@
 STR_CONFIG_PATCHES_SMOOTH_ECONOMY                               :{LTBLUE}Luba sujuv majandus (väiksemad muutused)
 STR_CONFIG_PATCHES_ALLOW_SHARES                                 :{LTBLUE}Luba teiste ettevõtete aktsiate ostmine
 STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY                         :{LTBLUE}Venitades rajatavate signaalide paigutustihedus: {ORANGE}{STRING} ühik(ut)
-STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Ehita semaforid automaatselt enne: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE                  :{LTBLUE}Ehita ise semaforid enne: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID                          :{WHITE}Stsenaariumiredaktor ei tunnista "ilma teedeta" linnaplaneeringut
 STR_CONFIG_PATCHES_TOWN_LAYOUT                                  :{LTBLUE}Vali linnale teedeplaneering: {ORANGE}{STRING}
@@ -1262,7 +1262,7 @@
 STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER                         :{LTBLUE}Algne linna suuruse kordaja: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_GUI                                          :{BLACK}Välimus
-STR_CONFIG_PATCHES_CONSTRUCTION                                 :{BLACK}Ehituskulud
+STR_CONFIG_PATCHES_CONSTRUCTION                                 :{BLACK}Ehitamine
 STR_CONFIG_PATCHES_VEHICLES                                     :{BLACK}Sõidukid
 STR_CONFIG_PATCHES_STATIONS                                     :{BLACK}Jaamad
 STR_CONFIG_PATCHES_ECONOMY                                      :{BLACK}Majandus
@@ -1807,7 +1807,7 @@
 STR_201D_OFFICE_BLOCK                                           :Büroohoone
 STR_201E_STADIUM                                                :Staadion
 STR_201F_OLD_HOUSES                                             :Vanad majad
-STR_2020_LOCAL_AUTHORITY                                        :{BLACK}Kohalik omavalitsus
+STR_2020_LOCAL_AUTHORITY                                        :{BLACK}Omavalitsus
 STR_2021_SHOW_INFORMATION_ON_LOCAL                              :{BLACK}Näita teavet kohaliku omavalitsuse kohta
 STR_2022_LOCAL_AUTHORITY                                        :{WHITE}{TOWN} kohalik omavalitsus
 STR_2023_TRANSPORT_COMPANY_RATINGS                              :{BLACK}Ettevõtete hinnangud:
@@ -1859,7 +1859,7 @@
 STR_2051_BUILD_A_STATUE_IN_HONOR                                :{WHITE}{STRING}{}{YELLOW} Oma ettevõtte auks kuju ehitamine.{} Hind: {CURRENCY}
 STR_2052_FUND_THE_CONSTRUCTION_OF                               :{WHITE}{STRING}{}{YELLOW} Uute ärihoonete ehitamise rahastamine selles linnas.{} Hind: {CURRENCY}
 STR_2053_BUY_1_YEAR_S_EXCLUSIVE                                 :{WHITE}{STRING}{}{YELLOW} Üheks aastaks monopoolsete veoõiguste ostmine selles linnas. Linna omavalitsus lubab reisijate ja kauba veoks kasutada ainult sinu jaamasid.{} Hind: {CURRENCY}
-STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC                         :{WHITE}{STRING}{}{YELLOW} Linna omavalitusele ettevõtu reitingu tõstmise eesmärgil altkäemaksu pakkumine. Vahele jäädes korral tuleb trahvi maksta.{} Hind: {CURRENCY}
+STR_TOWN_BRIBE_THE_LOCAL_AUTHORITY_DESC                         :{WHITE}{STRING}{}{YELLOW} Linna omavalitusele ettevõtte hinnangu tõstmise eesmärgil altkäemaksu pakkumine. Vahele jäädes tuleb trahvi maksta.{} Hind: {CURRENCY}
 STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING                       :{BIGFONT}{BLACK}Liikluskaos linnas {TOWN}!{}{}Ettevõtte {COMPANY} poolt rahastatud teedeehitus tekitab 6 kuu jooksul maanteedel liiklushäireid!
 STR_2056                                                        :{TINYFONT}{WHITE}{TOWN}
 STR_2057                                                        :{ORANGE}{TOWN}{BLACK} ({COMMA})
@@ -2026,7 +2026,7 @@
 STR_480A_STEEL_MILL                                             :terasetööstus
 STR_480B_FARM                                                   :talu
 STR_480C_COPPER_ORE_MINE                                        :vasemaagikaevandus
-STR_480D_OIL_WELLS                                              :nafta puurauk
+STR_480D_OIL_WELLS                                              :naftapuurauk
 STR_480E_BANK                                                   :pank
 STR_480F_FOOD_PROCESSING_PLANT                                  :toiduainetetööstus
 STR_4810_PAPER_MILL                                             :paberivabrik
@@ -2269,7 +2269,7 @@
 STR_700E_FINANCES                                               :{WHITE}{COMPANY} rahavoogude aruanne {BLACK}{PLAYERNAME}
 STR_700F_EXPENDITURE_INCOME                                     :{WHITE}Kulud/tulud
 STR_7010                                                        :{WHITE}{NUM}
-STR_7011_CONSTRUCTION                                           :{GOLD}Ehitamine
+STR_7011_CONSTRUCTION                                           :{GOLD}Ehituskulud
 STR_7012_NEW_VEHICLES                                           :{GOLD}Uus veerem
 STR_7013_TRAIN_RUNNING_COSTS                                    :{GOLD}Rongide käituskulud
 STR_7014_ROAD_VEH_RUNNING_COSTS                                 :{GOLD}Mootorsõidukite käituskulud
@@ -2330,7 +2330,7 @@
 STR_704D_SHOW_KEY_TO_GRAPHS                                     :{BLACK}Näita selgitust graafikute juures
 STR_704E_KEY_TO_COMPANY_GRAPHS                                  :{WHITE}Ettevõttegraafiku selgitus
 STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY                           :{BLACK}Klõpsa, et ettevõtte graafikut sisse ja välja lülitada
-STR_7050_UNITS_OF_CARGO_DELIVERED                               :{WHITE}Transporditud veoste kogus
+STR_7050_UNITS_OF_CARGO_DELIVERED                               :{WHITE}Veetud veoste kogus
 STR_7051_COMPANY_PERFORMANCE_RATINGS                            :{WHITE}Ettevõtte tegevushinnang (suurim hinnang saab olla 1000)
 STR_7052_COMPANY_VALUES                                         :{WHITE}Firmaväärtus
 STR_7053_COMPANY_LEAGUE_TABLE                                   :{WHITE}Ettevõtete edetabel
@@ -2386,11 +2386,11 @@
 STR_7080_PROTECTED                                              :{WHITE}See ettevõtte pole veel piisavalt vana, et aktsiaid vahetada...
 
 STR_LIVERY_DEFAULT                                              :Firmavärv
-STR_LIVERY_STEAM                                                :Aurumootor
-STR_LIVERY_DIESEL                                               :Diiselmootor
-STR_LIVERY_ELECTRIC                                             :Elektrivedur
-STR_LIVERY_MONORAIL                                             :Monorelsi Mootor
-STR_LIVERY_MAGLEV                                               :Maglev'i Mootor
+STR_LIVERY_STEAM                                                :Aurumootorvedur
+STR_LIVERY_DIESEL                                               :Diiselmootorvedur
+STR_LIVERY_ELECTRIC                                             :Elektrimootorvedur
+STR_LIVERY_MONORAIL                                             :Monorelss-mootorvedur
+STR_LIVERY_MAGLEV                                               :Elektromagneetiline mootorvedur
 STR_LIVERY_DMU                                                  :DMU
 STR_LIVERY_EMU                                                  :EMU
 STR_LIVERY_PASSENGER_WAGON_STEAM                                :Reisivagun (auru)
@@ -2399,22 +2399,22 @@
 STR_LIVERY_FREIGHT_WAGON                                        :Kaubavagun
 STR_LIVERY_BUS                                                  :Buss
 STR_LIVERY_TRUCK                                                :Veoauto
-STR_LIVERY_PASSENGER_SHIP                                       :Reisijate Praam
+STR_LIVERY_PASSENGER_SHIP                                       :Reisipraam
 STR_LIVERY_FREIGHT_SHIP                                         :Kaubalaev
 STR_LIVERY_HELICOPTER                                           :Helikopter
-STR_LIVERY_SMALL_PLANE                                          :Väike Lennuk
-STR_LIVERY_LARGE_PLANE                                          :Suur Lennuk
+STR_LIVERY_SMALL_PLANE                                          :Väikelennuk
+STR_LIVERY_LARGE_PLANE                                          :Suurlennuk
 STR_LIVERY_PASSENGER_TRAM                                       :Reisitramm
 STR_LIVERY_FREIGHT_TRAM                                         :Kaubatramm
 
-STR_LIVERY_GENERAL_TIP                                          :{BLACK}Näita üldiseid värvivalikuid
+STR_LIVERY_GENERAL_TIP                                          :{BLACK}Näita üldiseid värvistikke
 STR_LIVERY_TRAIN_TIP                                            :{BLACK}Näita rongide värvistikke
-STR_LIVERY_ROADVEH_TIP                                          :{BLACK}Näita mootorsõidukite värvivalikuid
-STR_LIVERY_SHIP_TIP                                             :{BLACK}Näita laevade värvivalikuid
-STR_LIVERY_AIRCRAFT_TIP                                         :{BLACK}Näita lennukite värvivalikuid
-STR_LIVERY_PRIMARY_TIP                                          :{BLACK}Vali põhivärv valitud skeemile
-STR_LIVERY_SECONDARY_TIP                                        :{BLACK}Vali teine värv valitud skeemile
-STR_LIVERY_PANEL_TIP                                            :{BLACK}Vali värvivalik, mida muuta - või mitu kasutades CTRL+hiireklõps kombinatsiooni. Klõpsa kastil, et muuta värvivaliku kasutust.
+STR_LIVERY_ROADVEH_TIP                                          :{BLACK}Näita mootorsõidukite värvistikke
+STR_LIVERY_SHIP_TIP                                             :{BLACK}Näita laevavärvistikke
+STR_LIVERY_AIRCRAFT_TIP                                         :{BLACK}Näita lennukivärvistikke
+STR_LIVERY_PRIMARY_TIP                                          :{BLACK}Vali põhivärv värvistikule
+STR_LIVERY_SECONDARY_TIP                                        :{BLACK}Vali teine värv valitud värvistikule
+STR_LIVERY_PANEL_TIP                                            :{BLACK}Vali muudetav värvivalik - või mitu CTRL+klõps abil. Klõpsa kastil, et muuta värvivaliku kasutust.
 
 ##id 0x8000
 STR_8000_KIRBY_PAUL_TANK_STEAM                                  :Kirby Paul Tank (auruvedur)
@@ -2876,6 +2876,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Mootorsõiduki valimisnimekiri - andmete saamiseks klõpsa sõidukile
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Ehita valitud mootorsõiduk
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Hind: {CURRENCY}{}Tippkiirus: {VELOCITY}{}Käituskulud: {CURRENCY}/aastas{}Kandevõime: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Kandevõime: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Nimeta mootorsõiduk ümber
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Ei saa maanteveokit ümber nimetada...
@@ -3057,8 +3059,8 @@
 STR_BRIBE_FAILED_2                                              :{WHITE}kohalike uurijate poolt avastatud
 STR_BUILD_DATE                                                  :{BLACK}Ehitatud: {LTBLUE}{DATE_LONG}
 
-STR_PERFORMANCE_DETAIL                                          :{WHITE}Detailne tegevuse reiting
-STR_PERFORMANCE_DETAIL_KEY                                      :{BLACK}Detailne
+STR_PERFORMANCE_DETAIL                                          :{WHITE}Üksikasjalik tulemushinnang
+STR_PERFORMANCE_DETAIL_KEY                                      :{BLACK}Üksikasjalik
 STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY                          :{BLACK}({CURRCOMPACT}/{CURRCOMPACT})
 STR_PERFORMANCE_DETAIL_AMOUNT_INT                               :{BLACK}({COMMA}/{COMMA})
 STR_PERFORMANCE_DETAIL_PERCENT                                  :{WHITE}{NUM}%
@@ -3069,21 +3071,21 @@
 STR_PERFORMANCE_DETAIL_MIN_PROFIT                               :{BLACK}Vähim kasum:
 STR_PERFORMANCE_DETAIL_MIN_INCOME                               :{BLACK}Vähim tulu:
 STR_PERFORMANCE_DETAIL_MAX_INCOME                               :{BLACK}Suurim tulu:
-STR_PERFORMANCE_DETAIL_DELIVERED                                :{BLACK}Transporditud:
+STR_PERFORMANCE_DETAIL_DELIVERED                                :{BLACK}Veetud:
 STR_PERFORMANCE_DETAIL_CARGO                                    :{BLACK}Kaupu:
 STR_PERFORMANCE_DETAIL_MONEY                                    :{BLACK}Raha:
 STR_PERFORMANCE_DETAIL_LOAN                                     :{BLACK}Laen:
 STR_PERFORMANCE_DETAIL_TOTAL                                    :{BLACK}Kokku:
 ############ End of order list
 STR_PERFORMANCE_DETAIL_VEHICLES_TIP                             :{BLACK}Veeremit kokku; sisaldab sõidutee-, rööbastee- ja õhusõidukeid, ning laevu
-STR_PERFORMANCE_DETAIL_STATIONS_TIP                             :{BLACK}Jaamablokkide arv. Iga osa jaamast (nt. rongijaam, bussipeatus, lennujaam) loetakse eraldi, isegi kui naad on ühendatud üheks jaamaks
+STR_PERFORMANCE_DETAIL_STATIONS_TIP                             :{BLACK}Jaamablokkide arv. Iga osa jaamast (nt. raudteejaam, bussipeatus, lennujaam) loetakse eraldi, isegi kui naad on ühendatud üheks jaamaks
 STR_PERFORMANCE_DETAIL_MIN_PROFIT_TIP                           :{BLACK}Kõige väiksema tuluga sõiduki kasum (kõikidest vähemalt 2 aastastest veovahenditest)
 STR_PERFORMANCE_DETAIL_MIN_INCOME_TIP                           :{BLACK}Väikseim kuukasum viimase 12 kvartali jooksul
 STR_PERFORMANCE_DETAIL_MAX_INCOME_TIP                           :{BLACK}Suurim kuukasum viimase 12 kvartali jooksul
 STR_PERFORMANCE_DETAIL_DELIVERED_TIP                            :{BLACK}Kauba arv, mis on veatud viimase 4 kvartali jooksul
 STR_PERFORMANCE_DETAIL_CARGO_TIP                                :{BLACK}Kauba arv, mis on veatud viimasel kvartalil
 STR_PERFORMANCE_DETAIL_MONEY_TIP                                :{BLACK}Raha arv, mis on sellel firmal pangas
-STR_PERFORMANCE_DETAIL_LOAN_TIP                                 :{BLACK}Raha arv, mida see firma on võtnud laenuks
+STR_PERFORMANCE_DETAIL_LOAN_TIP                                 :{BLACK}Selle ettevõtte kogulaen
 STR_PERFORMANCE_DETAIL_TOTAL_TIP                                :{BLACK}Kokku punkte võimalikest punktidest
 
 STR_NEWGRF_SETTINGS_BUTTON                                      :{BLACK}NewGRF seaded
@@ -3347,7 +3349,7 @@
 
 ########
 
-STR_FEEDER_CARGO_VALUE                                          :{BLACK}Kanna Raha: {LTBLUE}{CURRENCY}
+STR_FEEDER_CARGO_VALUE                                          :{BLACK}Ülekantud tulu: {LTBLUE}{CURRENCY}
 STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD                            :{WHITE}...see tee on omatud linna poolt
 STR_DRIVE_THROUGH_ERROR_DIRECTION                               :{WHITE}...tee on vales suunas
 
--- a/src/lang/french.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/french.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2664,6 +2664,7 @@
 STR_8833_CAN_T_INSERT_NEW_ORDER                                 :{WHITE}Impossible d'insérer un nouvel ordre...
 STR_8834_CAN_T_DELETE_THIS_ORDER                                :{WHITE}Impossible de supprimer cet ordre...
 STR_8835_CAN_T_MODIFY_THIS_ORDER                                :{WHITE}Impossible de modifier cet ordre...
+STR_CAN_T_MOVE_THIS_ORDER                                       :{WHITE}Impossible de déplacer cet ordre...
 STR_CAN_T_SKIP_ORDER                                            :{WHITE}Impossible de sauter l'ordre courant...
 STR_CAN_T_SKIP_TO_ORDER                                         :{WHITE}Impossible de sauter l'ordre sélectionné...
 STR_8837_CAN_T_MOVE_VEHICLE                                     :{WHITE}Impossible de déplacer le véhicule...
@@ -2776,6 +2777,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Choix du véhicule - cliquer sur un véhicule pour obtenir des informations
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Construire le véhicule sélectionné
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Prix: {CURRENCY}{}Vitesse: {VELOCITY}{}Coût d'entretien: {CURRENCY}/an{}Capacité: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Capacité: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Renommer le véhicule
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Impossible de renommer le véhicule...
--- a/src/lang/hungarian.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/hungarian.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2879,6 +2879,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Közúti jármű kiválasztása - kattints egy járműre az adataihoz
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}A kijelölt közúti jármű megvétele
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Ár: {CURRENCY}{}Sebesség: {VELOCITY}{}Működtetési költség: {CURRENCY}/év{}Kapacitás: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Kapacitás: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Közúti jármű átnevezése
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Nem nevezheted át a közúti járművet...
--- a/src/lang/italian.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/italian.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2778,6 +2778,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Elenco selezione automezzi - fare clic su un veicolo per informazioni
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Costruisce l'automezzo selezionato
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Costo: {CURRENCY}{}Velocità: {VELOCITY}{}Costo d'esercizio: {CURRENCY}/anno{}Capacità: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Capacità: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Rinomina l'automezzo
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Impossibile rinominare l'automezzo...
--- a/src/lang/korean.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/korean.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2777,6 +2777,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}자동차 선택 목록 - 차량 정보를 보려면 클릭
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}선택한 자동차 만들기
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}가격: {CURRENCY}{}속력: {VELOCITY}{}운행비용: {CURRENCY}/년{}수송량: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}수송량: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}자동차 이름 지정
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}자동차의 이름을 지정할 수 없습니다...
--- a/src/lang/romanian.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/romanian.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -817,9 +817,9 @@
 STR_02E0_CURRENCY_UNITS                                         :{BLACK}Unităţi monetare
 STR_02E1                                                        :{BLACK}{SKIP}{STRING}
 STR_02E2_CURRENCY_UNITS_SELECTION                               :{BLACK}Alege unitatea monetară
-STR_MEASURING_UNITS                                             :{BLACK}Unitãti de mãsurã
+STR_MEASURING_UNITS                                             :{BLACK}Unităţi de măsură
 STR_02E4                                                        :{BLACK}{SKIP}{SKIP}{STRING}
-STR_MEASURING_UNITS_SELECTION                                   :{BLACK}Selectie unitãti de mãsurã
+STR_MEASURING_UNITS_SELECTION                                   :{BLACK}Selecţie unităţi de măsură
 STR_02E6_ROAD_VEHICLES                                          :{BLACK}Autovehiculele circulă...
 STR_02E7                                                        :{BLACK}{SKIP}{SKIP}{SKIP}{STRING}
 STR_02E8_SELECT_SIDE_OF_ROAD_FOR                                :{BLACK}Alege partea străzii pe care se circulă
@@ -1309,9 +1309,9 @@
 STR_NETWORK_MULTIPLAYER                                         :{WHITE}Multiplayer
 
 STR_NETWORK_PLAYER_NAME                                         :{BLACK}Numele jucãtorului:
-STR_NETWORK_ENTER_NAME_TIP                                      :{BLACK}Acesta este numele prin care te vor identifica ceilalti
+STR_NETWORK_ENTER_NAME_TIP                                      :{BLACK}Acesta este numele prin care te vor identifica ceilalţi
 STR_NETWORK_CONNECTION                                          :{BLACK}Conexiune:
-STR_NETWORK_CONNECTION_TIP                                      :{BLACK}Alege intre un joc pe internet si unul pe LAN
+STR_NETWORK_CONNECTION_TIP                                      :{BLACK}Alege între un joc pe internet şi unul în reţea (LAN)
 
 STR_NETWORK_START_SERVER                                        :{BLACK}Porneste serverul
 STR_NETWORK_START_SERVER_TIP                                    :{BLACK}Porneste un server propriu
@@ -1321,32 +1321,32 @@
 STR_NETWORK_INFO_ICONS_TIP                                      :{BLACK}Limba, versiunea serverului, etc.
 STR_NETWORK_CLICK_GAME_TO_SELECT                                :{BLACK}Click pe un joc din listã pentru a-l selecta
 
-STR_NETWORK_FIND_SERVER                                         :{BLACK}Cautã server
-STR_NETWORK_FIND_SERVER_TIP                                     :{BLACK}Cautã un server în retea
-STR_NETWORK_ADD_SERVER                                          :{BLACK}Adauga un server
-STR_NETWORK_ADD_SERVER_TIP                                      :{BLACK}Adauga un server pe lista care va fi verificata pentru jocuri active
+STR_NETWORK_FIND_SERVER                                         :{BLACK}Caută server
+STR_NETWORK_FIND_SERVER_TIP                                     :{BLACK}Caută un server în reţea
+STR_NETWORK_ADD_SERVER                                          :{BLACK}Adaugă un server
+STR_NETWORK_ADD_SERVER_TIP                                      :{BLACK}Adaugă un server pe lista care va fi verificată pentru jocuri active
 STR_NETWORK_ENTER_IP                                            :{BLACK}Introdu IP-ul serverului
 
 STR_NETWORK_GENERAL_ONLINE                                      :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA}
-STR_NETWORK_CLIENTS_CAPTION                                     :{BLACK}Clienti
+STR_NETWORK_CLIENTS_CAPTION                                     :{BLACK}Clienţi
 STR_NETWORK_CLIENTS_CAPTION_TIP                                 :{BLACK}Clienti online / Nr. max. clienti
 STR_NETWORK_GAME_INFO                                           :{SILVER}INFO JOC
 STR_ORANGE                                                      :{ORANGE}{STRING}
-STR_NETWORK_CLIENTS                                             :{SILVER}Clienti:  {WHITE}{COMMA} / {COMMA} - {COMMA} / {COMMA}
+STR_NETWORK_CLIENTS                                             :{SILVER}Clienţi:  {WHITE}{COMMA} / {COMMA} - {COMMA} / {COMMA}
 STR_NETWORK_LANGUAGE                                            :{SILVER}Limba:  {WHITE}{STRING}
 STR_NETWORK_TILESET                                             :{SILVER}Tileset:  {WHITE}{STRING}
 STR_NETWORK_MAP_SIZE                                            :{SILVER}Marimea hartii:  {WHITE}{COMMA}x{COMMA}
 STR_NETWORK_SERVER_VERSION                                      :{SILVER}Versiune server:  {WHITE}{STRING}
 STR_NETWORK_SERVER_ADDRESS                                      :{SILVER}Adresa serverului:  {WHITE}{STRING} : {NUM}
 STR_NETWORK_START_DATE                                          :{SILVER}Data de inceput:  {WHITE}{DATE_SHORT}
-STR_NETWORK_CURRENT_DATE                                        :{SILVER}Data curenta:  {WHITE}{DATE_SHORT}
+STR_NETWORK_CURRENT_DATE                                        :{SILVER}Data curentă:  {WHITE}{DATE_SHORT}
 STR_NETWORK_PASSWORD                                            :{SILVER}Protejat cu parola!
 STR_NETWORK_SERVER_OFFLINE                                      :{SILVER}SERVER OFFLINE
 STR_NETWORK_SERVER_FULL                                         :{SILVER}SERVER PLIN
 STR_NETWORK_VERSION_MISMATCH                                    :{SILVER}VERSIUNE DIFERITA
-STR_NETWORK_GRF_MISMATCH                                        :{SILVER}NEWGRF NEPOTRIVIRE
+STR_NETWORK_GRF_MISMATCH                                        :{SILVER}NEPOTRIVIRE NEWGRF
 
-STR_NETWORK_JOIN_GAME                                           :{BLACK}Intrã în joc
+STR_NETWORK_JOIN_GAME                                           :{BLACK}Intră în joc
 
 
 STR_NETWORK_START_GAME_WINDOW                                   :{WHITE}Începe un joc nou
@@ -1363,7 +1363,7 @@
 STR_NETWORK_LAN                                                 :LAN
 STR_NETWORK_INTERNET                                            :Internet
 STR_NETWORK_LAN_INTERNET                                        :LAN / Internet
-STR_NETWORK_INTERNET_ADVERTISE                                  :Internet (fa reclama)
+STR_NETWORK_INTERNET_ADVERTISE                                  :Internet (fă reclamă)
 STR_NETWORK_COMBO2                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 STR_NETWORK_0_PLAYERS                                           :0 jucãtori
 STR_NETWORK_1_PLAYERS                                           :1 jucãtor
@@ -1382,8 +1382,8 @@
 STR_NETWORK_NUMBER_OF_SPECTATORS                                :{BLACK}Maxim spectatori:
 STR_NETWORK_NUMBER_OF_SPECTATORS_TIP                            :{BLACK}Limiteazã serverul la un anumit numãr de spectatori
 STR_NETWORK_COMBO4                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
-STR_NETWORK_LANGUAGE_SPOKEN                                     :{BLACK}Limba vorbita:
-STR_NETWORK_LANGUAGE_TIP                                        :{BLACK}Ceilalti jucatori vor sti in ce limba se discuta per server.
+STR_NETWORK_LANGUAGE_SPOKEN                                     :{BLACK}Limba vorbită:
+STR_NETWORK_LANGUAGE_TIP                                        :{BLACK}Ceilalţi jucători vor şti în ce limbă se discută pe server.
 STR_NETWORK_COMBO5                                              :{BLACK}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{SKIP}{STRING}
 STR_NETWORK_START_GAME                                          :{BLACK}Începe jocul
 STR_NETWORK_START_GAME_TIP                                      :{BLACK}Incepe un joc nou in retea cu o harta aleatoare sau intr-un scenariu
@@ -1395,6 +1395,31 @@
 STR_NETWORK_LANG_ENGLISH                                        :Engleza
 STR_NETWORK_LANG_GERMAN                                         :Germana
 STR_NETWORK_LANG_FRENCH                                         :Franceza
+STR_NETWORK_LANG_BRAZILIAN                                      :Braziliana
+STR_NETWORK_LANG_BULGARIAN                                      :Bulgara
+STR_NETWORK_LANG_CHINESE                                        :Chineza
+STR_NETWORK_LANG_CZECH                                          :Ceha
+STR_NETWORK_LANG_DANISH                                         :Daneza
+STR_NETWORK_LANG_DUTCH                                          :Olandeza
+STR_NETWORK_LANG_ESPERANTO                                      :Esperanto
+STR_NETWORK_LANG_FINNISH                                        :Finlandeza
+STR_NETWORK_LANG_HUNGARIAN                                      :Ungara
+STR_NETWORK_LANG_ICELANDIC                                      :Islandeza
+STR_NETWORK_LANG_ITALIAN                                        :Italiana
+STR_NETWORK_LANG_JAPANESE                                       :Japoneza
+STR_NETWORK_LANG_KOREAN                                         :Coreana
+STR_NETWORK_LANG_LITHUANIAN                                     :Lituaniana
+STR_NETWORK_LANG_NORWEGIAN                                      :Norvegiana
+STR_NETWORK_LANG_POLISH                                         :Poloneza
+STR_NETWORK_LANG_PORTUGUESE                                     :Portugheza
+STR_NETWORK_LANG_ROMANIAN                                       :Româna
+STR_NETWORK_LANG_RUSSIAN                                        :Rusa
+STR_NETWORK_LANG_SLOVAK                                         :Slovaca
+STR_NETWORK_LANG_SLOVENIAN                                      :Slovena
+STR_NETWORK_LANG_SPANISH                                        :Spaniola
+STR_NETWORK_LANG_SWEDISH                                        :Suedeza
+STR_NETWORK_LANG_TURKISH                                        :Turca
+STR_NETWORK_LANG_UKRAINIAN                                      :Ucrainiana
 ############ End of leave-in-this-order
 
 STR_NETWORK_GAME_LOBBY                                          :{WHITE}Chatul jocului multiplayer
@@ -1405,8 +1430,8 @@
 STR_NETWORK_NEW_COMPANY_TIP                                     :{BLACK}Fondeazã o nouã companie
 STR_NETWORK_SPECTATE_GAME                                       :{BLACK}Modul spectator
 STR_NETWORK_SPECTATE_GAME_TIP                                   :{BLACK}Vizioneazã un joc din pozitia unui spectator
-STR_NETWORK_JOIN_COMPANY                                        :{BLACK}Alatura-te companiei
-STR_NETWORK_JOIN_COMPANY_TIP                                    :{BLACK}Ajuta la conducerea acestei companii
+STR_NETWORK_JOIN_COMPANY                                        :{BLACK}Alătură-te companiei
+STR_NETWORK_JOIN_COMPANY_TIP                                    :{BLACK}Ajută la conducerea acestei companii
 STR_NETWORK_REFRESH                                             :{BLACK}Actualizeaza serverul
 STR_NETWORK_REFRESH_TIP                                         :{BLACK}Actualizeaza informatiile despre server
 
@@ -1415,7 +1440,7 @@
 STR_NETWORK_COMPANY_NAME                                        :{SILVER}Numele companiei:  {WHITE}{STRING}
 STR_NETWORK_INAUGURATION_YEAR                                   :{SILVER}Inaugurarea:  {WHITE}{NUM}
 STR_NETWORK_VALUE                                               :{SILVER}Valoarea companiei:  {WHITE}{CURRENCY64}
-STR_NETWORK_CURRENT_BALANCE                                     :{SILVER}Balanta curenta:  {WHITE}{CURRENCY64}
+STR_NETWORK_CURRENT_BALANCE                                     :{SILVER}Balanţa curentă:  {WHITE}{CURRENCY64}
 STR_NETWORK_LAST_YEARS_INCOME                                   :{SILVER}Venituri anul trecut:  {WHITE}{CURRENCY64}
 STR_NETWORK_PERFORMANCE                                         :{SILVER}Performanta:  {WHITE}{NUM}
 
@@ -1427,64 +1452,64 @@
 
 ############ Leave those lines in this order!!
 STR_NETWORK_CONNECTING_1                                        :{BLACK}(1/6) Conectare..
-STR_NETWORK_CONNECTING_2                                        :{BLACK}(2/6) Authorizare..
-STR_NETWORK_CONNECTING_3                                        :{BLACK}(3/6) Asteptati..
-STR_NETWORK_CONNECTING_4                                        :{BLACK}(4/6) Descarcare harta..
+STR_NETWORK_CONNECTING_2                                        :{BLACK}(2/6) Autorizare..
+STR_NETWORK_CONNECTING_3                                        :{BLACK}(3/6) Aşteptaţi..
+STR_NETWORK_CONNECTING_4                                        :{BLACK}(4/6) Descărcare harta..
 STR_NETWORK_CONNECTING_5                                        :{BLACK}(5/6) Prelucrare date..
-STR_NETWORK_CONNECTING_6                                        :{BLACK}(6/6) Inregistrare...
+STR_NETWORK_CONNECTING_6                                        :{BLACK}(6/6) Înregistrare...
 
 STR_NETWORK_CONNECTING_SPECIAL_1                                :{BLACK}Preluare info joc..
 STR_NETWORK_CONNECTING_SPECIAL_2                                :{BLACK}Preluare info companie..
 ############ End of leave-in-this-order
-STR_NETWORK_CONNECTING_WAITING                                  :{BLACK}{NUM} client{P "" i} inaintea noastra
-STR_NETWORK_CONNECTING_DOWNLOADING                              :{BLACK}{NUM} / {NUM} kbytes descarcati pana acum
+STR_NETWORK_CONNECTING_WAITING                                  :{BLACK}{NUM} clien{P t ţi} înaintea noastră
+STR_NETWORK_CONNECTING_DOWNLOADING                              :{BLACK}{NUM} / {NUM} kbytes descărcaţi până acum
 
 STR_NETWORK_DISCONNECT                                          :{BLACK}Deconectare
 
-STR_NETWORK_GIVE_MONEY_CAPTION                                  :{WHITE}Introdu suma de bani pe care vrei sa o cedezi
+STR_NETWORK_GIVE_MONEY_CAPTION                                  :{WHITE}Introdu suma de bani pe care vrei să o cedezi
 STR_NETWORK_NEED_GAME_PASSWORD_CAPTION                          :{WHITE}Server protejat. Introdu parola
 STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION                       :{WHITE}Companie protejata. Introdu parola
-STR_NETWORK_CLIENT_LIST                                         :{WHITE}Lista de clienti
+STR_NETWORK_CLIENT_LIST                                         :{WHITE}Lista de clienţi
 
-STR_NETWORK_ERR_NOTAVAILABLE                                    :{WHITE}Nu a fost detectatã o placã de retea valabilã
-STR_NETWORK_ERR_NOSERVER                                        :{WHITE}Nu a fost gãsit nici un joc în retea
-STR_NETWORK_ERR_NOCONNECTION                                    :{WHITE}Serverul nu a rãspuns cererii
+STR_NETWORK_ERR_NOTAVAILABLE                                    :{WHITE}Nu a fost detectată o placă sau jocul a fost compilat fără ENABLE_NETWORK
+STR_NETWORK_ERR_NOSERVER                                        :{WHITE}Nu a fost găsit nici un joc în reţea
+STR_NETWORK_ERR_NOCONNECTION                                    :{WHITE}Serverul nu a răspuns cererii
 STR_NETWORK_ERR_NEWGRF_MISMATCH                                 :{WHITE} Nu m-am putut conecta din cauza unei nepotriviri NewGRF
-STR_NETWORK_ERR_DESYNC                                          :{WHITE} Sincronizarea jocului in retea a esuat.
-STR_NETWORK_ERR_LOSTCONNECTION                                  :{WHITE} Conexiunea jocului in reatea a fost intrerupta.
-STR_NETWORK_ERR_SAVEGAMEERROR                                   :{WHITE} Nu am reusit sa incarc jocul-server salvat.
+STR_NETWORK_ERR_DESYNC                                          :{WHITE} Sincronizarea jocului în reţea a eşuat.
+STR_NETWORK_ERR_LOSTCONNECTION                                  :{WHITE} Conexiunea jocului în reţea a fost întreruptă.
+STR_NETWORK_ERR_SAVEGAMEERROR                                   :{WHITE} Nu am reuşit să încarc jocul-server salvat.
 STR_NETWORK_ERR_SERVER_START                                    :{WHITE}Nu pot porni serverul.
 STR_NETWORK_ERR_CLIENT_START                                    :{WHITE}Nu pot efectua conectarea.
 STR_NETWORK_ERR_TIMEOUT                                         :{WHITE} Conexiunea #{NUM} a expirat.
-STR_NETWORK_ERR_SERVER_ERROR                                    :{WHITE}Eroare de protocol. Conexiunea a fost inchisa.
-STR_NETWORK_ERR_WRONG_REVISION                                  :{WHITE}Versiunea acestui client este diferita de cea a serverului.
-STR_NETWORK_ERR_WRONG_PASSWORD                                  :{WHITE}Parola gresita.
+STR_NETWORK_ERR_SERVER_ERROR                                    :{WHITE}Eroare de protocol. Conexiunea a fost închisă.
+STR_NETWORK_ERR_WRONG_REVISION                                  :{WHITE}Versiunea acestui client este diferită de cea a serverului.
+STR_NETWORK_ERR_WRONG_PASSWORD                                  :{WHITE}Parola greşită.
 STR_NETWORK_ERR_SERVER_FULL                                     :{WHITE}Serverul este plin
-STR_NETWORK_ERR_SERVER_BANNED                                   :{WHITE} Acessul tau este interzis pe acest server
-STR_NETWORK_ERR_KICKED                                          :{WHITE}Ai fost dat afara de pe server
+STR_NETWORK_ERR_SERVER_BANNED                                   :{WHITE} Acessul tău este interzis pe acest server
+STR_NETWORK_ERR_KICKED                                          :{WHITE}Ai fost dat afară de pe server
 STR_NETWORK_ERR_CHEATER                                         :{WHITE} Cheat-urile nu sunt permise pe acest server
 
-STR_NETWORK_ERR_LEFT                                            :a parasit jocul
+STR_NETWORK_ERR_LEFT                                            :a părăsit jocul
 ############ Leave those lines in this order!!
-STR_NETWORK_ERR_CLIENT_GENERAL                                  :eroare generala
+STR_NETWORK_ERR_CLIENT_GENERAL                                  :eroare generală
 STR_NETWORK_ERR_CLIENT_DESYNC                                   :eroare de desincronizare
-STR_NETWORK_ERR_CLIENT_SAVEGAME                                 :nu pot incarca harta
-STR_NETWORK_ERR_CLIENT_CONNECTION_LOST                          :conexiune pierduta
+STR_NETWORK_ERR_CLIENT_SAVEGAME                                 :nu pot încărca harta
+STR_NETWORK_ERR_CLIENT_CONNECTION_LOST                          :conexiune pierdută
 STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR                           :eroare de protocol
 STR_NETWORK_ERR_CLIENT_NEWGRF_MISMATCH                          :Nepotrivire NewGRF
 STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED                           :neautorizat
 STR_NETWORK_ERR_CLIENT_NOT_EXPECTED                             :primit pachet ciudat
-STR_NETWORK_ERR_CLIENT_WRONG_REVISION                           :versiune incorecta
+STR_NETWORK_ERR_CLIENT_WRONG_REVISION                           :versiune incorectă
 STR_NETWORK_ERR_CLIENT_NAME_IN_USE                              :nume folosit deja
-STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD                           :parola gresita
-STR_NETWORK_ERR_CLIENT_PLAYER_MISMATCH                          :player-id in DoCommand gresit
-STR_NETWORK_ERR_CLIENT_KICKED                                   :dat afara de pe server
-STR_NETWORK_ERR_CLIENT_CHEATER                                  :a incercat sa foloseasca un cheat
+STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD                           :parola greşită
+STR_NETWORK_ERR_CLIENT_PLAYER_MISMATCH                          :player-id greşit în DoCommand
+STR_NETWORK_ERR_CLIENT_KICKED                                   :dat afară de pe server
+STR_NETWORK_ERR_CLIENT_CHEATER                                  :a încercat să folosească un cheat
 STR_NETWORK_ERR_CLIENT_SERVER_FULL                              :server plin
 ############ End of leave-in-this-order
-STR_NETWORK_CLIENT_JOINED                                       :a intrat in joc
-STR_NETWORK_GIVE_MONEY                                          :ti-a dat o suma de bani ({CURRENCY})
-STR_NETWORK_GAVE_MONEY_AWAY                                     :ai donat o suma de bani companiei {STRING} ({CURRENCY})
+STR_NETWORK_CLIENT_JOINED                                       :a intrat în joc
+STR_NETWORK_GIVE_MONEY                                          :ţi-a dat o sumă de bani ({CURRENCY})
+STR_NETWORK_GAVE_MONEY_AWAY                                     :ai donat o sumă de bani companiei {STRING} ({CURRENCY})
 STR_NETWORK_CHAT_COMPANY_CAPTION                                :[Team] :
 STR_NETWORK_CHAT_COMPANY                                        :[Team] {STRING}: {GRAY}{STRING}
 STR_NETWORK_CHAT_TO_COMPANY                                     :[Team] To {STRING}: {GRAY}{STRING}
@@ -1503,9 +1528,9 @@
 
 STR_NETWORK_CLIENTLIST_NONE                                     :(none)
 STR_NETWORK_CLIENTLIST_KICK                                     :Kick
-STR_NETWORK_CLIENTLIST_GIVE_MONEY                               :Doneaza bani
-STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL                             :Vorbeste catre toti
-STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY                         :Vorbeste catre companie
+STR_NETWORK_CLIENTLIST_GIVE_MONEY                               :Donează bani
+STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL                             :Vorbeşte către toţi
+STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY                         :Vorbeşte către companie
 STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT                          :Mesaj privat
 
 
@@ -2154,7 +2179,7 @@
 STR_7025_OPERATING_PROFIT_GRAPH                                 :{WHITE}Graficul profitului din operare
 STR_7026_BANK_BALANCE                                           :{WHITE}Balanţă curentă
 STR_7027_LOAN                                                   :{WHITE}Credite
-STR_MAX_LOAN                                                    :{WHITE}Limita credite:  {BLACK}{CURRENCY64}
+STR_MAX_LOAN                                                    :{WHITE}Limită credite:  {BLACK}{CURRENCY64}
 STR_7028                                                        :{BLACK}{CURRENCY64}
 STR_7029_BORROW                                                 :{BLACK}Împrumută {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
 STR_702A_REPAY                                                  :{BLACK}Plăteşte înapoi {SKIP}{SKIP}{SKIP}{SKIP}{CURRENCY}
@@ -2534,7 +2559,7 @@
 STR_80FE_GURU_X2_HELICOPTER                                     :Elicopter Guru X2
 STR_80FF_POWERNAUT_HELICOPTER                                   :Elicopter Powernaut
 STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE                       :{WHITE}Mesaj de la producătorul de vehicule
-STR_8101_WE_HAVE_JUST_DESIGNED_A                                :{GOLD}Am creat un nou tip de {STRING}. Ati fi interesati de folosirea exclusivã pentru un an a acestui vehicul, astfel ca noi sa putem observa rezultatele înaintea lansãrii oficiale?
+STR_8101_WE_HAVE_JUST_DESIGNED_A                                :{GOLD}Am creat un nou tip de {STRING}. Aţi fi interesaţi de folosirea exclusivă pentru un an a acestui vehicul, astfel ca noi să-i putem observa performanţele înaintea lansării oficiale?
 STR_8102_RAILROAD_LOCOMOTIVE                                    :locomotivă
 STR_8103_ROAD_VEHICLE                                           :autovehicul
 STR_8104_AIRCRAFT                                               :aeronavă
@@ -2623,6 +2648,7 @@
 STR_8833_CAN_T_INSERT_NEW_ORDER                                 :{WHITE}Nu pot adăuga o comandă nouă...
 STR_8834_CAN_T_DELETE_THIS_ORDER                                :{WHITE}Nu pot şterge această comandă...
 STR_8835_CAN_T_MODIFY_THIS_ORDER                                :{WHITE}Nu pot modifica această comandă...
+STR_CAN_T_SKIP_TO_ORDER                                         :{WHITE}Nu pot sări la ordinul selectat...
 STR_8837_CAN_T_MOVE_VEHICLE                                     :{WHITE}Nu pot muta vehiculul...
 STR_REAR_ENGINE_FOLLOW_FRONT_ERROR                              :{WHITE}Al doilea vagon+motor va avea mereu aceeasi destinatie ca si primul
 STR_8838_N_A                                                    :N/A{SKIP}
@@ -2654,6 +2680,7 @@
 STR_8851_SHOW_CAPACITIES_OF_EACH                                :{BLACK}Afiseazã capacitãtile componentelor trenului
 STR_8852_SHOW_TOTAL_CARGO                                       :{BLACK}Afiseazã capacitãtile totale ale trenului, diferentiate pe tip de încãrcãturã
 STR_8852_ORDERS_LIST_CLICK_ON_ORDER                             :{BLACK}Lista de comenzi - clic pe comandã pentru a o selecta
+STR_8853_SKIP_THE_CURRENT_ORDER                                 :
 STR_8854_DELETE_THE_HIGHLIGHTED                                 :{BLACK}Sterge comanda selectatã
 STR_8855_MAKE_THE_HIGHLIGHTED_ORDER                             :{BLACK}Circulă fără oprire până la destinaţia selectată
 STR_8856_INSERT_A_NEW_ORDER_BEFORE                              :{BLACK}Introdu o comandã înaintea celei selectate sau adaugã o comandã la sfârsitul listei
@@ -2732,6 +2759,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Lista selectie vehicule rutiere - apasa pe vehicul pentru informatii
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Cumpãrã autovehiculul selectat
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Pret: {CURRENCY}{}Vitezã: {VELOCITY}{}Cost de rulare: {CURRENCY}/an{}Capacitate: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Capacitate: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Numele autovehiculului
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Nu pot redenumi autovehiculul...
@@ -3080,7 +3109,7 @@
 STR_MASS_START_DEPOT_SHIP_TIP                                   :{BLACK}Click pt pornirea tuturor vaselor din depou
 STR_MASS_START_HANGAR_TIP                                       :{BLACK}Click pt pornirea tuturor aeronavelor din hangar
 
-STR_MASS_STOP_LIST_TIP                                          :{BLACK}Click pt oprirea tuturor vehiculelor din lista
+STR_MASS_STOP_LIST_TIP                                          :{BLACK}Click pt oprirea tuturor vehiculelor din listă
 STR_MASS_START_LIST_TIP                                         :{BLACK}Apasa pentru pornirea tuturor vehiclulelor din lista
 
 STR_SHORT_DATE                                                  :{WHITE}{DATE_TINY}
@@ -3192,9 +3221,9 @@
 ############ Tooltip measurment
 
 STR_MEASURE_LENGTH                                              :{BLACK}Lungime: {NUM}
-STR_MEASURE_AREA                                                :{BLACK}Suprafata: {NUM} x {NUM}
-STR_MEASURE_LENGTH_HEIGHTDIFF                                   :{BLACK}Lungime: {NUM}{}Diferenta inaltime: {NUM} m
-STR_MEASURE_AREA_HEIGHTDIFF                                     :{BLACK}Suprafata: {NUM} x {NUM}{}Diferenta inaltime: {NUM} m
+STR_MEASURE_AREA                                                :{BLACK}Suprafaţa: {NUM} x {NUM}
+STR_MEASURE_LENGTH_HEIGHTDIFF                                   :{BLACK}Lungime: {NUM}{}Diferenţa de înălţime: {NUM} m
+STR_MEASURE_AREA_HEIGHTDIFF                                     :{BLACK}Suprafaţa: {NUM} x {NUM}{}Diferenţa de înălţime: {NUM} m
 
 ############ Date formatting
 STR_DATE_TINY                                                   :{STRING}-{STRING}-{NUM}
--- a/src/lang/swedish.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/swedish.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -1397,6 +1397,31 @@
 STR_NETWORK_LANG_ENGLISH                                        :Engelska
 STR_NETWORK_LANG_GERMAN                                         :Tyska
 STR_NETWORK_LANG_FRENCH                                         :Franska
+STR_NETWORK_LANG_BRAZILIAN                                      :Brasiliansk
+STR_NETWORK_LANG_BULGARIAN                                      :Belgisk
+STR_NETWORK_LANG_CHINESE                                        :Kines
+STR_NETWORK_LANG_CZECH                                          :Tjeckisk
+STR_NETWORK_LANG_DANISH                                         :Dansk
+STR_NETWORK_LANG_DUTCH                                          :Holländsk
+STR_NETWORK_LANG_ESPERANTO                                      :Spansk
+STR_NETWORK_LANG_FINNISH                                        :Finsk
+STR_NETWORK_LANG_HUNGARIAN                                      :Ungersk
+STR_NETWORK_LANG_ICELANDIC                                      :Isländsk
+STR_NETWORK_LANG_ITALIAN                                        :Italiensk
+STR_NETWORK_LANG_JAPANESE                                       :Japansk
+STR_NETWORK_LANG_KOREAN                                         :Koreansk
+STR_NETWORK_LANG_LITHUANIAN                                     :Litauisk
+STR_NETWORK_LANG_NORWEGIAN                                      :Norsk
+STR_NETWORK_LANG_POLISH                                         :Polsk
+STR_NETWORK_LANG_PORTUGUESE                                     :Portugisisk
+STR_NETWORK_LANG_ROMANIAN                                       :Rumänsk
+STR_NETWORK_LANG_RUSSIAN                                        :Rysk
+STR_NETWORK_LANG_SLOVAK                                         :Slovakisk
+STR_NETWORK_LANG_SLOVENIAN                                      :Slovensk
+STR_NETWORK_LANG_SPANISH                                        :Spansk
+STR_NETWORK_LANG_SWEDISH                                        :Svensk
+STR_NETWORK_LANG_TURKISH                                        :Turkisk
+STR_NETWORK_LANG_UKRAINIAN                                      :Ukrainsk
 ############ End of leave-in-this-order
 
 STR_NETWORK_GAME_LOBBY                                          :{WHITE}Nätverksspel
@@ -2638,6 +2663,9 @@
 STR_8833_CAN_T_INSERT_NEW_ORDER                                 :{WHITE}Kan inte sätta in ny order...
 STR_8834_CAN_T_DELETE_THIS_ORDER                                :{WHITE}Kan inte ta bort denna order...
 STR_8835_CAN_T_MODIFY_THIS_ORDER                                :{WHITE}Kan inte ändra denna order...
+STR_CAN_T_MOVE_THIS_ORDER                                       :{WHITE}Kan inte flytta denna order...
+STR_CAN_T_SKIP_ORDER                                            :{WHITE}Kan inte hoppa över nuvarande order...
+STR_CAN_T_SKIP_TO_ORDER                                         :{WHITE}Kan inte hoppa över till vald order...
 STR_8837_CAN_T_MOVE_VEHICLE                                     :{WHITE}Kan inte flytta fordon...
 STR_REAR_ENGINE_FOLLOW_FRONT_ERROR                              :{WHITE}Det bakre loket kommer alltid följa med det tillhörande främre loket
 STR_8838_N_A                                                    :N/A{SKIP}
@@ -2669,6 +2697,7 @@
 STR_8851_SHOW_CAPACITIES_OF_EACH                                :{BLACK}Visa kapaciteter för varje fordon
 STR_8852_SHOW_TOTAL_CARGO                                       :{BLACK}Visa tågets totala kapacitet, separera för typ av gods
 STR_8852_ORDERS_LIST_CLICK_ON_ORDER                             :{BLACK}Orderlista - klicka på order för att markera det
+STR_8853_SKIP_THE_CURRENT_ORDER                                 :{BLACK}Hoppa över nuvarande order och starta nästa. CTRL + klick hoppar över till vald order
 STR_8854_DELETE_THE_HIGHLIGHTED                                 :{BLACK}Ta bort markerad order
 STR_8855_MAKE_THE_HIGHLIGHTED_ORDER                             :{BLACK}Gör markerad order non-stop
 STR_8856_INSERT_A_NEW_ORDER_BEFORE                              :{BLACK}Infoga ny order före markerad order, eller lägg till i slutet av listan
@@ -2747,6 +2776,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Vägfordonslista - klicka på fordon för information
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Bygg markerat vägfordon
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Kostnad: {CURRENCY}{}Hastighet: {VELOCITY}{}Löpande kostnad: {CURRENCY}/år{}Kapacitet: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Kapacitet: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Byt namn på vägfordon
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Kan inte byta namn på vägfordon...
--- a/src/lang/ukrainian.txt	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/lang/ukrainian.txt	Tue Jun 12 19:52:26 2007 +0000
@@ -2826,6 +2826,7 @@
 STR_8833_CAN_T_INSERT_NEW_ORDER                                 :{WHITE}Неможливо додати наказ...
 STR_8834_CAN_T_DELETE_THIS_ORDER                                :{WHITE}Неможливо видалити наказ...
 STR_8835_CAN_T_MODIFY_THIS_ORDER                                :{WHITE}Неможливо змінити наказ...
+STR_CAN_T_MOVE_THIS_ORDER                                       :{WHITE}Не можна перемістити цей наказ...
 STR_CAN_T_SKIP_ORDER                                            :{WHITE}Не можна пропустити цей наказ...
 STR_CAN_T_SKIP_TO_ORDER                                         :{WHITE}Не можна перейти до цього наказу...
 STR_8837_CAN_T_MOVE_VEHICLE                                     :{WHITE}Неможливо перемістити транспорт...
@@ -2938,6 +2939,8 @@
 STR_9026_ROAD_VEHICLE_SELECTION                                 :{BLACK}Список авто - натисніть на авто для інформації
 STR_9027_BUILD_THE_HIGHLIGHTED_ROAD                             :{BLACK}Будувати вибране авто
 STR_902A_COST_SPEED_RUNNING_COST                                :{BLACK}Ціна: {CURRENCY}{}Швидкість: {VELOCITY}{}Транспортні витрати: {CURRENCY}/рік{}Місткість: {CARGO}
+STR_ARTICULATED_RV_CAPACITY                                     :{BLACK}Місткість: {LTBLUE}
+STR_BARE_CARGO                                                  :{CARGO}
 
 STR_902C_NAME_ROAD_VEHICLE                                      :{WHITE}Назвати авто
 STR_902D_CAN_T_NAME_ROAD_VEHICLE                                :{WHITE}Неможливо назвати авто...
--- a/src/main_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/main_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -30,6 +30,7 @@
 #include "waypoint.h"
 #include "variables.h"
 #include "train.h"
+#include "roadveh.h"
 #include "unmovable_map.h"
 #include "string.h"
 #include "screenshot.h"
@@ -849,7 +850,7 @@
 	int dis = -1;
 
 	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_ROAD) CLRBIT(dis, v->owner);
+		if (v->type == VEH_ROAD && IsRoadVehFront(v)) CLRBIT(dis, v->owner);
 	}
 	PopupMainPlayerToolbMenu(w, 332, 14, dis);
 }
--- a/src/misc_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/misc_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -35,6 +35,7 @@
 #include "date.h"
 #include "cargotype.h"
 #include "player_face.h"
+#include "fileio.h"
 
 #include "fios.h"
 /* Variables to display file lists */
@@ -1396,6 +1397,7 @@
 	SetDParam(1, p->name_2);
 	SetDParam(2, _date);
 	GetString(_edit_str_buf, STR_4004, lastof(_edit_str_buf));
+	SanitizeFilename(_edit_str_buf);
 }
 
 extern void StartupEngines();
--- a/src/newgrf.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -18,6 +18,7 @@
 #include "newgrf.h"
 #include "variables.h"
 #include "string.h"
+#include "strings.h"
 #include "table/strings.h"
 #include "bridge.h"
 #include "town.h"
@@ -3412,15 +3413,6 @@
 		STR_NEWGRF_ERROR_MSG_FATAL
 	};
 
-	/* AddGRFString expects the string to be referred to by an id in the newgrf
-	 * file. Errors messages are never referred to however, so invent ids that
-	 * are unlikely to be reached in a newgrf file so they don't overwrite
-	 * anything else. */
-	enum {
-		MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1,
-		MESSAGE_DATA_ID   = MAX_UVALUE(StringID)
-	};
-
 	if (!check_length(len, 6, "GRFLoadError")) return;
 
 	/* For now we can only show one message per newgrf file. */
@@ -3432,6 +3424,9 @@
 	byte message_id = grf_load_byte(&buf);
 	len -= 4;
 
+	/* Skip the error if it isn't valid for the current language. */
+	if (!CheckGrfLangID(lang, _cur_grffile->grf_version)) return;
+
 	/* Skip the error until the activation stage unless bit 7 of the severity
 	 * is set. */
 	if (!HASBIT(severity, 7) && _cur_stage == GLS_INIT) {
@@ -3461,7 +3456,6 @@
 		return;
 	}
 
-	bool new_scheme = _cur_grffile->grf_version >= 7;
 	GRFError *error = CallocT<GRFError>(1);
 
 	error->severity = sevstr[severity];
@@ -3471,7 +3465,7 @@
 		const char *message = grf_load_string(&buf, len);
 		len -= (strlen(message) + 1);
 
-		error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED);
+		error->custom_message = TranslateTTDPatchCodes(message);
 	} else {
 		error->message = msgstr[message_id];
 	}
@@ -3480,7 +3474,7 @@
 		const char *data = grf_load_string(&buf, len);
 		len -= (strlen(data) + 1);
 
-		error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED);
+		error->data = TranslateTTDPatchCodes(data);
 	}
 
 	/* Only two parameter numbers can be used in the string. */
@@ -4116,8 +4110,12 @@
 		/* If the file is not active but will be activated later, give an error
 		 * and disable this file. */
 		GRFError *error = CallocT<GRFError>(1);
+
+		char tmp[256];
+		GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
+		error->data = strdup(tmp);
+
 		error->message  = STR_NEWGRF_ERROR_LOAD_AFTER;
-		error->data     = STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE;
 		error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
 		if (_cur_grfconfig->error != NULL) free(_cur_grfconfig->error);
@@ -4268,8 +4266,8 @@
 	                   |                                        (0 << 0x13)  // followvehicle
 	                   |                                        (1 << 0x14)  // trams
 	                   |                                        (0 << 0x15)  // enhancetunnels
-	                   |                                        (0 << 0x16)  // shortrvs
-	                   |                                        (0 << 0x17)  // articulatedrvs
+	                   |                                        (1 << 0x16)  // shortrvs
+	                   |                                        (1 << 0x17)  // articulatedrvs
 	                   |                                        (1 << 0x1E); // variablerunningcosts
 }
 
@@ -4398,6 +4396,18 @@
 	_cur_grffile   = NULL;
 }
 
+static void ResetNewGRFErrors()
+{
+	for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
+		if (!HASBIT(c->flags, GCF_COPY) && c->error != NULL) {
+			free(c->error->custom_message);
+			free(c->error->data);
+			free(c->error);
+			c->error = NULL;
+		}
+	}
+}
+
 /**
  * Reset all NewGRF loaded data
  * TODO
@@ -4465,6 +4475,9 @@
 	/* Reset NewGRF files */
 	ResetNewGRF();
 
+	/* Reset NewGRF errors. */
+	ResetNewGRFErrors();
+
 	/* Add engine type to engine data. This is needed for the refit precalculation. */
 	AddTypeToEngines();
 
--- a/src/newgrf_config.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_config.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -97,7 +97,12 @@
 		free((*config)->full_path);
 		free((*config)->name);
 		free((*config)->info);
-		free((*config)->error);
+
+		if ((*config)->error != NULL) {
+			free((*config)->error->custom_message);
+			free((*config)->error->data);
+			free((*config)->error);
+		}
 	}
 	free(*config);
 	*config = NULL;
@@ -134,6 +139,8 @@
 		if (src->error     != NULL) {
 			c->error = CallocT<GRFError>(1);
 			memcpy(c->error, src->error, sizeof(GRFError));
+			if (src->error->data != NULL) c->error->data = strdup(src->error->data);
+			if (src->error->custom_message != NULL) c->error->custom_message = strdup(src->error->custom_message);
 		}
 
 		*dst = c;
--- a/src/newgrf_config.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_config.h	Tue Jun 12 19:52:26 2007 +0000
@@ -36,8 +36,9 @@
 };
 
 struct GRFError {
+	char *custom_message;
+	char *data;
 	StringID message;
-	StringID data;
 	StringID severity;
 	uint8 num_params;
 	uint8 param_number[2];
--- a/src/newgrf_engine.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_engine.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -507,7 +507,7 @@
 	switch (variable) {
 		case 0x40: // Get length of consist
 		case 0x41: // Get length of same consecutive wagons
-			if (v->type != VEH_TRAIN) return 1;
+			if (!v->HasFront()) return 1;
 
 			{
 				const Vehicle* u;
@@ -830,7 +830,7 @@
 	res->ResolveReal   = &VehicleResolveReal;
 
 	res->u.vehicle.self   = v;
-	res->u.vehicle.parent = (v != NULL && v->type == VEH_TRAIN) ? GetFirstVehicleInChain(v) : v;
+	res->u.vehicle.parent = (v != NULL && v->HasFront()) ? GetFirstVehicleInChain(v) : v;
 
 	res->u.vehicle.self_type = engine_type;
 
--- a/src/newgrf_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -48,7 +48,7 @@
 
 	if (c->error != NULL) {
 		SetDParamStr(0, c->filename);
-		SetDParam(1, c->error->data);
+		SetDParamStr(1, c->error->data);
 		for (uint i = 0; i < c->error->num_params; i++) {
 			uint32 param = 0;
 			byte param_number = c->error->param_number[i];
@@ -59,7 +59,7 @@
 		}
 
 		char message[512];
-		GetString(message, c->error->message, lastof(message));
+		GetString(message, c->error->custom_message != NULL ? BindCString(c->error->custom_message) : c->error->message, lastof(message));
 
 		SetDParamStr(0, message);
 		y += DrawStringMultiLine(x, y, c->error->severity, w, bottom - y);
--- a/src/newgrf_industries.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_industries.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -8,6 +8,7 @@
 #include "functions.h"
 #include "macros.h"
 #include "industry.h"
+#include "industry_map.h"
 #include "newgrf.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_spritegroup.h"
@@ -59,6 +60,51 @@
 	return best_dist;
 }
 
+/** Make an analysis of a tile and check for its belonging to the same
+ * industry, and/or the same grf file
+ * @param new_tile TileIndex of the tile to query
+ * @param old_tile TileINdex of teh reference tile
+ * @param i Industry to which old_tile belongs to
+ * @return value encoded as per NFO specs */
+uint32 GetIndustryIDAtOffset(TileIndex new_tile, TileIndex old_tile, const Industry *i)
+{
+	if (IsTileType(new_tile, MP_INDUSTRY)) {  // Is this an industry tile?
+
+		if (GetIndustryIndex(new_tile) == i->index) {  // Does it belong to the same industry?
+			IndustryGfx gfx = GetIndustryGfx(new_tile);
+			const IndustryTileSpec *indtsp = GetIndustryTileSpec(gfx);
+			const IndustryTileSpec *indold = GetIndustryTileSpec(GetIndustryGfx(old_tile));
+
+			if (gfx < NEW_INDUSTRYOFFSET) {  // Does it belongs to an old type?
+				/* It is an old tile.  We have to see if it's been overriden */
+				if (indtsp->grf_prop.override == INVALID_INDUSTRYTILE) {  // has it been overridden?
+					return 0xFF << 8 | gfx; // no. Tag FF + the gfx id of that tile
+				} else { // yes.  FInd out if it is from the same grf file or not
+					const IndustryTileSpec *old_tile_ovr = GetIndustryTileSpec(indtsp->grf_prop.override);
+
+					if (old_tile_ovr->grf_prop.grffile->grfid == indold->grf_prop.grffile->grfid) {
+						return old_tile_ovr->grf_prop.local_id; // same grf file
+					} else {
+						return 0xFFFE; // not the same grf file
+					}
+				}
+			} else {
+				if (indtsp->grf_prop.spritegroup != NULL) {  // tile has a spritegroup ?
+					if (indtsp->grf_prop.grffile->grfid == indold->grf_prop.grffile->grfid) {  // same industry, same grf ?
+						return indtsp->grf_prop.local_id;
+					} else {
+						return 0xFFFE;  // Defined in another grf file
+					}
+				} else {  // tile has no spritegroup
+					return 0xFF << 8 | indtsp->grf_prop.subst_id;  // so just give him the substitute
+				}
+			}
+		}
+	}
+
+	return 0xFFFF; // tile is not an industry one or  does not belong to the current industry
+}
+
 /** This function implements the industries variables that newGRF defines.
  * @param variable that is queried
  * @param parameter unused
@@ -85,16 +131,8 @@
 		/* TODO: somehow determine whether we're in water or not */
 		case 0x43: return GetClosestWaterDistance(tile, true); // Manhattan distance of closes dry/water tile
 
-		case 0x60: { /* Get industry ID at offset param */
-			/*The parameter of this variable is an offset from the northernmost tile of the industry:
-			 * the high nibble contains the Y offset, the low one the X offset; both are unsigned.
-			 * The high word of the return value is currently reserved, and the low word can be:
-			 * 00xxh if the tile is an industry tile and was defined in the current GRF with ID xx.
-			 * FFxxh if the tile is an industry tile of an old type, and has the ID xx.
-			 * FFFEh if the tile is an industry tile that was defined in another GRF file
-			 * FFFFh if the tile isn't an industry tile, or doesn't belong to the current industry */
-			return GetIndustry(GetNearbyTile(parameter, tile))->type;
-		}
+		/* Get industry ID at offset param */
+		case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, industry->xy), tile, industry);
 
 		case 0x61: return 0; // Get random tile bits at offset param
 
--- a/src/newgrf_industries.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_industries.h	Tue Jun 12 19:52:26 2007 +0000
@@ -10,5 +10,6 @@
 
 uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available);
 uint16 GetIndustryCallback(uint16 callback, uint32 param1, uint32 param2, Industry *industry, TileIndex tile);
+uint32 GetIndustryIDAtOffset(TileIndex new_tile, TileIndex old_tile, const Industry *i);
 
 #endif /* NEWGRF_INDUSTRIES_H */
--- a/src/newgrf_text.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_text.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -445,6 +445,20 @@
 	_currentLangID = ret;
 }
 
+bool CheckGrfLangID(byte lang_id, byte grf_version)
+{
+	if (grf_version < 7) {
+		switch (_currentLangID) {
+			case GRFLX_GERMAN:  return (lang_id & GRFLB_GERMAN)  != 0;
+			case GRFLX_FRENCH:  return (lang_id & GRFLB_FRENCH)  != 0;
+			case GRFLX_SPANISH: return (lang_id & GRFLB_SPANISH) != 0;
+			default:            return (lang_id & (GRFLB_ENGLISH | GRFLB_AMERICAN)) != 0;
+		}
+	}
+
+	return (lang_id == _currentLangID || lang_id == GRFLX_UNSPECIFIED);
+}
+
 /**
  * House cleaning.
  * Remove all strings and reset the text counter.
--- a/src/newgrf_text.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/newgrf_text.h	Tue Jun 12 19:52:26 2007 +0000
@@ -13,4 +13,6 @@
 void SetCurrentGrfLangID(const char *iso_name);
 char *TranslateTTDPatchCodes(const char *str);
 
+bool CheckGrfLangID(byte lang_id, byte grf_version);
+
 #endif /* NEWGRF_TEXT_H */
--- a/src/openttd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/openttd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -87,7 +87,7 @@
 extern Player* DoStartupNewPlayer(bool is_ai);
 extern void ShowOSErrorBox(const char *buf);
 
-const char *_default_blitter = "8bpp-optimzed";
+const char *_default_blitter = "8bpp-optimized";
 
 /* TODO: usrerror() for errors which are not of an internal nature but
  * caused by the user, i.e. missing files or fatal configuration errors.
--- a/src/player_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/player_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -17,6 +17,7 @@
 #include "economy.h"
 #include "network/network.h"
 #include "variables.h"
+#include "roadveh.h"
 #include "train.h"
 #include "aircraft.h"
 #include "date.h"
@@ -649,7 +650,7 @@
 		if (v->owner == player) {
 			switch (v->type) {
 				case VEH_TRAIN:    if (IsFrontEngine(v)) train++; break;
-				case VEH_ROAD:     road++; break;
+				case VEH_ROAD:     if (IsRoadVehFront(v)) road++; break;
 				case VEH_AIRCRAFT: if (IsNormalAircraft(v)) air++; break;
 				case VEH_SHIP:     ship++; break;
 				default: break;
--- a/src/rail_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/rail_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -175,7 +175,7 @@
 		trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER;
 	}
 
-	Track track = TrackBitsToTrack(trackbits);
+	Track track = FindFirstTrack(trackbits);
 
 	if (!_remove_button_clicked) {
 		uint32 p1 = track;
--- a/src/road_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/road_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -13,6 +13,7 @@
 #include "table/sprites.h"
 #include "table/strings.h"
 #include "functions.h"
+#include "window.h"
 #include "map.h"
 #include "landscape.h"
 #include "tile.h"
@@ -1356,7 +1357,13 @@
 			if (v->type == VEH_ROAD &&
 					v->u.road.frame == 11 &&
 					_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) {
-				VehicleEnterDepot(v);
+				v->u.road.state = RVSB_IN_DEPOT;
+				v->vehstatus |= VS_HIDDEN;
+				v->direction = ReverseDir(v->direction);
+				if (v->next == NULL) VehicleEnterDepot(v);
+				v->tile = tile;
+
+				InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 				return VETSB_ENTERED_WORMHOLE;
 			}
 			break;
--- a/src/roadveh.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/roadveh.h	Tue Jun 12 19:52:26 2007 +0000
@@ -8,6 +8,42 @@
 #include "vehicle.h"
 
 
+enum RoadVehicleSubType {
+	RVST_FRONT,
+	RVST_ARTIC_PART,
+};
+
+static inline bool IsRoadVehFront(const Vehicle *v)
+{
+	assert(v->type == VEH_ROAD);
+	return v->subtype == RVST_FRONT;
+}
+
+static inline void SetRoadVehFront(Vehicle *v)
+{
+	assert(v->type == VEH_ROAD);
+	v->subtype = RVST_FRONT;
+}
+
+static inline bool IsRoadVehArticPart(const Vehicle *v)
+{
+	assert(v->type == VEH_ROAD);
+	return v->subtype == RVST_ARTIC_PART;
+}
+
+static inline void SetRoadVehArticPart(Vehicle *v)
+{
+	assert(v->type == VEH_ROAD);
+	v->subtype = RVST_ARTIC_PART;
+}
+
+static inline bool RoadVehHasArticPart(const Vehicle *v)
+{
+	assert(v->type == VEH_ROAD);
+	return v->next != NULL && IsRoadVehArticPart(v->next);
+}
+
+
 static inline bool IsRoadVehInDepot(const Vehicle* v)
 {
 	assert(v->type == VEH_ROAD);
@@ -43,7 +79,12 @@
 	void UpdateDeltaXY(Direction direction);
 	ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_ROADVEH_INC : EXPENSES_ROADVEH_RUN; }
 	WindowClass GetVehicleListWindowClass() const { return WC_ROADVEH_LIST; }
-	bool IsPrimaryVehicle() const { return true; }
+	bool IsPrimaryVehicle() const { return IsRoadVehFront(this); }
+	bool HasFront() const { return true; }
 };
 
+byte GetRoadVehLength(const Vehicle *v);
+
+void RoadVehUpdateCache(Vehicle *v);
+
 #endif /* ROADVEH_H */
--- a/src/roadveh_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/roadveh_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -27,6 +27,7 @@
 #include "tunnel_map.h"
 #include "bridge_map.h"
 #include "vehicle_gui.h"
+#include "articulated_vehicles.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_engine.h"
 #include "newgrf_text.h"
@@ -89,7 +90,7 @@
 	int image;
 
 	if (is_custom_sprite(img)) {
-		image = GetCustomVehicleSprite(v, direction);
+		image = GetCustomVehicleSprite(v, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(img)));
 		if (image != 0) return image;
 		img = orig_road_vehicle_info[v->engine_type - ROAD_ENGINES_INDEX].image_index;
 	}
@@ -120,6 +121,35 @@
 	return ((_price.roadveh_base >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5;
 }
 
+byte GetRoadVehLength(const Vehicle *v)
+{
+	byte length = 8;
+
+	uint16 veh_len = GetVehicleCallback(CBID_TRAIN_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
+	if (veh_len != CALLBACK_FAILED) {
+		length -= clamp(veh_len, 0, 7);
+	}
+
+	return length;
+}
+
+void RoadVehUpdateCache(Vehicle *v)
+{
+	assert(v->type == VEH_ROAD);
+	assert(IsRoadVehFront(v));
+
+	for (Vehicle *u = v; u != NULL; u = u->next) {
+		/* Update the v->first cache. */
+		if (u->first == NULL) u->first = v;
+
+		/* Update the 'first engine' */
+		u->u.road.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
+
+		/* Update the length of the vehicle. */
+		u->u.road.cached_veh_length = GetRoadVehLength(u);
+	}
+}
+
 /** Build a road vehicle.
  * @param tile tile of depot where road vehicle is built
  * @param flags operation to perform
@@ -147,8 +177,17 @@
 
 	if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE);
 
-	v = AllocateVehicle();
-	if (v == NULL) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
+	uint num_vehicles = 1 + CountArticulatedParts(p1);
+
+	/* Allow for the front and up to 10 articulated parts. */
+	Vehicle *vl[11];
+	memset(&vl, 0, sizeof(vl));
+
+	if (!AllocateVehicles(vl, num_vehicles)) {
+		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
+	}
+
+	v = vl[0];
 
 	/* find the first free roadveh id */
 	unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD);
@@ -162,7 +201,7 @@
 		const RoadVehicleInfo *rvi = RoadVehInfo(p1);
 
 		v->unitnumber = unit_num;
-		v->direction = INVALID_DIR;
+		v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
 		v->owner = _current_player;
 
 		v->tile = tile;
@@ -193,9 +232,6 @@
 		v->max_speed = rvi->max_speed;
 		v->engine_type = (byte)p1;
 
-		v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
-		v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
-
 		e = GetEngine(p1);
 		v->reliability = e->reliability;
 		v->reliability_spd_dec = e->reliability_spd_dec;
@@ -212,12 +248,20 @@
 		v = new (v) RoadVehicle();
 		v->cur_image = 0xC15;
 		v->random_bits = VehicleRandomBits();
+		SetRoadVehFront(v);
+
+		v->u.road.roadtype = HASBIT(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
+		v->u.road.compatible_roadtypes = RoadTypeToRoadTypes(v->u.road.roadtype);
+		v->u.road.cached_veh_length = GetRoadVehLength(v);
 
 		v->vehicle_flags = 0;
 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 
+		v->first = NULL;
 		v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity);
 
+		AddArticulatedParts(vl, VEH_ROAD);
+
 		VehiclePositionChanged(v);
 
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
@@ -285,6 +329,18 @@
 	DEBUG(ms, 3, "Clearing slot at 0x%X", rs->xy);
 }
 
+static bool CheckRoadVehInDepotStopped(const Vehicle *v)
+{
+	TileIndex tile = v->tile;
+
+	if (!IsTileDepotType(tile, TRANSPORT_ROAD) || !(v->vehstatus & VS_STOPPED)) return false;
+
+	for (; v != NULL; v = v->next) {
+		if (v->u.road.state != RVSB_IN_DEPOT || v->tile != tile) return false;
+	}
+	return true;
+}
+
 /** Sell a road vehicle.
  * @param tile unused
  * @param flags operation to perform
@@ -303,7 +359,7 @@
 
 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
 
-	if (!IsRoadVehInDepotStopped(v)) {
+	if (!CheckRoadVehInDepotStopped(v)) {
 		return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
 	}
 
@@ -536,8 +592,12 @@
 	rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY));
 }
 
-static void RoadVehDelete(Vehicle *v)
+static void DeleteLastRoadVeh(Vehicle *v)
 {
+	Vehicle *u = v;
+	for (; v->next != NULL; v = v->next) u = v;
+	u->next = NULL;
+
 	DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 
 	RebuildVehicleLists();
@@ -574,13 +634,15 @@
 		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
 	};
 
-	uint32 r = Random();
+	do {
+		uint32 r = Random();
 
-	v->direction = ChangeDir(v->direction, delta[r & 3]);
-	BeginVehicleMove(v);
-	v->UpdateDeltaXY(v->direction);
-	v->cur_image = GetRoadVehImage(v, v->direction);
-	SetRoadVehPosition(v, v->x_pos, v->y_pos);
+		v->direction = ChangeDir(v->direction, delta[r & 3]);
+		BeginVehicleMove(v);
+		v->UpdateDeltaXY(v->direction);
+		v->cur_image = GetRoadVehImage(v, v->direction);
+		SetRoadVehPosition(v, v->x_pos, v->y_pos);
+	} while ((v = v->next) != NULL);
 }
 
 static void RoadVehIsCrashed(Vehicle *v)
@@ -590,8 +652,8 @@
 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 	} else if (v->u.road.crashed_ctr <= 45) {
 		if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
-	} else if (v->u.road.crashed_ctr >= 2220) {
-		RoadVehDelete(v);
+	} else if (v->u.road.crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
+		DeleteLastRoadVeh(v);
 	}
 }
 
@@ -609,18 +671,22 @@
 
 static void RoadVehCrash(Vehicle *v)
 {
-	uint16 pass;
+	uint16 pass = 1;
 
 	v->u.road.crashed_ctr++;
-	v->vehstatus |= VS_CRASHED;
+
+	for (Vehicle *u = v; u != NULL; u = u->next) {
+		if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo_count;
+
+		u->vehstatus |= VS_CRASHED;
+
+		MarkAllViewportsDirty(u->left_coord, u->top_coord, u->right_coord + 1, u->bottom_coord + 1);
+	}
+
 	ClearSlot(v);
 
 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
-	pass = 1;
-	if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count;
-	v->cargo_count = 0;
-
 	SetDParam(0, pass);
 	AddNewsItem(
 		(pass == 1) ?
@@ -636,16 +702,18 @@
 
 static void RoadVehCheckTrainCrash(Vehicle *v)
 {
-	TileIndex tile;
-
-	if (v->u.road.state == RVSB_WORMHOLE) return;
+	for (Vehicle *u = v; u != NULL; u = u->next) {
+		if (u->u.road.state == RVSB_WORMHOLE) continue;
 
-	tile = v->tile;
+		TileIndex tile = u->tile;
 
-	if (!IsLevelCrossingTile(tile)) return;
+		if (!IsLevelCrossingTile(tile)) continue;
 
-	if (VehicleFromPos(tile, v, EnumCheckRoadVehCrashTrain) != NULL)
-		RoadVehCrash(v);
+		if (VehicleFromPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain) != NULL) {
+			RoadVehCrash(v);
+			return;
+		}
+	}
 }
 
 static void HandleBrokenRoadVeh(Vehicle *v)
@@ -798,11 +866,11 @@
 	short y_diff = v->y_pos - rvf->y;
 
 	return
-		rvf->veh != v &&
 		v->type == VEH_ROAD &&
 		!IsRoadVehInDepot(v) &&
 		myabs(v->z_pos - rvf->veh->z_pos) < 6 &&
 		v->direction == rvf->dir &&
+		GetFirstVehicleInChain(rvf->veh) != GetFirstVehicleInChain(v) &&
 		(dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
 		(dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
 		(dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
@@ -821,7 +889,7 @@
 	rvf.y = y;
 	rvf.dir = dir;
 	rvf.veh = v;
-	u = (Vehicle*)VehicleFromPos(TileVirtXY(x, y), &rvf, EnumCheckRoadVehClose);
+	u = (Vehicle*)VehicleFromPosXY(x, y, &rvf, EnumCheckRoadVehClose);
 
 	/* This code protects a roadvehicle from being blocked for ever
 	 * If more than 1480 / 74 days a road vehicle is blocked, it will
@@ -972,6 +1040,9 @@
 	/* Trams can't overtake other trams */
 	if (v->u.road.roadtype == ROADTYPE_TRAM) return;
 
+	/* For now, articulated road vehicles can't overtake anything. */
+	if (RoadVehHasArticPart(v)) return;
+
 	if (v->direction != u->direction || !(v->direction & 1)) return;
 
 	/* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
@@ -1267,7 +1338,95 @@
 	15, 15, 11, 11
 };
 
-static void RoadVehController(Vehicle *v)
+static bool RoadVehLeaveDepot(Vehicle *v, bool first)
+{
+	/* Don't leave if not all the wagons are in the depot. */
+	for (const Vehicle *u = v; u != NULL; u = u->next) {
+		if (u->u.road.state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
+	}
+
+	DiagDirection dir = GetRoadDepotDirection(v->tile);
+	v->direction = DiagDirToDir(dir);
+
+	Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
+	const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir];
+
+	int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
+	int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
+
+	if (first) {
+		if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return true;
+
+		VehicleServiceInDepot(v);
+
+		StartRoadVehSound(v);
+
+		/* Vehicle is about to leave a depot */
+		v->cur_speed = 0;
+	}
+
+	BeginVehicleMove(v);
+
+	v->vehstatus &= ~VS_HIDDEN;
+	v->u.road.state = tdir;
+	v->u.road.frame = RVC_DEPOT_START_FRAME;
+
+	v->cur_image = GetRoadVehImage(v, v->direction);
+	v->UpdateDeltaXY(v->direction);
+	SetRoadVehPosition(v,x,y);
+
+	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
+
+	return true;
+}
+
+static Trackdir FollowPreviousRoadVehicle(const Vehicle *v, const Vehicle *prev, TileIndex tile, DiagDirection entry_dir)
+{
+	if (prev->tile == v->tile) {
+		/* If the previous vehicle is on the same tile as this vehicle is
+		 * then it must have reversed. */
+		return _road_reverse_table[entry_dir];
+	}
+
+	byte prev_state = prev->u.road.state;
+	Trackdir dir;
+
+	if (prev_state == RVSB_WORMHOLE || prev_state == RVSB_IN_DEPOT) {
+		DiagDirection diag_dir = INVALID_DIAGDIR;
+
+		if (IsTunnelTile(tile)) {
+			diag_dir = GetTunnelDirection(tile);
+		} else if (IsBridgeTile(tile)) {
+			diag_dir = GetBridgeRampDirection(tile);
+		} else if (IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_DEPOT) {
+			diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
+		}
+
+		if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
+		dir = DiagdirToDiagTrackdir(diag_dir);
+	} else if (HASBIT(prev_state, RVS_IN_DT_ROAD_STOP)) {
+		dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
+	} else if (prev_state < TRACKDIR_END) {
+		dir = (Trackdir)prev_state;
+	} else {
+		return INVALID_TRACKDIR;
+	}
+
+	/* Do some sanity checking. */
+	static const RoadBits required_roadbits[] = {
+		ROAD_X,            ROAD_Y,            ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE,
+		ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X,            ROAD_Y
+	};
+	RoadBits required = required_roadbits[dir & 0x07];
+
+	if ((required & GetAnyRoadBits(tile, v->u.road.roadtype)) == ROAD_NONE) {
+		dir = INVALID_TRACKDIR;
+	}
+
+	return dir;
+}
+
+static bool IndividualRoadVehicleController(Vehicle *v, const Vehicle *prev)
 {
 	Direction new_dir;
 	Direction old_dir;
@@ -1275,74 +1434,6 @@
 	int x,y;
 	uint32 r;
 
-	/* decrease counters */
-	v->tick_counter++;
-	if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
-
-	/* handle crashed */
-	if (v->u.road.crashed_ctr != 0) {
-		RoadVehIsCrashed(v);
-		return;
-	}
-
-	RoadVehCheckTrainCrash(v);
-
-	/* road vehicle has broken down? */
-	if (v->breakdown_ctr != 0) {
-		if (v->breakdown_ctr <= 2) {
-			HandleBrokenRoadVeh(v);
-			return;
-		}
-		v->breakdown_ctr--;
-	}
-
-	if (v->vehstatus & VS_STOPPED) return;
-
-	ProcessRoadVehOrder(v);
-	v->HandleLoading();
-
-	if (v->current_order.type == OT_LOADING) return;
-
-	if (IsRoadVehInDepot(v)) {
-		/* Vehicle is about to leave a depot */
-		DiagDirection dir;
-		const RoadDriveEntry* rdp;
-		Trackdir tdir;
-
-		v->cur_speed = 0;
-
-		dir = GetRoadDepotDirection(v->tile);
-		v->direction = DiagDirToDir(dir);
-
-		tdir = _roadveh_depot_exit_trackdir[dir];
-		rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir];
-
-		x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
-		y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
-
-		if (RoadVehFindCloseTo(v, x, y, v->direction) != NULL) return;
-
-		VehicleServiceInDepot(v);
-
-		StartRoadVehSound(v);
-
-		BeginVehicleMove(v);
-
-		v->vehstatus &= ~VS_HIDDEN;
-		v->u.road.state = tdir;
-		v->u.road.frame = RVC_DEPOT_START_FRAME;
-
-		v->cur_image = GetRoadVehImage(v, v->direction);
-		v->UpdateDeltaXY(v->direction);
-		SetRoadVehPosition(v,x,y);
-
-		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
-		return;
-	}
-
-	/* Check if vehicle needs to proceed, return if it doesn't */
-	if (!RoadVehAccelerate(v)) return;
-
 	if (v->u.road.overtaking != 0)  {
 		if (++v->u.road.overtaking_ctr >= 35)
 			/* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
@@ -1353,6 +1444,11 @@
 			}
 	}
 
+	/* If this vehicle is in a depot and we've reached this point it must be
+	 * one of the articulated parts. It will stay in the depot until activated
+	 * by the previous vehicle in the chain when it gets to the right place. */
+	if (IsRoadVehInDepot(v)) return true;
+
 	/* Save old vehicle position to use at end of move to set viewport area dirty */
 	BeginVehicleMove(v);
 
@@ -1363,7 +1459,7 @@
 		const Vehicle *u = RoadVehFindCloseTo(v, gp.x, gp.y, v->direction);
 		if (u != NULL && u->cur_speed < v->cur_speed) {
 			v->cur_speed = u->cur_speed;
-			return;
+			return false;
 		}
 
 		if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
@@ -1371,14 +1467,14 @@
 			v->cur_image = GetRoadVehImage(v, v->direction);
 			v->UpdateDeltaXY(v->direction);
 			SetRoadVehPosition(v,gp.x,gp.y);
-			return;
+			return true;
 		}
 
 		v->x_pos = gp.x;
 		v->y_pos = gp.y;
 		VehiclePositionChanged(v);
 		if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
-		return;
+		return true;
 	}
 
 	/* Get move position data for next frame.
@@ -1390,14 +1486,22 @@
 
 	if (rd.x & RDE_NEXT_TILE) {
 		TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3);
-		Trackdir dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
+		Trackdir dir;
 		uint32 r;
 		Direction newdir;
 		const RoadDriveEntry *rdp;
 
+		if (IsRoadVehFront(v)) {
+			/* If this is the front engine, look for the right path. */
+			dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
+		} else {
+			dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3));
+		}
+
 		if (dir == INVALID_TRACKDIR) {
+			if (!IsRoadVehFront(v)) error("!Disconnecting road vehicle.");
 			v->cur_speed = 0;
-			return;
+			return false;
 		}
 
 again:
@@ -1415,11 +1519,11 @@
 				if (!IsTileType(tile, MP_STREET) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || HasRoadWorks(tile) || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) {
 					/* The tram cannot turn here */
 					v->cur_speed = 0;
-					return;
+					return false;
 				}
 			} else if (IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_NORMAL && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
 				v->cur_speed = 0;
-				return;
+				return false;
 			} else {
 				tile = v->tile;
 			}
@@ -1432,13 +1536,13 @@
 		y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y;
 
 		newdir = RoadVehGetSlidingDirection(v, x, y);
-		if (RoadVehFindCloseTo(v, x, y, newdir) != NULL) return;
+		if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false;
 
 		r = VehicleEnterTile(v, tile, x, y);
 		if (HASBIT(r, VETS_CANNOT_ENTER)) {
 			if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
 				v->cur_speed = 0;
-				return;
+				return false;
 			}
 			/* Try an about turn to re-enter the previous tile */
 			dir = _road_reverse_table[rd.x & 3];
@@ -1450,7 +1554,7 @@
 				/* New direction is trying to turn vehicle around.
 				 * We can't turn at the exit of a road stop so wait.*/
 				v->cur_speed = 0;
-				return;
+				return false;
 			}
 			if (IsRoadStop(v->tile)) {
 				RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
@@ -1478,7 +1582,7 @@
 		v->cur_image = GetRoadVehImage(v, newdir);
 		v->UpdateDeltaXY(v->direction);
 		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
-		return;
+		return true;
 	}
 
 	if (rd.x & RDE_TURNED) {
@@ -1490,7 +1594,7 @@
 
 		if (dir == INVALID_TRACKDIR) {
 			v->cur_speed = 0;
-			return;
+			return false;
 		}
 
 		rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir];
@@ -1499,12 +1603,12 @@
 		y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y;
 
 		newdir = RoadVehGetSlidingDirection(v, x, y);
-		if (RoadVehFindCloseTo(v, x, y, newdir) != NULL) return;
+		if (IsRoadVehFront(v) && RoadVehFindCloseTo(v, x, y, newdir) != NULL) return false;
 
 		r = VehicleEnterTile(v, v->tile, x, y);
 		if (HASBIT(r, VETS_CANNOT_ENTER)) {
 			v->cur_speed = 0;
-			return;
+			return false;
 		}
 
 		v->u.road.state = dir;
@@ -1518,7 +1622,18 @@
 		v->cur_image = GetRoadVehImage(v, newdir);
 		v->UpdateDeltaXY(v->direction);
 		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
-		return;
+		return true;
+	}
+
+	/* This vehicle is not in a wormhole and it hasn't entered a new tile. If
+	 * it's on a depot tile, check if it's time to activate the next vehicle in
+	 * the chain yet. */
+	if (v->next != NULL &&
+			IsTileType(v->tile, MP_STREET) && GetRoadTileType(v->tile) == ROAD_TILE_DEPOT) {
+
+		if (v->u.road.frame == v->u.road.cached_veh_length + RVC_DEPOT_START_FRAME) {
+			RoadVehLeaveDepot(v->next, false);
+		}
 	}
 
 	/* Calculate new position for the vehicle */
@@ -1527,7 +1642,7 @@
 
 	new_dir = RoadVehGetSlidingDirection(v, x, y);
 
-	if (!IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
+	if (IsRoadVehFront(v) && !IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
 		/* Vehicle is not in a road stop.
 		 * Check for another vehicle to overtake */
 		Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir);
@@ -1536,7 +1651,7 @@
 			v->cur_speed = u->cur_speed;
 			/* There is a vehicle in front overtake it if possible */
 			if (v->u.road.overtaking == 0) RoadVehCheckOvertake(v, u);
-			return;
+			return false;
 		}
 	}
 
@@ -1552,7 +1667,7 @@
 			/* Note, return here means that the frame counter is not incremented
 			 * for vehicles changing direction in a road stop. This causes frames to
 			 * be repeated. (XXX) Is this intended? */
-			return;
+			return true;
 		}
 	}
 
@@ -1561,12 +1676,12 @@
 	 * and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
 	 * (the station test and stop type test ensure that other vehicles, using the road stop as
 	 * a through route, do not stop) */
-	if ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
+	if (IsRoadVehFront(v) && ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
 			_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) ||
 			(IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 			v->current_order.dest == GetStationIndex(v->tile) &&
 			GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
-			v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME)) {
+			v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
 		RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
 		Station* st = GetStationByTile(v->tile);
@@ -1596,7 +1711,7 @@
 
 						v->u.road.frame++;
 						RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
-						return;
+						return true;
 					}
 				}
 			}
@@ -1608,7 +1723,7 @@
 			RoadVehArrivesAt(v, st);
 			v->BeginLoading();
 
-			return;
+			return false;
 		}
 
 		/* Vehicle is ready to leave a bay in a road stop */
@@ -1616,7 +1731,7 @@
 			if (rs->IsEntranceBusy()) {
 				/* Road stop entrance is busy, so wait as there is nowhere else to go */
 				v->cur_speed = 0;
-				return;
+				return false;
 			}
 			v->current_order.Free();
 			ClearSlot(v);
@@ -1659,7 +1774,7 @@
 	r = VehicleEnterTile(v, v->tile, x, y);
 	if (HASBIT(r, VETS_CANNOT_ENTER)) {
 		v->cur_speed = 0;
-		return;
+		return false;
 	}
 
 	/* Move to next frame unless vehicle arrived at a stop position
@@ -1669,6 +1784,47 @@
 	v->cur_image = GetRoadVehImage(v, v->direction);
 	v->UpdateDeltaXY(v->direction);
 	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
+	return true;
+}
+
+static void RoadVehController(Vehicle *v)
+{
+	/* decrease counters */
+	v->tick_counter++;
+	if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
+
+	/* handle crashed */
+	if (v->u.road.crashed_ctr != 0) {
+		RoadVehIsCrashed(v);
+		return;
+	}
+
+	RoadVehCheckTrainCrash(v);
+
+	/* road vehicle has broken down? */
+	if (v->breakdown_ctr != 0) {
+		if (v->breakdown_ctr <= 2) {
+			HandleBrokenRoadVeh(v);
+			return;
+		}
+		v->breakdown_ctr--;
+	}
+
+	if (v->vehstatus & VS_STOPPED) return;
+
+	ProcessRoadVehOrder(v);
+	v->HandleLoading();
+
+	if (v->current_order.type == OT_LOADING) return;
+
+	if (IsRoadVehInDepot(v) && RoadVehLeaveDepot(v, true)) return;
+
+	/* Check if vehicle needs to proceed, return if it doesn't */
+	if (!RoadVehAccelerate(v)) return;
+
+	for (Vehicle *prev = NULL; v != NULL; prev = v, v = v->next) {
+		if (!IndividualRoadVehicleController(v, prev)) break;
+	}
 }
 
 static void AgeRoadVehCargo(Vehicle *v)
@@ -1680,7 +1836,8 @@
 void RoadVeh_Tick(Vehicle *v)
 {
 	AgeRoadVehCargo(v);
-	RoadVehController(v);
+
+	if (IsRoadVehFront(v)) RoadVehController(v);
 }
 
 static void CheckIfRoadVehNeedsService(Vehicle *v)
@@ -1738,6 +1895,8 @@
 {
 	int32 cost;
 
+	if (!IsRoadVehFront(v)) return;
+
 	if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v);
 	if (v->u.road.blocked_ctr == 0) CheckVehicleBreakdown(v);
 
@@ -1862,7 +2021,7 @@
 	v = GetVehicle(p1);
 
 	if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
-	if (!IsRoadVehInDepotStopped(v)) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
+	if (!CheckRoadVehInDepotStopped(v)) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE);
 
 	if (new_cid >= NUM_CARGO || !CanRefitTo(v->engine_type, new_cid)) return CMD_ERROR;
 
--- a/src/roadveh_gui.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/roadveh_gui.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -11,6 +11,7 @@
 #include "table/strings.h"
 #include "window.h"
 #include "gui.h"
+#include "strings.h"
 #include "vehicle.h"
 #include "viewport.h"
 #include "command.h"
@@ -18,22 +19,61 @@
 #include "vehicle_gui.h"
 #include "newgrf_engine.h"
 
-void DrawRoadVehImage(const Vehicle *v, int x, int y, VehicleID selection)
+static inline int RoadVehLengthToPixels(int length)
 {
-	SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
-	DrawSprite(GetRoadVehImage(v, DIR_W), pal, x + 14, y + 6);
+	return (length * 28) / 8;
+}
 
-	if (v->index == selection) {
-		DrawFrameRect(x - 1, y - 1, x + 28, y + 12, 15, FR_BORDERONLY);
-	}
+void DrawRoadVehImage(const Vehicle *v, int x, int y, int count, VehicleID selection)
+{
+	int dx = 0;
+
+	/* Road vehicle lengths are measured in eighths of the standard length, so
+	 * count is the number of standard vehicles that should be drawn. If it is
+	 * 0, we draw enough vehicles for 10 standard vehicle lengths. */
+	int max_length = (count == 0) ? 80 : count * 8;
+
+	do {
+		int length = v->u.road.cached_veh_length;
+
+		if (dx + length > 0 && dx <= max_length) {
+			SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
+			DrawSprite(GetRoadVehImage(v, DIR_W), pal, x + 14 + RoadVehLengthToPixels(dx), y + 6);
+
+			if (v->index == selection) {
+				DrawFrameRect(x - 1, y - 1, x + 28, y + 12, 15, FR_BORDERONLY);
+			}
+		}
+
+		dx += length;
+		v = v->next;
+	} while (v != NULL && dx < max_length);
 }
 
 static void RoadVehDetailsWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: {
+		const Vehicle *v = GetVehicle(w->window_number);
+
+		if (!RoadVehHasArticPart(v)) break;
+
+		/* Draw the text under the vehicle instead of next to it, minus the
+		 * height already allocated for the cargo of the first vehicle. */
+		uint height_extension = 15 - 11;
+
+		/* Add space for the cargo amount for each part. */
+		do {
+			height_extension += 11;
+		} while ((v = v->next) != NULL);
+
+		ResizeWindow(w, 0, height_extension);
+	} break;
+
 	case WE_PAINT: {
 		const Vehicle *v = GetVehicle(w->window_number);
 		StringID str;
+		uint y_offset = RoadVehHasArticPart(v) ? 15 :0;
 
 		SetWindowWidgetDisabledState(w, 2, v->owner != _local_player);
 		/* disable service-scroller when interval is set to disabled */
@@ -76,37 +116,81 @@
 			DrawString(2, 45, STR_9010_RELIABILITY_BREAKDOWNS, 0);
 		}
 
-		/* Draw service interval text */
-		{
-			SetDParam(0, v->service_interval);
-			SetDParam(1, v->date_of_last_service);
-			DrawString(13, 102, _patches.servint_ispercent?STR_SERVICING_INTERVAL_PERCENT:STR_883C_SERVICING_INTERVAL_DAYS, 0);
-		}
-
-		DrawRoadVehImage(v, 3, 57, INVALID_VEHICLE);
+		DrawRoadVehImage(v, 3, 57, 0, INVALID_VEHICLE);
 
 		SetDParam(0, GetCustomEngineName(v->engine_type));
 		SetDParam(1, v->build_year);
 		SetDParam(2, v->value);
-		DrawString(34, 57, STR_9011_BUILT_VALUE, 0);
-
-		SetDParam(0, v->cargo_type);
-		SetDParam(1, v->cargo_cap);
-		DrawString(34, 67, STR_9012_CAPACITY, 0);
+		DrawString(34, 57 + y_offset, STR_9011_BUILT_VALUE, 0);
 
-		str = STR_8812_EMPTY;
-		if (v->cargo_count != 0) {
+		if (RoadVehHasArticPart(v)) {
+			AcceptedCargo max_cargo;
+			char capacity[512];
+
+			memset(max_cargo, 0, sizeof(max_cargo));
+
+			for (const Vehicle *u = v; u != NULL; u = u->next) {
+				max_cargo[u->cargo_type] += u->cargo_cap;
+			}
+
+			GetString(capacity, STR_ARTICULATED_RV_CAPACITY, lastof(capacity));
+
+			bool first = true;
+			for (CargoID i = 0; i < NUM_CARGO; i++) {
+				if (max_cargo[i] > 0) {
+					char buffer[128];
+
+					SetDParam(0, i);
+					SetDParam(1, max_cargo[i]);
+					GetString(buffer, STR_BARE_CARGO, lastof(buffer));
+
+					if (!first) strecat(capacity, ", ", lastof(capacity));
+					strecat(capacity, buffer, lastof(capacity));
+				}
+			}
+
+			SetDParamStr(0, capacity);
+			DrawStringTruncated(34, 67 + y_offset, STR_JUST_STRING, 0, w->width - 34);
+
+			for (const Vehicle *u = v; u != NULL; u = u->next) {
+				str = STR_8812_EMPTY;
+				if (u->cargo_count != 0) {
+					SetDParam(0, u->cargo_type);
+					SetDParam(1, u->cargo_count);
+					SetDParam(2, u->cargo_source);
+					str = STR_8813_FROM;
+				}
+				DrawString(34, 78 + y_offset, str, 0);
+
+				y_offset += 11;
+			}
+
+			y_offset -= 11;
+		} else {
 			SetDParam(0, v->cargo_type);
-			SetDParam(1, v->cargo_count);
-			SetDParam(2, v->cargo_source);
-			str = STR_8813_FROM;
+			SetDParam(1, v->cargo_cap);
+			DrawString(34, 67 + y_offset, STR_9012_CAPACITY, 0);
+
+			str = STR_8812_EMPTY;
+			if (v->cargo_count != 0) {
+				SetDParam(0, v->cargo_type);
+				SetDParam(1, v->cargo_count);
+				SetDParam(2, v->cargo_source);
+				str = STR_8813_FROM;
+			}
+			DrawString(34, 78 + y_offset, str, 0);
 		}
-		DrawString(34, 78, str, 0);
 
 		/* Draw Transfer credits text */
 		SetDParam(0, v->cargo_feeder_share);
-		DrawString(34, 89, STR_FEEDER_CARGO_VALUE, 0);
+		DrawString(34, 90 + y_offset, STR_FEEDER_CARGO_VALUE, 0);
 
+		/* Draw service interval text */
+		{
+			SetDParam(0, v->service_interval);
+			SetDParam(1, v->date_of_last_service);
+			DrawString(13, 102 + y_offset, _patches.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, 0);
+		}
 	} break;
 
 	case WE_CLICK: {
@@ -151,10 +235,10 @@
 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   339,     0,    13, STR_900C_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS},
 { WWT_PUSHTXTBTN,   RESIZE_NONE,    14,   340,   379,     0,    13, STR_01AA_NAME,    STR_902E_NAME_ROAD_VEHICLE},
 {      WWT_PANEL,   RESIZE_NONE,    14,     0,   379,    14,    55, 0x0,              STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,    14,     0,   379,    56,   100, 0x0,              STR_NULL},
-{ WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,    10,   101,   106, STR_0188,         STR_884D_INCREASE_SERVICING_INTERVAL},
-{ WWT_PUSHTXTBTN,   RESIZE_NONE,    14,     0,    10,   107,   112, STR_0189,         STR_884E_DECREASE_SERVICING_INTERVAL},
-{      WWT_PANEL,   RESIZE_NONE,    14,    11,   379,   101,   112, 0x0,              STR_NULL},
+{      WWT_PANEL,   RESIZE_BOTTOM,  14,     0,   379,    56,   100, 0x0,              STR_NULL},
+{ WWT_PUSHTXTBTN,   RESIZE_TB,      14,     0,    10,   101,   106, STR_0188,         STR_884D_INCREASE_SERVICING_INTERVAL},
+{ WWT_PUSHTXTBTN,   RESIZE_TB,      14,     0,    10,   107,   112, STR_0189,         STR_884E_DECREASE_SERVICING_INTERVAL},
+{      WWT_PANEL,   RESIZE_TB,      14,    11,   379,   101,   112, 0x0,              STR_NULL},
 {   WIDGETS_END},
 };
 
--- a/src/screenshot.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/screenshot.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -14,6 +14,7 @@
 #include "variables.h"
 #include "date.h"
 #include "helpers.hpp"
+#include "fileio.h"
 
 char _screenshot_format_name[8];
 uint _num_screenshot_formats;
@@ -505,6 +506,7 @@
 		GetString(_screenshot_name, STR_4004, lastof(_screenshot_name));
 	}
 
+	SanitizeFilename(_screenshot_name);
 	base = strchr(_screenshot_name, 0);
 	base[0] = '.'; strcpy(base + 1, ext);
 
--- a/src/spritecache.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/spritecache.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -118,7 +118,7 @@
 
 void* AllocSprite(size_t);
 
-static void* ReadSprite(SpriteCache *sc, SpriteID id)
+static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite)
 {
 	uint32 file_pos = sc->file_pos;
 
@@ -139,12 +139,65 @@
 	byte type = FioReadByte();
 	/* Type 0xFF indicates either a colormap or some other non-sprite info */
 	if (type == 0xFF) {
+		if (real_sprite) {
+			static byte warning_level = 0;
+			DEBUG(sprite, 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);
+		}
+
 		byte *dest = (byte *)AllocSprite(num);
 
 		sc->ptr = dest;
 		FioReadBlock(dest, num);
 
-		return dest;
+		return sc->ptr;
+	}
+	/* Ugly hack to work around the problem that the old landscape
+	 *  generator assumes that those sprites are stored uncompressed in
+	 *  the memory, and they are only read directly by the code, never
+	 *  send to the blitter. So do not send it to the blitter (which will
+	 *  result in a data array in the format the blitter likes most), but
+	 *  read the data directly from disk and store that as sprite.
+	 * Ugly: yes. Other solution: no. Blame the original author or
+	 *  something ;) The image should really have been a data-stream
+	 *  (so type = 0xFF basicly). */
+	if (id >= 4845 && id <= 4881) {
+		uint height = FioReadByte();
+		uint width  = FioReadWord();
+		Sprite *sprite;
+		byte *dest;
+
+		num = width * height;
+		sprite = (Sprite *)AllocSprite(sizeof(*sprite) + num);
+		sc->ptr = sprite;
+		sprite->height = height;
+		sprite->width  = width;
+		sprite->x_offs = FioReadWord();
+		sprite->y_offs = FioReadWord();
+
+		dest = sprite->data;
+		while (num > 0) {
+			int8 i = FioReadByte();
+			if (i >= 0) {
+				num -= i;
+				for (; i > 0; --i) *dest++ = FioReadByte();
+			} else {
+				const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
+				i = -(i >> 3);
+				num -= i;
+				for (; i > 0; --i) *dest++ = *rel++;
+			}
+		}
+
+		return sc->ptr;
+	}
+
+	if (!real_sprite) {
+		static byte warning_level = 0;
+		DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
+		warning_level = 6;
 	}
 
 	SpriteLoaderGrf sprite_loader;
@@ -364,7 +417,7 @@
 }
 
 
-const void *GetRawSprite(SpriteID sprite)
+const void *GetRawSprite(SpriteID sprite, bool real_sprite)
 {
 	SpriteCache *sc;
 	void* p;
@@ -379,7 +432,7 @@
 	p = sc->ptr;
 
 	/* Load the sprite, if it is not loaded, yet */
-	if (p == NULL) p = ReadSprite(sc, sprite);
+	if (p == NULL) p = ReadSprite(sc, sprite, real_sprite);
 	return p;
 }
 
--- a/src/spritecache.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/spritecache.h	Tue Jun 12 19:52:26 2007 +0000
@@ -15,17 +15,17 @@
 
 extern uint _sprite_cache_size;
 
-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 (Sprite*)GetRawSprite(sprite);
+	return (Sprite*)GetRawSprite(sprite, true);
 }
 
 static inline const byte *GetNonSprite(SpriteID sprite)
 {
-	return (byte*)GetRawSprite(sprite);
+	return (byte*)GetRawSprite(sprite, false);
 }
 
 void GfxInitSpriteMem();
--- a/src/spriteloader/grf.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/spriteloader/grf.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1,3 +1,7 @@
+/* $Id$ */
+
+/** @file grf.cpp */
+
 #include "../stdafx.h"
 #include "../gfx.h"
 #include "../fileio.h"
--- a/src/station_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/station_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -30,6 +30,7 @@
 #include "sprite.h"
 #include "depot.h"
 #include "train.h"
+#include "roadveh.h"
 #include "water_map.h"
 #include "industry_map.h"
 #include "newgrf_callbacks.h"
@@ -2280,7 +2281,7 @@
 		}
 	} else if (v->type == VEH_ROAD) {
 		if (v->u.road.state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)v->u.road.state) && v->u.road.frame == 0) {
-			if (IsRoadStop(tile)) {
+			if (IsRoadStop(tile) && IsRoadVehFront(v)) {
 				/* Attempt to allocate a parking bay in a road stop */
 				RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile));
 
--- a/src/table/ai_rail.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/table/ai_rail.h	Tue Jun 12 19:52:26 2007 +0000
@@ -567,8 +567,32 @@
 	{1, 0, {0, 0}}
 };
 
+static const AiDefaultBlockData _airportdata_ai_3[] = {
+	MKAIR(3, 0, 0),
+	{1, 0, {0, 0}},
+};
+
+static const AiDefaultBlockData _airportdata_ai_4[] = {
+	MKAIR(4, 0, 0),
+	{1, 0, {0, 0}},
+};
+
+static const AiDefaultBlockData _airportdata_ai_5[] = {
+	MKAIR(5, 0, 0),
+	{1, 0, {0, 0}},
+};
+
+static const AiDefaultBlockData _airportdata_ai_7[] = {
+	MKAIR(7, 0, 0),
+	{1, 0, {0, 0}}
+};
+
 static const AiDefaultBlockData * const _airport_default_block_data[] = {
+	_airportdata_ai_7, // intercontinental airport
+	_airportdata_ai_4, // international airport
+	_airportdata_ai_3, // metropolitan airport
 	_airportdata_ai_0, // city airport
+	_airportdata_ai_5, // commuter airport
 	_airportdata_ai_1, // country airport
 	NULL
 };
--- a/src/train_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/train_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -576,7 +576,7 @@
 
 			v->group_id = DEFAULT_GROUP;
 
-			AddArticulatedParts(vl);
+			AddArticulatedParts(vl, VEH_TRAIN);
 
 			_new_vehicle_id = v->index;
 
@@ -755,7 +755,7 @@
 				vl[0]->u.rail.other_multiheaded_part = vl[1];
 				vl[1]->u.rail.other_multiheaded_part = vl[0];
 			} else {
-				AddArticulatedParts(vl);
+				AddArticulatedParts(vl, VEH_TRAIN);
 			}
 
 			TrainConsistChanged(v);
@@ -2722,7 +2722,7 @@
 	tcc.v_skip = v->next;
 
 	/* find colliding vehicle */
-	Vehicle *realcoll = (Vehicle*)VehicleFromPos(TileVirtXY(v->x_pos, v->y_pos), &tcc, FindTrainCollideEnum);
+	Vehicle *realcoll = (Vehicle*)VehicleFromPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
 	if (realcoll == NULL) return;
 
 	Vehicle *coll = GetFirstVehicleInChain(realcoll);
@@ -2775,6 +2775,8 @@
 
 	/* For every vehicle after and including the given vehicle */
 	for (prev = GetPrevVehicleInChain(v); v != NULL; prev = v, v = v->next) {
+		DiagDirection enterdir = DIAGDIR_BEGIN;
+		bool update_signals = false;
 		BeginVehicleMove(v);
 
 		GetNewVehiclePosResult gp = GetNewVehiclePos(v);
@@ -2810,7 +2812,7 @@
 
 				/* Determine what direction we're entering the new tile from */
 				Direction dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile);
-				DiagDirection enterdir = DirToDiagDir(dir);
+				enterdir = DirToDiagDir(dir);
 				assert(IsValidDiagDirection(enterdir));
 
 				/* Get the status of the tracks in the new tile and mask
@@ -2917,11 +2919,9 @@
 					assert(v->u.rail.track);
 				}
 
-				if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir);
-
-				/* Signals can only change when the first
-				 * (above) or the last vehicle moves. */
-				if (v->next == NULL) TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
+				/* We need to update signal status, but after the vehicle position hash
+				 * has been updated by AfterSetTrainPos() */
+				update_signals = true;
 
 				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
 
@@ -2958,6 +2958,14 @@
 			/* This is the first vehicle in the train */
 			AffectSpeedByZChange(v, old_z);
 		}
+
+		if (update_signals) {
+			if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir);
+
+			/* Signals can only change when the first
+			 * (above) or the last vehicle moves. */
+			if (v->next == NULL) TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
+		}
 	}
 	return;
 
--- a/src/tunnelbridge_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/tunnelbridge_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -1426,7 +1426,7 @@
 	} else if (IsBridge(tile)) { // XXX is this necessary?
 		DiagDirection dir;
 
-		if (v->type == VEH_ROAD || (v->type == VEH_TRAIN && IsFrontEngine(v))) {
+		if (v->HasFront() && v->IsPrimaryVehicle()) {
 			/* modify speed of vehicle */
 			uint16 spd = _bridge[GetBridgeType(tile)].speed;
 
--- a/src/vehicle.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/vehicle.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -230,11 +230,15 @@
 
 		v->first = NULL;
 		if (v->type == VEH_TRAIN) v->u.rail.first_engine = INVALID_ENGINE;
+		if (v->type == VEH_ROAD)  v->u.road.first_engine = INVALID_ENGINE;
 	}
 
 	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)))
+		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
 			TrainConsistChanged(v);
+		} else if (v->type == VEH_ROAD && IsRoadVehFront(v)) {
+			RoadVehUpdateCache(v);
+		}
 	}
 
 	FOR_ALL_VEHICLES(v) {
@@ -390,44 +394,117 @@
 	return true;
 }
 
-
-static Vehicle *_vehicle_position_hash[0x1000];
+/* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
+ * lookup times at the expense of memory usage. */
+const int HASH_BITS = 7;
+const int HASH_SIZE = 1 << HASH_BITS;
+const int HASH_MASK = HASH_SIZE - 1;
+const int TOTAL_HASH_SIZE = 1 << (HASH_BITS * 2);
+const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
+
+/* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
+ * Profiling results show that 0 is fastest. */
+const int HASH_RES = 0;
+
+static Vehicle *_new_vehicle_position_hash[TOTAL_HASH_SIZE];
+
+static void *VehicleFromHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc)
+{
+	for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
+		for (int x = xl; ; x = (x + 1) & HASH_MASK) {
+			Vehicle *v = _new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
+			for (; v != NULL; v = v->next_new_hash) {
+				void *a = proc(v, data);
+				if (a != NULL) return a;
+			}
+			if (x == xu) break;
+		}
+		if (y == yu) break;
+	}
+
+	return NULL;
+}
+
+
+void *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
+{
+	const int COLL_DIST = 6;
+
+	/* Hash area to scan is from xl,yl to xu,yu */
+	int xl = GB((x - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
+	int xu = GB((x + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS);
+	int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
+	int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
+
+	return VehicleFromHash(xl, yl, xu, yu, data, proc);
+}
+
 
 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
 {
-	Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, 0);
-
-	/* The hash area to scan */
-	const int xl = GB(pt.x - 174, 7, 6);
-	const int xu = GB(pt.x + 104, 7, 6);
-	const int yl = GB(pt.y - 294, 6, 6) << 6;
-	const int yu = GB(pt.y +  56, 6, 6) << 6;
-
-	int x;
-	int y;
-
-	for (y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
-		for (x = xl;; x = (x + 1) & 0x3F) {
-			Vehicle *v = _vehicle_position_hash[(x + y) & 0xFFFF];
-
-			while (v != NULL) {
-				void* a = proc(v, data);
-
-				if (a != NULL) return a;
-				v = v->next_hash;
-			}
-
-			if (x == xu) break;
-		}
-
-		if (y == yu) break;
+	int x = GB(TileX(tile), HASH_RES, HASH_BITS);
+	int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
+
+	Vehicle *v = _new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
+	for (; v != NULL; v = v->next_new_hash) {
+		if (v->tile != tile) continue;
+
+		void *a = proc(v, data);
+		if (a != NULL) return a;
 	}
+
 	return NULL;
 }
 
+static void UpdateNewVehiclePosHash(Vehicle *v)
+{
+	Vehicle **old_hash = v->old_new_hash;
+	Vehicle **new_hash;
+
+	if (v->tile == INVALID_TILE || v->tile == 0) {
+		new_hash = NULL;
+	} else {
+		int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
+		int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
+		new_hash = &_new_vehicle_position_hash[(x + y) & TOTAL_HASH_MASK];
+	}
+
+	if (old_hash == new_hash) return;
+
+	/* Remove from the old position in the hash table */
+	if (old_hash != NULL) {
+		Vehicle *last = NULL;
+		Vehicle *u = *old_hash;
+		while (u != v) {
+			last = u;
+			u = u->next_new_hash;
+			assert(u != NULL);
+		}
+
+		if (last == NULL) {
+			*old_hash = v->next_new_hash;
+		} else {
+			last->next_new_hash = v->next_new_hash;
+		}
+	}
+
+	/* Insert vehicle at beginning of the new position in the hash table */
+	if (new_hash != NULL) {
+		v->next_new_hash = *new_hash;
+		*new_hash = v;
+		assert(v != v->next_new_hash);
+	}
+
+	/* Remember current hash position */
+	v->old_new_hash = new_hash;
+}
+
+static Vehicle *_vehicle_position_hash[0x1000];
 
 static void UpdateVehiclePosHash(Vehicle* v, int x, int y)
 {
+	UpdateNewVehiclePosHash(v);
+
 	Vehicle **old_hash, **new_hash;
 	int old_x = v->left_coord;
 	int old_y = v->top_coord;
@@ -464,6 +541,7 @@
 void ResetVehiclePosHash()
 {
 	memset(_vehicle_position_hash, 0, sizeof(_vehicle_position_hash));
+	memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
 }
 
 void InitializeVehicles()
@@ -498,7 +576,7 @@
 {
 	Vehicle *u;
 
-	FOR_ALL_VEHICLES(u) if (u->type == VEH_TRAIN && u->next == v) return u;
+	FOR_ALL_VEHICLES(u) if (u->type == v->type && u->next == v) return u;
 
 	return NULL;
 }
@@ -531,10 +609,14 @@
 	Vehicle* u;
 
 	assert(v != NULL);
-	assert(v->type == VEH_TRAIN);
+	assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
 
 	if (v->first != NULL) {
-		if (IsFrontEngine(v->first) || IsFreeWagon(v->first)) return v->first;
+		if (v->type == VEH_TRAIN) {
+			if (IsFrontEngine(v->first) || IsFreeWagon(v->first)) return v->first;
+		} else {
+			if (IsRoadVehFront(v->first)) return v->first;
+		}
 
 		DEBUG(misc, 0, "v->first cache faulty. We shouldn't be here, rebuilding cache!");
 	}
@@ -548,8 +630,10 @@
 	while ((u = GetPrevVehicleInChain_bruteforce(v)) != NULL) v = u;
 
 	/* Set the first pointer of all vehicles in that chain to the first wagon */
-	if (IsFrontEngine(v) || IsFreeWagon(v))
+	if ((v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) ||
+			(v->type == VEH_ROAD && IsRoadVehFront(v))) {
 		for (u = (Vehicle *)v; u != NULL; u = u->next) u->first = (Vehicle *)v;
+	}
 
 	return (Vehicle*)v;
 }
@@ -572,9 +656,8 @@
 		case VEH_TRAIN:
 			return !IsArticulatedPart(v) && // tenders and other articulated parts
 			(!IsMultiheaded(v) || IsTrainEngine(v)); // rear parts of multiheaded engines
-		case VEH_ROAD:
-		case VEH_SHIP:
-			return true;
+		case VEH_ROAD: return IsRoadVehFront(v);
+		case VEH_SHIP: return true;
 		default: return false; // Only count player buildable vehicles
 	}
 }
@@ -602,14 +685,18 @@
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 	}
 
+	v->tile = INVALID_TILE;
 	UpdateVehiclePosHash(v, INVALID_COORD, 0);
 	v->next_hash = NULL;
+	v->next_new_hash = NULL;
 	if (IsPlayerBuildableVehicleType(v)) DeleteVehicleOrders(v);
 
 	/* Now remove any artic part. This will trigger an other
 	 *  destroy vehicle, which on his turn can remove any
 	 *  other artic parts. */
-	if (v->type == VEH_TRAIN && EngineHasArticPart(v)) DeleteVehicle(v->next);
+	if ((v->type == VEH_TRAIN && EngineHasArticPart(v)) || (v->type == VEH_ROAD && RoadVehHasArticPart(v))) {
+		DeleteVehicle(v->next);
+	}
 }
 
 /**
@@ -621,7 +708,7 @@
  */
 void DeleteVehicleChain(Vehicle *v)
 {
-	assert(v->type != VEH_TRAIN);
+	assert(v->type != VEH_TRAIN && v->type != VEH_ROAD);
 
 	do {
 		Vehicle *u = v;
@@ -705,6 +792,7 @@
 			case VEH_SHIP:
 				if (v->type == VEH_TRAIN && IsTrainWagon(v)) continue;
 				if (v->type == VEH_AIRCRAFT && v->subtype != AIR_HELICOPTER) continue;
+				if (v->type == VEH_ROAD && !IsRoadVehFront(v)) continue;
 
 				v->motion_counter += (v->direction & 1) ? (v->cur_speed * 3) / 4 : v->cur_speed;
 				/* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
@@ -1876,6 +1964,8 @@
 
 				if (w->type == VEH_TRAIN && EngineHasArticPart(w)) {
 					w = GetNextArticPart(w);
+				} else if (w->type == VEH_ROAD && RoadVehHasArticPart(w)) {
+					w = w->next;
 				} else {
 					break;
 				}
@@ -1886,7 +1976,15 @@
 					total_cost += GetRefitCost(v->engine_type);
 				}
 			}
-		} while (v->type == VEH_TRAIN && EngineHasArticPart(v) && (v = GetNextArticPart(v)) != NULL);
+
+			if (v->type == VEH_TRAIN && EngineHasArticPart(v)) {
+				v = GetNextArticPart(v);
+			} else if (v->type == VEH_ROAD && RoadVehHasArticPart(v)) {
+				v = v->next;
+			} else {
+				break;
+			}
+		} while (v != NULL);
 
 		if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w);
 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
@@ -1964,7 +2062,7 @@
 
 		case VEH_ROAD:
 			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_ROAD && IsRoadVehInDepot(v)) {
+				if (v->tile == tile && v->type == VEH_ROAD && IsRoadVehInDepot(v) && IsRoadVehFront(v)) {
 					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
 					(*engine_list)[(*engine_count)++] = v;
 				}
@@ -2163,7 +2261,7 @@
 
 		case VEH_ROAD:
 			InvalidateWindowClasses(WC_ROADVEH_LIST);
-			v->u.road.state = RVSB_IN_DEPOT;
+			if (!IsRoadVehFront(v)) v = GetFirstVehicleInChain(v);
 			break;
 
 		case VEH_SHIP:
--- a/src/vehicle.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/vehicle.h	Tue Jun 12 19:52:26 2007 +0000
@@ -189,6 +189,8 @@
 	byte reverse_ctr;
 	struct RoadStop *slot;
 	byte slot_age;
+	EngineID first_engine;
+	byte cached_veh_length;
 
 	RoadType roadtype;
 	RoadTypes compatible_roadtypes;
@@ -288,6 +290,8 @@
 	int32 right_coord;
 	int32 bottom_coord;
 	Vehicle *next_hash;
+	Vehicle *next_new_hash;
+	Vehicle **old_new_hash;
 
 	/* Related to age and service time */
 	Date age;     // Age in days
@@ -495,6 +499,7 @@
 bool IsEngineCountable(const Vehicle *v);
 void DeleteVehicleChain(Vehicle *v);
 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
+void *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc);
 void CallVehicleTicks();
 Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z);
 
--- a/src/vehicle_gui.h	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/vehicle_gui.h	Tue Jun 12 19:52:26 2007 +0000
@@ -51,7 +51,7 @@
 int DrawVehiclePurchaseInfo(int x, int y, uint w, EngineID engine_number);
 
 void DrawTrainImage(const Vehicle *v, int x, int y, int count, int skip, VehicleID selection);
-void DrawRoadVehImage(const Vehicle *v, int x, int y, VehicleID selection);
+void DrawRoadVehImage(const Vehicle *v, int x, int y, int count, VehicleID selection);
 void DrawShipImage(const Vehicle *v, int x, int y, VehicleID selection);
 void DrawAircraftImage(const Vehicle *v, int x, int y, VehicleID selection);
 
@@ -75,7 +75,7 @@
 {
 	switch (v->type) {
 		case VEH_TRAIN:    DrawTrainImage(v, x, y, count, skip, selection); break;
-		case VEH_ROAD:     DrawRoadVehImage(v, x, y, selection);            break;
+		case VEH_ROAD:     DrawRoadVehImage(v, x, y, count, selection);     break;
 		case VEH_SHIP:     DrawShipImage(v, x, y, selection);               break;
 		case VEH_AIRCRAFT: DrawAircraftImage(v, x, y, selection);           break;
 		default: NOT_REACHED();
--- a/src/viewport.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/viewport.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -23,6 +23,7 @@
 #include "waypoint.h"
 #include "variables.h"
 #include "train.h"
+#include "roadveh.h"
 
 #define VIEWPORT_DRAW_MEM (65536 * 2)
 
@@ -1764,12 +1765,18 @@
 	ShowTrainViewWindow(v);
 }
 
+static void SafeShowRoadVehViewWindow(const Vehicle *v)
+{
+	if (!IsRoadVehFront(v)) v = GetFirstVehicleInChain(v);
+	ShowRoadVehViewWindow(v);
+}
+
 static void Nop(const Vehicle *v) {}
 
 typedef void OnVehicleClickProc(const Vehicle *v);
 static OnVehicleClickProc* const _on_vehicle_click_proc[] = {
 	SafeShowTrainViewWindow,
-	ShowRoadVehViewWindow,
+	SafeShowRoadVehViewWindow,
 	ShowShipViewWindow,
 	ShowAircraftViewWindow,
 	Nop, // Special vehicles
--- a/src/water_cmd.cpp	Tue Jun 12 18:02:11 2007 +0000
+++ b/src/water_cmd.cpp	Tue Jun 12 19:52:26 2007 +0000
@@ -23,6 +23,7 @@
 #include "depot.h"
 #include "vehicle_gui.h"
 #include "train.h"
+#include "roadveh.h"
 #include "water_map.h"
 #include "newgrf.h"
 #include "newgrf_canal.h"
@@ -641,21 +642,13 @@
 	if (!(v->vehstatus & VS_CRASHED)) {
 		uint16 pass = 0;
 
-		if (v->type == VEH_ROAD) { // flood bus/truck
-			pass = 1; // driver
-			if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count;
-
-			v->vehstatus |= VS_CRASHED;
-			v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast
-			RebuildVehicleLists();
-		} else if (v->type == VEH_TRAIN) {
+		if (v->type == VEH_TRAIN || v->type == VEH_ROAD) {
 			Vehicle *u;
 
 			v = GetFirstVehicleInChain(v);
 			u = v;
-			if (IsFrontEngine(v)) pass = 4; // driver
 
-			/* crash all wagons, and count passangers */
+			/* crash all wagons, and count passengers */
 			BEGIN_ENUM_WAGONS(v)
 				if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count;
 				v->vehstatus |= VS_CRASHED;
@@ -663,7 +656,15 @@
 			END_ENUM_WAGONS(v)
 
 			v = u;
-			v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast
+
+			if (v->type == VEH_TRAIN) {
+				if (IsFrontEngine(v)) pass += 4; // driver
+				v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast
+			} else {
+				if (IsRoadVehFront(v)) pass += 1; // driver
+				v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast
+			}
+
 			RebuildVehicleLists();
 		} else {
 			return;