(svn r9892) -Codechange: lots of ground work for allowing multiple types of "road" with multiple owners on a single tile.

This commit is contained in:
rubidium 2007-05-20 19:14:08 +00:00
parent c685a7179f
commit d86b5e5e93
15 changed files with 415 additions and 169 deletions

View File

@ -2579,11 +2579,11 @@ static int32 AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData
if (p->mode == 2) {
if (IsTileType(c, MP_STREET) &&
GetRoadTileType(c) == ROAD_TILE_NORMAL &&
(GetRoadBits(c) & p->attr) != 0) {
(GetRoadBits(c, ROADTYPE_ROAD) & p->attr) != 0) {
roadflag |= 2;
// all bits are already built?
if ((GetRoadBits(c) & p->attr) == p->attr) continue;
if ((GetRoadBits(c, ROADTYPE_ROAD) & p->attr) == p->attr) continue;
}
ret = DoCommand(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);

View File

@ -211,7 +211,6 @@ static inline void SetBridgeMiddle(TileIndex t, Axis a)
SETBIT(_m[t].m6, 6 + a);
}
/**
* Generic part to make a bridge ramp for both roads and rails.
* @param t the tile to make a bridge ramp
@ -219,13 +218,15 @@ static inline void SetBridgeMiddle(TileIndex t, Axis a)
* @param bridgetype the type of bridge this bridge ramp belongs to
* @param d the direction this ramp must be facing
* @param tt the transport type of the bridge
* @param rt the road or rail type
* @note this function should not be called directly.
*/
static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, TransportType tt)
static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, TransportType tt, uint rt)
{
SetTileType(t, MP_TUNNELBRIDGE);
SetTileOwner(t, o);
_m[t].m2 = bridgetype << 4;
_m[t].m3 = rt;
_m[t].m4 = 0;
_m[t].m5 = 1 << 7 | tt << 2 | d;
}
@ -236,11 +237,11 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDir
* @param o the new owner of the bridge ramp
* @param bridgetype the type of bridge this bridge ramp belongs to
* @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, uint bridgetype, DiagDirection d)
static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, RoadTypes r)
{
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD);
_m[t].m3 = 0;
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD, r);
}
/**
@ -253,8 +254,7 @@ static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, uint bridgetype, Dia
*/
static inline void MakeRailBridgeRamp(TileIndex t, Owner o, uint bridgetype, DiagDirection d, RailType r)
{
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL);
_m[t].m3 = r;
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL, r);
}

View File

@ -1108,8 +1108,8 @@ static void ConvertTownOwner()
for (tile = 0; tile != MapSize(); tile++) {
switch (GetTileType(tile)) {
case MP_STREET:
if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) & 0x80) {
SetCrossingRoadOwner(tile, OWNER_TOWN);
if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HASBIT(_m[tile].m4, 7)) {
_m[tile].m4 = OWNER_TOWN;
}
/* FALLTHROUGH */
@ -1414,6 +1414,70 @@ bool AfterLoadGame()
}
}
if (CheckSavegameVersion(48)) {
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_RAILWAY:
if (IsPlainRailTile(t)) {
/* Swap ground type and signal type for plain rail tiles, so the
* ground type uses the same bits as for depots and waypoints. */
uint tmp = GB(_m[t].m4, 0, 4);
SB(_m[t].m4, 0, 4, GB(_m[t].m2, 0, 4));
SB(_m[t].m2, 0, 4, tmp);
} else if (HASBIT(_m[t].m5, 2)) {
/* Split waypoint and depot rail type and remove the subtype. */
CLRBIT(_m[t].m5, 2);
CLRBIT(_m[t].m5, 6);
}
break;
case MP_STREET:
/* Swap m3 and m4, so the track type for rail crossings is the
* same as for normal rail. */
Swap(_m[t].m3, _m[t].m4);
break;
default: break;
}
}
}
if (CheckSavegameVersion(61)) {
/* Added the RoadType */
for (TileIndex t = 0; t < map_size; t++) {
switch(GetTileType(t)) {
case MP_STREET:
SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2));
switch (GetRoadTileType(t)) {
default: NOT_REACHED();
case ROAD_TILE_NORMAL:
SB(_m[t].m4, 0, 4, GB(_m[t].m5, 0, 4));
SB(_m[t].m4, 4, 4, 0);
SB(_m[t].m6, 2, 4, 0);
break;
case ROAD_TILE_CROSSING:
SB(_m[t].m4, 5, 2, GB(_m[t].m5, 2, 2));
break;
case ROAD_TILE_DEPOT: break;
}
SetRoadTypes(t, ROADTYPES_ROAD);
break;
case MP_STATION:
if (IsRoadStop(t)) SetRoadTypes(t, ROADTYPES_ROAD);
break;
case MP_TUNNELBRIDGE:
if ((IsTunnel(t) ? GetTunnelTransportType(t) : GetBridgeTransportType(t)) == TRANSPORT_ROAD) {
SetRoadTypes(t, ROADTYPES_ROAD);
}
break;
default: break;
}
}
}
if (CheckSavegameVersion(42)) {
Vehicle* v;
@ -1436,9 +1500,10 @@ bool AfterLoadGame()
MakeRoadNormal(
t,
GetTileOwner(t),
axis == AXIS_X ? ROAD_Y : ROAD_X,
town
ROADTYPES_ROAD,
town,
GetTileOwner(t), OWNER_NONE, OWNER_NONE
);
}
} else {
@ -1486,34 +1551,6 @@ bool AfterLoadGame()
}
}
if (CheckSavegameVersion(48)) {
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_RAILWAY:
if (IsPlainRailTile(t)) {
/* Swap ground type and signal type for plain rail tiles, so the
* ground type uses the same bits as for depots and waypoints. */
uint tmp = GB(_m[t].m4, 0, 4);
SB(_m[t].m4, 0, 4, GB(_m[t].m2, 0, 4));
SB(_m[t].m2, 0, 4, tmp);
} else if (HASBIT(_m[t].m5, 2)) {
/* Split waypoint and depot rail type and remove the subtype. */
CLRBIT(_m[t].m5, 2);
CLRBIT(_m[t].m5, 6);
}
break;
case MP_STREET:
/* Swap m3 and m4, so the track type for rail crossings is the
* same as for normal rail. */
Swap(_m[t].m3, _m[t].m4);
break;
default: break;
}
}
}
/* Elrails got added in rev 24 */
if (CheckSavegameVersion(24)) {
Vehicle *v;
@ -1772,8 +1809,6 @@ bool AfterLoadGame()
* space for newhouses grf features. A new byte, m7, was also added. */
if (CheckSavegameVersion(53)) {
for (TileIndex t = 0; t < map_size; t++) {
_me[t].m7 = 0;
if (IsTileType(t, MP_HOUSE)) {
if (GB(_m[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) {
/* Move the construction stage from m3[7..6] to m5[5..4].

View File

@ -295,10 +295,25 @@ int32 CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
if ((track == TRACK_X && GetRoadBits(tile) == ROAD_Y) ||
(track == TRACK_Y && GetRoadBits(tile) == ROAD_X)) {
RoadTypes roadtypes = GetRoadTypes(tile);
RoadBits road = GetRoadBits(tile, ROADTYPE_ROAD);
RoadBits tram = GetRoadBits(tile, ROADTYPE_TRAM);
switch (roadtypes) {
default: break;
case ROADTYPES_ROADTRAM: if (road == tram) break;
/* FALL THROUGH */
case ROADTYPES_ROADHWAY: // Road and highway are incompatible in this case
case ROADTYPES_TRAMHWAY: // Tram and highway are incompatible in this case
case ROADTYPES_ALL: // Also incompatible
return CMD_ERROR;
}
road |= tram | GetRoadBits(tile, ROADTYPE_HWAY);
if ((track == TRACK_X && road == ROAD_Y) ||
(track == TRACK_Y && road == ROAD_X)) {
if (flags & DC_EXEC) {
MakeRoadCrossing(tile, GetTileOwner(tile), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, GetTownIndex(tile));
MakeRoadCrossing(tile, GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY), _current_player, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile));
}
break;
}
@ -359,7 +374,7 @@ int32 CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
if (flags & DC_EXEC) {
MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile));
MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY));
}
break;
}

View File

@ -7,6 +7,68 @@
#include "helpers.hpp"
/**
* The different roadtypes we support
* @note currently only ROADTYPE_ROAD is supported.
*/
enum RoadType {
ROADTYPE_ROAD = 0,
ROADTYPE_TRAM = 1,
ROADTYPE_HWAY = 2, ///< Only a placeholder. Not sure what we are going to do with this road type.
ROADTYPE_END,
INVALID_ROADTYPE = 0xFF
};
DECLARE_POSTFIX_INCREMENT(RoadType);
/**
* The different roadtypes we support, but then a bitmask of them
* @note currently only ROADTYPES_ROAD is supported.
*/
enum RoadTypes {
ROADTYPES_NONE = 0,
ROADTYPES_ROAD = 1 << ROADTYPE_ROAD,
ROADTYPES_TRAM = 1 << ROADTYPE_TRAM,
ROADTYPES_HWAY = 1 << ROADTYPE_HWAY,
ROADTYPES_ROADTRAM = ROADTYPES_ROAD | ROADTYPES_TRAM,
ROADTYPES_ROADHWAY = ROADTYPES_ROAD | ROADTYPES_HWAY,
ROADTYPES_TRAMHWAY = ROADTYPES_TRAM | ROADTYPES_HWAY,
ROADTYPES_ALL = ROADTYPES_ROAD | ROADTYPES_TRAM | ROADTYPES_HWAY,
};
DECLARE_ENUM_AS_BIT_SET(RoadTypes);
/**
* Whether the given roadtype is valid.
* @param rt the roadtype to check for validness
* @return true if and only if valid
*/
static inline bool IsValidRoadType(RoadType rt)
{
return rt == ROADTYPE_ROAD;
}
/**
* Are the given bits pointing to valid roadtypes?
* @param rts the roadtypes to check for validness
* @return true if and only if valid
*/
static inline bool AreValidRoadTypes(RoadTypes rts)
{
return rts == ROADTYPES_ROAD;
}
/**
* Maps a RoadType to the corresponding RoadTypes value
*/
static inline RoadTypes RoadTypeToRoadTypes(RoadType rt)
{
return (RoadTypes)(1 << rt);
}
static inline RoadTypes ComplementRoadTypes(RoadTypes r)
{
return (RoadTypes)(ROADTYPES_ALL ^ r);
}
enum RoadBits {
ROAD_NONE = 0U,
ROAD_NW = 1U,
@ -48,8 +110,9 @@ static inline bool IsStraightRoadTrackdir(Trackdir dir)
* @param remove the roadbits that are going to be removed
* @param owner the actual owner of the roadbits of the tile
* @param edge_road are the removed bits from a town?
* @param rt the road type to remove the bits from
* @return true when it is allowed to remove the road bits
*/
bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road);
bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt);
#endif /* ROAD_H */

View File

@ -41,13 +41,13 @@ static uint CountRoadBits(RoadBits r)
}
bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road)
bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt)
{
RoadBits present;
RoadBits n;
*edge_road = true;
if (_game_mode == GM_EDITOR) return true;
if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true;
/* Only do the special processing for actual players. */
if (!IsValidPlayer(_current_player)) return true;
@ -60,11 +60,11 @@ bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *ed
/* Get a bitmask of which neighbouring roads has a tile */
n = ROAD_NONE;
present = GetAnyRoadBits(tile);
if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0)) & ROAD_SW) n |= ROAD_NE;
if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1)) & ROAD_NW) n |= ROAD_SE;
if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0)) & ROAD_NE) n |= ROAD_SW;
if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1)) & ROAD_SE) n |= ROAD_NW;
present = GetAnyRoadBits(tile, rt);
if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0), rt) & ROAD_SW) n |= ROAD_NE;
if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1), rt) & ROAD_NW) n |= ROAD_SE;
if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0), rt) & ROAD_NE) n |= ROAD_SW;
if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1), rt) & ROAD_SE) n |= ROAD_NW;
/* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
* then allow it */
@ -84,15 +84,16 @@ bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *ed
return true;
}
static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road)
static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
{
return CheckAllowRemoveRoad(tile, remove, IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile), edge_road);
return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
}
/** Delete a piece of road.
* @param tile tile where to remove road from
* @param flags operation to perform
* @param p1 bit 0..3 road pieces to remove (RoadBits)
* bit 4..5 road type
* @param p2 unused
*/
int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
@ -100,7 +101,6 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
/* cost for removing inner/edge -roads */
static const uint16 road_remove_cost[2] = {50, 18};
Owner owner;
Town *t;
/* true if the roadpiece was always removeable,
* false if it was a center piece. Affects town ratings drop */
@ -108,9 +108,10 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
if (!IsTileType(tile, MP_STREET)) return CMD_ERROR;
RoadType rt = (RoadType)GB(p1, 4, 2);
if (!IsTileType(tile, MP_STREET) || !IsValidRoadType(rt)) return CMD_ERROR;
owner = IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile);
Owner owner = GetRoadOwner(tile, rt);
if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) {
t = GetTownByTile(tile);
@ -119,8 +120,11 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
RoadBits pieces = Extract<RoadBits, 0>(p1);
RoadTypes rts = GetRoadTypes(tile);
/* The tile doesn't have the given road type */
if (!HASBIT(rts, rt)) return CMD_ERROR;
if (!CheckAllowRemoveRoad(tile, pieces, &edge_road)) return CMD_ERROR;
if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
@ -130,7 +134,7 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
switch (GetRoadTileType(tile)) {
case ROAD_TILE_NORMAL: {
RoadBits present = GetRoadBits(tile);
RoadBits present = GetRoadBits(tile, rt);
RoadBits c = pieces;
if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
@ -150,9 +154,14 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
present ^= c;
if (present == 0) {
DoClearSquare(tile);
RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
if (rts == ROADTYPES_NONE) {
DoClearSquare(tile);
} else {
SetRoadTypes(tile, rts);
}
} else {
SetRoadBits(tile, present);
SetRoadBits(tile, present, rt);
MarkTileDirtyByTile(tile);
}
}
@ -165,9 +174,16 @@ int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
if (flags & DC_EXEC) {
ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
if (rt == ROADTYPE_ROAD) {
ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
}
MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
if (rts == ROADTYPES_NONE) {
MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));
} else {
SetRoadTypes(tile, rts);
}
MarkTileDirtyByTile(tile);
YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
}
@ -255,6 +271,7 @@ static uint32 CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing)
* @param tile tile where to build road
* @param flags operation to perform
* @param p1 bit 0..3 road pieces to build (RoadBits)
* bit 4..5 road type
* @param p2 the town that is building the road (0 if not applicable)
*/
int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
@ -272,6 +289,9 @@ int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
RoadBits pieces = Extract<RoadBits, 0>(p1);
RoadType rt = (RoadType)GB(p1, 4, 2);
if (!IsValidRoadType(rt)) return CMD_ERROR;
tileh = GetTileSlope(tile, NULL);
switch (GetTileType(tile)) {
@ -280,7 +300,7 @@ int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
case ROAD_TILE_NORMAL:
if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS);
existing = GetRoadBits(tile);
existing = GetRoadBits(tile, rt);
if ((existing & pieces) == pieces) {
return_cmd_error(STR_1007_ALREADY_BUILT);
}
@ -288,10 +308,9 @@ int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
break;
case ROAD_TILE_CROSSING:
if (pieces != GetCrossingRoadBits(tile)) { // XXX is this correct?
return_cmd_error(STR_1007_ALREADY_BUILT);
}
goto do_clear;
if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) goto do_clear;
break;
default:
case ROAD_TILE_DEPOT:
@ -332,7 +351,7 @@ int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (flags & DC_EXEC) {
YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
MakeRoadCrossing(tile, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), p2);
MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt), p2);
MarkTileDirtyByTile(tile);
}
return _price.build_road * 2;
@ -362,9 +381,13 @@ do_clear:;
if (flags & DC_EXEC) {
if (IsTileType(tile, MP_STREET)) {
SetRoadBits(tile, existing | pieces);
if (existing == 0) {
SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
SetRoadOwner(tile, rt, _current_player);
}
SetRoadBits(tile, existing | pieces, rt);
} else {
MakeRoadNormal(tile, _current_player, pieces, p2);
MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_player, _current_player, _current_player);
}
MarkTileDirtyByTile(tile);
@ -411,6 +434,7 @@ int32 DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
* - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
* - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
* - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
* - p2 = (bit 3) - road type
*/
int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
{
@ -422,6 +446,7 @@ int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
if (p1 >= MapSize()) return CMD_ERROR;
start_tile = p1;
RoadType rt = (RoadType)HASBIT(p2, 3);
/* Only drag in X or Y direction dictated by the direction variable */
if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
@ -444,7 +469,7 @@ int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
ret = DoCommand(tile, bits, 0, flags, CMD_BUILD_ROAD);
ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
if (CmdFailed(ret)) {
if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
_error_message = INVALID_STRING_ID;
@ -468,6 +493,7 @@ int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
* - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
* - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
* - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
* - p2 = (bit 3) - road type
*/
int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
{
@ -479,6 +505,7 @@ int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
if (p1 >= MapSize()) return CMD_ERROR;
start_tile = p1;
RoadType rt = (RoadType)HASBIT(p2, 3);
/* Only drag in X or Y direction dictated by the direction variable */
if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
@ -503,7 +530,7 @@ int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
/* try to remove the halves. */
if (bits != 0) {
ret = DoCommand(tile, bits, 0, flags, CMD_REMOVE_ROAD);
ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
if (!CmdFailed(ret)) cost += ret;
}
@ -519,6 +546,7 @@ int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
* @param tile tile where to build the depot
* @param flags operation to perform
* @param p1 bit 0..1 entrance direction (DiagDirection)
* bit 2 road type
* @param p2 unused
*
* @todo When checking for the tile slope,
@ -533,6 +561,7 @@ int32 CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
DiagDirection dir = Extract<DiagDirection, 0>(p1);
RoadType rt = (RoadType)HASBIT(p1, 2);
tileh = GetTileSlope(tile, NULL);
if (tileh != SLOPE_FLAT && (
@ -555,7 +584,7 @@ int32 CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
dep->xy = tile;
dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
MakeRoadDepot(tile, _current_player, dir);
MakeRoadDepot(tile, _current_player, dir, rt);
MarkTileDirtyByTile(tile);
}
return cost + _price.build_road_depot;
@ -577,7 +606,7 @@ static int32 ClearTile_Road(TileIndex tile, byte flags)
{
switch (GetRoadTileType(tile)) {
case ROAD_TILE_NORMAL: {
RoadBits b = GetRoadBits(tile);
RoadBits b = GetAllRoadBits(tile);
#define M(x) (1 << (x))
/* Clear the road if only one piece is on the tile OR the AI tries
@ -685,7 +714,7 @@ static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside)
*/
static void DrawRoadBits(TileInfo* ti)
{
RoadBits road = GetRoadBits(ti->tile);
RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
const DrawRoadTileStruct *drts;
SpriteID image = 0;
SpriteID pal = PAL_NONE;
@ -836,7 +865,7 @@ static uint GetSlopeZ_Road(TileIndex tile, uint x, uint y)
if (tileh == SLOPE_FLAT) return z;
if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
if (f != 0) {
if (IsSteepSlope(tileh)) {
@ -856,7 +885,7 @@ static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh)
{
if (tileh == SLOPE_FLAT) return SLOPE_FLAT;
if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) {
uint f = GetRoadFoundation(tileh, GetRoadBits(tile));
uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile));
if (f == 0) return tileh;
if (f < 15) return SLOPE_FLAT; // leveled foundation
@ -924,7 +953,7 @@ static void TileLoop_Road(TileIndex tile)
/* 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 && (GetRoadBits(tile) == ROAD_X || GetRoadBits(tile) == ROAD_Y)) {
GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) {
if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
StartRoadWorks(tile);
@ -978,15 +1007,18 @@ static const byte _road_trackbits[16] = {
static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode)
{
RoadType rt = ROADTYPE_ROAD;
switch (mode) {
case TRANSPORT_RAIL:
if (!IsLevelCrossing(tile)) return 0;
return GetCrossingRailBits(tile) * 0x101;
case TRANSPORT_ROAD:
if (!HASBIT(GetRoadTypes(tile), rt)) return 0;
switch (GetRoadTileType(tile)) {
case ROAD_TILE_NORMAL:
return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile)] * 0x101;
return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile, rt)] * 0x101;
case ROAD_TILE_CROSSING: {
uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101;
@ -1060,30 +1092,26 @@ static uint32 VehicleEnter_Road(Vehicle *v, TileIndex tile, int x, int y)
static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
{
if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) == old_player) {
SetCrossingRoadOwner(tile, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) {
DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
return;
}
if (!IsTileOwner(tile, old_player)) return;
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
if (!HASBIT(GetRoadTypes(tile), rt)) continue;
if (new_player != PLAYER_SPECTATOR) {
SetTileOwner(tile, new_player);
} else {
switch (GetRoadTileType(tile)) {
case ROAD_TILE_NORMAL:
SetTileOwner(tile, OWNER_NONE);
break;
if (GetRoadOwner(tile, rt) == old_player) {
SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
case ROAD_TILE_CROSSING:
MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile));
break;
default:
case ROAD_TILE_DEPOT:
DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
break;
if (rt == ROADTYPE_TRAM) {
DoCommand(tile, ROADTYPE_TRAM << 4 | GetRoadBits(tile, ROADTYPE_ROAD), 0, DC_EXEC, CMD_REMOVE_ROAD);
}
}
}
if (IsLevelCrossing(tile)) {
MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY));
}
}

View File

@ -69,7 +69,7 @@ void CcBuildRoadTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2)
static void PlaceRoad_Tunnel(TileIndex tile)
{
DoCommandP(tile, 0x200, 0, CcBuildRoadTunnel, CMD_BUILD_TUNNEL | CMD_AUTO | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
DoCommandP(tile, 0x200 | ROADTYPES_ROAD, 0, CcBuildRoadTunnel, CMD_BUILD_TUNNEL | CMD_AUTO | CMD_MSG(STR_5016_CAN_T_BUILD_TUNNEL_HERE));
}
static void BuildRoadOutsideStation(TileIndex tile, DiagDirection direction)
@ -113,7 +113,7 @@ static void PlaceRoad_BusStation(TileIndex tile)
if (_remove_button_clicked) {
DoCommandP(tile, 0, RoadStop::BUS, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_CAN_T_REMOVE_BUS_STATION));
} else {
PlaceRoadStop(tile, RoadStop::BUS, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1808_CAN_T_BUILD_BUS_STATION));
PlaceRoadStop(tile, ROADTYPES_ROAD << 2 | RoadStop::BUS, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1808_CAN_T_BUILD_BUS_STATION));
}
}
@ -122,7 +122,7 @@ static void PlaceRoad_TruckStation(TileIndex tile)
if (_remove_button_clicked) {
DoCommandP(tile, 0, RoadStop::TRUCK, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_CAN_T_REMOVE_TRUCK_STATION));
} else {
PlaceRoadStop(tile, RoadStop::TRUCK, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1809_CAN_T_BUILD_TRUCK_STATION));
PlaceRoadStop(tile, ROADTYPES_ROAD << 2 | RoadStop::TRUCK, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1809_CAN_T_BUILD_TRUCK_STATION));
}
}
@ -297,7 +297,7 @@ static void BuildRoadToolbWndProc(Window *w, WindowEvent *e)
if (e->we.place.userdata == 0) {
ResetObjectToPlace();
ShowBuildBridgeWindow(start_tile, end_tile, 0x80);
ShowBuildBridgeWindow(start_tile, end_tile, 0x80 | ROADTYPES_ROAD);
} else if (e->we.place.userdata != 4) {
DoCommandP(end_tile, start_tile, _place_road_flag, CcPlaySound1D,
_remove_button_clicked ?
@ -312,7 +312,7 @@ static void BuildRoadToolbWndProc(Window *w, WindowEvent *e)
case WE_PLACE_PRESIZE: {
TileIndex tile = e->we.place.tile;
DoCommand(tile, 0x200, 0, DC_AUTO, CMD_BUILD_TUNNEL);
DoCommand(tile, 0x200 | ROADTYPES_ROAD, 0, DC_AUTO, CMD_BUILD_TUNNEL);
VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
break;
}

View File

@ -14,13 +14,15 @@
#include "depot.h"
RoadBits GetAnyRoadBits(TileIndex tile)
RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt)
{
if (!HASBIT(GetRoadTypes(tile), rt)) return ROAD_NONE;
switch (GetTileType(tile)) {
case MP_STREET:
switch (GetRoadTileType(tile)) {
default:
case ROAD_TILE_NORMAL: return GetRoadBits(tile);
case ROAD_TILE_NORMAL: return GetRoadBits(tile, rt);
case ROAD_TILE_CROSSING: return GetCrossingRoadBits(tile);
case ROAD_TILE_DEPOT: return DiagDirToRoadBits(GetRoadDepotDirection(tile));
}
@ -44,15 +46,16 @@ RoadBits GetAnyRoadBits(TileIndex tile)
}
TrackBits GetAnyRoadTrackBits(TileIndex tile)
TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt)
{
uint32 r;
/* Don't allow local authorities to build roads through road depots or road stops. */
if ((IsTileType(tile, MP_STREET) && IsTileDepotType(tile, TRANSPORT_ROAD)) || (IsTileType(tile, MP_STATION) && !IsDriveThroughStopTile(tile))) {
if ((IsTileType(tile, MP_STREET) && IsTileDepotType(tile, TRANSPORT_ROAD)) || (IsTileType(tile, MP_STATION) && !IsDriveThroughStopTile(tile)) || !HASBIT(GetRoadTypes(tile), rt)) {
return TRACK_BIT_NONE;
}
r = GetTileTrackStatus(tile, TRANSPORT_ROAD);
return (TrackBits)(byte)(r | (r >> 8));
}

View File

@ -18,9 +18,9 @@ enum RoadTileType {
};
static inline RoadTileType GetRoadTileType(TileIndex t)
{
{
assert(IsTileType(t, MP_STREET));
return (RoadTileType)GB(_m[t].m5, 4, 4);
return (RoadTileType)GB(_m[t].m5, 6, 2);
}
static inline bool IsLevelCrossing(TileIndex t)
@ -33,23 +33,104 @@ static inline bool IsLevelCrossingTile(TileIndex t)
return IsTileType(t, MP_STREET) && IsLevelCrossing(t);
}
static inline RoadBits GetRoadBits(TileIndex t)
static inline RoadBits GetRoadBits(TileIndex t, RoadType rt)
{
assert(GetRoadTileType(t) == ROAD_TILE_NORMAL);
return (RoadBits)GB(_m[t].m5, 0, 4);
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m4, 0, 4);
case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m4, 4, 4);
case ROADTYPE_HWAY: return (RoadBits)GB(_m[t].m6, 2, 4);
}
}
static inline void SetRoadBits(TileIndex t, RoadBits r)
static inline RoadBits GetAllRoadBits(TileIndex tile)
{
return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM) | GetRoadBits(tile, ROADTYPE_HWAY);
}
static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt)
{
assert(GetRoadTileType(t) == ROAD_TILE_NORMAL); // XXX incomplete
SB(_m[t].m5, 0, 4, r);
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: SB(_m[t].m4, 0, 4, r); break;
case ROADTYPE_TRAM: SB(_m[t].m4, 4, 4, r); break;
case ROADTYPE_HWAY: SB(_m[t].m6, 2, 4, r); break;
}
}
static inline RoadTypes GetRoadTypes(TileIndex t)
{
if (IsTileType(t, MP_STREET)) {
return (RoadTypes)GB(_me[t].m7, 5, 3);
} else {
return (RoadTypes)GB(_m[t].m3, 0, 3);
}
}
static inline void SetRoadTypes(TileIndex t, RoadTypes rt)
{
if (IsTileType(t, MP_STREET)) {
SB(_me[t].m7, 5, 3, rt);
} else {
assert(IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE));
SB(_m[t].m3, 0, 2, rt);
}
}
static inline Owner GetRoadOwner(TileIndex t, RoadType rt)
{
if (!IsTileType(t, MP_STREET)) return GetTileOwner(t);
switch (GetRoadTileType(t)) {
default: NOT_REACHED();
case ROAD_TILE_NORMAL:
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: return (Owner)GB( _m[t].m1, 0, 5);
case ROADTYPE_TRAM: return (Owner)GB( _m[t].m5, 0, 5);
case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5);
}
case ROAD_TILE_CROSSING:
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: return (Owner)GB( _m[t].m4, 0, 5);
case ROADTYPE_TRAM: return (Owner)GB( _m[t].m5, 0, 5);
case ROADTYPE_HWAY: return (Owner)GB(_me[t].m7, 0, 5);
}
case ROAD_TILE_DEPOT: return GetTileOwner(t);
}
}
static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
{
if (!IsTileType(t, MP_STREET)) return SetTileOwner(t, o);
switch (GetRoadTileType(t)) {
default: NOT_REACHED();
case ROAD_TILE_NORMAL:
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break;
case ROADTYPE_TRAM: SB( _m[t].m5, 0, 5, o); break;
case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
}
case ROAD_TILE_CROSSING:
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break;
case ROADTYPE_TRAM: SB( _m[t].m5, 0, 5, o); break;
case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
}
case ROAD_TILE_DEPOT: return SetTileOwner(t, o);
}
}
static inline Axis GetCrossingRoadAxis(TileIndex t)
{
assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
return (Axis)GB(_m[t].m5, 3, 1);
return (Axis)GB(_m[t].m4, 6, 1);
}
static inline RoadBits GetCrossingRoadBits(TileIndex tile)
@ -63,35 +144,22 @@ static inline TrackBits GetCrossingRailBits(TileIndex tile)
}
// TODO swap owner of road and rail
static inline Owner GetCrossingRoadOwner(TileIndex t)
{
assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
return (Owner)_m[t].m4;
}
static inline void SetCrossingRoadOwner(TileIndex t, Owner o)
{
assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
_m[t].m4 = o;
}
static inline void UnbarCrossing(TileIndex t)
{
assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
CLRBIT(_m[t].m5, 2);
CLRBIT(_m[t].m4, 5);
}
static inline void BarCrossing(TileIndex t)
{
assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
SETBIT(_m[t].m5, 2);
SETBIT(_m[t].m4, 5);
}
static inline bool IsCrossingBarred(TileIndex t)
{
assert(GetRoadTileType(t) == ROAD_TILE_CROSSING);
return HASBIT(_m[t].m5, 2);
return HASBIT(_m[t].m4, 5);
}
#define IsOnDesert IsOnSnow
@ -174,9 +242,10 @@ static inline DiagDirection GetRoadDepotDirection(TileIndex t)
* - bridge ramps: start of the ramp is treated as road piece
* - bridge middle parts: bridge itself is ignored
* @param tile the tile to get the road bits for
* @param rt the road type to get the road bits form
* @return the road bits of the given tile
*/
RoadBits GetAnyRoadBits(TileIndex tile);
RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt);
/**
* Get the accessible track bits for the given tile.
@ -186,39 +255,45 @@ RoadBits GetAnyRoadBits(TileIndex tile);
* @param tile the tile to get the track bits for
* @return the track bits for the given tile
*/
TrackBits GetAnyRoadTrackBits(TileIndex tile);
TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt);
static inline void MakeRoadNormal(TileIndex t, Owner owner, RoadBits bits, TownID town)
static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, Owner hway)
{
SetTileType(t, MP_STREET);
SetTileOwner(t, owner);
SetTileOwner(t, road);
_m[t].m2 = town;
_m[t].m3 = 0 << 7 | 0 << 4 | 0;
_m[t].m4 = 0;
_m[t].m5 = ROAD_TILE_NORMAL << 4 | bits;
_m[t].m3 = 0;
_m[t].m4 = (HASBIT(rot, ROADTYPE_ROAD) ? bits : 0) << 4 | HASBIT(rot, ROADTYPE_TRAM) ? bits : 0;
_m[t].m5 = ROAD_TILE_NORMAL << 6 | tram;
SB(_m[t].m6, 2, 4, HASBIT(rot, ROADTYPE_HWAY) ? bits : 0);
_me[t].m7 = rot << 5 | hway;
}
static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner rail, Axis roaddir, RailType rt, uint town)
static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner hway, Owner rail, Axis roaddir, RailType rat, RoadTypes rot, uint town)
{
SetTileType(t, MP_STREET);
SetTileOwner(t, rail);
_m[t].m2 = town;
_m[t].m3 = 0 << 7 | 0 << 4 | rt;
_m[t].m4 = road;
_m[t].m5 = ROAD_TILE_CROSSING << 4 | roaddir << 3 | 0 << 2;
_m[t].m3 = rat;
_m[t].m4 = roaddir << 6 | road;
_m[t].m5 = ROAD_TILE_CROSSING << 6 | tram;
SB(_m[t].m6, 2, 4, 0);
_me[t].m7 = rot << 5 | hway;
}
static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir)
static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir, RoadType rt)
{
SetTileType(t, MP_STREET);
SetTileOwner(t, owner);
_m[t].m2 = 0;
_m[t].m3 = 0;
_m[t].m4 = 0;
_m[t].m5 = ROAD_TILE_DEPOT << 4 | dir;
_m[t].m5 = ROAD_TILE_DEPOT << 6 | dir;
SB(_m[t].m6, 2, 4, 0);
_me[t].m7 = RoadTypeToRoadTypes(rt) << 5;
}
#endif /* ROAD_MAP_H */

View File

@ -29,7 +29,7 @@
#include <setjmp.h>
#include <list>
extern const uint16 SAVEGAME_VERSION = 60;
extern const uint16 SAVEGAME_VERSION = 61;
uint16 _sl_version; ///< the major savegame version identifier
byte _sl_minor_version; ///< the minor savegame version, DO NOT USE!

View File

@ -1214,6 +1214,7 @@ static RoadStop **FindRoadStopSpot(bool truck_station, Station* st)
* @param p1 entrance direction (DiagDirection)
* @param p2 bit 0: 0 for Bus stops, 1 for truck stops
* bit 1: 0 for normal, 1 for drive-through
* bit 2..4: the roadtypes
*/
int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
@ -1222,17 +1223,23 @@ int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
bool build_over_road = is_drive_through && IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
bool town_owned_road = build_over_road && IsTileOwner(tile, OWNER_TOWN);
Owner cur_owner = _current_player;
RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR;
/* Saveguard the parameters */
if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
/* If it is a drive-through stop check for valid axis */
if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
/* Road bits in the wrong direction */
if (build_over_road && (GetRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
if (build_over_road && (GetAllRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
/* Not allowed to build over this road */
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 (!IsTileOwner(tile, OWNER_TOWN) && !CheckOwnership(GetTileOwner(tile))) return CMD_ERROR;
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;
/* Do not remove roadtypes! */
if (rts != GetRoadTypes(tile) && rts != ROADTYPES_ROADTRAM) return CMD_ERROR;
}
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@ -1311,9 +1318,9 @@ int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
if (is_drive_through) {
MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, (Axis)p1, town_owned_road);
MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, rts, (Axis)p1, town_owned_road);
} else {
MakeRoadStop(tile, st->owner, st->index, rs_type, (DiagDirection)p1);
MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
}
UpdateStationVirtCoordDirty(st);
@ -1389,7 +1396,8 @@ int32 CmdRemoveRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
Station *st = GetStationByTile(tile);
/* Save the stop info before it is removed */
bool is_drive_through = IsDriveThroughStopTile(tile);
RoadBits road_bits = GetAnyRoadBits(tile);
RoadTypes rts = GetRoadTypes(tile);
RoadBits road_bits = GetAnyRoadBits(tile, HASBIT(rts, ROADTYPE_ROAD) ? ROADTYPE_ROAD : ROADTYPE_TRAM);
bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
int32 ret = RemoveRoadStop(st, flags, tile);
@ -1403,7 +1411,12 @@ int32 CmdRemoveRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
index = ClosestTownFromTile(tile, (uint)-1)->index;
_current_player = OWNER_TOWN;
}
DoCommand(tile, road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
if (HASBIT(rts, ROADTYPE_ROAD)) {
DoCommand(tile, ROADTYPE_ROAD << 4 | road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
}
if (HASBIT(rts, ROADTYPE_TRAM)) {
DoCommand(tile, ROADTYPE_TRAM << 4 | road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
}
_current_player = cur_owner;
}
@ -2676,7 +2689,8 @@ static bool CanRemoveRoadWithStop(TileIndex tile)
if (!GetStopBuiltOnTownRoad(tile)) return true;
bool edge_road;
return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile), OWNER_TOWN, &edge_road);
return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, &edge_road, ROADTYPE_ROAD) &&
CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_TRAM), OWNER_TOWN, &edge_road, ROADTYPE_TRAM);
}
static int32 ClearTile_Station(TileIndex tile, byte flags)

View File

@ -6,6 +6,7 @@
#define STATION_MAP_H
#include "rail_map.h"
#include "road_map.h"
#include "station.h"
typedef byte StationGfx;
@ -309,15 +310,17 @@ static inline void MakeRailStation(TileIndex t, Owner o, StationID sid, Axis a,
SetRailType(t, rt);
}
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, DiagDirection d)
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, RoadTypes rt, DiagDirection d)
{
MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE : GFX_TRUCK_BASE) + d);
SetRoadTypes(t, rt);
}
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, Axis a, bool on_town_road)
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, RoadTypes rt, Axis a, bool on_town_road)
{
MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE_EXT : GFX_TRUCK_BASE_EXT) + a);
SB(_m[t].m6, 3, 1, on_town_road);
SetRoadTypes(t, rt);
}
static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section)

View File

@ -636,7 +636,7 @@ void OnTick_Town()
static RoadBits GetTownRoadMask(TileIndex tile)
{
TrackBits b = GetAnyRoadTrackBits(tile);
TrackBits b = GetAnyRoadTrackBits(tile, ROADTYPE_ROAD);
RoadBits r = ROAD_NONE;
if (b & TRACK_BIT_X) r |= ROAD_X;
@ -676,7 +676,7 @@ static bool IsRoadAllowedHere(TileIndex tile, int dir)
for (;;) {
/* Check if there already is a road at this point? */
if (GetAnyRoadTrackBits(tile) == 0) {
if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) == 0) {
/* No, try to build one in the direction.
* if that fails clear the land, and if that fails exit.
* This is to make sure that we can build a road here later. */
@ -1221,7 +1221,7 @@ static bool GrowTown(Town *t)
/* Find a road that we can base the construction on. */
tile = t->xy;
for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
if (GetAnyRoadTrackBits(tile) != 0) {
if (GetAnyRoadTrackBits(tile, ROADTYPE_ROAD) != 0) {
int r = GrowTownAtRoad(t, tile);
_current_player = old_player;
return r != 0;
@ -2208,7 +2208,7 @@ Town *ClosestTownFromTile(TileIndex tile, uint threshold)
{
if (IsTileType(tile, MP_HOUSE) || (
IsTileType(tile, MP_STREET) &&
(IsLevelCrossing(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile)) == OWNER_TOWN
GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN
)) {
return GetTownByTile(tile);
} else {

View File

@ -9,6 +9,7 @@
#include "macros.h"
#include "map.h"
#include "rail.h"
#include "road.h"
/**
* Is this a tunnel (entrance)?
@ -93,13 +94,14 @@ bool IsTunnelInWay(TileIndex, uint z);
* @param t the entrance of the tunnel
* @param o the owner of the entrance
* @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)
static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTypes r)
{
SetTileType(t, MP_TUNNELBRIDGE);
SetTileOwner(t, o);
_m[t].m2 = 0;
_m[t].m3 = 0;
_m[t].m3 = r;
_m[t].m4 = 0;
_m[t].m5 = TRANSPORT_ROAD << 2 | d;
}

View File

@ -172,12 +172,14 @@ bool CheckBridge_Stuff(byte bridge_type, uint bridge_len)
* @param p1 packed start tile coords (~ dx)
* @param p2 various bitstuffed elements
* - p2 = (bit 0- 7) - bridge type (hi bh)
* - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge.
* - p2 = (bit 8-..) - rail type or road types.
* - p2 = (bit 15 ) - set means road bridge.
*/
int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
{
uint bridge_type;
RailType railtype;
RoadTypes roadtypes;
uint x;
uint y;
uint sx;
@ -207,6 +209,8 @@ int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
/* type of bridge */
if (HASBIT(p2, 15)) {
railtype = INVALID_RAILTYPE; // road bridge
roadtypes = (RoadTypes)GB(p2, 8, 2);
if (roadtypes > ROADTYPES_ALL || roadtypes == ROADTYPES_NONE) return CMD_ERROR;
} else {
if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR;
railtype = (RailType)GB(p2, 8, 8);
@ -352,8 +356,8 @@ int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype);
} else {
MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir);
MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir));
MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes);
MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), roadtypes);
}
MarkTileDirtyByTile(tile_start);
MarkTileDirtyByTile(tile_end);
@ -442,7 +446,7 @@ not_valid_below:;
/** Build Tunnel.
* @param start_tile start tile of tunnel
* @param flags type of operation
* @param p1 railtype, 0x200 for road tunnel
* @param p1 railtype or roadtypes. bit 9 set means road tunnel
* @param p2 unused
*/
int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
@ -459,7 +463,11 @@ int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
_build_tunnel_endtile = 0;
if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR;
if (HASBIT(p1, 9)) {
if (!ValParamRailtype(p1)) return CMD_ERROR;
} else if (GB(p1, 0, 4) > ROADTYPES_ALL || GB(p1, 0, 4) == ROADTYPES_NONE) {
return CMD_ERROR;
}
start_tileh = GetTileSlope(start_tile, &start_z);
@ -519,8 +527,8 @@ int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
UpdateSignalsOnSegment(start_tile, direction);
YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction)));
} else {
MakeRoadTunnel(start_tile, _current_player, direction);
MakeRoadTunnel(end_tile, _current_player, ReverseDiagDir(direction));
MakeRoadTunnel(start_tile, _current_player, direction, (RoadTypes)GB(p1, 0, 4));
MakeRoadTunnel(end_tile, _current_player, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 4));
}
}