summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorterkhen <terkhen@openttd.org>2010-02-24 21:55:03 +0000
committerterkhen <terkhen@openttd.org>2010-02-24 21:55:03 +0000
commita4a66ec1aa2a7772ed174b8dcc1905e9bc5dd02d (patch)
treef51b3f2e3540e485a807591436e56978483539db
parentaba24e44cf76479a33e78cc0a8d6d5279aeef00b (diff)
downloadopenttd-a4a66ec1aa2a7772ed174b8dcc1905e9bc5dd02d.tar.xz
(svn r19231) -Feature: Allow overbuilding of road stops.
-rw-r--r--bin/ai/compat_0.7.nut16
-rw-r--r--bin/ai/compat_1.0.nut19
-rw-r--r--bin/ai/regression/regression.txt16
-rw-r--r--src/ai/api/ai_changelog.hpp4
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/station_cmd.cpp110
6 files changed, 123 insertions, 43 deletions
diff --git a/bin/ai/compat_0.7.nut b/bin/ai/compat_0.7.nut
index 3e4b4fa68..db56fdaee 100644
--- a/bin/ai/compat_0.7.nut
+++ b/bin/ai/compat_0.7.nut
@@ -258,3 +258,19 @@ class AIWaypointList extends _AIWaypointList {
::_AIWaypointList.constructor(AIWaypoint.WAYPOINT_RAIL);
}
}
+
+AIRoad._BuildRoadStation <- AIRoad.BuildRoadStation;
+AIRoad.BuildRoadStation <- function(tile, front, road_veh_type, station_id)
+{
+ if (AIRoad.IsRoadStationTile(tile)) return false;
+
+ return AIRoad._BuildRoadStation(tile, front, road_veh_type, station_id);
+}
+
+AIRoad._BuildDriveThroughRoadStation <- AIRoad.BuildDriveThroughRoadStation;
+AIRoad.BuildDriveThroughRoadStation <- function(tile, front, road_veh_type, station_id)
+{
+ if (AIRoad.IsRoadStationTile(tile)) return false;
+
+ return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id);
+}
diff --git a/bin/ai/compat_1.0.nut b/bin/ai/compat_1.0.nut
index f14520c1e..77ae2525a 100644
--- a/bin/ai/compat_1.0.nut
+++ b/bin/ai/compat_1.0.nut
@@ -7,5 +7,20 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Enable when adding the first compatability code:
- * AILog.Info("1.0 API compatability in effect"); */
+AILog.Info("1.0 API compatability in effect.");
+
+AIRoad._BuildRoadStation <- AIRoad.BuildRoadStation;
+AIRoad.BuildRoadStation <- function(tile, front, road_veh_type, station_id)
+{
+ if (AIRoad.IsRoadStationTile(tile)) return false;
+
+ return AIRoad._BuildRoadStation(tile, front, road_veh_type, station_id);
+}
+
+AIRoad._BuildDriveThroughRoadStation <- AIRoad.BuildDriveThroughRoadStation;
+AIRoad.BuildDriveThroughRoadStation <- function(tile, front, road_veh_type, station_id)
+{
+ if (AIRoad.IsRoadStationTile(tile)) return false;
+
+ return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id);
+}
diff --git a/bin/ai/regression/regression.txt b/bin/ai/regression/regression.txt
index be69ce388..aa45f1151 100644
--- a/bin/ai/regression/regression.txt
+++ b/bin/ai/regression/regression.txt
@@ -7259,7 +7259,7 @@
BuildRoadStation(): false
BuildRoadStation(): false
BuildRoadStation(): true
- BuildRoadStation(): false
+ BuildRoadStation(): true
IsStationTile(): true
IsStationTile(): false
HasRoadType(Road): true
@@ -8452,11 +8452,11 @@
14 => 1
12 => 1
Age ListDump:
+ 14 => 1
+ 13 => 1
+ 12 => 1
17 => 0
16 => 0
- 14 => 0
- 13 => 0
- 12 => 0
MaxAge ListDump:
16 => 10980
14 => 10980
@@ -8465,10 +8465,10 @@
12 => 5490
AgeLeft ListDump:
16 => 10980
- 14 => 10980
+ 14 => 10979
17 => 7320
- 13 => 5490
- 12 => 5490
+ 13 => 5489
+ 12 => 5489
CurrentSpeed ListDump:
12 => 21
17 => 0
@@ -8486,7 +8486,7 @@
16 => 0
14 => 0
13 => 0
- 12 => 0
+ 12 => -1
ProfitLastYear ListDump:
17 => 0
16 => 0
diff --git a/src/ai/api/ai_changelog.hpp b/src/ai/api/ai_changelog.hpp
index d554b4418..16b9505b7 100644
--- a/src/ai/api/ai_changelog.hpp
+++ b/src/ai/api/ai_changelog.hpp
@@ -18,6 +18,10 @@
*
* 1.1.0 is not yet released. The following changes are not set in stone yet.
*
+ * Other changes:
+ * \li AIRoad::BuildRoadStation now allows overbuilding
+ * \li AIRoad::BuildDriveThroughRoadStation now allows overbuilding
+ *
* \b 1.0.0
*
* 1.0.0 is not yet released. The following changes are not set in stone yet.
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 2da50d2e4..643b518c0 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -3425,6 +3425,7 @@ STR_ERROR_CAN_T_REMOVE_BUS_STATION :{WHITE}Can't re
STR_ERROR_CAN_T_REMOVE_TRUCK_STATION :{WHITE}Can't remove lorry station...
STR_ERROR_CAN_T_REMOVE_PASSENGER_TRAM_STATION :{WHITE}Can't remove passenger tram station...
STR_ERROR_CAN_T_REMOVE_CARGO_TRAM_STATION :{WHITE}Can't remove freight tram station...
+STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST :{WHITE}Must remove road stop first
STR_ERROR_MUST_DEMOLISH_RAILROAD :{WHITE}Must demolish railway station first
STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST :{WHITE}Must demolish bus station first
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 6a2216d7a..c30f4108b 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -804,11 +804,13 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl
* @param flags Operation to perform.
* @param invalid_dirs Prohibited directions (set of DiagDirections).
* @param is_drive_through True if trying to build a drive-through station.
+ * @param is_truck_stop True when building a truck stop, false otherwise.
* @param axis Axis of a drive-through road stop.
+ * @param station StationID to be queried and returned if available.
* @param rts Road types to build. Bits already built at the tile will be removed.
* @return The cost in case of success, or an error code if it failed.
*/
-static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, Axis axis, RoadTypes &rts)
+static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadTypes &rts)
{
CommandCost cost(EXPENSES_CONSTRUCTION);
int allowed_z = -1;
@@ -818,43 +820,64 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
if (ret.Failed()) return ret;
cost.AddCost(ret);
- bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
- /* Road bits in the wrong direction. */
- if (build_over_road && (GetAllRoadBits(cur_tile) & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
-
- RoadTypes cur_rts = IsNormalRoadTile(cur_tile) ? GetRoadTypes(cur_tile) : ROADTYPES_NONE;
- uint num_roadbits = 0;
- if (build_over_road) {
- /* There is a road, check if we can build road+tram stop over it. */
- if (HasBit(cur_rts, ROADTYPE_ROAD)) {
- Owner road_owner = GetRoadOwner(cur_tile, ROADTYPE_ROAD);
- if (road_owner == OWNER_TOWN) {
- if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
- } else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) {
- return CMD_ERROR;
+ /* If station is set, then we have special handling to allow building on top of already existing stations.
+ * Station points to INVALID_STATION if we can build on any station.
+ * Or it points to a station if we're only allowed to build on exactly that station. */
+ if (station != NULL && IsTileType(cur_tile, MP_STATION)) {
+ if (!IsRoadStop(cur_tile)) {
+ return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
+ } else {
+ if (is_truck_stop != IsTruckStop(cur_tile) ||
+ is_drive_through != IsDriveThroughStopTile(cur_tile) ||
+ HasBit(rts, ROADTYPE_TRAM) != HasBit(GetRoadTypes(cur_tile), ROADTYPE_TRAM)) {
+ return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
+ }
+ StationID st = GetStationIndex(cur_tile);
+ if (*station == INVALID_STATION) {
+ *station = st;
+ } else if (*station != st) {
+ return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
}
- num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD));
}
+ } else {
+ bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile);
+ /* Road bits in the wrong direction. */
+ if (build_over_road && (GetAllRoadBits(cur_tile) & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION);
+
+ RoadTypes cur_rts = IsNormalRoadTile(cur_tile) ? GetRoadTypes(cur_tile) : ROADTYPES_NONE;
+ uint num_roadbits = 0;
+ if (build_over_road) {
+ /* There is a road, check if we can build road+tram stop over it. */
+ if (HasBit(cur_rts, ROADTYPE_ROAD)) {
+ Owner road_owner = GetRoadOwner(cur_tile, ROADTYPE_ROAD);
+ if (road_owner == OWNER_TOWN) {
+ if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
+ } else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) {
+ return CMD_ERROR;
+ }
+ num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD));
+ }
- /* There is a tram, check if we can build road+tram stop over it. */
- if (HasBit(cur_rts, ROADTYPE_TRAM)) {
- Owner tram_owner = GetRoadOwner(cur_tile, ROADTYPE_TRAM);
- if (!_settings_game.construction.road_stop_on_competitor_road && tram_owner != OWNER_NONE && !CheckOwnership(tram_owner)) {
- return CMD_ERROR;
+ /* There is a tram, check if we can build road+tram stop over it. */
+ if (HasBit(cur_rts, ROADTYPE_TRAM)) {
+ Owner tram_owner = GetRoadOwner(cur_tile, ROADTYPE_TRAM);
+ if (!_settings_game.construction.road_stop_on_competitor_road && tram_owner != OWNER_NONE && !CheckOwnership(tram_owner)) {
+ return CMD_ERROR;
+ }
+ num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_TRAM));
}
- num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_TRAM));
+
+ /* Do not remove roadtypes! */
+ rts |= cur_rts;
+ } else {
+ ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+ if (ret.Failed()) return ret;
+ cost.AddCost(ret);
}
- /* Do not remove roadtypes! */
- rts |= cur_rts;
- } else {
- ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
- if (ret.Failed()) return ret;
- cost.AddCost(ret);
+ uint roadbits_to_build = CountBits(rts) * 2 - num_roadbits;
+ cost.AddCost(_price[PR_BUILD_ROAD] * roadbits_to_build);
}
-
- uint roadbits_to_build = CountBits(rts) * 2 - num_roadbits;
- cost.AddCost(_price[PR_BUILD_ROAD] * roadbits_to_build);
}
return cost;
@@ -1595,6 +1618,22 @@ static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
}
}
+static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags);
+
+/**
+ * Find a nearby station that joins this road stop.
+ * @param existing_stop an existing road stop we build over
+ * @param station_to_join the station to join to
+ * @param adjacent whether adjacent stations are allowed
+ * @param ta the area of the newly build station
+ * @param st 'return' pointer for the found station
+ * @return command cost with the error or 'okay'
+ */
+static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
+{
+ return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST>(existing_stop, station_to_join, adjacent, ta, st);
+}
+
/** Build a bus or truck stop.
* @param tile Northernmost tile of the stop.
* @param flags Operation to perform.
@@ -1651,12 +1690,13 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
/* Total road stop cost. */
CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[type ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
- CommandCost ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << ddir : 1 << ddir, is_drive_through, DiagDirToAxis(ddir), rts);
+ StationID est = INVALID_STATION;
+ CommandCost ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << ddir : 1 << ddir, is_drive_through, type, DiagDirToAxis(ddir), &est, rts);
if (ret.Failed()) return ret;
cost.AddCost(ret);
Station *st = NULL;
- ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p2, 5), roadstop_area, &st);
+ ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 5), roadstop_area, &st);
if (ret.Failed()) return ret;
/* Find a deleted station close to us */
@@ -1690,6 +1730,10 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
if (flags & DC_EXEC) {
/* Check every tile in the area. */
TILE_AREA_LOOP(cur_tile, roadstop_area) {
+ if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
+ RemoveRoadStop(cur_tile, flags);
+ }
+
RoadStop *road_stop = new RoadStop(cur_tile);
/* Insert into linked list of RoadStops. */
RoadStop **currstop = FindRoadStopSpot(type, st);