Index: src/road.h =================================================================== --- src/road.h (Revision 10850) +++ src/road.h (Arbeitskopie) @@ -6,6 +6,7 @@ #define ROAD_H #include "helpers.hpp" +#include "rail_map.h" /** * The different roadtypes we support @@ -116,6 +117,19 @@ } /** + * Calculate the mirrored RoadBits + * + * Simply move the bits to their new position. + * + * @param r the current RoadBits + * @return the mirrored RoadBits + */ +static inline RoadBits MirrorRoadBits(RoadBits r) +{ + return ((RoadBits)GB(r, 2, 2) | (RoadBits)(GB(r, 0, 2) << 2)); +} + +/** * Create the road-part which belongs to the given DiagDirection * * This function returns a RoadBits value which belongs to @@ -160,7 +174,56 @@ */ bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt); +const TileIndexDiffC _roadblock_tileadd[] = { + { 0, -1}, ///< Direction NW + { 1, 0}, ///< Direction SW + { 0, 1}, ///< Direction SE + {-1, 0}, ///< Direction NE + + /* Store the first 3 elements again. + * Lets us rotate without using &3. */ + { 0, -1}, ///< Direction NW + { 1, 0}, ///< Direction SW + { 0, 1} ///< Direction SE +}; + /** + * Clean up unneccesary RoadBits of a planed tile. + * @param tile current tile + * @param rcmd planed RoadBits + * @return optimised RoadBits + */ +RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits rcmd); + +/** + * Return if the tile is a valid tile for a crossing. + * + * @note function is overloaded + * @param tile the curent tile + * @param ax the axis of the road over the rail + * @return true if it is a valid tile + */ +static inline bool IsPossibleCrossing(const TileIndex tile, Axis ax) +{ + return (IsTileType(tile, MP_RAILWAY) && + !HasSignals(tile) && + GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) && + GetTileSlope(tile, NULL) == SLOPE_FLAT); +} + +/** + * Return if the tile is a valid tile for a crossing. + * + * @note function is overloaded + * @param tile the curent tile + * @param rb the roadbits of the road over the rail + * @return true if it is a valid tile + */ +static inline bool IsPossibleCrossing(const TileIndex tile, RoadBits rb) { + return IsPossibleCrossing(tile, rb == ROAD_X ? AXIS_X : AXIS_Y); +} + +/** * Draw the catenary for tram road bits * @param ti information about the tile (position, slope) * @param tram the roadbits to draw the catenary for Index: src/town_cmd.cpp =================================================================== --- src/town_cmd.cpp (Revision 10850) +++ src/town_cmd.cpp (Arbeitskopie) @@ -563,20 +563,6 @@ /* not used */ } - -static const TileIndexDiffC _roadblock_tileadd[] = { - { 0, -1}, - { 1, 0}, - { 0, 1}, - {-1, 0}, - - /* Store the first 3 elements again. - * Lets us rotate without using &3. */ - { 0, -1}, - { 1, 0}, - { 0, 1} -}; - /** * Distance multiplyer * Defines the possible distances between 2 road tiles @@ -791,34 +777,7 @@ } else if (!lx && ly) { ///< It is a X-dir road tile return ROAD_X; } else { ///< It is a crossing tile - /* Presets for junctions on slopes - * not nice :( */ - switch (GetTileSlope(tile, NULL)) { - case SLOPE_W: - return ROAD_NW | ROAD_SW; - case SLOPE_S: - return ROAD_SE | ROAD_SW; - case SLOPE_SW: - return ROAD_Y | ROAD_SW; - case SLOPE_E: - return ROAD_NE | ROAD_SE; - case SLOPE_SE: - return ROAD_X | ROAD_SE; - case SLOPE_N: - return ROAD_NW | ROAD_NE; - case SLOPE_NW: - return ROAD_X | ROAD_NW; - case SLOPE_NE: - return ROAD_Y | ROAD_NE; - case SLOPE_STEEP_W: - case SLOPE_STEEP_N: - return ROAD_X; - case SLOPE_STEEP_S: - case SLOPE_STEEP_E: - return ROAD_Y; - default: - return ROAD_ALL; - } + return ROAD_ALL; } } @@ -947,22 +906,10 @@ * Always OK. */ _grow_town_result = 0; - switch (_patches.town_layout) { - default: NOT_REACHED(); + if (_patches.town_layout == TL_NO_ROADS) return; ///< Disallow roads - case TL_NO_ROADS: /* Disallow Roads */ - return; + rcmd = ROAD_ALL; - case TL_3X3_GRID: - case TL_2X2_GRID: - rcmd = GetTownRoadGridElement(t1, tile); - break; - - case TL_BETTER_ROADS: - case TL_ORIGINAL: - rcmd = (RoadBits)(1 << (block ^ 2)); - break; - } } else { int i; bool allow_house = false; @@ -1055,6 +1002,10 @@ default: build_road_and_exit: + rcmd = CleanUpRoadBits(tile, rcmd); + /* If there are no more Roadbits further stuff is unneeded */ + if (rcmd == ROAD_NONE) return; + if (CmdSucceeded(DoCommand(tile, rcmd, t1->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) { _grow_town_result = -1; } Index: src/road.cpp =================================================================== --- src/road.cpp (Revision 0) +++ src/road.cpp (Revision 0) @@ -0,0 +1,134 @@ +#include "stdafx.h" +#include "openttd.h" +#include "functions.h" +#include "road.h" +#include "road_map.h" +#include "water_map.h" +#include "macros.h" + +RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits rcmd) +{ + RoadBits prefered_rb = ROAD_NONE; + + for (uint8 i = 0 ; i <= 3 ; i++) { + /* Cycle counter around the tile NW->SW->SE->NE */ + const TileIndex neighbor_tile = AddTileIndexDiffCWrap(tile, _roadblock_tileadd[i]); + + /* Get the Roadbit pointing to the neighbor_tile */ + const RoadBits current_rb = (RoadBits)(ROAD_NW << i); + + /* If the roadbit is in the current plan */ + if (HASBITS(rcmd, current_rb)) { + bool connective = false; + const RoadBits mirrored_rb = MirrorRoadBits(current_rb); + + switch (GetTileType(neighbor_tile)) { + /* Allways connective ones */ + case MP_CLEAR: case MP_TREES: + connective = true; + break; + + /* The conditionaly connective ones */ + case MP_TUNNELBRIDGE: + case MP_STATION: + case MP_ROAD: { + const RoadBits neighbor_rb_road = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD); + const RoadBits neighbor_rb_tram = GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM); + + /* Accept only connective tiles */ + connective = HASBITS(neighbor_rb_road | neighbor_rb_tram, mirrored_rb); + /* Prefer road */ + if (HASBITS(neighbor_rb_road, mirrored_rb)) prefered_rb |= current_rb; + + } break; + + case MP_RAILWAY: + connective = IsPossibleCrossing(neighbor_tile, current_rb | mirrored_rb); + break; + + case MP_WATER: + /* Check for real water tile */ + connective = !IsWater(neighbor_tile); + break; + + /* The defentetly not connective ones */ + default: break; + } + + /* If the neighbor tile is inconnective remove the planed road connection to it */ + if (!connective) rcmd ^= current_rb; + + } + } + + /* Optimise the Roadbits for slopes */ + RoadBits slope_rb[3]; ///< recommended RoadBits + switch (GetTileSlope(tile, NULL)) { + case SLOPE_N: + slope_rb[0] = ROAD_NW | ROAD_NE; + slope_rb[1] = ROAD_X; + slope_rb[2] = ROAD_Y; + break; + + case SLOPE_W: + slope_rb[0] = ROAD_NW | ROAD_SW; + slope_rb[1] = ROAD_X; + slope_rb[2] = ROAD_Y; + break; + + case SLOPE_S: + slope_rb[0] = ROAD_SW | ROAD_SE; + slope_rb[1] = ROAD_X; + slope_rb[2] = ROAD_Y; + break; + + case SLOPE_E: + slope_rb[0] = ROAD_SE | ROAD_NE; + slope_rb[1] = ROAD_X; + slope_rb[2] = ROAD_Y; + break; + + case SLOPE_NW: + slope_rb[0] = ROAD_X | ROAD_NW; + slope_rb[1] = ROAD_Y; + slope_rb[2] = ROAD_NONE; + break; + + case SLOPE_SW: + slope_rb[0] = ROAD_Y | ROAD_SW; + slope_rb[1] = ROAD_X; + slope_rb[2] = ROAD_NONE; + break; + + case SLOPE_SE: + slope_rb[0] = ROAD_X | ROAD_SE; + slope_rb[1] = ROAD_Y; + slope_rb[2] = ROAD_NONE; + break; + + case SLOPE_NE: + slope_rb[0] = ROAD_Y | ROAD_NE; + slope_rb[1] = ROAD_X; + slope_rb[2] = ROAD_NONE; + break; + + default: + slope_rb[0] = ROAD_ALL; + break; + } + + for (uint cur = 0; cur < 3; cur++) { + + if (slope_rb[cur] == ROAD_ALL) + return rcmd; + + if (slope_rb[cur] == ROAD_NONE && cur > 0) + return rcmd & slope_rb[cur - 1]; + + if (HASBITS(prefered_rb, slope_rb[cur])) + return prefered_rb & slope_rb[cur]; + } + + return ROAD_NONE; +} + Index: src/road_cmd.cpp =================================================================== --- src/road_cmd.cpp (Revision 10850) +++ src/road_cmd.cpp (Arbeitskopie) @@ -1195,8 +1195,8 @@ /* Show an animation to indicate road work */ if (t->road_build_months != 0 && (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && - GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) { - if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) { + GetRoadTileType(tile) == ROAD_TILE_NORMAL && CountRoadBits(GetAllRoadBits(tile)) > 1 ) { + if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) { StartRoadWorks(tile); SndPlayTileFx(SND_21_JACKHAMMER, tile); @@ -1234,6 +1234,27 @@ } } else if (IncreaseRoadWorksCounter(tile)) { TerminateRoadWorks(tile); + + /* Generate a nicer town surface */ + const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD); + const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); + if (old_rb != new_rb) { + + /* Protect against roads with no roadbits */ + if (new_rb == ROAD_NONE) { + const RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(ROADTYPE_ROAD)); + + if (rts == ROADTYPES_NONE) { + DoClearSquare(tile); + } else { + SetRoadBits(tile, ROAD_NONE, ROADTYPE_ROAD); + SetRoadTypes(tile, rts); + } + } else { + SetRoadBits(tile, new_rb, ROADTYPE_ROAD); + } + } + MarkTileDirtyByTile(tile); } } Index: projects/openttd.vcproj =================================================================== --- projects/openttd.vcproj (Revision 10850) +++ projects/openttd.vcproj (Arbeitskopie) @@ -320,6 +320,9 @@ RelativePath=".\..\src\rail.cpp"> + + + + Index: source.list =================================================================== --- source.list (Revision 10850) +++ source.list (Arbeitskopie) @@ -57,6 +57,7 @@ players.cpp queue.cpp rail.cpp +road.cpp saveload.cpp screenshot.cpp #if SDL