1
0
Fork 0

(svn r15601) -Fix [FS#2615]: bridges/tunnels don't store tram owner making it possible to remove someone's tram tracks.

-Feature: allow building road stops on road/tram tracks of competitors.
release/0.7
rubidium 2009-03-02 22:57:47 +00:00
parent 6dd3703a4c
commit 7831346ef8
19 changed files with 305 additions and 229 deletions

View File

@ -514,8 +514,8 @@
<td> <td>
<ul> <ul>
<li>m2: Index into the array of towns (owning town for town roads; closest town otherwise, INVALID_TOWN if there is no town or we are creating a town)</li> <li>m2: Index into the array of towns (owning town for town roads; closest town otherwise, INVALID_TOWN if there is no town or we are creating a town)</li>
<li>m3 bit 7 set = on snow or desert</li> <li>m7 bit 5 set = on snow or desert</li>
<li>m7 bits 7..5: present road types <li>m7 bits 7..6: present road types
<table> <table>
<tr> <tr>
<td>bit 0&nbsp; </td> <td>bit 0&nbsp; </td>
@ -526,16 +526,11 @@
<td>bit 1&nbsp; </td> <td>bit 1&nbsp; </td>
<td>tram</td> <td>tram</td>
</tr> </tr>
<tr>
<td>bit 2&nbsp; </td>
<td>reserved</td>
</tr>
</table> </table>
</li> </li>
<li>m5 bits 7 clear: road or level-crossing <li>m5 bits 7 clear: road or level-crossing
<ul> <ul>
<li>m3 bits 6..4: <li>m6 bits 5..3:
<table> <table>
<tr> <tr>
<td><tt>0</tt>&nbsp; </td> <td><tt>0</tt>&nbsp; </td>
@ -567,13 +562,12 @@
</tr> </tr>
</table> </table>
</li> </li>
<li>m5 bits 3..0: <a href="#OwnershipInfo">owner</a> of road type 1 (tram); OWNER_NONE (<tt>10</tt>) is stored as OWNER_TOWN (<tt>0F</tt>) <li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of road type 1 (tram); OWNER_NONE (<tt>10</tt>) is stored as OWNER_TOWN (<tt>0F</tt>)
<li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road type 2 (reserved)
<li>m5 bit 6 clear: road <li>m5 bit 6 clear: road
<ul> <ul>
<li>m1: <a href="#OwnershipInfo">owner</a> of the road type 0 (normal road)</li> <li>m1: <a href="#OwnershipInfo">owner</a> of the road type 0 (normal road)</li>
<li>m3 bits 3..0: counter for the roadworks</li> <li>m7 bits 3..0: counter for the roadworks</li>
<li>m4 bits 3..0: road layout road type 0 (normal road): bit set = road piece present: <li>m5 bits 3..0: road layout road type 0 (normal road): bit set = road piece present:
<table> <table>
<tr> <tr>
<td align=left>bit 0: </td> <td align=left>bit 0: </td>
@ -593,8 +587,7 @@
</tr> </tr>
</table> </table>
</li> </li>
<li>m4 bits 7..4: road layout road type 1 (tram)</li> <li>m3 bits 0..3: road layout road type 1 (tram)</li>
<li>m6 bits 5..2: road layout road type 2 (reserved)</li>
<li>m5 bits 5..4: bits to disallow vehicles to go a specific direction <li>m5 bits 5..4: bits to disallow vehicles to go a specific direction
<table> <table>
<tr> <tr>
@ -613,7 +606,7 @@
<ul> <ul>
<li>m1: <a href="#OwnershipInfo">owner</a> of the railway track</li> <li>m1: <a href="#OwnershipInfo">owner</a> of the railway track</li>
<li>m3 bits 3..0: <a href="#TrackType">railway track type</a></li> <li>m3 bits 3..0: <a href="#TrackType">railway track type</a></li>
<li>m4 bit 6: direction <li>m5 bit 0: direction
<table> <table>
<tr> <tr>
<td align=left><tt>0</tt>&nbsp; </td> <td align=left><tt>0</tt>&nbsp; </td>
@ -625,8 +618,8 @@
</tr> </tr>
</table> </table>
</li> </li>
<li>m4 bit 5: set if crossing lights are on</li> <li>m5 bit 5: set if crossing lights are on</li>
<li>m4 bits 4..0: <a href="#OwnershipInfo">owner</a> of the road type 0 (normal road)</li> <li>m6 bits 4..0: <a href="#OwnershipInfo">owner</a> of the road type 0 (normal road)</li>
<li>m5 bit 4: pbs reservation state</li> <li>m5 bit 4: pbs reservation state</li>
</ul> </ul>
</li> </li>
@ -842,9 +835,9 @@
<ul> <ul>
<li>m1: <a href="#OwnershipInfo">owner</a> of the station</li> <li>m1: <a href="#OwnershipInfo">owner</a> of the station</li>
<li>m2: index into the array of stations</li> <li>m2: index into the array of stations</li>
<li>m3 bits 7..4: persistent random data for newstations</li> <li>m3 bits 7..4: persistent random data for newstations (train station)</li>
<li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of tram tracks (road stop)</li>
<li>m3 bits 3..0: <a href="#TrackType">track type</a> for railway stations</li> <li>m3 bits 3..0: <a href="#TrackType">track type</a> for railway stations</li>
<li>m3 bits 2..0: present road types for road stops</li>
<li>m3 bits 1..0: water class for buoys and water part of docks</li> <li>m3 bits 1..0: water class for buoys and water part of docks</li>
<li>m4: custom station id; 0 means standard graphics</li> <li>m4: custom station id; 0 means standard graphics</li>
<li>m5: graphics index (range from 0..255 for each station type): <li>m5: graphics index (range from 0..255 for each station type):
@ -943,10 +936,12 @@
</table> </table>
</li> </li>
<li>m6 bits 5..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy)</li> <li>m6 bits 5..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy)</li>
<li>m6 bit 2: 1 when a drive through road stop is built over a town owned road, otherwise 0</li>
<li>m6 bit 2: pbs reservation state for railway stations</li> <li>m6 bit 2: pbs reservation state for railway stations</li>
<li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li> <li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
<li>m7: animation frame</li> <li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road (road stops)</li>
<li>m7 bits 7..6: present road types (road stops)</li>
<li>m7: animation frame (train station)</li>
</ul> </ul>
</td> </td>
</tr> </tr>
@ -1413,15 +1408,13 @@
<td> <td>
<ul> <ul>
<li>m1: <a href="#OwnershipInfo">owner</a></li> <li>m1: <a href="#OwnershipInfo">owner</a></li>
<li>m2 bits 7..4: see bridge ramp</li> <li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of tram</li>
<li>m3 bits 3..0: <a href="#TrackType">track type</a> for railway</li> <li>m3 bits 3..0: <a href="#TrackType">track type</a> for railway</li>
<li>m3 bits 2..0: present road types for road</li>
<li>m4 bit 7 set = on snow or desert</li>
<li>m5 bit 4: pbs reservation state for railway</li> <li>m5 bit 4: pbs reservation state for railway</li>
<li>m5 bits 7 clear: tunnel entrance/exit</li> <li>m5 bits 7 clear: tunnel entrance/exit</li>
<li>m5 bit 7 set: bridge ramp <li>m5 bit 7 set: bridge ramp
<ul> <ul>
<li>m2 bits 7..4: <a name="BridgeType">bridge type</a>: <li>m6 bits 5..2: <a name="BridgeType">bridge type</a>:
<table> <table>
<tr> <tr>
<th align=left>Type&nbsp;</th> <th align=left>Type&nbsp;</th>
@ -1552,6 +1545,9 @@
</li> </li>
<li>m6 bits 7..6 : Possibility of a bridge above, in the <a href="#bridge_direction">direction specified</a></li> <li>m6 bits 7..6 : Possibility of a bridge above, in the <a href="#bridge_direction">direction specified</a></li>
<li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li> <li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
<li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road</li>
<li>m7 bit 5 set = on snow or desert</li>
<li>m7 bits 7..6: present road types for road</li>
</ul> </ul>
</td> </td>
</tr> </tr>

View File

@ -137,10 +137,10 @@ the array so you can quickly see what is used and what is not.
<td class="bits"><span class="option">~~~</span>X XXXX</td> <td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits">XXXX XXXX XXXX XXXX</td> <td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits">XXXX XXXX</td> <td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XXXX XXXX</td> <td class="bits">XXXX XXXX</td>
<td class="bits">XXXX XXXX</td> <td class="bits">XXXX X<span class="free">O</span>XX</td>
<td class="bits">XXXX XXXX</td> <td class="bits">XXX<span class="free">O</span> XXXX</td>
<td class="bits">XXXX XXXX</td>
</tr> </tr>
<tr> <tr>
<td class="caption">level crossing</td> <td class="caption">level crossing</td>
@ -148,17 +148,17 @@ the array so you can quickly see what is used and what is not.
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">XXXX <span class="option">~~</span>XX</td> <td class="bits">XXXX <span class="option">~~</span>XX</td>
<td class="bits"><span class="free">O</span>XXX XXXX</td>
<td class="bits">XX<span class="free">O</span>X XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">XXXX<span class="free"> OOO</span>X</td>
<td class="bits">XXXX X<span class="free">O</span>XX</td>
<td class="bits">XXXX XXXX</td>
</tr> </tr>
<tr> <tr>
<td class="caption">road depot</td> <td class="caption">road depot</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">X<span class="free">OOO OOOO</span></td> <td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO OOOO</span></td> <td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">XX<span class="free">OO OO</span>XX</td> <td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td> <td class="bits">XX<span class="free">OO OO</span>XX</td>
@ -205,11 +205,11 @@ the array so you can quickly see what is used and what is not.
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO O</span>XXX</td> <td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~~ ~~~~</span></td> <td class="bits"><span class="option">~~~~ ~~~~</span></td>
<td class="bits"><span class="option">~~~~ ~</span>XXX</td> <td class="bits"><span class="option">~~~~ ~</span>XXX</td>
<td class="bits"><span class="free">OO</span>XX XXXX</td> <td class="bits"><span class="free">OO</span>XX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td> <td class="bits">XXXX X<span class="free">O</span>XX</td>
</tr> </tr>
<tr> <tr>
<td class="caption">dock</td> <td class="caption">dock</td>
@ -308,22 +308,22 @@ the array so you can quickly see what is used and what is not.
<td class="bits">XXXX XXXX</td> <td class="bits">XXXX XXXX</td>
<td class="bits"><span class="option">~~~</span>X XXXX</td> <td class="bits"><span class="option">~~~</span>X XXXX</td>
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td> <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~</span><span class="abuse">XXX</span></td> <td class="bits">XXXX <span class="option">~~</span>XX</td>
<td class="bits">X<span class="free">OOO OOOO</span></td>
<td class="bits">X<span class="free">OO</span>X <span class="option">~</span>XXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td> <td class="bits"><span class="free">OOOO OOOO</span></td>
<td class="bits">X<span class="free">OO</span>X XXXX</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td>
<td class="bits">XXXX X<span class="free">O</span>XX</td>
</tr> </tr>
<tr> <tr>
<td>bridge ramp</td> <td>bridge ramp</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits">-inherit-</td> <td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO OOOO</span> XXXX <span class="free">OOOO</span></td> <td class="bits">-inherit-</td>
<td class="bits"><span class="free">OOOO</span> <span class="option">~</span><span class="abuse">XXX</span></td> <td class="bits">-inherit-</td>
<td class="bits">X<span class="free">OOO OOOO</span></td> <td class="bits">-inherit-</td>
<td class="bits">X<span class="free">OO</span>X XXXX</td> <td class="bits">-inherit-</td>
<td class="bits">XX<span class="free">OO OO</span>XX</td> <td class="bits">XXXX XXXX</td>
<td class="bits"><span class="free">OOOO OOOO</span></td> <td class="bits">-inherit-</td>
</tr> </tr>
<tr> <tr>
<td rowspan=2>A</td> <td rowspan=2>A</td>

View File

@ -71,7 +71,7 @@ static inline bool IsBridgeAbove(TileIndex t)
static inline BridgeType GetBridgeType(TileIndex t) static inline BridgeType GetBridgeType(TileIndex t)
{ {
assert(IsBridgeTile(t)); assert(IsBridgeTile(t));
return GB(_m[t].m2, 4, 4); return GB(_m[t].m6, 2, 4);
} }
/** /**
@ -168,10 +168,11 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D
{ {
SetTileType(t, MP_TUNNELBRIDGE); SetTileType(t, MP_TUNNELBRIDGE);
SetTileOwner(t, o); SetTileOwner(t, o);
_m[t].m2 = bridgetype << 4; _m[t].m2 = 0;
_m[t].m3 = rt; _m[t].m3 = rt;
_m[t].m4 = 0; _m[t].m4 = 0;
_m[t].m5 = 1 << 7 | tt << 2 | d; _m[t].m5 = 1 << 7 | tt << 2 | d;
SB(_m[t].m6, 2, 4, bridgetype);
} }
/** /**
@ -184,7 +185,10 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D
*/ */
static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, DiagDirection d, RoadTypes r) static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, DiagDirection d, RoadTypes r)
{ {
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD, r); MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD, 0);
SetRoadOwner(t, ROADTYPE_ROAD, o);
if (o != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, o);
SetRoadTypes(t, r);
} }
/** /**

View File

@ -945,6 +945,7 @@ STR_CONFIG_SETTING_NONUNIFORM_STATIONS :{LTBLUE}Nonunif
STR_CONFIG_SETTING_FREIGHT_TRAINS :{LTBLUE}Weight multiplier for freight to simulate heavy trains: {ORANGE}{STRING} STR_CONFIG_SETTING_FREIGHT_TRAINS :{LTBLUE}Weight multiplier for freight to simulate heavy trains: {ORANGE}{STRING}
STR_CONFIG_SETTING_PLANE_SPEED :{LTBLUE}Plane speed factor: {ORANGE}1 / {STRING1} STR_CONFIG_SETTING_PLANE_SPEED :{LTBLUE}Plane speed factor: {ORANGE}1 / {STRING1}
STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :{LTBLUE}Allow drive-through road stops on town owned roads: {ORANGE}{STRING} STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :{LTBLUE}Allow drive-through road stops on town owned roads: {ORANGE}{STRING}
STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :{LTBLUE}Allow drive-through road stops on roads owned by competitors: {ORANGE}{STRING}
STR_CONFIG_SETTING_ADJACENT_STATIONS :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING} STR_CONFIG_SETTING_ADJACENT_STATIONS :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING}
STR_CONFIG_SETTING_DYNAMIC_ENGINES :{LTBLUE}Enable multiple NewGRF engine sets: {ORANGE}{STRING} STR_CONFIG_SETTING_DYNAMIC_ENGINES :{LTBLUE}Enable multiple NewGRF engine sets: {ORANGE}{STRING}
STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Changing this setting is not possible when there are vehicles. STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Changing this setting is not possible when there are vehicles.

View File

@ -378,20 +378,17 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
roadtypes |= ROADTYPES_ROAD; roadtypes |= ROADTYPES_ROAD;
break; break;
case ROADTYPES_ROADTRAM: if (road == tram) break; case ROADTYPES_ALL:
/* FALL THROUGH */ if (road != tram) return CMD_ERROR;
case ROADTYPES_ROADHWAY: // Road and highway are incompatible in this case break;
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); road |= tram;
if ((track == TRACK_X && road == ROAD_Y) || if ((track == TRACK_X && road == ROAD_Y) ||
(track == TRACK_Y && road == ROAD_X)) { (track == TRACK_Y && road == ROAD_X)) {
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
MakeRoadCrossing(tile, GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY), _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile)); MakeRoadCrossing(tile, GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile));
UpdateLevelCrossing(tile, false); UpdateLevelCrossing(tile, false);
} }
break; break;
@ -475,7 +472,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1,
if (v != NULL) FreeTrainTrackReservation(v); if (v != NULL) FreeTrainTrackReservation(v);
} }
owner = GetTileOwner(tile); owner = GetTileOwner(tile);
MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY)); MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM));
} }
break; break;
} }

View File

@ -176,8 +176,6 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec
/* The tile doesn't have the given road type */ /* The tile doesn't have the given road type */
if (!HasBit(rts, rt)) return CMD_ERROR; if (!HasBit(rts, rt)) return CMD_ERROR;
bool town_road_under_stop = false;
switch (GetTileType(tile)) { switch (GetTileType(tile)) {
case MP_ROAD: case MP_ROAD:
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
@ -185,7 +183,6 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec
case MP_STATION: case MP_STATION:
if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
if (rt == ROADTYPE_ROAD) town_road_under_stop = GetStopBuiltOnTownRoad(tile);
if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
break; break;
@ -198,7 +195,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec
return CMD_ERROR; return CMD_ERROR;
} }
if (!CheckAllowRemoveRoad(tile, pieces, town_road_under_stop ? OWNER_TOWN : GetRoadOwner(tile, rt), rt, flags, town_check)) return CMD_ERROR; if (!CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rt), rt, flags, town_check)) return CMD_ERROR;
if (!IsTileType(tile, MP_ROAD)) { if (!IsTileType(tile, MP_ROAD)) {
/* If it's the last roadtype, just clear the whole tile */ /* If it's the last roadtype, just clear the whole tile */
@ -213,6 +210,15 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec
SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
/* If the owner of the bridge sells all it's road, also move the ownership
* to the owner of the other roadtype. */
RoadType other_rt = (rt == ROADTYPE_ROAD) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
Owner other_owner = GetRoadOwner(tile, other_rt);
if (other_owner != GetTileOwner(tile)) {
SetTileOwner(tile, other_owner);
SetTileOwner(other_end, other_owner);
}
/* Mark tiles diry that have been repaved */ /* Mark tiles diry that have been repaved */
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(other_end); MarkTileDirtyByTile(other_end);
@ -547,7 +553,7 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile)));
/* Always add road to the roadtypes (can't draw without it) */ /* Always add road to the roadtypes (can't draw without it) */
bool reserved = HasBit(GetTrackReservation(tile), AxisToTrack(OtherAxis(roaddir))); bool reserved = HasBit(GetTrackReservation(tile), AxisToTrack(OtherAxis(roaddir)));
MakeRoadCrossing(tile, _current_company, _current_company, _current_company, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2); MakeRoadCrossing(tile, _current_company, _current_company, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2);
SetCrossingReservation(tile, reserved); SetCrossingReservation(tile, reserved);
UpdateLevelCrossing(tile, false); UpdateLevelCrossing(tile, false);
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);
@ -639,6 +645,8 @@ do_clear:;
SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt)); SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt));
SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
SetRoadOwner(other_end, rt, _current_company);
SetRoadOwner(tile, rt, _current_company);
/* Mark tiles diry that have been repaved */ /* Mark tiles diry that have been repaved */
MarkTileDirtyByTile(other_end); MarkTileDirtyByTile(other_end);
@ -653,11 +661,11 @@ do_clear:;
case MP_STATION: case MP_STATION:
assert(IsDriveThroughStopTile(tile)); assert(IsDriveThroughStopTile(tile));
SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
if (rt == ROADTYPE_ROAD) SetStopBuiltOnTownRoad(tile, false); SetRoadOwner(tile, rt, _current_company);
break; break;
default: default:
MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_company, _current_company, _current_company); MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_company, _current_company);
break; break;
} }
@ -911,7 +919,7 @@ static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlag flags)
/* Must iterate over the roadtypes in a reverse manner because /* Must iterate over the roadtypes in a reverse manner because
* tram tracks must be removed before the road bits. */ * tram tracks must be removed before the road bits. */
RoadType rt = ROADTYPE_HWAY; RoadType rt = ROADTYPE_TRAM;
do { do {
if (HasBit(rts, rt)) { if (HasBit(rts, rt)) {
CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false); CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false);

View File

@ -59,9 +59,8 @@ static inline RoadBits GetRoadBits(TileIndex t, RoadType rt)
assert(IsNormalRoad(t)); assert(IsNormalRoad(t));
switch (rt) { switch (rt) {
default: NOT_REACHED(); default: NOT_REACHED();
case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m4, 0, 4); case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m5, 0, 4);
case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m4, 4, 4); case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m3, 0, 4);
case ROADTYPE_HWAY: return (RoadBits)GB(_m[t].m6, 2, 4);
} }
} }
@ -74,9 +73,7 @@ static inline RoadBits GetRoadBits(TileIndex t, RoadType rt)
*/ */
static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt) static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt)
{ {
return ((rt == ROADTYPE_ROAD) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_ROAD)) | return GetRoadBits(t, rt == ROADTYPE_ROAD ? ROADTYPE_TRAM : ROADTYPE_ROAD);
((rt == ROADTYPE_TRAM) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_TRAM)) |
((rt == ROADTYPE_HWAY) ? ROAD_NONE : GetRoadBits(t, ROADTYPE_HWAY));
} }
/** /**
@ -87,7 +84,7 @@ static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt)
*/ */
static inline RoadBits GetAllRoadBits(TileIndex tile) static inline RoadBits GetAllRoadBits(TileIndex tile)
{ {
return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM) | GetRoadBits(tile, ROADTYPE_HWAY); return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM);
} }
static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt) static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt)
@ -95,29 +92,20 @@ static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt)
assert(IsNormalRoad(t)); // XXX incomplete assert(IsNormalRoad(t)); // XXX incomplete
switch (rt) { switch (rt) {
default: NOT_REACHED(); default: NOT_REACHED();
case ROADTYPE_ROAD: SB(_m[t].m4, 0, 4, r); break; case ROADTYPE_ROAD: SB(_m[t].m5, 0, 4, r); break;
case ROADTYPE_TRAM: SB(_m[t].m4, 4, 4, r); break; case ROADTYPE_TRAM: SB(_m[t].m3, 0, 4, r); break;
case ROADTYPE_HWAY: SB(_m[t].m6, 2, 4, r); break;
} }
} }
static inline RoadTypes GetRoadTypes(TileIndex t) static inline RoadTypes GetRoadTypes(TileIndex t)
{ {
if (IsTileType(t, MP_ROAD)) { return (RoadTypes)GB(_me[t].m7, 6, 2);
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) static inline void SetRoadTypes(TileIndex t, RoadTypes rt)
{ {
if (IsTileType(t, MP_ROAD)) { assert(IsTileType(t, MP_ROAD) || IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE));
SB(_me[t].m7, 5, 3, rt); SB(_me[t].m7, 6, 2, rt);
} else {
assert(IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE));
SB(_m[t].m3, 0, 2, rt);
}
} }
static inline bool HasTileRoadType(TileIndex t, RoadType rt) static inline bool HasTileRoadType(TileIndex t, RoadType rt)
@ -127,63 +115,24 @@ static inline bool HasTileRoadType(TileIndex t, RoadType rt)
static inline Owner GetRoadOwner(TileIndex t, RoadType rt) static inline Owner GetRoadOwner(TileIndex t, RoadType rt)
{ {
if (!IsTileType(t, MP_ROAD)) return GetTileOwner(t); switch (rt) {
switch (GetRoadTileType(t)) {
default: NOT_REACHED(); default: NOT_REACHED();
case ROAD_TILE_NORMAL: case ROADTYPE_ROAD: return (Owner)GB(IsNormalRoadTile(t) ? _m[t].m1 : _me[t].m7, 0, 5);
switch (rt) { case ROADTYPE_TRAM: {
default: NOT_REACHED(); /* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
case ROADTYPE_ROAD: return (Owner)GB( _m[t].m1, 0, 5); * to OWNER_TOWN makes it use one bit less */
case ROADTYPE_TRAM: { Owner o = (Owner)GB(_m[t].m3, 4, 4);
/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE return o == OWNER_TOWN ? OWNER_NONE : o;
* to OWNER_TOWN makes it use one bit less */ }
Owner o = (Owner)GB( _m[t].m5, 0, 4);
return o == OWNER_TOWN ? OWNER_NONE : o;
}
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: {
/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
* to OWNER_TOWN makes it use one bit less */
Owner o = (Owner)GB( _m[t].m5, 0, 4);
return o == OWNER_TOWN ? OWNER_NONE : o;
}
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) static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
{ {
if (!IsTileType(t, MP_ROAD)) return SetTileOwner(t, o); switch (rt) {
switch (GetRoadTileType(t)) {
default: NOT_REACHED(); default: NOT_REACHED();
case ROAD_TILE_NORMAL: case ROADTYPE_ROAD: SB(IsNormalRoadTile(t) ? _m[t].m1 : _me[t].m7, 0, 5, o); break;
switch (rt) { case ROADTYPE_TRAM: SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); break;
default: NOT_REACHED();
case ROADTYPE_ROAD: SB( _m[t].m1, 0, 5, o); break;
case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break;
case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
}
break;
case ROAD_TILE_CROSSING:
switch (rt) {
default: NOT_REACHED();
case ROADTYPE_ROAD: SB( _m[t].m4, 0, 5, o); break;
/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
* to OWNER_TOWN makes it use one bit less */
case ROADTYPE_TRAM: SB( _m[t].m5, 0, 4, o == OWNER_NONE ? OWNER_TOWN : o); break;
case ROADTYPE_HWAY: SB(_me[t].m7, 0, 5, o); break;
}
break;
case ROAD_TILE_DEPOT: return SetTileOwner(t, o);
} }
} }
@ -200,7 +149,6 @@ static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o)
*/ */
static inline bool HasTownOwnedRoad(TileIndex t) static inline bool HasTownOwnedRoad(TileIndex t)
{ {
assert(IsTileType(t, MP_ROAD));
return HasTileRoadType(t, ROADTYPE_ROAD) && IsRoadOwner(t, ROADTYPE_ROAD, OWNER_TOWN); return HasTileRoadType(t, ROADTYPE_ROAD) && IsRoadOwner(t, ROADTYPE_ROAD, OWNER_TOWN);
} }
@ -240,7 +188,7 @@ static inline void SetDisallowedRoadDirections(TileIndex t, DisallowedRoadDirect
static inline Axis GetCrossingRoadAxis(TileIndex t) static inline Axis GetCrossingRoadAxis(TileIndex t)
{ {
assert(IsLevelCrossing(t)); assert(IsLevelCrossing(t));
return (Axis)GB(_m[t].m4, 6, 1); return (Axis)GB(_m[t].m5, 0, 1);
} }
static inline Axis GetCrossingRailAxis(TileIndex t) static inline Axis GetCrossingRailAxis(TileIndex t)
@ -304,13 +252,13 @@ static inline TrackBits GetRailCrossingReservation(TileIndex t)
static inline bool IsCrossingBarred(TileIndex t) static inline bool IsCrossingBarred(TileIndex t)
{ {
assert(IsLevelCrossing(t)); assert(IsLevelCrossing(t));
return HasBit(_m[t].m4, 5); return HasBit(_m[t].m5, 5);
} }
static inline void SetCrossingBarred(TileIndex t, bool barred) static inline void SetCrossingBarred(TileIndex t, bool barred)
{ {
assert(IsLevelCrossing(t)); assert(IsLevelCrossing(t));
SB(_m[t].m4, 5, 1, barred); SB(_m[t].m5, 5, 1, barred ? 1 : 0);
} }
static inline void UnbarCrossing(TileIndex t) static inline void UnbarCrossing(TileIndex t)
@ -326,13 +274,13 @@ static inline void BarCrossing(TileIndex t)
#define IsOnDesert IsOnSnow #define IsOnDesert IsOnSnow
static inline bool IsOnSnow(TileIndex t) static inline bool IsOnSnow(TileIndex t)
{ {
return HasBit(_m[t].m3, 7); return HasBit(_me[t].m7, 5);
} }
#define ToggleDesert ToggleSnow #define ToggleDesert ToggleSnow
static inline void ToggleSnow(TileIndex t) static inline void ToggleSnow(TileIndex t)
{ {
ToggleBit(_m[t].m3, 7); ToggleBit(_me[t].m7, 5);
} }
@ -348,12 +296,12 @@ enum Roadside {
static inline Roadside GetRoadside(TileIndex tile) static inline Roadside GetRoadside(TileIndex tile)
{ {
return (Roadside)GB(_m[tile].m3, 4, 3); return (Roadside)GB(_m[tile].m6, 3, 3);
} }
static inline void SetRoadside(TileIndex tile, Roadside s) static inline void SetRoadside(TileIndex tile, Roadside s)
{ {
SB(_m[tile].m3, 4, 3, s); SB(_m[tile].m6, 3, 3, s);
} }
static inline bool HasRoadWorks(TileIndex t) static inline bool HasRoadWorks(TileIndex t)
@ -363,9 +311,9 @@ static inline bool HasRoadWorks(TileIndex t)
static inline bool IncreaseRoadWorksCounter(TileIndex t) static inline bool IncreaseRoadWorksCounter(TileIndex t)
{ {
AB(_m[t].m3, 0, 4, 1); AB(_me[t].m7, 0, 4, 1);
return GB(_m[t].m3, 0, 4) == 15; return GB(_me[t].m7, 0, 4) == 15;
} }
static inline void StartRoadWorks(TileIndex t) static inline void StartRoadWorks(TileIndex t)
@ -384,7 +332,7 @@ static inline void TerminateRoadWorks(TileIndex t)
assert(HasRoadWorks(t)); assert(HasRoadWorks(t));
SetRoadside(t, (Roadside)(GetRoadside(t) - ROADSIDE_GRASS_ROAD_WORKS + ROADSIDE_GRASS)); SetRoadside(t, (Roadside)(GetRoadside(t) - ROADSIDE_GRASS_ROAD_WORKS + ROADSIDE_GRASS));
/* Stop the counter */ /* Stop the counter */
SB(_m[t].m3, 0, 4, 0); SB(_me[t].m7, 0, 4, 0);
} }
@ -434,31 +382,32 @@ TrackBits GetAnyRoadTrackBits(TileIndex tile, RoadType rt);
bool IsPossibleCrossing(const TileIndex tile, Axis ax); bool IsPossibleCrossing(const TileIndex tile, Axis ax);
static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram, Owner hway) static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram)
{ {
SetTileType(t, MP_ROAD); SetTileType(t, MP_ROAD);
SetTileOwner(t, road); SetTileOwner(t, road);
_m[t].m2 = town; _m[t].m2 = town;
_m[t].m3 = 0; _m[t].m3 = (HasBit(rot, ROADTYPE_TRAM) ? bits : 0);
_m[t].m4 = (HasBit(rot, ROADTYPE_TRAM) ? bits : 0) << 4 | (HasBit(rot, ROADTYPE_ROAD) ? bits : 0); _m[t].m4 = 0;
_m[t].m5 = ROAD_TILE_NORMAL << 6; _m[t].m5 = (HasBit(rot, ROADTYPE_ROAD) ? bits : 0) | ROAD_TILE_NORMAL << 6;
SetRoadOwner(t, ROADTYPE_TRAM, tram);
SB(_m[t].m6, 2, 4, 0);
_me[t].m7 = rot << 6;
SetRoadOwner(t, ROADTYPE_TRAM, tram); SetRoadOwner(t, ROADTYPE_TRAM, 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 tram, Owner hway, Owner rail, Axis roaddir, RailType rat, RoadTypes rot, uint town) static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadTypes rot, uint town)
{ {
SetTileType(t, MP_ROAD); SetTileType(t, MP_ROAD);
SetTileOwner(t, rail); SetTileOwner(t, rail);
_m[t].m2 = town; _m[t].m2 = town;
_m[t].m3 = rat; _m[t].m3 = rat;
_m[t].m4 = roaddir << 6 | road; _m[t].m4 = 0;
_m[t].m5 = ROAD_TILE_CROSSING << 6; _m[t].m5 = ROAD_TILE_CROSSING << 6 | roaddir;
SetRoadOwner(t, ROADTYPE_TRAM, tram);
SB(_m[t].m6, 2, 4, 0); SB(_m[t].m6, 2, 4, 0);
_me[t].m7 = rot << 5 | hway; _me[t].m7 = rot << 6 | road;
SetRoadOwner(t, ROADTYPE_TRAM, tram);
} }
@ -471,7 +420,8 @@ static inline void MakeRoadDepot(TileIndex t, Owner owner, DiagDirection dir, Ro
_m[t].m4 = 0; _m[t].m4 = 0;
_m[t].m5 = ROAD_TILE_DEPOT << 6 | dir; _m[t].m5 = ROAD_TILE_DEPOT << 6 | dir;
SB(_m[t].m6, 2, 4, 0); SB(_m[t].m6, 2, 4, 0);
_me[t].m7 = RoadTypeToRoadTypes(rt) << 5; _me[t].m7 = RoadTypeToRoadTypes(rt) << 6 | owner;
SetRoadOwner(t, ROADTYPE_TRAM, owner);
} }
#endif /* ROAD_MAP_H */ #endif /* ROAD_MAP_H */

View File

@ -16,7 +16,6 @@ enum RoadType {
ROADTYPE_BEGIN = 0, ///< Used for iterations ROADTYPE_BEGIN = 0, ///< Used for iterations
ROADTYPE_ROAD = 0, ///< Basic road type ROADTYPE_ROAD = 0, ///< Basic road type
ROADTYPE_TRAM = 1, ///< Trams ROADTYPE_TRAM = 1, ///< Trams
ROADTYPE_HWAY = 2, ///< Only a placeholder. Not sure what we are going to do with this road type.
ROADTYPE_END, ///< Used for iterations ROADTYPE_END, ///< Used for iterations
INVALID_ROADTYPE = 0xFF ///< flag for invalid roadtype INVALID_ROADTYPE = 0xFF ///< flag for invalid roadtype
}; };
@ -27,16 +26,12 @@ DECLARE_POSTFIX_INCREMENT(RoadType);
* @note currently only roadtypes with ROADTYPE_ROAD and ROADTYPE_TRAM are supported. * @note currently only roadtypes with ROADTYPE_ROAD and ROADTYPE_TRAM are supported.
*/ */
enum RoadTypes { enum RoadTypes {
ROADTYPES_NONE = 0, ///< No roadtypes ROADTYPES_NONE = 0, ///< No roadtypes
ROADTYPES_ROAD = 1 << ROADTYPE_ROAD, ///< Road ROADTYPES_ROAD = 1 << ROADTYPE_ROAD, ///< Road
ROADTYPES_TRAM = 1 << ROADTYPE_TRAM, ///< Trams ROADTYPES_TRAM = 1 << ROADTYPE_TRAM, ///< Trams
ROADTYPES_HWAY = 1 << ROADTYPE_HWAY, ///< Highway (or whatever substitute) ROADTYPES_ALL = ROADTYPES_ROAD | ROADTYPES_TRAM, ///< Road + trams
ROADTYPES_ROADTRAM = ROADTYPES_ROAD | ROADTYPES_TRAM, ///< Road + trams ROADTYPES_END, ///< Used for iterations?
ROADTYPES_ROADHWAY = ROADTYPES_ROAD | ROADTYPES_HWAY, ///< Road + highway (or whatever substitute) INVALID_ROADTYPES = 0xFF ///< Invalid roadtypes
ROADTYPES_TRAMHWAY = ROADTYPES_TRAM | ROADTYPES_HWAY, ///< Trams + highway (or whatever substitute)
ROADTYPES_ALL = ROADTYPES_ROAD | ROADTYPES_TRAM | ROADTYPES_HWAY, ///< Road + trams + highway (or whatever substitute)
ROADTYPES_END, ///< Used for iterations?
INVALID_ROADTYPES = 0xFF ///< Invalid roadtypes
}; };
DECLARE_ENUM_AS_BIT_SET(RoadTypes); DECLARE_ENUM_AS_BIT_SET(RoadTypes);
template <> struct EnumPropsT<RoadTypes> : MakeEnumPropsT<RoadTypes, byte, ROADTYPES_NONE, ROADTYPES_END, INVALID_ROADTYPES> {}; template <> struct EnumPropsT<RoadTypes> : MakeEnumPropsT<RoadTypes, byte, ROADTYPES_NONE, ROADTYPES_END, INVALID_ROADTYPES> {};

View File

@ -312,7 +312,7 @@ static void FixOwnerOfRailTrack(TileIndex t)
if (IsLevelCrossingTile(t)) { if (IsLevelCrossingTile(t)) {
/* else change the crossing to normal road (road vehicles won't care) */ /* else change the crossing to normal road (road vehicles won't care) */
MakeRoadNormal(t, GetCrossingRoadBits(t), GetRoadTypes(t), GetTownIndex(t), MakeRoadNormal(t, GetCrossingRoadBits(t), GetRoadTypes(t), GetTownIndex(t),
GetRoadOwner(t, ROADTYPE_ROAD), GetRoadOwner(t, ROADTYPE_TRAM), GetRoadOwner(t, ROADTYPE_HWAY)); GetRoadOwner(t, ROADTYPE_ROAD), GetRoadOwner(t, ROADTYPE_TRAM));
return; return;
} }
@ -709,7 +709,7 @@ bool AfterLoadGame()
/* Added the RoadType */ /* Added the RoadType */
bool old_bridge = CheckSavegameVersion(42); bool old_bridge = CheckSavegameVersion(42);
for (TileIndex t = 0; t < map_size; t++) { for (TileIndex t = 0; t < map_size; t++) {
switch(GetTileType(t)) { switch (GetTileType(t)) {
case MP_ROAD: case MP_ROAD:
SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2)); SB(_m[t].m5, 6, 2, GB(_m[t].m5, 4, 2));
switch (GetRoadTileType(t)) { switch (GetRoadTileType(t)) {
@ -744,6 +744,73 @@ bool AfterLoadGame()
} }
} }
if (CheckSavegameVersion(114)) {
bool fix_roadtypes = !CheckSavegameVersion(61);
bool old_bridge = CheckSavegameVersion(42);
for (TileIndex t = 0; t < map_size; t++) {
switch (GetTileType(t)) {
case MP_ROAD:
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_me[t].m7, 5, 3));
SB(_me[t].m7, 5, 1, GB(_m[t].m3, 7, 1)); //snow/desert
switch (GetRoadTileType(t)) {
default: NOT_REACHED();
case ROAD_TILE_NORMAL:
SB(_me[t].m7, 0, 4, GB(_m[t].m3, 0, 4)); // road works
SB(_m[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
SB(_m[t].m3, 0, 4, GB(_m[t].m4, 4, 4)); // tram bits
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
SB(_m[t].m5, 0, 4, GB(_m[t].m4, 0, 4)); // road bits
break;
case ROAD_TILE_CROSSING:
SB(_me[t].m7, 0, 5, GB(_m[t].m4, 0, 5)); // road owner
SB(_m[t].m6, 3, 3, GB(_m[t].m3, 4, 3)); // ground
SB(_m[t].m3, 4, 4, GB(_m[t].m5, 0, 4)); // tram owner
SB(_m[t].m5, 0, 1, GB(_m[t].m4, 6, 1)); // road axis
SB(_m[t].m5, 5, 1, GB(_m[t].m4, 5, 1)); // crossing state
break;
case ROAD_TILE_DEPOT:
break;
}
if (!HasTownOwnedRoad(t)) {
const Town *town = CalcClosestTownFromTile(t, (uint)-1);
if (town != NULL) SetTownIndex(t, town->index);
}
_m[t].m4 = 0;
break;
case MP_STATION:
if (!IsRoadStop(t)) break;
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
SB(_me[t].m7, 0, 5, HasBit(_m[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
SB(_m[t].m3, 4, 4, _m[t].m1);
_m[t].m4 = 0;
break;
case MP_TUNNELBRIDGE:
if (old_bridge && IsBridge(t) && HasBit(_m[t].m5, 6)) break;
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(_m[t].m5, 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
Owner o = GetTileOwner(t);
SB(_me[t].m7, 0, 5, o); // road owner
SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); // tram owner
}
SB(_m[t].m6, 2, 4, GB(_m[t].m2, 4, 4)); // bridge type
SB(_me[t].m7, 5, 1, GB(_m[t].m4, 7, 1)); // snow/desert
_m[t].m2 = 0;
_m[t].m4 = 0;
break;
default: break;
}
}
}
if (CheckSavegameVersion(42)) { if (CheckSavegameVersion(42)) {
Vehicle *v; Vehicle *v;
@ -769,7 +836,7 @@ bool AfterLoadGame()
axis == AXIS_X ? ROAD_Y : ROAD_X, axis == AXIS_X ? ROAD_Y : ROAD_X,
ROADTYPES_ROAD, ROADTYPES_ROAD,
town, town,
GetTileOwner(t), OWNER_NONE, OWNER_NONE GetTileOwner(t), OWNER_NONE
); );
} }
} else { } else {
@ -942,10 +1009,6 @@ bool AfterLoadGame()
} }
break; break;
case MP_ROAD: /* Clear PBS reservation on crossing */
if (IsLevelCrossing(t)) ClrBit(_m[t].m5, 0);
break;
case MP_STATION: /* Clear PBS reservation on station */ case MP_STATION: /* Clear PBS reservation on station */
ClrBit(_m[t].m3, 6); ClrBit(_m[t].m3, 6);
break; break;

View File

@ -38,7 +38,7 @@
#include "saveload_internal.h" #include "saveload_internal.h"
extern const uint16 SAVEGAME_VERSION = 113; extern const uint16 SAVEGAME_VERSION = 114;
SavegameType _savegame_type; ///< type of savegame we are loading SavegameType _savegame_type; ///< type of savegame we are loading

View File

@ -1379,6 +1379,7 @@ const SettingDesc _settings[] = {
SDT_BOOL(GameSettings, station.modified_catchment, 0, 0, true, STR_CONFIG_SETTING_CATCHMENT, NULL), SDT_BOOL(GameSettings, station.modified_catchment, 0, 0, true, STR_CONFIG_SETTING_CATCHMENT, NULL),
SDT_CONDBOOL(GameSettings, order.gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_GRADUAL_LOADING, NULL), SDT_CONDBOOL(GameSettings, order.gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_GRADUAL_LOADING, NULL),
SDT_CONDBOOL(GameSettings, construction.road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD, NULL), SDT_CONDBOOL(GameSettings, construction.road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD, NULL),
SDT_CONDBOOL(GameSettings, construction.road_stop_on_competitor_road, 114, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD,NULL),
SDT_CONDBOOL(GameSettings, station.adjacent_stations, 62, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_ADJACENT_STATIONS, NULL), SDT_CONDBOOL(GameSettings, station.adjacent_stations, 62, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_ADJACENT_STATIONS, NULL),
SDT_CONDBOOL(GameSettings, economy.station_noise_level, 96, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_SETTING_NOISE_LEVEL, InvalidateTownViewWindow), SDT_CONDBOOL(GameSettings, economy.station_noise_level, 96, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_SETTING_NOISE_LEVEL, InvalidateTownViewWindow),
SDT_CONDBOOL(GameSettings, station.distant_join_stations, 106, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS, DeleteSelectStationWindow), SDT_CONDBOOL(GameSettings, station.distant_join_stations, 106, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS, DeleteSelectStationWindow),

View File

@ -1096,6 +1096,7 @@ static SettingEntry _settings_stations[] = {
SettingEntry("economy.station_noise_level"), SettingEntry("economy.station_noise_level"),
SettingEntry("station.modified_catchment"), SettingEntry("station.modified_catchment"),
SettingEntry("construction.road_stop_on_town_road"), SettingEntry("construction.road_stop_on_town_road"),
SettingEntry("construction.road_stop_on_competitor_road"),
}; };
/** Stations sub-page */ /** Stations sub-page */
static SettingsPage _settings_stations_page = {_settings_stations, lengthof(_settings_stations)}; static SettingsPage _settings_stations_page = {_settings_stations, lengthof(_settings_stations)};

View File

@ -166,6 +166,7 @@ struct ConstructionSettings {
bool signal_side; ///< show signals on right side bool signal_side; ///< show signals on right side
bool extra_dynamite; ///< extra dynamite bool extra_dynamite; ///< extra dynamite
bool road_stop_on_town_road; ///< allow building of drive-through road stops on town owned roads bool road_stop_on_town_road; ///< allow building of drive-through road stops on town owned roads
bool road_stop_on_competitor_road; ///< allow building of drive-through road stops on roads owned by competitors
uint8 raw_industry_construction; ///< type of (raw) industry construction (none, "normal", prospecting) uint8 raw_industry_construction; ///< type of (raw) industry construction (none, "normal", prospecting)
bool freeform_edges; ///< allow terraforming the tiles at the map edges bool freeform_edges; ///< allow terraforming the tiles at the map edges
}; };

View File

@ -1392,7 +1392,7 @@ static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
* @param p1 entrance direction (DiagDirection) * @param p1 entrance direction (DiagDirection)
* @param p2 bit 0: 0 for Bus stops, 1 for truck stops * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
* bit 1: 0 for normal, 1 for drive-through * bit 1: 0 for normal, 1 for drive-through
* bit 2..4: the roadtypes * bit 2..3: the roadtypes
* bit 5: allow stations directly adjacent to other stations. * bit 5: allow stations directly adjacent to other stations.
* bit 16..31: station ID to join (INVALID_STATION if build new one) * bit 16..31: station ID to join (INVALID_STATION if build new one)
*/ */
@ -1401,10 +1401,11 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
bool type = HasBit(p2, 0); bool type = HasBit(p2, 0);
bool is_drive_through = HasBit(p2, 1); bool is_drive_through = HasBit(p2, 1);
bool build_over_road = is_drive_through && IsNormalRoadTile(tile); bool build_over_road = is_drive_through && IsNormalRoadTile(tile);
bool town_owned_road = false; RoadTypes rts = (RoadTypes)GB(p2, 2, 2);
RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
StationID station_to_join = GB(p2, 16, 16); StationID station_to_join = GB(p2, 16, 16);
bool distant_join = (station_to_join != INVALID_STATION); bool distant_join = (station_to_join != INVALID_STATION);
Owner tram_owner = _current_company;
Owner road_owner = _current_company;
if (distant_join && (!_settings_game.station.distant_join_stations || !IsValidStationID(station_to_join))) return CMD_ERROR; if (distant_join && (!_settings_game.station.distant_join_stations || !IsValidStationID(station_to_join))) return CMD_ERROR;
@ -1428,20 +1429,21 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
if (build_over_road) { if (build_over_road) {
/* there is a road, check if we can build road+tram stop over it */ /* there is a road, check if we can build road+tram stop over it */
if (HasBit(cur_rts, ROADTYPE_ROAD)) { if (HasBit(cur_rts, ROADTYPE_ROAD)) {
Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD); road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (road_owner == OWNER_TOWN) { if (road_owner == OWNER_TOWN) {
town_owned_road = true;
if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD); if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
} else { } else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) {
if (road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR; return CMD_ERROR;
} }
num_roadbits += CountBits(GetRoadBits(tile, ROADTYPE_ROAD)); num_roadbits += CountBits(GetRoadBits(tile, ROADTYPE_ROAD));
} }
/* there is a tram, check if we can build road+tram stop over it */ /* there is a tram, check if we can build road+tram stop over it */
if (HasBit(cur_rts, ROADTYPE_TRAM)) { if (HasBit(cur_rts, ROADTYPE_TRAM)) {
Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM); tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
if (tram_owner != OWNER_NONE && !CheckOwnership(tram_owner)) return CMD_ERROR; if (!_settings_game.construction.road_stop_on_competitor_road && tram_owner != OWNER_NONE && !CheckOwnership(tram_owner)) {
return CMD_ERROR;
}
num_roadbits += CountBits(GetRoadBits(tile, ROADTYPE_TRAM)); num_roadbits += CountBits(GetRoadBits(tile, ROADTYPE_TRAM));
} }
@ -1516,7 +1518,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS; RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
if (is_drive_through) { if (is_drive_through) {
MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, rts, (Axis)p1, town_owned_road); MakeDriveThroughRoadStop(tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts, (Axis)p1);
} else { } else {
MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1); MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
} }
@ -1629,7 +1631,6 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
RoadBits road_bits = IsDriveThroughStopTile(tile) ? RoadBits road_bits = IsDriveThroughStopTile(tile) ?
((GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y) : ((GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y) :
DiagDirToRoadBits(GetRoadStopDir(tile)); DiagDirToRoadBits(GetRoadStopDir(tile));
bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
CommandCost ret = RemoveRoadStop(st, flags, tile); CommandCost ret = RemoveRoadStop(st, flags, tile);
@ -1639,7 +1640,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
* removed by the owner of the roadstop, _current_company is the * removed by the owner of the roadstop, _current_company is the
* owner of the road stop. */ * owner of the road stop. */
MakeRoadNormal(tile, road_bits, rts, ClosestTownFromTile(tile, UINT_MAX)->index, MakeRoadNormal(tile, road_bits, rts, ClosestTownFromTile(tile, UINT_MAX)->index,
is_towns_road ? OWNER_TOWN : _current_company, _current_company, _current_company); GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM));
} }
return ret; return ret;
@ -2478,10 +2479,27 @@ static void GetAcceptedCargo_Station(TileIndex tile, AcceptedCargo ac)
static void GetTileDesc_Station(TileIndex tile, TileDesc *td) static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
{ {
td->owner[0] = GetTileOwner(tile); td->owner[0] = GetTileOwner(tile);
if (IsDriveThroughStopTile(tile) && HasTileRoadType(tile, ROADTYPE_ROAD) && GetStopBuiltOnTownRoad(tile)) { if (IsDriveThroughStopTile(tile)) {
/* Display a second owner */ Owner road_owner = INVALID_OWNER;
td->owner_type[1] = STR_ROAD_OWNER; Owner tram_owner = INVALID_OWNER;
td->owner[1] = OWNER_TOWN; RoadTypes rts = GetRoadTypes(tile);
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
/* Is there a mix of owners? */
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
uint i = 1;
if (road_owner != INVALID_OWNER) {
td->owner_type[i] = STR_ROAD_OWNER;
td->owner[i] = road_owner;
i++;
}
if (tram_owner != INVALID_OWNER) {
td->owner_type[i] = STR_TRAM_OWNER;
td->owner[i] = tram_owner;
}
}
} }
td->build_date = GetStationByTile(tile)->build_date; td->build_date = GetStationByTile(tile)->build_date;
@ -3117,6 +3135,15 @@ void DeleteOilRig(TileIndex tile)
static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner) static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner)
{ {
if (IsDriveThroughStopTile(tile)) {
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
/* Update all roadtypes, no matter if they are present */
if (GetRoadOwner(tile, rt) == old_owner) {
SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
}
}
}
if (!IsTileOwner(tile, old_owner)) return; if (!IsTileOwner(tile, old_owner)) return;
if (new_owner != INVALID_OWNER) { if (new_owner != INVALID_OWNER) {
@ -3150,10 +3177,16 @@ static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_o
*/ */
static bool CanRemoveRoadWithStop(TileIndex tile, DoCommandFlag flags) static bool CanRemoveRoadWithStop(TileIndex tile, DoCommandFlag flags)
{ {
/* The road can always be cleared if it was not a town-owned road */ Owner road_owner = _current_company;
if (!GetStopBuiltOnTownRoad(tile)) return true; Owner tram_owner = _current_company;
return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags); RoadTypes rts = GetRoadTypes(tile);
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
if ((road_owner != OWNER_TOWN && !CheckOwnership(road_owner)) || !CheckOwnership(tram_owner)) return false;
return road_owner != OWNER_TOWN || CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags);
} }
static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags) static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)

View File

@ -145,19 +145,6 @@ static inline bool IsDriveThroughStopTile(TileIndex t)
return IsRoadStopTile(t) && GetStationGfx(t) >= GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET; return IsRoadStopTile(t) && GetStationGfx(t) >= GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET;
} }
static inline bool GetStopBuiltOnTownRoad(TileIndex t)
{
assert(IsDriveThroughStopTile(t));
return HasBit(_m[t].m6, 2);
}
static inline void SetStopBuiltOnTownRoad(TileIndex t, bool on_town_road)
{
assert(IsDriveThroughStopTile(t));
SB(_m[t].m6, 2, 1, on_town_road);
}
/** /**
* Gets the direction the road stop entrance points towards. * Gets the direction the road stop entrance points towards.
*/ */
@ -341,13 +328,16 @@ static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopTyp
{ {
MakeStation(t, o, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), d); MakeStation(t, o, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), d);
SetRoadTypes(t, rt); SetRoadTypes(t, rt);
SetRoadOwner(t, ROADTYPE_ROAD, o);
SetRoadOwner(t, ROADTYPE_TRAM, o);
} }
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, Axis a, bool on_town_road) static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadTypes rt, Axis a)
{ {
MakeStation(t, o, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a); MakeStation(t, station, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a);
SB(_m[t].m6, 2, 1, on_town_road);
SetRoadTypes(t, rt); SetRoadTypes(t, rt);
SetRoadOwner(t, ROADTYPE_ROAD, road);
SetRoadOwner(t, ROADTYPE_TRAM, tram);
} }
static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section) static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section)

View File

@ -649,9 +649,6 @@ static void ToolbarBuildRoadClick(Window *w)
const Company *c = GetCompany(_local_company); const Company *c = GetCompany(_local_company);
DropDownList *list = new DropDownList(); DropDownList *list = new DropDownList();
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
/* Highways don't exist */
if (rt == ROADTYPE_HWAY) continue;
/* The standard road button is *always* available */ /* The standard road button is *always* available */
list->push_back(new DropDownListStringItem(STR_180A_ROAD_CONSTRUCTION + rt, rt, !(HasBit(c->avail_roadtypes, rt) || rt == ROADTYPE_ROAD))); list->push_back(new DropDownListStringItem(STR_180A_ROAD_CONSTRUCTION + rt, rt, !(HasBit(c->avail_roadtypes, rt) || rt == ROADTYPE_ROAD)));
} }

View File

@ -9,7 +9,7 @@
#include "rail_type.h" #include "rail_type.h"
#include "road_type.h" #include "road_type.h"
#include "transport_type.h" #include "transport_type.h"
#include "tile_map.h" #include "road_map.h"
/** /**
@ -50,9 +50,12 @@ static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTyp
SetTileType(t, MP_TUNNELBRIDGE); SetTileType(t, MP_TUNNELBRIDGE);
SetTileOwner(t, o); SetTileOwner(t, o);
_m[t].m2 = 0; _m[t].m2 = 0;
_m[t].m3 = r; _m[t].m3 = 0;
_m[t].m4 = 0; _m[t].m4 = 0;
_m[t].m5 = TRANSPORT_ROAD << 2 | d; _m[t].m5 = TRANSPORT_ROAD << 2 | d;
SetRoadOwner(t, ROADTYPE_ROAD, o);
if (o != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, o);
SetRoadTypes(t, r);
} }
/** /**

View File

@ -211,7 +211,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
/* type of bridge */ /* type of bridge */
switch (transport_type) { switch (transport_type) {
case TRANSPORT_ROAD: case TRANSPORT_ROAD:
roadtypes = (RoadTypes)GB(p2, 8, 3); roadtypes = (RoadTypes)GB(p2, 8, 2);
if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR; if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR;
break; break;
@ -354,7 +354,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
/* do the drill? */ /* do the drill? */
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
DiagDirection dir = AxisToDiagDir(direction); DiagDirection dir = AxisToDiagDir(direction);
Owner owner = (replace_bridge && IsTileOwner(tile_start, OWNER_TOWN)) ? OWNER_TOWN : _current_company; Owner owner = replace_bridge ? GetTileOwner(tile_start) : _current_company;
switch (transport_type) { switch (transport_type) {
case TRANSPORT_RAIL: case TRANSPORT_RAIL:
@ -480,7 +480,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
if (transport_type == TRANSPORT_RAIL) { if (transport_type == TRANSPORT_RAIL) {
if (!ValParamRailtype((RailType)p1)) return CMD_ERROR; if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
} else { } else {
const RoadTypes rts = (RoadTypes)GB(p1, 0, 3); const RoadTypes rts = (RoadTypes)GB(p1, 0, 2);
if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR; if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
} }
@ -570,8 +570,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company); AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company);
YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction)); YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
} else { } else {
MakeRoadTunnel(start_tile, _current_company, direction, (RoadTypes)GB(p1, 0, 3)); MakeRoadTunnel(start_tile, _current_company, direction, (RoadTypes)GB(p1, 0, 2));
MakeRoadTunnel(end_tile, _current_company, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3)); MakeRoadTunnel(end_tile, _current_company, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 2));
} }
} }
@ -583,11 +583,19 @@ static inline bool CheckAllowRemoveTunnelBridge(TileIndex tile)
{ {
/* Floods can remove anything as well as the scenario editor */ /* Floods can remove anything as well as the scenario editor */
if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return true; if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return true;
/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true; RoadTypes rts = GetRoadTypes(tile);
/* Otherwise we can only remove town-owned stuff with extra settings, or cheat */ Owner road_owner = _current_company;
if (IsTileOwner(tile, OWNER_TOWN) && (_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return true; Owner tram_owner = _current_company;
return false;
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
/* We can remove unowned road and if the town allows it */
if (road_owner == OWNER_NONE || (road_owner == OWNER_TOWN && (_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value))) road_owner = _current_company;
if (tram_owner == OWNER_NONE) tram_owner = _current_company;
return CheckOwnership(road_owner) && CheckOwnership(tram_owner);
} }
static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
@ -1242,6 +1250,27 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
td->str = (tt == TRANSPORT_WATER) ? STR_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt]; td->str = (tt == TRANSPORT_WATER) ? STR_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
} }
td->owner[0] = GetTileOwner(tile); td->owner[0] = GetTileOwner(tile);
Owner road_owner = INVALID_OWNER;
Owner tram_owner = INVALID_OWNER;
RoadTypes rts = GetRoadTypes(tile);
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
/* Is there a mix of owners? */
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
uint i = 1;
if (road_owner != INVALID_OWNER) {
td->owner_type[i] = STR_ROAD_OWNER;
td->owner[i] = road_owner;
i++;
}
if (tram_owner != INVALID_OWNER) {
td->owner_type[i] = STR_TRAM_OWNER;
td->owner[i] = tram_owner;
}
}
} }
@ -1292,6 +1321,13 @@ static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType
static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner) static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
{ {
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
/* Update all roadtypes, no matter if they are present */
if (GetRoadOwner(tile, rt) == old_owner) {
SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
}
}
if (!IsTileOwner(tile, old_owner)) return; if (!IsTileOwner(tile, old_owner)) return;
if (new_owner != INVALID_OWNER) { if (new_owner != INVALID_OWNER) {

View File

@ -52,7 +52,7 @@ static inline TransportType GetTunnelBridgeTransportType(TileIndex t)
static inline bool HasTunnelBridgeSnowOrDesert(TileIndex t) static inline bool HasTunnelBridgeSnowOrDesert(TileIndex t)
{ {
assert(IsTileType(t, MP_TUNNELBRIDGE)); assert(IsTileType(t, MP_TUNNELBRIDGE));
return HasBit(_m[t].m4, 7); return HasBit(_me[t].m7, 5);
} }
/** /**
@ -66,7 +66,7 @@ static inline bool HasTunnelBridgeSnowOrDesert(TileIndex t)
static inline void SetTunnelBridgeSnowOrDesert(TileIndex t, bool snow_or_desert) static inline void SetTunnelBridgeSnowOrDesert(TileIndex t, bool snow_or_desert)
{ {
assert(IsTileType(t, MP_TUNNELBRIDGE)); assert(IsTileType(t, MP_TUNNELBRIDGE));
SB(_m[t].m4, 7, 1, snow_or_desert); SB(_me[t].m7, 5, 1, snow_or_desert);
} }
/** /**