From 17390241e651cb9d5ef60aceb56e14fd50a16199 Mon Sep 17 00:00:00 2001 From: rubidium Date: Fri, 25 May 2007 22:07:40 +0000 Subject: [PATCH] (svn r9923) -Add: support for Action 0 Road vehicles, property 1C, bit 0. --- bin/data/tramtrkw.grf | Bin 0 -> 42018 bytes readme.txt | 1 + src/gfxinit.cpp | 3 + src/lang/english.txt | 26 ++- src/main_gui.cpp | 2 +- src/misc_gui.cpp | 1 + src/newgrf.cpp | 10 +- src/road.h | 6 +- src/road_cmd.cpp | 68 ++++++- src/road_gui.cpp | 65 ++++++- src/roadveh_cmd.cpp | 31 +++- src/roadveh_gui.cpp | 2 +- src/station_cmd.cpp | 32 +++- src/table/files.h | 1 + src/table/road_land.h | 35 ++++ src/table/roadveh.h | 385 ++++++++++++++++++++++++++++++++++++++- src/table/sprites.h | 22 +++ src/tunnelbridge_cmd.cpp | 76 +++++++- 18 files changed, 730 insertions(+), 36 deletions(-) create mode 100644 bin/data/tramtrkw.grf diff --git a/bin/data/tramtrkw.grf b/bin/data/tramtrkw.grf new file mode 100644 index 0000000000000000000000000000000000000000..d4a38d1f8c4a69f892d875d66961b98c070e8a50 GIT binary patch literal 42018 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 yosdG}dszlpVTA3I*rI_OCVRAO8hiRT3@$ literal 0 HcmV?d00001 diff --git a/readme.txt b/readme.txt index 41bb82da19..7b32a912ab 100644 --- a/readme.txt +++ b/readme.txt @@ -317,6 +317,7 @@ Thanks to: 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! diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 6ff742f0c5..5faad52d49 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -396,6 +396,9 @@ static void LoadSpriteTables() 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(); diff --git a/src/lang/english.txt b/src/lang/english.txt index 49b46ba28c..e01f17c9e0 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1597,22 +1597,38 @@ STR_MUST_REMOVE_RAILWAY_STATION_FIRST :{WHITE}Must rem 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_1817_ROAD_VEHICLE_DEPOT :Road vehicle de 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_303F_NO_LONGER_ACCEPTS_OR :{WHITE}{STATION 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_902D_CAN_T_NAME_ROAD_VEHICLE :{WHITE}Can't na 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... diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 97d146cad6..d48cd82fb7 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -938,7 +938,7 @@ static void ToolbarBuildRoadClick(Window *w) { 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; } diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 34c1564d57..92c7ac9ce9 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -239,6 +239,7 @@ static const char *credits[] = { "", " 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!", diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 6095832ed0..9c04ec9d1a 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2905,6 +2905,14 @@ static void GraphicsNew(byte *buf, int len) 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 @@ static void InitializeGRFSpecial() | (1 << 0x11) // autoreplace | (1 << 0x12) // autoslope | (0 << 0x13) // followvehicle - | (0 << 0x14) // trams + | (1 << 0x14) // trams | (0 << 0x15) // enhancetunnels | (0 << 0x16) // shortrvs | (0 << 0x17) // articulatedrvs diff --git a/src/road.h b/src/road.h index 4c875dce00..acb958246e 100644 --- a/src/road.h +++ b/src/road.h @@ -43,7 +43,7 @@ DECLARE_ENUM_AS_BIT_SET(RoadTypes); */ static inline bool IsValidRoadType(RoadType rt) { - return rt == ROADTYPE_ROAD; + return rt == ROADTYPE_ROAD || rt == ROADTYPE_TRAM; } /** @@ -53,7 +53,7 @@ static inline bool IsValidRoadType(RoadType rt) */ static inline bool AreValidRoadTypes(RoadTypes rts) { - return rts == ROADTYPES_ROAD; + return HASBIT(rts, ROADTYPE_ROAD) || HASBIT(rts, ROADTYPE_TRAM); } /** @@ -115,4 +115,6 @@ static inline bool IsStraightRoadTrackdir(Trackdir dir) */ bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt); +void DrawTramCatenary(TileInfo *ti, RoadBits tram); + #endif /* ROAD_H */ diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 394dcc3700..b85017d2e4 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -814,6 +814,42 @@ static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside) roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS)); } +/** + * 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 @@ -821,13 +857,15 @@ static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside) 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 @@ static void DrawRoadBits(TileInfo* ti) 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 @@ static void DrawRoadBits(TileInfo* ti) 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 @@ static void DrawTile_Road(TileInfo *ti) 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 @@ static void DrawTile_Road(TileInfo *ti) 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; diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 3723f675f2..c5dbc9c2ae 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -94,6 +94,16 @@ static const RoadTypeInfo _road_type_infos[] = { 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 @@ static const WindowDesc _build_road_desc = { 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 @@ static const Widget _build_road_depot_widgets[] = { { 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 @@ static const WindowDesc _build_road_depot_desc = { 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 const WindowDesc _bus_station_picker_desc = { 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 const WindowDesc _truck_station_picker_desc = { 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() diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 9a00a6af4d..4381572ec4 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -472,6 +472,7 @@ int32 CmdTurnRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) 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 @@ static void RoadVehArrivesAt(const Vehicle* v, Station* st) 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 @@ static void RoadVehArrivesAt(const Vehicle* v, Station* st) 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 @@ static void RoadVehController(Vehicle *v) 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 @@ static void RoadVehController(Vehicle *v) /* 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 @@ static void RoadVehController(Vehicle *v) 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 @@ again: 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; diff --git a/src/roadveh_gui.cpp b/src/roadveh_gui.cpp index b5f80b4f7e..332a8042d2 100644 --- a/src/roadveh_gui.cpp +++ b/src/roadveh_gui.cpp @@ -192,7 +192,7 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e) 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 || diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 026c503d7a..b1338b5ab9 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1266,9 +1266,13 @@ int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) 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 @@ extern void DrawCanalWater(TileIndex tile); 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 @@ static void DrawTile_Station(TileInfo *ti) 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 @@ void StationPickerDrawSprite(int x, int y, RailType railtype, RoadType roadtype, 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 @@ static int32 ClearTile_Station(TileIndex tile, byte flags) 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: diff --git a/src/table/files.h b/src/table/files.h index 79522ab34c..bd7b0a439e 100644 --- a/src/table/files.h +++ b/src/table/files.h @@ -63,4 +63,5 @@ static MD5File files_openttd[] = { { "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 } }, }; diff --git a/src/table/road_land.h b/src/table/road_land.h index 9e40b54bc9..bf3f616939 100644 --- a/src/table/road_land.h +++ b/src/table/road_land.h @@ -32,6 +32,35 @@ static const DrawTileSprites _road_depot[] = { { 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 @@ static const SpriteID _road_tile_sprites_1[16] = { 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 } diff --git a/src/table/roadveh.h b/src/table/roadveh.h index 8f051e876d..59ffe344af 100644 --- a/src/table/roadveh.h +++ b/src/table/roadveh.h @@ -1011,7 +1011,7 @@ static const RoadDriveEntry _roadveh_drive_data_59[] = { {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 @@ static const RoadDriveEntry * const _road_drive_data[] = { 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, +}; diff --git a/src/table/sprites.h b/src/table/sprites.h index 83d8e93775..75274205a4 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -150,6 +150,24 @@ enum Sprites { 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 @@ enum Sprites { 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 @@ enum CursorSprite { /* 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, diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 4be63214b7..1b84e09d02 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -858,6 +858,36 @@ uint GetBridgeFoundation(Slope tileh, Axis axis) return i + 15; } +/** + * 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. @@ -887,7 +917,17 @@ static void DrawTile_TunnelBridge(TileInfo *ti) 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 @@ static void DrawTile_TunnelBridge(TileInfo *ti) 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 @@ static void DrawTile_TunnelBridge(TileInfo *ti) * 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 @@ void DrawBridgeMiddle(const TileInfo* ti) 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 @@ void DrawBridgeMiddle(const TileInfo* ti) 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); }