diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 797ead1..67e8329 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -36,6 +36,8 @@ static BridgeType _last_railbridge_type = 0; /** The type of the last built road bridge */ static BridgeType _last_roadbridge_type = 0; +uint8 _bridge_cur_road_subtype = 0; + /** * Carriage for the data we need if we want to build a bridge */ @@ -117,7 +119,10 @@ private: case TRANSPORT_ROAD: _last_roadbridge_type = this->bridges->Get(i)->index; break; default: break; } - DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index, + // Alberth: It's hacky, but it ensures your bits are preserved (shifting 17 times in a value with width 8 is undefined behavior) + uint32 w = _bridge_cur_road_subtype; + w <<= 17; + DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index | w, CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE), CcBuildBridge); } @@ -358,10 +363,12 @@ static WindowDesc _build_bridge_desc( * @param transport_type The transport type * @param road_rail_type The road/rail type */ -void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type) +void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type, uint8 cur_road_subtype) { DeleteWindowByClass(WC_BUILD_BRIDGE); + _bridge_cur_road_subtype = cur_road_subtype; + /* Data type for the bridge. * Bit 16,15 = transport type, * 14..8 = road/rail types, diff --git a/src/bridge_map.h b/src/bridge_map.h index 74c6974..4e7984e 100644 --- a/src/bridge_map.h +++ b/src/bridge_map.h @@ -148,12 +148,16 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D * @param d the direction this ramp must be facing * @param r the road type of the bridge */ -static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes r) +static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes r, uint8 cur_road_subtype) { MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD, 0); SetRoadOwner(t, ROADTYPE_ROAD, owner_road); if (owner_tram != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, owner_tram); SetRoadTypes(t, r); + printf("!! Unfinished split between road and tram subtypes in MakeRoadBridgeRamp !! \n"); + // !! should split before calling this, and pass appropriate road and tram subtypes based on existing / new subtypes for the tile + SetRoadSubtype(t, cur_road_subtype); + SetTramSubtype(t, cur_road_subtype); } /** diff --git a/src/gui.h b/src/gui.h index 39f1ea6..97ee592 100644 --- a/src/gui.h +++ b/src/gui.h @@ -61,7 +61,7 @@ void ShowExtraViewPortWindow(TileIndex tile = INVALID_TILE); void ShowExtraViewPortWindowForTileUnderCursor(); /* bridge_gui.cpp */ -void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type); +void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type, uint8 cur_road_subtype = 0); void ShowBuildIndustryWindow(); void ShowFoundTownWindow(); diff --git a/src/lang/english.txt b/src/lang/english.txt index 0bd430b..b02e251 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -439,8 +439,13 @@ STR_RAIL_MENU_MAGLEV_CONSTRUCTION :Maglev construc ############ range ends here ############ range for road construction menu starts -STR_ROAD_MENU_ROAD_CONSTRUCTION :Road construction -STR_ROAD_MENU_TRAM_CONSTRUCTION :Tramway construction +STR_ROAD_MENU_ROAD_CONSTRUCTION :(Deprecated) +STR_ROAD_MENU_TRAM_CONSTRUCTION :(Deprecated) +STR_ROAD_MENU_ROAD_CONSTRUCTION_0 :Road construction 0 +STR_ROAD_MENU_ROAD_CONSTRUCTION_1 :Road construction 1 +STR_ROAD_MENU_TRAM_CONSTRUCTION_0 :Tramway construction 0 +STR_ROAD_MENU_TRAM_CONSTRUCTION_1 :Tramway construction 1 +STR_ROAD_MENU_TRAM_CONSTRUCTION_2 :Tramway construction 2 ############ range ends here ############ range for waterways construction menu starts diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index 9f19b02..59c7777 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -102,6 +102,7 @@ struct CFollowTrackT assert(IsTram()); // this function shouldn't be called in other cases if (IsNormalRoadTile(tile)) { + return INVALID_DIAGDIR; RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM); switch (rb) { case ROAD_NW: return DIAGDIR_NW; diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 2010f9b..68fd2de 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -33,6 +33,7 @@ #include "strings_func.h" #include "company_gui.h" #include "object_map.h" +#include "road_type.h" #include "table/strings.h" #include "table/railtypes.h" @@ -636,6 +637,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, owner = GetTileOwner(tile); Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR; DirtyCompanyInfrastructureWindows(owner); + // !! needs subtype detection for crossings MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM)); DeleteNewGRFInspectWindow(GSF_RAILTYPES, tile); } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index aa445eb..b566d44 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -326,7 +326,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec if (present == ROAD_NONE) { RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); - if (rts == ROADTYPES_NONE) { + if (!HasRoadType(rt) && !HasTramType(rt)) { /* Includes MarkTileDirtyByTile() */ DoClearSquare(tile); } else { @@ -374,7 +374,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec } Track railtrack = GetCrossingRailTrack(tile); - RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); + //RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); if (rts == ROADTYPES_NONE) { TrackBits tracks = GetCrossingRailBits(tile); bool reserved = HasCrossingReservation(tile); @@ -515,6 +515,7 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; DisallowedRoadDirections toggle_drd = Extract(p1); + uint8 cur_road_subtype = GB(p1, 8, 8); Slope tileh = GetTileSlope(tile); @@ -749,6 +750,8 @@ do_clear:; if (rt == ROADTYPE_ROAD) SetTownIndex(tile, p2); } if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt); + SetRoadSubtype(tile, cur_road_subtype); + SetTramSubtype(tile, cur_road_subtype); break; } @@ -759,6 +762,8 @@ do_clear:; SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); SetRoadOwner(other_end, rt, company); SetRoadOwner(tile, rt, company); + //SetBridgeRoadTramCatenary(other_end, _catenary_flag); + //SetBridgeRoadTramCatenary(tile, _catenary_flag); /* Mark tiles dirty that have been repaved */ if (IsBridge(tile)) { @@ -777,7 +782,15 @@ do_clear:; break; default: - MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, company, company); + uint8 road_subtype = 0; + uint8 tram_subtype = 0; + if (rt == ROADTYPE_ROAD) { + road_subtype = cur_road_subtype; + } + if (rt == ROADTYPE_TRAM) { + tram_subtype = cur_road_subtype; + } + MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, company, company, road_subtype, tram_subtype); break; } @@ -794,7 +807,6 @@ do_clear:; SetDisallowedRoadDirections(tile, IsStraightRoad(existing) ? GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE); } - MarkTileDirtyByTile(tile); } return cost; @@ -886,8 +898,8 @@ CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p if (tile == end_tile && !HasBit(p2, 1)) bits &= DiagDirToRoadBits(ReverseDiagDir(dir)); if (tile == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir); } - - CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD); + uint8 _cur_road_subtype = GB(p2, 7, 8); + CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits | _cur_road_subtype << 8 , 0, flags, CMD_BUILD_ROAD); if (ret.Failed()) { last_error = ret; if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) { @@ -1298,7 +1310,7 @@ static void DrawRoadBits(TileInfo *ti) return; } - if (tram != ROAD_NONE) DrawTramCatenary(ti, tram); + if (RoadTileHasCatenary(ti->tile)) 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; @@ -1388,7 +1400,7 @@ static void DrawTile_Road(TileInfo *ti) if (HasTileRoadType(ti->tile, ROADTYPE_TRAM)) { DrawGroundSprite(SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal); - DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile)); + if (RoadTileHasCatenary(ti->tile)) DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile)); } if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti); break; @@ -1623,6 +1635,21 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, u RoadType rt = (RoadType)FindFirstBit(sub_mode); RoadBits bits = GetRoadBits(tile, rt); + // subtype not sub_mode + uint8 road_subtype = GetRoadSubtype(tile); + uint8 tram_subtype = GetTramSubtype(tile); + // !! ROADTYPES is a bitmask afaict, testing '==' with it is a bad solution? + if (sub_mode == ROADTYPES_ROAD) { + // road + printf("GetTileTrackStatus_Road: road_subtype = %d \n", road_subtype); + if (road_subtype != 0) break; + } + if (sub_mode == ROADTYPES_TRAM) { + // tram + printf("GetTileTrackStatus_Road: tram_subtype = %d \n", tram_subtype); + if (tram_subtype != 0) break; + } + /* no roadbit at this side of tile, return 0 */ if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break; @@ -1757,6 +1784,7 @@ static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int default: break; } + return VETSB_CONTINUE; } diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 92c660e..d989048 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -60,6 +60,7 @@ DECLARE_ENUM_AS_BIT_SET(RoadFlags) static RoadFlags _place_road_flag; static RoadType _cur_roadtype; +uint8 _cur_road_subtype; static DiagDirection _road_depot_orientation; static DiagDirection _road_station_picker_orientation; @@ -231,6 +232,7 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, u ddir -= DIAGDIR_END; // Adjust picker result to actual direction. } p2 |= ddir << 6; // Set the DiagDirecion into p2 bits 6 and 7. + SB(p2, 9, 1, _cur_road_subtype); // !! set _cur_road_subtype into p2 bit 9, only works whilst valid subtype values are 0-1 TileArea ta(start_tile, end_tile); CommandContainer cmdcont = { ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, CcRoadStop, "" }; @@ -535,7 +537,7 @@ struct BuildRoadToolbarWindow : Window { break; case WID_ROT_BUILD_TUNNEL: - DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, + DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), _cur_road_subtype, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel); break; @@ -610,7 +612,8 @@ struct BuildRoadToolbarWindow : Window { default: NOT_REACHED(); case DDSP_BUILD_BRIDGE: if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); - ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype)); + printf("OnPlaceMouseUp: _cur_road_subtype: %d \n", _cur_road_subtype); + ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype), _cur_road_subtype); break; case DDSP_DEMOLISH_AREA: @@ -626,7 +629,7 @@ struct BuildRoadToolbarWindow : Window { * not the 3rd bit set) */ _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3)); - DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), + DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5) | (_cur_road_subtype << 7), _remove_button_clicked ? CMD_REMOVE_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) : CMD_BUILD_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road), CcPlaySound1D); @@ -657,7 +660,7 @@ struct BuildRoadToolbarWindow : Window { virtual void OnPlacePresize(Point pt, TileIndex tile) { - DoCommand(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL); + DoCommand(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), _cur_road_subtype, DC_AUTO, CMD_BUILD_TUNNEL); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } @@ -802,10 +805,11 @@ static WindowDesc _build_tramway_desc( * * @return newly opened road toolbar, or NULL if the toolbar could not be opened. */ -Window *ShowBuildRoadToolbar(RoadType roadtype) +Window *ShowBuildRoadToolbar(RoadType roadtype, uint8 road_subtype) { if (!Company::IsValidID(_local_company)) return NULL; _cur_roadtype = roadtype; + _cur_road_subtype = road_subtype; DeleteWindowByClass(WC_BUILD_TOOLBAR); return AllocateWindowDescFront(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD); diff --git a/src/road_gui.h b/src/road_gui.h index c56443c..1802e11 100644 --- a/src/road_gui.h +++ b/src/road_gui.h @@ -16,7 +16,7 @@ #include "tile_type.h" #include "direction_type.h" -struct Window *ShowBuildRoadToolbar(RoadType roadtype); +struct Window *ShowBuildRoadToolbar(RoadType roadtype, uint8 road_subtype = 0); struct Window *ShowBuildRoadScenToolbar(); void ConnectRoadToStructure(TileIndex tile, DiagDirection direction); diff --git a/src/road_internal.h b/src/road_internal.h index c8cae84..0b7532b 100644 --- a/src/road_internal.h +++ b/src/road_internal.h @@ -13,6 +13,7 @@ #define ROAD_INTERNAL_H #include "tile_cmd.h" +#include "road_map.h" #include "road_type.h" RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb); @@ -21,4 +22,11 @@ CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, R void DrawTramCatenary(const TileInfo *ti, RoadBits tram); +static inline bool RoadTileHasCatenary(const TileIndex tile) { + uint8 road_subtype = GetRoadSubtype(tile); + uint8 tram_subtype = GetTramSubtype(tile); + return (RoadSubtypeHasCatenary(road_subtype) || TramSubtypeHasCatenary(tram_subtype)); +} + + #endif /* ROAD_INTERNAL_H */ diff --git a/src/road_map.h b/src/road_map.h index 6937302..663517a 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -286,6 +286,30 @@ static inline void SetDisallowedRoadDirections(TileIndex t, DisallowedRoadDirect SB(_m[t].m5, 4, 2, drd); } +static inline void SetRoadSubtype(TileIndex t, uint8 subtype) +{ + assert(IsTileType(t, MP_ROAD) || IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE)); + //assert(subtype <= 3); // we're only using 2 bits here, only 4 subtypes permitted + SB(_m[t].m4, 4, 4, subtype); +} + +static inline void SetTramSubtype(TileIndex t, uint8 subtype) +{ + assert(IsTileType(t, MP_ROAD) || IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE)); + //assert(subtype <= 3); // we're only using 2 bits here, only 4 subtypes permitted + SB(_m[t].m4, 0, 4, subtype); +} + +static inline uint8 GetRoadSubtype(TileIndex t) +{ + return GB(_m[t].m4, 4, 4); +} + +static inline uint8 GetTramSubtype(TileIndex t) +{ + return GB(_m[t].m4, 0, 4); +} + /** * Get the road axis of a level crossing. * @param t The tile to query. @@ -550,7 +574,7 @@ RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt, bool straight_tunnel_bridge * @param road New owner of road. * @param tram New owner of tram tracks. */ -static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram) +static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, uint8 road_subtype = 0, uint8 tram_subtype = 0) { SetTileType(t, MP_ROAD); SetTileOwner(t, road); @@ -561,6 +585,8 @@ static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, Tow SB(_me[t].m6, 2, 4, 0); _me[t].m7 = rot << 6; SetRoadOwner(t, ROADTYPE_TRAM, tram); + SetRoadSubtype(t, road_subtype); + SetTramSubtype(t, tram_subtype); } /** diff --git a/src/road_type.h b/src/road_type.h index 5251a53..40b961e 100644 --- a/src/road_type.h +++ b/src/road_type.h @@ -29,22 +29,42 @@ enum RoadType { DECLARE_POSTFIX_INCREMENT(RoadType) template <> struct EnumPropsT : MakeEnumPropsT {}; -/** - * The different roadtypes we support, but then a bitmask of them - * @note currently only roadtypes with ROADTYPE_ROAD and ROADTYPE_TRAM are supported. - */ +// RoadTypes, with ability to get road type, tram type, or look up roadtype given subtype enum RoadTypes { - ROADTYPES_NONE = 0, ///< No roadtypes - ROADTYPES_ROAD = 1 << ROADTYPE_ROAD, ///< Road - ROADTYPES_TRAM = 1 << ROADTYPE_TRAM, ///< Trams - ROADTYPES_ALL = ROADTYPES_ROAD | ROADTYPES_TRAM, ///< Road + trams - ROADTYPES_END, ///< Used for iterations? - INVALID_ROADTYPES = 0xFF, ///< Invalid roadtypes + ROADTYPES_ROAD_BASE = 0, + ROADTYPES_ROAD_LENGTH = 4, ///< Number of bit + ROADTYPES_INVALID_ROAD = 0x7, ///< Road-type denoting 'no road'. + + ROADTYPES_TRAM_BASE = 4, ///< Start bit of the tram types. + ROADTYPES_TRAM_LENGTH = 4, ///< Number of bits for the tram types. + ROADTYPES_INVALID_TRAM = 0x7, ///< Tram-type denoting 'no tram'. }; -DECLARE_ENUM_AS_BIT_SET(RoadTypes) -template <> struct EnumPropsT : MakeEnumPropsT {}; -typedef SimpleTinyEnumT RoadTypesByte; +static inline uint8 GetRoadType(RoadTypes rt) { + return GB(rt, ROADTYPES_ROAD_BASE, ROADTYPES_ROAD_LENGTH); +} + +static inline uint8 GetTramType(RoadTypes rt) { + return GB(rt, ROADTYPES_TRAM_BASE, ROADTYPES_TRAM_LENGTH); +} + +static inline RoadTypes SetRoadType(RoadTypes rt, uint8 road_type) { + assert((road_type & ((1 << ROADTYPES_ROAD_LENGTH) - 1)) == road_type); + return (RoadTypes)SB(rt, ROADTYPES_ROAD_BASE, ROADTYPES_ROAD_LENGTH, road_type); +} + +static inline RoadTypes SetTramType(RoadTypes rt, uint8 tram_type) { + assert((tram_type & ((1 << ROADTYPES_TRAM_LENGTH) - 1)) == tram_type); + return (RoadTypes)SB(rt, ROADTYPES_TRAM_BASE, ROADTYPES_TRAM_LENGTH, tram_type); +} + +static inline bool HasRoadType(rt) { + return GetRoadType(rt) != ROADTYPES_ROAD_INVALID; +} + +static inline bool HasTramType(rt) { + return GetTramType(rt) != ROADTYPES_TRAM_INVALID; +} /** * Enumeration for the road parts on a tile. @@ -73,4 +93,19 @@ enum RoadBits { DECLARE_ENUM_AS_BIT_SET(RoadBits) template <> struct EnumPropsT : MakeEnumPropsT {}; +static inline bool RoadSubtypeHasCatenary(uint8 subtype) { + if (subtype == 1) { + return true; + } else { + return false; + } +} +static inline bool TramSubtypeHasCatenary(uint8 subtype) { + if (subtype == 1) { + return true; + } else { + return false; + } +} + #endif /* ROAD_TYPE_H */ diff --git a/src/roadveh.h b/src/roadveh.h index 5b265f0..ed2f409 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -95,7 +95,8 @@ struct RoadVehicle FINAL : public GroundVehicle { byte reverse_ctr; RoadType roadtype; - RoadTypes compatible_roadtypes; + uint8 subtype; + uint16 compatible_roadtypes; // first 8 bits are RoadTypes, next bits are subtype /** We don't want GCC to zero our struct! It already is zeroed and has an index! */ RoadVehicle() : GroundVehicleBase() {} diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 35c671d..7149bd5 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1208,7 +1208,7 @@ again: } if ((v->Previous() != NULL && v->Previous()->tile == tile) || (v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) && - (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) { + (needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE) && (GetTramSubtype(tile) == 0)) { /* * Taking the 'big' corner for trams only happens when: * - The previous vehicle in this (articulated) tram chain is diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index eb90c29..1109193 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1759,6 +1759,11 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin bool reuse = (station_to_join != NEW_STATION); if (!reuse) station_to_join = INVALID_STATION; bool distant_join = (station_to_join != INVALID_STATION); + bool catenary_flag = HasBit(p2, 9); // the setting from the selected roadtype + bool cur_tile_catenary_flag = catenary_flag; // used to set catenary flag on any given tile + printf("CmdBuildRoadStop called %d ", tile); + printf("catenary_flag %d ", catenary_flag); + printf("\n"); uint8 width = (uint8)GB(p1, 0, 8); uint8 lenght = (uint8)GB(p1, 8, 8); @@ -1815,6 +1820,12 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Check every tile in the area. */ TILE_AREA_LOOP(cur_tile, roadstop_area) { RoadTypes cur_rts = GetRoadTypes(cur_tile); + // don't remove existing catenary if present + if (RoadTileHasCatenary(cur_tile)) { + cur_tile_catenary_flag = true; + } else { + cur_tile_catenary_flag = catenary_flag; + } Owner road_owner = HasBit(cur_rts, ROADTYPE_ROAD) ? GetRoadOwner(cur_tile, ROADTYPE_ROAD) : _current_company; Owner tram_owner = HasBit(cur_rts, ROADTYPE_TRAM) ? GetRoadOwner(cur_tile, ROADTYPE_TRAM) : _current_company; @@ -1851,7 +1862,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin } } - MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts | cur_rts, axis); + MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts | cur_rts, axis, cur_tile_catenary_flag); road_stop->MakeDriveThrough(); } else { /* Non-drive-through stop never overbuild and always count as two road bits. */ @@ -2013,6 +2024,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui uint8 width = (uint8)GB(p1, 0, 8); uint8 height = (uint8)GB(p1, 8, 8); bool keep_drive_through_roads = !HasBit(p2, 1); + bool keep_catenary = false; /* Check for incorrect width / height. */ if (width == 0 || height == 0) return CMD_ERROR; @@ -2030,6 +2042,11 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui TILE_AREA_LOOP(cur_tile, roadstop_area) { /* Make sure the specified tile is a road stop of the correct type */ if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue; + if (RoadTileHasCatenary(cur_tile)) { + keep_catenary = true; + } else { + keep_catenary = false; + } /* Save information on to-be-restored roads before the stop is removed. */ RoadTypes rts = ROADTYPES_NONE; @@ -2057,7 +2074,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui /* Restore roads. */ if ((flags & DC_EXEC) && rts != ROADTYPES_NONE) { MakeRoadNormal(cur_tile, road_bits, rts, ClosestTownFromTile(cur_tile, UINT_MAX)->index, - road_owner[ROADTYPE_ROAD], road_owner[ROADTYPE_TRAM]); + road_owner[ROADTYPE_ROAD], road_owner[ROADTYPE_TRAM], keep_catenary); /* Update company infrastructure counts. */ RoadType rt; @@ -2902,7 +2919,7 @@ draw_default_foundation: 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 (HasRoadTramCatenary(ti->tile)) DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y); } if (IsRailWaypoint(ti->tile)) { diff --git a/src/station_map.h b/src/station_map.h index 7ca9bd7..8a101ad 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -521,6 +521,17 @@ static inline byte GetStationTileRandomBits(TileIndex t) return GB(_m[t].m3, 4, 4); } +static inline void SetRoadTramCatenary(TileIndex t, bool b) +{ + assert(IsTileType(t, MP_STATION)); + SB(_m[t].m1, 7, 1, b ? 1 : 0); +} + +static inline bool HasRoadTramCatenary(TileIndex t) +{ + return GB(_m[t].m1, 7, 1); +} + /** * Make the given tile a station tile. * @param t the tile to make a station tile @@ -604,12 +615,13 @@ static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopTyp * @param rt the roadtypes on this tile * @param a the direction of the roadstop */ -static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadTypes rt, Axis a) +static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadTypes rt, Axis a, bool catenary_flag) { MakeStation(t, station, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a); SetRoadTypes(t, rt); SetRoadOwner(t, ROADTYPE_ROAD, road); SetRoadOwner(t, ROADTYPE_TRAM, tram); + SetRoadTramCatenary(t, catenary_flag); } /** diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 45d751d..c62c395 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -891,7 +891,8 @@ static CallBackFunction ToolbarBuildRoadClick(Window *w) DropDownList *list = new DropDownList(); /* Road is always visible and available. */ - *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION_0, 0, false); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION_1, 1, false); /* Tram is only visible when there will be a tram, and available when that has been introduced. */ Engine *e; @@ -899,7 +900,9 @@ static CallBackFunction ToolbarBuildRoadClick(Window *w) if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue; if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue; - *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION_0, 2, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION_1, 3, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)); + *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION_2, 4, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)); break; } ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true); @@ -915,8 +918,24 @@ static CallBackFunction ToolbarBuildRoadClick(Window *w) */ static CallBackFunction MenuClickBuildRoad(int index) { - _last_built_roadtype = (RoadType)index; - ShowBuildRoadToolbar(_last_built_roadtype); + uint8 _last_built_road_subtype = 0; + if (index == 0) { + _last_built_roadtype = (RoadType)ROADTYPE_ROAD; + _last_built_road_subtype = 0; + } else if (index == 1) { + _last_built_roadtype = (RoadType)ROADTYPE_ROAD; + _last_built_road_subtype = 1; + } else if (index == 2) { + _last_built_roadtype = (RoadType)ROADTYPE_TRAM; + _last_built_road_subtype = 0; + } else if (index == 3) { + _last_built_roadtype = (RoadType)ROADTYPE_TRAM; + _last_built_road_subtype = 1; + } else if (index == 4) { + _last_built_roadtype = (RoadType)ROADTYPE_TRAM; + _last_built_road_subtype = 2; + } + ShowBuildRoadToolbar(_last_built_roadtype, _last_built_road_subtype); return CBF_NONE; } diff --git a/src/tunnel_map.h b/src/tunnel_map.h index e200a12..d9c24dd 100644 --- a/src/tunnel_map.h +++ b/src/tunnel_map.h @@ -48,7 +48,7 @@ bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir); * @param d the direction facing out of the tunnel * @param r the road type used in the tunnel */ -static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTypes r) +static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTypes r, uint8 cur_road_subtype) { SetTileType(t, MP_TUNNELBRIDGE); SetTileOwner(t, o); @@ -61,6 +61,10 @@ static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTyp SetRoadOwner(t, ROADTYPE_ROAD, o); if (o != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, o); SetRoadTypes(t, r); + printf("!! Unfinished split between road and tram subtypes in MakeRoadTunnel !! \n"); + // !! should split before calling this, and pass appropriate road and tram subtypes based on existing / new subtypes for the tile + SetRoadSubtype(t, cur_road_subtype); + SetTramSubtype(t, cur_road_subtype); } /** diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 5f2534b..4160cb5 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -40,6 +40,7 @@ #include "object_base.h" #include "water.h" #include "company_gui.h" +#include "road_internal.h" #include "table/strings.h" #include "table/bridge_land.h" @@ -515,8 +516,9 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u } Owner owner_road = HasBit(prev_roadtypes, ROADTYPE_ROAD) ? GetRoadOwner(tile_start, ROADTYPE_ROAD) : company; Owner owner_tram = HasBit(prev_roadtypes, ROADTYPE_TRAM) ? GetRoadOwner(tile_start, ROADTYPE_TRAM) : company; - MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes); - MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes); + uint8 cur_road_subtype = GB(p2, 17, 8); + MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes, cur_road_subtype); + MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes, cur_road_subtype); break; } @@ -589,6 +591,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, RailType railtype = INVALID_RAILTYPE; RoadTypes rts = ROADTYPES_NONE; _build_tunnel_endtile = 0; + uint8 _build_tunnel_cur_road_subtype = GB(p2, 0, 8); + switch (transport_type) { case TRANSPORT_RAIL: railtype = Extract(p1); @@ -731,8 +735,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits. } } - MakeRoadTunnel(start_tile, company, direction, rts); - MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), rts); + MakeRoadTunnel(start_tile, company, direction, rts, _build_tunnel_cur_road_subtype); + MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), rts, _build_tunnel_cur_road_subtype); } DirtyCompanyInfrastructureWindows(company); } @@ -1087,7 +1091,7 @@ static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis * @param overlay do we want to still see the road? * @param head are we drawing bridge head? */ -static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head) +static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head, bool has_catenary) { 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, 96, 99, 102, 100, 101 }; @@ -1107,7 +1111,7 @@ static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bo } /* Do not draw catenary if it is set invisible */ - if (!IsInvisibilitySet(TO_CATENARY)) { + if (has_catenary && !IsInvisibilitySet(TO_CATENARY)) { AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE, x, y, size_x[offset], size_y[offset], 0x28, z, IsTransparencySet(TO_CATENARY)); @@ -1118,7 +1122,7 @@ static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bo StartSpriteCombine(); /* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */ - if (!IsInvisibilitySet(TO_CATENARY)) { + if (has_catenary && !IsInvisibilitySet(TO_CATENARY)) { AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE, x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z, IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]); @@ -1193,7 +1197,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE); /* Do not draw wires if they are invisible */ - if (!IsInvisibilitySet(TO_CATENARY)) { + if (RoadTileHasCatenary(ti->tile) && !IsInvisibilitySet(TO_CATENARY)) { catenary = true; StartSpriteCombine(); AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR); @@ -1303,7 +1307,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti) offset += 2; } /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */ - DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true); + DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true, RoadTileHasCatenary(ti->tile)); } EndSpriteCombine(); } else if (transport_type == TRANSPORT_RAIL) { @@ -1466,7 +1470,7 @@ void DrawBridgeMiddle(const TileInfo *ti) if (HasBit(rts, ROADTYPE_TRAM)) { /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */ - DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false); + DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false, RoadTileHasCatenary(ti->tile)); } else { EndSpriteCombine(); StartSpriteCombine();