(svn r9923) -Add: support for Action 0 Road vehicles, property 1C, bit 0.
authorrubidium
Fri, 25 May 2007 22:07:40 +0000
changeset 7187 f7dc3204d457
parent 7186 fe5c15ed69fd
child 7188 78055acf1785
(svn r9923) -Add: support for Action 0 Road vehicles, property 1C, bit 0.
bin/data/tramtrkw.grf
readme.txt
src/gfxinit.cpp
src/lang/english.txt
src/main_gui.cpp
src/misc_gui.cpp
src/newgrf.cpp
src/road.h
src/road_cmd.cpp
src/road_gui.cpp
src/roadveh_cmd.cpp
src/roadveh_gui.cpp
src/station_cmd.cpp
src/table/files.h
src/table/road_land.h
src/table/roadveh.h
src/table/sprites.h
src/tunnelbridge_cmd.cpp
Binary file bin/data/tramtrkw.grf has changed
--- a/readme.txt	Fri May 25 15:49:14 2007 +0000
+++ b/readme.txt	Fri May 25 22:07:40 2007 +0000
@@ -317,6 +317,7 @@
   Richard Kempton (RichK67)      - Additional airports, initial TGP implementation
   Michael Blunck                 - For revolutionizing TTD with awesome graphics
   George                         - Canal graphics
+  David Dallaston (Pikka)        - Tram tracks
   All Translators                - For their support to make OpenTTD a truly international game
   Bug Reporters                  - Thanks for all bug reports
   Chris Sawyer                   - For an amazing game!
--- a/src/gfxinit.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/gfxinit.cpp	Fri May 25 22:07:40 2007 +0000
@@ -396,6 +396,9 @@
 	assert(load_index == SPR_GROUP_BASE);
 	load_index += LoadGrfFile("group.grf", load_index, i++);
 
+	assert(load_index == SPR_TRAMWAY_BASE);
+	load_index += LoadGrfFile("tramtrkw.grf", load_index, i++);
+
 	/* Initialize the unicode to sprite mapping table */
 	InitializeUnicodeGlyphMap();
 
--- a/src/lang/english.txt	Fri May 25 15:49:14 2007 +0000
+++ b/src/lang/english.txt	Fri May 25 22:07:40 2007 +0000
@@ -1597,22 +1597,38 @@
 STR_1801_MUST_REMOVE_ROAD_FIRST                                 :{WHITE}Must remove road first
 STR_ROAD_WORKS_IN_PROGRESS                                      :{WHITE}Road works in progress
 STR_1802_ROAD_CONSTRUCTION                                      :{WHITE}Road Construction
+STR_1802_TRAMWAY_CONSTRUCTION                                   :{WHITE}Tramway Construction
 STR_1803_SELECT_ROAD_BRIDGE                                     :{WHITE}Select Road Bridge
 STR_1804_CAN_T_BUILD_ROAD_HERE                                  :{WHITE}Can't build road here...
+STR_1804_CAN_T_BUILD_TRAMWAY_HERE                               :{WHITE}Can't build tramway here...
 STR_1805_CAN_T_REMOVE_ROAD_FROM                                 :{WHITE}Can't remove road from here...
+STR_1805_CAN_T_REMOVE_TRAMWAY_FROM                              :{WHITE}Can't remove tramway from here...
 STR_1806_ROAD_DEPOT_ORIENTATION                                 :{WHITE}Road Depot Orientation
+STR_1806_TRAM_DEPOT_ORIENTATION                                 :{WHITE}Tram Depot Orientation
 STR_1807_CAN_T_BUILD_ROAD_VEHICLE                               :{WHITE}Can't build road vehicle depot here...
+STR_1807_CAN_T_BUILD_TRAM_VEHICLE                               :{WHITE}Can't build tram vehicle depot here...
 STR_1808_CAN_T_BUILD_BUS_STATION                                :{WHITE}Can't build bus station...
 STR_1809_CAN_T_BUILD_TRUCK_STATION                              :{WHITE}Can't build lorry station...
+STR_1808_CAN_T_BUILD_PASSENGER_TRAM_STATION                     :{WHITE}Can't build passenger tram station...
+STR_1809_CAN_T_BUILD_CARGO_TRAM_STATION                         :{WHITE}Can't build cargo tram station...
 STR_180A_ROAD_CONSTRUCTION                                      :Road construction
+STR_180A_TRAMWAY_CONSTRUCTION                                   :Tramway construction
 STR_180B_BUILD_ROAD_SECTION                                     :{BLACK}Build road section
+STR_180B_BUILD_TRAMWAY_SECTION                                  :{BLACK}Build tramway section
 STR_180C_BUILD_ROAD_VEHICLE_DEPOT                               :{BLACK}Build road vehicle depot (for building and servicing vehicles)
+STR_180C_BUILD_TRAM_VEHICLE_DEPOT                               :{BLACK}Build tram vehicle depot (for building and servicing vehicles)
 STR_180D_BUILD_BUS_STATION                                      :{BLACK}Build bus station
 STR_180E_BUILD_TRUCK_LOADING_BAY                                :{BLACK}Build lorry loading bay
+STR_180D_BUILD_PASSENGER_TRAM_STATION                           :{BLACK}Build passenger tram station
+STR_180E_BUILD_CARGO_TRAM_STATION                               :{BLACK}Build cargo tram station
 STR_180F_BUILD_ROAD_BRIDGE                                      :{BLACK}Build road bridge
+STR_180F_BUILD_TRAMWAY_BRIDGE                                   :{BLACK}Build tramway bridge
 STR_1810_BUILD_ROAD_TUNNEL                                      :{BLACK}Build road tunnel
+STR_1810_BUILD_TRAMWAY_TUNNEL                                   :{BLACK}Build tramway tunnel
 STR_1811_TOGGLE_BUILD_REMOVE_FOR                                :{BLACK}Toggle build/remove for road construction
+STR_1811_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS                       :{BLACK}Toggle build/remove for tramway construction
 STR_1813_SELECT_ROAD_VEHICLE_DEPOT                              :{BLACK}Select road vehicle depot orientation
+STR_1813_SELECT_TRAM_VEHICLE_DEPOT                              :{BLACK}Select tram vehicle depot orientation
 STR_1814_ROAD                                                   :Road
 STR_1815_ROAD_WITH_STREETLIGHTS                                 :Road with streetlights
 STR_1816_TREE_LINED_ROAD                                        :Tree-lined road
@@ -1620,6 +1636,8 @@
 STR_1818_ROAD_RAIL_LEVEL_CROSSING                               :Road/rail level crossing
 STR_CAN_T_REMOVE_BUS_STATION                                    :{WHITE}Can't remove bus station...
 STR_CAN_T_REMOVE_TRUCK_STATION                                  :{WHITE}Can't remove lorry station...
+STR_CAN_T_REMOVE_PASSENGER_TRAM_STATION                         :{WHITE}Can't remove passenger tram station...
+STR_CAN_T_REMOVE_CARGO_TRAM_STATION                             :{WHITE}Can't remove cargo tram station...
 
 ##id 0x2000
 STR_2000_TOWNS                                                  :{WHITE}Towns
@@ -1783,9 +1801,13 @@
 STR_3040_NOW_ACCEPTS                                            :{WHITE}{STATION} now accepts {STRING}
 STR_3041_NOW_ACCEPTS_AND                                        :{WHITE}{STATION} now accepts {STRING} and {STRING}
 STR_3042_BUS_STATION_ORIENTATION                                :{WHITE}Bus Station Orientation
-STR_3043_TRUCK_STATION_ORIENT                                   :{WHITE}Lorry Station Orient.
+STR_3043_TRUCK_STATION_ORIENT                                   :{WHITE}Lorry Station Orientation
+STR_3042_PASSENGER_TRAM_STATION_ORIENTATION                     :{WHITE}Passenger Tram Orientation
+STR_3043_CARGO_TRAM_STATION_ORIENT                              :{WHITE}Cargo Tram Orientation
 STR_3046_MUST_DEMOLISH_BUS_STATION                              :{WHITE}Must demolish bus station first
 STR_3047_MUST_DEMOLISH_TRUCK_STATION                            :{WHITE}Must demolish lorry station first
+STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION                   :{WHITE}Must demolish passenger tram station first
+STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION                       :{WHITE}Must demolish cargo tram station first
 STR_3048_STATIONS                                               :{WHITE}{COMPANY} - {COMMA} Station{P "" s}
 STR_3049_0                                                      :{YELLOW}{STATION} {STATIONFEATURES}
 STR_304A_NONE                                                   :{YELLOW}- None -
@@ -2720,6 +2742,8 @@
 STR_902E_NAME_ROAD_VEHICLE                                      :{BLACK}Name road vehicle
 STR_902F_CITIZENS_CELEBRATE_FIRST                               :{BLACK}{BIGFONT}Citizens celebrate . . .{}First bus arrives at {STATION}!
 STR_9030_CITIZENS_CELEBRATE_FIRST                               :{BLACK}{BIGFONT}Citizens celebrate . . .{}First truck arrives at {STATION}!
+STR_902F_CITIZENS_CELEBRATE_FIRST_TRAM                          :{BLACK}{BIGFONT}Citizens celebrate . . .{}First passenger tram arrives at {STATION}!
+STR_9030_CITIZENS_CELEBRATE_FIRST_TRAM                          :{BLACK}{BIGFONT}Citizens celebrate . . .{}First cargo tram arrives at {STATION}!
 STR_9031_ROAD_VEHICLE_CRASH_DRIVER                              :{BLACK}{BIGFONT}Road Vehicle Crash!{}Driver dies in fireball after collision with train
 STR_9032_ROAD_VEHICLE_CRASH_DIE                                 :{BLACK}{BIGFONT}Road Vehicle Crash!{}{COMMA} die in fireball after collision with train
 STR_9033_CAN_T_MAKE_VEHICLE_TURN                                :{WHITE}Can't make vehicle turn around...
--- a/src/main_gui.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/main_gui.cpp	Fri May 25 22:07:40 2007 +0000
@@ -938,7 +938,7 @@
 {
 	const Player *p = GetPlayer(_local_player);
 	/* The standard road button is *always* available */
-	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 1, ~(p->avail_roadtypes | 1));
+	Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | 1));
 	WP(w2, menu_d).sel_index = _last_built_roadtype;
 }
 
--- a/src/misc_gui.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/misc_gui.cpp	Fri May 25 22:07:40 2007 +0000
@@ -239,6 +239,7 @@
 	"",
 	"  Michael Blunck - Pre-Signals and Semaphores © 2003",
 	"  George - Canal/Lock graphics © 2003-2004",
+	"  David Dallaston - Tram tracks",
 	"  Marcin Grzegorczyk - Foundations for Tracks on Slopes",
 	"  All Translators - Who made OpenTTD a truly international game",
 	"  Bug Reporters - Without whom OpenTTD would still be full of bugs!",
--- a/src/newgrf.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/newgrf.cpp	Fri May 25 22:07:40 2007 +0000
@@ -2905,6 +2905,14 @@
 			replace = SPR_2CCMAP_BASE;
 			break;
 
+		case 0x0B: // tramways
+			if (num != 113) {
+				grfmsg(1, "GraphicsNews: Tramway graphics sprite count must be 113, skipping");
+				return;
+			}
+			replace = SPR_TRAMWAY_BASE;
+			break;
+
 		case 0x0D: // Coast graphics
 			if (num != 16) {
 				grfmsg(1, "GraphicsNew: Coast graphics sprite count must be 16, skipping");
@@ -4237,7 +4245,7 @@
 	                   |                                        (1 << 0x11)  // autoreplace
 	                   |                                        (1 << 0x12)  // autoslope
 	                   |                                        (0 << 0x13)  // followvehicle
-	                   |                                        (0 << 0x14)  // trams
+	                   |                                        (1 << 0x14)  // trams
 	                   |                                        (0 << 0x15)  // enhancetunnels
 	                   |                                        (0 << 0x16)  // shortrvs
 	                   |                                        (0 << 0x17)  // articulatedrvs
--- a/src/road.h	Fri May 25 15:49:14 2007 +0000
+++ b/src/road.h	Fri May 25 22:07:40 2007 +0000
@@ -43,7 +43,7 @@
  */
 static inline bool IsValidRoadType(RoadType rt)
 {
-	return rt == ROADTYPE_ROAD;
+	return rt == ROADTYPE_ROAD || rt == ROADTYPE_TRAM;
 }
 
 /**
@@ -53,7 +53,7 @@
  */
 static inline bool AreValidRoadTypes(RoadTypes rts)
 {
-	return rts == ROADTYPES_ROAD;
+	return HASBIT(rts, ROADTYPE_ROAD) || HASBIT(rts, ROADTYPE_TRAM);
 }
 
 /**
@@ -115,4 +115,6 @@
  */
 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt);
 
+void DrawTramCatenary(TileInfo *ti, RoadBits tram);
+
 #endif /* ROAD_H */
--- a/src/road_cmd.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/road_cmd.cpp	Fri May 25 22:07:40 2007 +0000
@@ -815,19 +815,57 @@
 }
 
 /**
+ * Draws the catenary for the given tile
+ * @param ti   information about the tile (slopes, height etc)
+ * @param tram the roadbits for the tram
+ */
+void DrawTramCatenary(TileInfo *ti, RoadBits tram)
+{
+	/* Don't draw the catenary under a low bridge */
+	if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !HASBIT(_transparent_opt, TO_BUILDINGS)) {
+		uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
+
+		if (height <= TilePixelHeight(ti->tile) + TILE_HEIGHT) return;
+	}
+
+	SpriteID front;
+	SpriteID back;
+
+	if (ti->tileh != SLOPE_FLAT) {
+		back  = SPR_TRAMWAY_BACK_WIRES_SLOPED  + _road_sloped_sprites[ti->tileh - 1];
+		front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
+	} else {
+		back  = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[tram];
+		front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[tram];
+	}
+
+	SpriteID pal = PAL_NONE;
+	if (HASBIT(_transparent_opt, TO_BUILDINGS)) {
+		SETBIT(front, PALETTE_MODIFIER_TRANSPARENT);
+		SETBIT(back,  PALETTE_MODIFIER_TRANSPARENT);
+		pal = PALETTE_TO_TRANSPARENT;
+	}
+
+	AddSortableSpriteToDraw(back,  pal, ti->x, ti->y, 16, 16, 0x20, ti->z);
+	AddSortableSpriteToDraw(front, pal, ti->x, ti->y, 16, 16, 0, ti->z);
+}
+
+/**
  * Draw ground sprite and road pieces
  * @param ti TileInfo
  */
 static void DrawRoadBits(TileInfo* ti)
 {
 	RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
+	RoadBits tram = GetRoadBits(ti->tile, ROADTYPE_TRAM);
+
 	const DrawRoadTileStruct *drts;
 	SpriteID image = 0;
 	SpriteID pal = PAL_NONE;
 	Roadside roadside;
 
 	if (ti->tileh != SLOPE_FLAT) {
-		int foundation = GetRoadFoundation(ti->tileh, road);
+		int foundation = GetRoadFoundation(ti->tileh, road | tram);
 
 		if (foundation != 0) DrawFoundation(ti, foundation);
 
@@ -836,7 +874,7 @@
 		if (ti->tileh != SLOPE_FLAT) image = _road_sloped_sprites[ti->tileh - 1] + 0x53F;
 	}
 
-	if (image == 0) image = _road_tile_sprites_1[road];
+	if (image == 0) image = _road_tile_sprites_1[road != ROAD_NONE ? road : tram];
 
 	roadside = GetRoadside(ti->tile);
 
@@ -853,12 +891,27 @@
 
 	DrawGroundSprite(image, pal);
 
+	/* For tram we overlay the road graphics with either tram tracks only
+	 * (when there is actual road beneath the trams) or with tram tracks
+	 * and some dirts which hides the road graphics */
+	if (tram != ROAD_NONE) {
+		if (ti->tileh != SLOPE_FLAT) {
+			image = _road_sloped_sprites[ti->tileh - 1] + SPR_TRAMWAY_SLOPED_OFFSET;
+		} else {
+			image = _road_tile_sprites_1[tram] - SPR_ROAD_Y;
+		}
+		image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY;
+		DrawGroundSprite(image, pal);
+	}
+
 	if (HasRoadWorks(ti->tile)) {
 		/* Road works */
-		DrawGroundSprite(road & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
+		DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
 		return;
 	}
 
+	if (tram != ROAD_NONE) DrawTramCatenary(ti, tram);
+
 	/* Return if full detail is disabled, or we are zoomed fully out. */
 	if (!HASBIT(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
 
@@ -916,7 +969,12 @@
 
 			palette = PLAYER_SPRITE_COLOR(GetTileOwner(ti->tile));
 
-			dts =  &_road_depot[GetRoadDepotDirection(ti->tile)];
+			if (HASBIT(GetRoadTypes(ti->tile), ROADTYPE_TRAM)) {
+				dts =  &_tram_depot[GetRoadDepotDirection(ti->tile)];
+			} else {
+				dts =  &_road_depot[GetRoadDepotDirection(ti->tile)];
+			}
+
 			DrawGroundSprite(dts->ground_sprite, PAL_NONE);
 
 			for (dtss = dts->seq; dtss->image != 0; dtss++) {
@@ -948,7 +1006,7 @@
 void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt)
 {
 	SpriteID palette = PLAYER_SPRITE_COLOR(_local_player);
-	const DrawTileSprites* dts =  &_road_depot[dir];
+	const DrawTileSprites* dts = (rt == ROADTYPE_TRAM) ? &_tram_depot[dir] : &_road_depot[dir];
 	const DrawTileSeqStruct* dtss;
 
 	x += 33;
--- a/src/road_gui.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/road_gui.cpp	Fri May 25 22:07:40 2007 +0000
@@ -94,6 +94,16 @@
 		SPR_CURSOR_ROAD_NESW,
 		SPR_CURSOR_ROAD_NWSE,
 	},
+	{
+		STR_1804_CAN_T_BUILD_TRAMWAY_HERE,
+		STR_1805_CAN_T_REMOVE_TRAMWAY_FROM,
+		STR_1807_CAN_T_BUILD_TRAM_VEHICLE,
+		{ STR_1808_CAN_T_BUILD_PASSENGER_TRAM_STATION, STR_1809_CAN_T_BUILD_CARGO_TRAM_STATION },
+		{ STR_CAN_T_REMOVE_PASSENGER_TRAM_STATION,     STR_CAN_T_REMOVE_CARGO_TRAM_STATION     },
+
+		SPR_CURSOR_TRAMWAY_NESW,
+		SPR_CURSOR_TRAMWAY_NWSE,
+	},
 };
 
 static void PlaceRoad_Tunnel(TileIndex tile)
@@ -375,13 +385,39 @@
 	BuildRoadToolbWndProc
 };
 
+static const Widget _build_tramway_widgets[] = {
+{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                   STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   205,     0,    13, STR_1802_TRAMWAY_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{  WWT_STICKYBOX,   RESIZE_NONE,     7,   206,   217,     0,    13, 0x0,                        STR_STICKY_BUTTON},
+
+{     WWT_IMGBTN,   RESIZE_NONE,     7,     0,    21,    14,    35, SPR_IMG_TRAMWAY_NW,         STR_180B_BUILD_TRAMWAY_SECTION},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    22,    43,    14,    35, SPR_IMG_TRAMWAY_NE,         STR_180B_BUILD_TRAMWAY_SECTION},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    44,    65,    14,    35, SPR_IMG_DYNAMITE,           STR_018D_DEMOLISH_BUILDINGS_ETC},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    66,    87,    14,    35, SPR_IMG_ROAD_DEPOT,         STR_180C_BUILD_TRAM_VEHICLE_DEPOT},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,    88,   109,    14,    35, SPR_IMG_BUS_STATION,        STR_180D_BUILD_PASSENGER_TRAM_STATION},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,   110,   131,    14,    35, SPR_IMG_TRUCK_BAY,          STR_180E_BUILD_CARGO_TRAM_STATION},
+
+{     WWT_IMGBTN,   RESIZE_NONE,     7,   132,   173,    14,    35, SPR_IMG_BRIDGE,             STR_180F_BUILD_TRAMWAY_BRIDGE},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,   174,   195,    14,    35, SPR_IMG_ROAD_TUNNEL,        STR_1810_BUILD_TRAMWAY_TUNNEL},
+{     WWT_IMGBTN,   RESIZE_NONE,     7,   196,   217,    14,    35, SPR_IMG_REMOVE,             STR_1811_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS},
+{   WIDGETS_END},
+};
+
+static const WindowDesc _build_tramway_desc = {
+	WDP_ALIGN_TBR, 22, 218, 36,
+	WC_BUILD_TOOLBAR, WC_NONE,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
+	_build_tramway_widgets,
+	BuildRoadToolbWndProc
+};
+
 void ShowBuildRoadToolbar(RoadType roadtype)
 {
 	if (!IsValidPlayer(_current_player)) return;
 	_cur_roadtype = roadtype;
 
 	DeleteWindowById(WC_BUILD_TOOLBAR, 0);
-	Window *w = AllocateWindowDesc(&_build_road_desc);
+	Window *w = AllocateWindowDesc(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc);
 	if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w);
 }
 
@@ -462,6 +498,17 @@
 {   WIDGETS_END},
 };
 
+static const Widget _build_tram_depot_widgets[] = {
+{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                        STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   139,     0,    13, STR_1806_TRAM_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{      WWT_PANEL,   RESIZE_NONE,     7,     0,   139,    14,   121, 0x0,                             STR_NULL},
+{      WWT_PANEL,   RESIZE_NONE,    14,    71,   136,    17,    66, 0x0,                             STR_1813_SELECT_TRAM_VEHICLE_DEPOT},
+{      WWT_PANEL,   RESIZE_NONE,    14,    71,   136,    69,   118, 0x0,                             STR_1813_SELECT_TRAM_VEHICLE_DEPOT},
+{      WWT_PANEL,   RESIZE_NONE,    14,     3,    68,    69,   118, 0x0,                             STR_1813_SELECT_TRAM_VEHICLE_DEPOT},
+{      WWT_PANEL,   RESIZE_NONE,    14,     3,    68,    17,    66, 0x0,                             STR_1813_SELECT_TRAM_VEHICLE_DEPOT},
+{   WIDGETS_END},
+};
+
 static const WindowDesc _build_road_depot_desc = {
 	WDP_AUTO, WDP_AUTO, 140, 122,
 	WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
@@ -470,9 +517,17 @@
 	BuildRoadDepotWndProc
 };
 
+static const WindowDesc _build_tram_depot_desc = {
+	WDP_AUTO, WDP_AUTO, 140, 122,
+	WC_BUILD_DEPOT, WC_BUILD_TOOLBAR,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+	_build_tram_depot_widgets,
+	BuildRoadDepotWndProc
+};
+
 static void ShowRoadDepotPicker()
 {
-	AllocateWindowDesc(&_build_road_depot_desc);
+	AllocateWindowDesc(_cur_roadtype == ROADTYPE_ROAD ? &_build_road_depot_desc : &_build_tram_depot_desc);
 }
 
 static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
@@ -581,7 +636,8 @@
 
 static void ShowBusStationPicker()
 {
-	AllocateWindowDesc(&_bus_station_picker_desc);
+	Window *w = AllocateWindowDesc(&_bus_station_picker_desc);
+	if (w != NULL) w->widget[1].data = (_cur_roadtype == ROADTYPE_ROAD) ? STR_3042_BUS_STATION_ORIENTATION : STR_3042_PASSENGER_TRAM_STATION_ORIENTATION;
 }
 
 static const Widget _truck_station_picker_widgets[] = {
@@ -610,7 +666,8 @@
 
 static void ShowTruckStationPicker()
 {
-	AllocateWindowDesc(&_truck_station_picker_desc);
+	Window *w = AllocateWindowDesc(&_truck_station_picker_desc);
+	if (w != NULL) w->widget[1].data = (_cur_roadtype == ROADTYPE_ROAD) ? STR_3043_TRUCK_STATION_ORIENT : STR_3043_CARGO_TRAM_STATION_ORIENT;
 }
 
 void InitializeRoadGui()
--- a/src/roadveh_cmd.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/roadveh_cmd.cpp	Fri May 25 22:07:40 2007 +0000
@@ -472,6 +472,7 @@
 	if (v->type != VEH_ROAD || !CheckOwnership(v->owner)) return CMD_ERROR;
 
 	if (v->vehstatus & VS_STOPPED ||
+			v->u.road.roadtype == ROADTYPE_TRAM ||
 			v->u.road.crashed_ctr != 0 ||
 			v->breakdown_ctr != 0 ||
 			v->u.road.overtaking != 0 ||
@@ -836,7 +837,7 @@
 			SetDParam(0, st->index);
 			flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
 			AddNewsItem(
-				STR_902F_CITIZENS_CELEBRATE_FIRST,
+				v->u.road.roadtype == ROADTYPE_ROAD ? STR_902F_CITIZENS_CELEBRATE_FIRST : STR_902F_CITIZENS_CELEBRATE_FIRST_TRAM,
 				flags,
 				v->index,
 				0);
@@ -850,7 +851,7 @@
 			SetDParam(0, st->index);
 			flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
 			AddNewsItem(
-				STR_9030_CITIZENS_CELEBRATE_FIRST,
+				v->u.road.roadtype == ROADTYPE_ROAD ? STR_9030_CITIZENS_CELEBRATE_FIRST : STR_9030_CITIZENS_CELEBRATE_FIRST_TRAM,
 				flags,
 				v->index,
 				0
@@ -1303,7 +1304,7 @@
 		v->direction = DiagDirToDir(dir);
 
 		tdir = _roadveh_depot_exit_trackdir[dir];
-		rdp = _road_drive_data[(_opt.road_side << RVS_DRIVE_SIDE) + tdir];
+		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);
@@ -1372,7 +1373,7 @@
 	/* Get move position data for next frame.
 	 * For a drive-through road stop use 'straight road' move data.
 	 * In this case v->u.road.state is masked to give the road stop entry direction. */
-	rd = _road_drive_data[(
+	rd = _road_drive_data[v->u.road.roadtype][(
 		(HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
 		(_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
 
@@ -1391,11 +1392,27 @@
 again:
 		if (IsReversingRoadTrackdir(dir)) {
 			/* Turning around */
-			tile = v->tile;
+			if (v->u.road.roadtype == ROADTYPE_TRAM) {
+				RoadBits needed; // The road bits the tram needs to be able to turn around
+				switch (dir) {
+					default: NOT_REACHED();
+					case TRACKDIR_RVREV_NE: needed = ROAD_SW; break;
+					case TRACKDIR_RVREV_SE: needed = ROAD_NW; break;
+					case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
+					case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
+				}
+				if (!IsTileType(tile, MP_STREET) || (needed & GetRoadBits(tile, ROADTYPE_TRAM)) == ROAD_NONE) {
+					/* The tram cannot turn here */
+					v->cur_speed = 0;
+					return;
+				}
+			} else {
+				tile = v->tile;
+			}
 		}
 
 		/* Get position data for first frame on the new tile */
-		rdp = _road_drive_data[(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking];
+		rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking];
 
 		x = TileX(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].x;
 		y = TileY(tile) * TILE_SIZE + rdp[RVC_DEFAULT_START_FRAME].y;
@@ -1462,7 +1479,7 @@
 			return;
 		}
 
-		rdp = _road_drive_data[(_opt.road_side << RVS_DRIVE_SIDE) + dir];
+		rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir];
 
 		x = TileX(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].x;
 		y = TileY(v->tile) * TILE_SIZE + rdp[RVC_TURN_AROUND_START_FRAME].y;
--- a/src/roadveh_gui.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/roadveh_gui.cpp	Fri May 25 22:07:40 2007 +0000
@@ -192,7 +192,7 @@
 		bool is_localplayer = v->owner == _local_player;
 
 		SetWindowWidgetDisabledState(w,  7, !is_localplayer);
-		SetWindowWidgetDisabledState(w,  8, !is_localplayer);
+		SetWindowWidgetDisabledState(w,  8, !is_localplayer || v->u.road.roadtype == ROADTYPE_TRAM);
 		SetWindowWidgetDisabledState(w, 11, !is_localplayer);
 		/* Disable refit button if vehicle not refittable */
 		SetWindowWidgetDisabledState(w, 12, !is_localplayer ||
--- a/src/station_cmd.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/station_cmd.cpp	Fri May 25 22:07:40 2007 +0000
@@ -1266,9 +1266,13 @@
 	if (build_over_road) {
 		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
 		if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) return CMD_ERROR;
-		if (!IsTileOwner(tile, OWNER_TOWN) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD)) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR;
+
+		RoadTypes cur_rts = GetRoadTypes(tile);
+		if (!IsTileOwner(tile, OWNER_TOWN) && (
+				((HASBIT(cur_rts, ROADTYPE_ROAD) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD)))) ||
+				((HASBIT(cur_rts, ROADTYPE_TRAM) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM)))))) return CMD_ERROR;
 		/* Do not remove roadtypes! */
-		if (rts != GetRoadTypes(tile) && rts != ROADTYPES_ROADTRAM) return CMD_ERROR;
+		rts |= GetRoadTypes(tile);
 	}
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1986,7 +1990,15 @@
 static void DrawTile_Station(TileInfo *ti)
 {
 	const DrawTileSprites *t = NULL;
-	RailType railtype = GetRailType(ti->tile);
+	RailType railtype;
+	RoadTypes roadtypes;
+	if (IsRailwayStation(ti->tile)) {
+		railtype = GetRailType(ti->tile);
+		roadtypes = ROADTYPES_NONE;
+	} else {
+		roadtypes = GetRoadTypes(ti->tile);
+		railtype = RAILTYPE_BEGIN;
+	}
 	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 	uint32 relocation = 0;
 	const Station *st = NULL;
@@ -2045,6 +2057,12 @@
 
 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
 
+	if (HASBIT(roadtypes, ROADTYPE_TRAM)) {
+		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
+		DrawGroundSprite((HASBIT(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
+		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
+	}
+
 	if (IsBuoyTile(ti->tile) && (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER))) DrawCanalWater(ti->tile);
 
 	const DrawTileSeqStruct *dtss;
@@ -2088,6 +2106,10 @@
 	SpriteID img = t->ground_sprite;
 	DrawSprite(img + rti->total_offset, HASBIT(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
 
+	if (roadtype == ROADTYPE_TRAM) {
+		DrawSprite(SPR_TRAMWAY_TRAM + (t->ground_sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
+	}
+
 	const DrawTileSeqStruct *dtss;
 	foreach_draw_tile_seq(dtss, t->seq) {
 		Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z);
@@ -2742,8 +2764,8 @@
 		switch (GetStationType(tile)) {
 			case STATION_RAIL:    return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD);
 			case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST);
-			case STATION_TRUCK:   return_cmd_error(STR_3047_MUST_DEMOLISH_TRUCK_STATION);
-			case STATION_BUS:     return_cmd_error(STR_3046_MUST_DEMOLISH_BUS_STATION);
+			case STATION_TRUCK:   return_cmd_error(HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION);
+			case STATION_BUS:     return_cmd_error(HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION);
 			case STATION_BUOY:    return_cmd_error(STR_306A_BUOY_IN_THE_WAY);
 			case STATION_DOCK:    return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST);
 			case STATION_OILRIG:
--- a/src/table/files.h	Fri May 25 15:49:14 2007 +0000
+++ b/src/table/files.h	Fri May 25 22:07:40 2007 +0000
@@ -63,4 +63,5 @@
 	{ "trkfoundw.grf", { 0x12, 0x33, 0x3f, 0xa3, 0xd1, 0x86, 0x8b, 0x04, 0x53, 0x18, 0x9c, 0xee, 0xf9, 0x2d, 0xf5, 0x95 } },
 	{ "roadstops.grf", { 0x8c, 0xd9, 0x45, 0x21, 0x28, 0x82, 0x96, 0x45, 0x33, 0x22, 0x7a, 0xb9, 0x0d, 0xf3, 0x67, 0x4a } },
 	{ "group.grf",     { 0xe8, 0x52, 0x5f, 0x1c, 0x3e, 0xf9, 0x91, 0x9d, 0x0f, 0x70, 0x8c, 0x8a, 0x21, 0xa4, 0xc7, 0x02 } },
+	{ "tramtrkw.grf",  { 0x83, 0x0a, 0xf4, 0x9f, 0x29, 0x10, 0x48, 0xfd, 0x76, 0xe9, 0xda, 0xac, 0x5d, 0xa2, 0x30, 0x45 } },
 };
--- a/src/table/road_land.h	Fri May 25 15:49:14 2007 +0000
+++ b/src/table/road_land.h	Fri May 25 22:07:40 2007 +0000
@@ -32,6 +32,35 @@
 	{ 0xA4A, PAL_NONE, _road_depot_NW }
 };
 
+static const DrawTileSeqStruct _tram_depot_NE[] = {
+	TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x35 | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE, 0, 15, 16, 1)
+	TILE_SEQ_END()
+};
+
+static const DrawTileSeqStruct _tram_depot_SE[] = {
+	TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x31, PAL_NONE, 0, 0, 1, 16)
+	TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x32 | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE, 15, 0, 1, 16)
+	TILE_SEQ_END()
+};
+
+static const DrawTileSeqStruct _tram_depot_SW[] = {
+	TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x33, PAL_NONE, 0, 0, 16, 1)
+	TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x34 | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE, 0, 15, 16, 1)
+	TILE_SEQ_END()
+};
+
+static const DrawTileSeqStruct _tram_depot_NW[] = {
+	TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x36 | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE, 15, 0, 1, 16)
+	TILE_SEQ_END()
+};
+
+static const DrawTileSprites _tram_depot[] = {
+	{ 0xA4A, PAL_NONE, _tram_depot_NE },
+	{ 0xA4A, PAL_NONE, _tram_depot_SE },
+	{ 0xA4A, PAL_NONE, _tram_depot_SW },
+	{ 0xA4A, PAL_NONE, _tram_depot_NW }
+};
+
 #undef TILE_SEQ_BEGIN
 #undef TILE_SEQ_LINE
 #undef TILE_SEQ_END
@@ -42,7 +71,13 @@
   0x543, 0x53C, 0x535, 0x538, 0x53D, 0x537, 0x53A, 0x536
 };
 
+static const SpriteID _road_frontwire_sprites_1[16] = {
+	0, 0x37, 0x37, 0x3F, 0x37, 0x37, 0x43, 0x37, 0x37, 0x3F, 0x37, 0x37, 0x3F, 0x37, 0x37, 0x37
+};
 
+static const SpriteID _road_backpole_sprites_1[16] = {
+	0, 0x38, 0x39, 0x40, 0x38, 0x38, 0x43, 0x3E, 0x39, 0x41, 0x39, 0x3C, 0x42, 0x3B, 0x3D, 0x3A
+};
 
 #define MAKELINE(a, b, c) { a, b, c },
 #define ENDLINE { 0, 0, 0 }
--- a/src/table/roadveh.h	Fri May 25 15:49:14 2007 +0000
+++ b/src/table/roadveh.h	Fri May 25 22:07:40 2007 +0000
@@ -1011,7 +1011,7 @@
 	{RDE_NEXT_TILE | DIAGDIR_SE, 0}
 };
 
-static const RoadDriveEntry * const _road_drive_data[] = {
+static const RoadDriveEntry * const _road_road_drive_data[] = {
 	_roadveh_drive_data_0,
 	_roadveh_drive_data_1,
 	_roadveh_drive_data_2,
@@ -1077,3 +1077,386 @@
 	NULL,
 	NULL,
 };
+
+static const RoadDriveEntry _roadveh_tram_turn_ne_0[] = {
+	{15, 5},
+	{14, 5},
+	{13, 5},
+	{12, 5},
+	{11, 5},
+	{10, 5},
+	{ 9, 5},
+	{ 8, 5},
+	{ 7, 5},
+	{ 6, 5},
+	{ 5, 5},
+	{ 4, 5},
+	{ 3, 5},
+	{ 2, 5},
+	{ 1, 5},
+	{ 0, 5},
+	{ 0, 6},
+	{ 0, 7},
+	{ 0, 8},
+	{ 0, 9},
+	{ 1, 9},
+	{ 2, 9},
+	{ 3, 9},
+	{ 4, 9},
+	{ 5, 9},
+	{ 6, 9},
+	{ 7, 9},
+	{ 8, 9},
+	{ 9, 9},
+	{10, 9},
+	{11, 9},
+	{12, 9},
+	{13, 9},
+	{14, 9},
+	{15, 9},
+	{RDE_NEXT_TILE | DIAGDIR_SW, 0}
+};
+
+static const RoadDriveEntry _roadveh_tram_turn_ne_1[] = {
+	{15, 9},
+	{14, 9},
+	{13, 9},
+	{12, 9},
+	{11, 9},
+	{10, 9},
+	{ 9, 9},
+	{ 8, 9},
+	{ 7, 9},
+	{ 6, 9},
+	{ 5, 9},
+	{ 4, 9},
+	{ 3, 9},
+	{ 2, 9},
+	{ 1, 9},
+	{ 0, 9},
+	{ 0, 8},
+	{ 0, 7},
+	{ 0, 6},
+	{ 0, 5},
+	{ 1, 5},
+	{ 2, 5},
+	{ 3, 5},
+	{ 4, 5},
+	{ 5, 5},
+	{ 6, 5},
+	{ 7, 5},
+	{ 8, 5},
+	{ 9, 5},
+	{10, 5},
+	{11, 5},
+	{12, 5},
+	{13, 5},
+	{14, 5},
+	{15, 5},
+	{RDE_NEXT_TILE | DIAGDIR_SW, 0}
+};
+
+static const RoadDriveEntry _roadveh_tram_turn_se_0[] = {
+	{5,  0},
+	{5,  1},
+	{5,  2},
+	{5,  3},
+	{5,  4},
+	{5,  5},
+	{5,  6},
+	{5,  7},
+	{5,  8},
+	{5,  9},
+	{5, 10},
+	{5, 11},
+	{5, 12},
+	{5, 13},
+	{5, 14},
+	{5, 15},
+	{6, 15},
+	{7, 15},
+	{8, 15},
+	{9, 15},
+	{9, 14},
+	{9, 13},
+	{9, 12},
+	{9, 11},
+	{9, 10},
+	{9,  9},
+	{9,  8},
+	{9,  7},
+	{9,  6},
+	{9,  5},
+	{9,  4},
+	{9,  3},
+	{9,  2},
+	{9,  1},
+	{9,  0},
+	{RDE_TURNED | DIAGDIR_NW, 0}
+};
+
+static const RoadDriveEntry _roadveh_tram_turn_se_1[] = {
+	{9,  0},
+	{9,  1},
+	{9,  2},
+	{9,  3},
+	{9,  4},
+	{9,  5},
+	{9,  6},
+	{9,  7},
+	{9,  8},
+	{9,  9},
+	{9, 10},
+	{9, 11},
+	{9, 12},
+	{9, 13},
+	{9, 14},
+	{9, 15},
+	{8, 15},
+	{7, 15},
+	{6, 15},
+	{5, 15},
+	{5, 14},
+	{5, 13},
+	{5, 12},
+	{5, 11},
+	{5, 10},
+	{5,  9},
+	{5,  8},
+	{5,  7},
+	{5,  6},
+	{5,  5},
+	{5,  4},
+	{5,  3},
+	{5,  2},
+	{5,  1},
+	{5,  0},
+	{RDE_NEXT_TILE | DIAGDIR_NW, 0}
+};
+
+static const RoadDriveEntry _roadveh_tram_turn_sw_0[] = {
+	{ 0, 9},
+	{ 1, 9},
+	{ 2, 9},
+	{ 3, 9},
+	{ 4, 9},
+	{ 5, 9},
+	{ 6, 9},
+	{ 7, 9},
+	{ 8, 9},
+	{ 9, 9},
+	{10, 9},
+	{11, 9},
+	{12, 9},
+	{13, 9},
+	{14, 9},
+	{15, 9},
+	{15, 8},
+	{15, 7},
+	{15, 6},
+	{15, 5},
+	{14, 5},
+	{13, 5},
+	{12, 5},
+	{11, 5},
+	{10, 5},
+	{ 9, 5},
+	{ 8, 5},
+	{ 7, 5},
+	{ 6, 5},
+	{ 5, 5},
+	{ 4, 5},
+	{ 3, 5},
+	{ 2, 5},
+	{ 1, 5},
+	{ 0, 5},
+	{RDE_NEXT_TILE | DIAGDIR_NE, 0}
+};
+static const RoadDriveEntry _roadveh_tram_turn_sw_1[] = {
+	{ 0, 5},
+	{ 1, 5},
+	{ 2, 5},
+	{ 3, 5},
+	{ 4, 5},
+	{ 5, 5},
+	{ 6, 5},
+	{ 7, 5},
+	{ 8, 5},
+	{ 9, 5},
+	{10, 5},
+	{11, 5},
+	{12, 5},
+	{13, 5},
+	{14, 5},
+	{15, 5},
+	{15, 6},
+	{15, 7},
+	{15, 8},
+	{15, 9},
+	{14, 9},
+	{13, 9},
+	{12, 9},
+	{11, 9},
+	{10, 9},
+	{ 9, 9},
+	{ 8, 9},
+	{ 7, 9},
+	{ 6, 9},
+	{ 5, 9},
+	{ 4, 9},
+	{ 3, 9},
+	{ 2, 9},
+	{ 1, 9},
+	{ 0, 9},
+	{RDE_NEXT_TILE | DIAGDIR_NE, 0}
+};
+
+static const RoadDriveEntry _roadveh_tram_turn_nw_0[] = {
+	{9, 15},
+	{9, 14},
+	{9, 13},
+	{9, 12},
+	{9, 11},
+	{9, 10},
+	{9,  9},
+	{9,  8},
+	{9,  7},
+	{9,  6},
+	{9,  5},
+	{9,  4},
+	{9,  3},
+	{9,  2},
+	{9,  1},
+	{9,  0},
+	{8,  0},
+	{7,  0},
+	{6,  0},
+	{5,  0},
+	{5,  1},
+	{5,  2},
+	{5,  3},
+	{5,  4},
+	{5,  5},
+	{5,  6},
+	{5,  7},
+	{5,  8},
+	{5,  9},
+	{5, 10},
+	{5, 11},
+	{5, 12},
+	{5, 13},
+	{5, 14},
+	{5, 15},
+	{RDE_NEXT_TILE | DIAGDIR_SE, 0}
+};
+static const RoadDriveEntry _roadveh_tram_turn_nw_1[] = {
+	{5, 15},
+	{5, 14},
+	{5, 13},
+	{5, 12},
+	{5, 11},
+	{5, 10},
+	{5,  9},
+	{5,  8},
+	{5,  7},
+	{5,  6},
+	{5,  5},
+	{5,  4},
+	{5,  3},
+	{5,  2},
+	{5,  1},
+	{5,  0},
+	{6,  0},
+	{7,  0},
+	{8,  0},
+	{9,  0},
+	{9,  1},
+	{9,  2},
+	{9,  3},
+	{9,  4},
+	{9,  5},
+	{9,  6},
+	{9,  7},
+	{9,  8},
+	{9,  9},
+	{9, 10},
+	{9, 11},
+	{9, 12},
+	{9, 13},
+	{9, 14},
+	{9, 15},
+	{RDE_NEXT_TILE | DIAGDIR_SE, 0}
+};
+
+static const RoadDriveEntry * const _road_tram_drive_data[] = {
+	_roadveh_drive_data_0,
+	_roadveh_drive_data_1,
+	_roadveh_drive_data_2,
+	_roadveh_drive_data_3,
+	_roadveh_drive_data_4,
+	_roadveh_drive_data_5,
+	_roadveh_tram_turn_ne_0,
+	_roadveh_tram_turn_se_0,
+	_roadveh_drive_data_8,
+	_roadveh_drive_data_9,
+	_roadveh_drive_data_10,
+	_roadveh_drive_data_11,
+	_roadveh_drive_data_12,
+	_roadveh_drive_data_13,
+	_roadveh_tram_turn_sw_0,
+	_roadveh_tram_turn_nw_0,
+	_roadveh_drive_data_16,
+	_roadveh_drive_data_17,
+	_roadveh_drive_data_18,
+	_roadveh_drive_data_19,
+	_roadveh_drive_data_20,
+	_roadveh_drive_data_21,
+	_roadveh_tram_turn_ne_1,
+	_roadveh_tram_turn_se_1,
+	_roadveh_drive_data_24,
+	_roadveh_drive_data_25,
+	_roadveh_drive_data_26,
+	_roadveh_drive_data_27,
+	_roadveh_drive_data_28,
+	_roadveh_drive_data_29,
+	_roadveh_tram_turn_sw_1,
+	_roadveh_tram_turn_nw_1,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+};
+
+static const RoadDriveEntry * const * const _road_drive_data[2] = {
+	_road_road_drive_data,
+	_road_tram_drive_data,
+};
--- a/src/table/sprites.h	Fri May 25 15:49:14 2007 +0000
+++ b/src/table/sprites.h	Fri May 25 22:07:40 2007 +0000
@@ -150,6 +150,24 @@
 	SPR_GROUP_REPLACE_OFF_SHIP     = SPR_GROUP_BASE + 18,
 	SPR_GROUP_REPLACE_OFF_AIRCRAFT = SPR_GROUP_BASE + 19,
 
+	/* Tramway sprites */
+	SPR_TRAMWAY_BASE                 = SPR_GROUP_BASE + 20,
+	SPR_TRAMWAY_OVERLAY              = SPR_TRAMWAY_BASE + 4,
+	SPR_TRAMWAY_TRAM                 = SPR_TRAMWAY_BASE + 27,
+	SPR_TRAMWAY_SLOPED_OFFSET        = 11,
+	SPR_TRAMWAY_BUS_STOP_DT_Y_W      = SPR_TRAMWAY_BASE + 25,
+	SPR_TRAMWAY_BUS_STOP_DT_Y_E      = SPR_TRAMWAY_BASE + 23,
+	SPR_TRAMWAY_BUS_STOP_DT_X_W      = SPR_TRAMWAY_BASE + 24,
+	SPR_TRAMWAY_BUS_STOP_DT_X_E      = SPR_TRAMWAY_BASE + 26,
+	SPR_TRAMWAY_PAVED_STRAIGHT_Y     = SPR_TRAMWAY_BASE + 46,
+	SPR_TRAMWAY_PAVED_STRAIGHT_X     = SPR_TRAMWAY_BASE + 47,
+	SPR_TRAMWAY_BACK_WIRES_STRAIGHT  = SPR_TRAMWAY_BASE + 55,
+	SPR_TRAMWAY_FRONT_WIRES_STRAIGHT = SPR_TRAMWAY_BASE + 56,
+	SPR_TRAMWAY_BACK_WIRES_SLOPED    = SPR_TRAMWAY_BASE + 72,
+	SPR_TRAMWAY_FRONT_WIRES_SLOPED   = SPR_TRAMWAY_BASE + 68,
+	SPR_TRAMWAY_TUNNEL_WIRES         = SPR_TRAMWAY_BASE + 80,
+	SPR_TRAMWAY_BRIDGE               = SPR_TRAMWAY_BASE + 107,
+
 	/* Manager face sprites */
 	SPR_GRADIENT = 874, // background gradient behind manager face
 
@@ -1178,6 +1196,8 @@
 	SPR_IMG_BRIDGE        = 2594,
 	SPR_IMG_ROAD_TUNNEL   = 2429,
 	SPR_IMG_REMOVE        = 714,
+	SPR_IMG_TRAMWAY_NW    = SPR_TRAMWAY_BASE + 0,
+	SPR_IMG_TRAMWAY_NE    = SPR_TRAMWAY_BASE + 1,
 
 	/* rail_gui.c */
 	SPR_IMG_RAIL_NS    = 1251,
@@ -1294,6 +1314,8 @@
 	/* road cursors */
 	SPR_CURSOR_ROAD_NESW      = 1311,
 	SPR_CURSOR_ROAD_NWSE      = 1312,
+	SPR_CURSOR_TRAMWAY_NESW   = SPR_TRAMWAY_BASE + 2,
+	SPR_CURSOR_TRAMWAY_NWSE   = SPR_TRAMWAY_BASE + 3,
 
 	SPR_CURSOR_ROAD_DEPOT     = 1297,
 	SPR_CURSOR_BUS_STATION    = 2725,
--- a/src/tunnelbridge_cmd.cpp	Fri May 25 15:49:14 2007 +0000
+++ b/src/tunnelbridge_cmd.cpp	Fri May 25 22:07:40 2007 +0000
@@ -859,6 +859,36 @@
 }
 
 /**
+ * Draws the trambits over an already drawn (lower end) of a bridge.
+ * @param x       the x of the bridge
+ * @param y       the y of the bridge
+ * @param z       the z of the bridge
+ * @param offset  number representing whether to level or sloped and the direction
+ * @param overlay do we want to still see the road?
+ */
+static void DrawBridgeTramBits(int x, int y, byte z, int offset, bool overlay)
+{
+	static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
+	static const SpriteID back_offsets[6]    =   {  95,  95,  99, 102, 100, 101 };
+	static const SpriteID front_offsets[6]   =   {  97,  98, 103, 106, 104, 105 };
+
+	AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE, x, y, 16, 16, offset >= 2 ? 1 : 0, z);
+
+	SpriteID front = SPR_TRAMWAY_BASE + front_offsets[offset];
+	SpriteID back  = SPR_TRAMWAY_BASE + back_offsets[offset];
+	SpriteID pal   = PAL_NONE;
+	if (HASBIT(_transparent_opt, TO_BUILDINGS)) {
+		SETBIT(front, PALETTE_MODIFIER_TRANSPARENT);
+		SETBIT(back,  PALETTE_MODIFIER_TRANSPARENT);
+		pal = PALETTE_TO_TRANSPARENT;
+	}
+
+	AddSortableSpriteToDraw(back,  pal, x, y, 16, 16, 0, z);
+	/* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
+	AddSortableSpriteToDraw(front, pal, x, y, 16, 16, offset >= 2 ? 0x30 : 0x10, z);
+}
+
+/**
  * Draws a tunnel of bridge tile.
  * For tunnels, this is rather simple, as you only needa draw the entrance.
  * Bridges are a bit more complex. base_offset is where the sprite selection comes into play
@@ -887,7 +917,17 @@
 
 		image += GetTunnelDirection(ti->tile) * 2;
 		DrawGroundSprite(image, PAL_NONE);
-		if (GetTunnelTransportType(ti->tile) == TRANSPORT_RAIL && GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
+		if (GetTunnelTransportType(ti->tile) == TRANSPORT_ROAD) {
+			DiagDirection dir = GetTunnelDirection(ti->tile);
+			RoadTypes rts = GetRoadTypes(ti->tile);
+
+			if (HASBIT(rts, ROADTYPE_TRAM)) {
+				static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, {  5, 76, 77,  4 } };
+
+				DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][dir], PAL_NONE);
+				AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + dir, PAL_NONE, ti->x, ti->y, 16, 16, 16, (byte)ti->z);
+			}
+		} else if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
 			DrawCatenary(ti);
 		}
 
@@ -927,10 +967,6 @@
 			DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh], PAL_NONE);
 		}
 
-		if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL && GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
-			DrawCatenary(ti);
-		}
-
 		image = psid->sprite;
 
 		/* draw ramp */
@@ -945,9 +981,26 @@
 		 * it doesn't disappear behind it
 		 */
 		AddSortableSpriteToDraw(
-			image, pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 1 : 8, ti->z
+			image, pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z
 		);
 
+		if (GetBridgeTransportType(ti->tile) == TRANSPORT_ROAD) {
+			RoadTypes rts = GetRoadTypes(ti->tile);
+
+			if (HASBIT(rts, ROADTYPE_TRAM)) {
+				uint offset = GetBridgeRampDirection(ti->tile);
+				if (ti->tileh != SLOPE_FLAT) {
+					offset = (offset + 1) & 1;
+					ti->z += TILE_HEIGHT;
+				} else {
+					offset += 2;
+				}
+				DrawBridgeTramBits(ti->x, ti->y, ti->z, offset, HASBIT(rts, ROADTYPE_ROAD));
+			}
+		} else if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
+			DrawCatenary(ti);
+		}
+
 		DrawBridgeMiddle(ti);
 	}
 }
@@ -1023,7 +1076,8 @@
 
 	x = ti->x;
 	y = ti->y;
-	z = GetBridgeHeight(rampsouth) - 3;
+	uint bridge_z = GetBridgeHeight(rampsouth);
+	z = bridge_z - 3;
 
 	image = psid->sprite;
 	if (HASBIT(_transparent_opt, TO_BRIDGES)) {
@@ -1048,7 +1102,13 @@
 		pal = psid->pal;
 	}
 
-	if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) {
+	if (GetBridgeTransportType(rampsouth) == TRANSPORT_ROAD) {
+		RoadTypes rts = GetRoadTypes(rampsouth);
+
+		if (HASBIT(rts, ROADTYPE_TRAM)) {
+			DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HASBIT(rts, ROADTYPE_ROAD));
+		}
+	} else if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) {
 		DrawCatenary(ti);
 	}