summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichi_cc <michi_cc@openttd.org>2011-07-11 16:32:35 +0000
committermichi_cc <michi_cc@openttd.org>2011-07-11 16:32:35 +0000
commitd579af11e8c903c8019489c9a567b68cdd153b69 (patch)
tree5ec23b092d4f0fa6dc6529605e62a20c022b65c3
parente5dd6f922799a5f741d5e040efcd689f0f5e875b (diff)
downloadopenttd-d579af11e8c903c8019489c9a567b68cdd153b69.tar.xz
(svn r22659) -Add: [NewGRF] Support for the land slope check callback for stations.
-rw-r--r--src/newgrf_callbacks.h2
-rw-r--r--src/newgrf_commons.cpp6
-rw-r--r--src/newgrf_commons.h3
-rw-r--r--src/newgrf_spritegroup.h1
-rw-r--r--src/newgrf_station.cpp47
-rw-r--r--src/newgrf_station.h1
-rw-r--r--src/station_cmd.cpp20
7 files changed, 72 insertions, 8 deletions
diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h
index 6af6ee884..93d42ef0e 100644
--- a/src/newgrf_callbacks.h
+++ b/src/newgrf_callbacks.h
@@ -211,7 +211,7 @@ enum CallbackID {
CBID_HOUSE_WATCHED_CARGO_ACCEPTED = 0x148, // 15 bit callback, not implemented
/** Callback done for each tile of a station to check the slope. */
- CBID_STATION_LAND_SLOPE_CHECK = 0x149, // 15 bit callback, not implemented
+ CBID_STATION_LAND_SLOPE_CHECK = 0x149, // 15 bit callback
/** Called to determine the colour of an industry. */
CBID_INDUSTRY_DECIDE_COLOUR = 0x14A, // 4 bit callback
diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp
index 8b01c1268..83d1d4f44 100644
--- a/src/newgrf_commons.cpp
+++ b/src/newgrf_commons.cpp
@@ -413,9 +413,10 @@ uint32 GetTerrainType(TileIndex tile, TileContext context)
* @param parameter The NewGRF "encoded" offset.
* @param tile The tile to base the offset from.
* @param signed_offsets Whether the offsets are to be interpreted as signed or not.
+ * @param axis Axis of a railways station.
* @return The tile at the offset.
*/
-TileIndex GetNearbyTile(byte parameter, TileIndex tile, bool signed_offsets)
+TileIndex GetNearbyTile(byte parameter, TileIndex tile, bool signed_offsets, Axis axis)
{
int8 x = GB(parameter, 0, 4);
int8 y = GB(parameter, 4, 4);
@@ -424,7 +425,8 @@ TileIndex GetNearbyTile(byte parameter, TileIndex tile, bool signed_offsets)
if (signed_offsets && y >= 8) y -= 16;
/* Swap width and height depending on axis for railway stations */
- if (HasStationTileRail(tile) && GetRailStationAxis(tile) == AXIS_Y) Swap(x, y);
+ if (axis == INVALID_AXIS && HasStationTileRail(tile)) axis = GetRailStationAxis(tile);
+ if (axis == AXIS_Y) Swap(x, y);
/* Make sure we never roam outside of the map, better wrap in that case */
return TILE_MASK(tile + TileDiffXY(x, y));
diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h
index f1977b252..77d62479e 100644
--- a/src/newgrf_commons.h
+++ b/src/newgrf_commons.h
@@ -20,6 +20,7 @@
#include "core/alloc_type.hpp"
#include "core/smallvec_type.hpp"
#include "command_type.h"
+#include "direction_type.h"
/** Context for tile accesses */
enum TileContext {
@@ -266,7 +267,7 @@ extern AirportTileOverrideManager _airporttile_mngr;
extern ObjectOverrideManager _object_mngr;
uint32 GetTerrainType(TileIndex tile, TileContext context = TCX_NORMAL);
-TileIndex GetNearbyTile(byte parameter, TileIndex tile, bool signed_offsets = true);
+TileIndex GetNearbyTile(byte parameter, TileIndex tile, bool signed_offsets = true, Axis axis = INVALID_AXIS);
uint32 GetNearbyTileInformation(TileIndex tile);
CommandCost GetErrorMessageFromLocationCallbackResult(uint16 cb_res, uint32 grfid, StringID default_error);
diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h
index d18ad643f..757e92e93 100644
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -334,6 +334,7 @@ struct ResolverObject {
struct BaseStation *st;
const struct StationSpec *statspec;
CargoID cargo_type;
+ Axis axis; ///< Station axis, used only for the slope check callback.
} station;
struct {
TileIndex tile;
diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp
index e3178feaa..f5236159d 100644
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -279,7 +279,7 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by
}
if (st == NULL) {
- /* Station does not exist, so we're in a purchase list */
+ /* Station does not exist, so we're in a purchase list or the land slope check callback. */
switch (variable) {
case 0x40:
case 0x41:
@@ -289,6 +289,17 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by
case 0x42: return 0; // Rail type (XXX Get current type from GUI?)
case 0x43: return _current_company; // Station owner
case 0x44: return 2; // PBS status
+ case 0x67: // Land info of nearby tile
+ if (object->u.station.axis != INVALID_AXIS && tile != INVALID_TILE) {
+ if (parameter != 0) tile = GetNearbyTile(parameter, tile, true, object->u.station.axis); // only perform if it is required
+
+ Slope tileh = GetTileSlope(tile, NULL);
+ bool swap = (object->u.station.axis == AXIS_Y && HasBit(tileh, CORNER_W) != HasBit(tileh, CORNER_E));
+
+ return GetNearbyTileInformation(tile) ^ (swap ? SLOPE_EW : 0);
+ }
+ break;
+
case 0xFA: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); // Build date, clamped to a 16 bit value
}
@@ -544,6 +555,7 @@ static void NewStationResolver(ResolverObject *res, const StationSpec *statspec,
res->u.station.st = st;
res->u.station.statspec = statspec;
res->u.station.tile = tile;
+ res->u.station.axis = INVALID_AXIS;
res->callback = CBID_NO_CALLBACK;
res->callback_param1 = 0;
@@ -653,6 +665,39 @@ uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, con
return group->GetCallbackResult();
}
+/**
+ * Check the slope of a tile of a new station.
+ * @param north_tile Norther tile of the station rect.
+ * @param cur_tile Tile to check.
+ * @param statspec Station spec.
+ * @param axis Axis of the new station.
+ * @param plat_len Platform length.
+ * @param numtracks Number of platforms.
+ * @return Succeeded or failed command.
+ */
+CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, byte plat_len, byte numtracks)
+{
+ TileIndexDiff diff = cur_tile - north_tile;
+ Slope slope = GetTileSlope(cur_tile, NULL);
+
+ ResolverObject object;
+ NewStationResolver(&object, statspec, NULL, cur_tile);
+
+ object.callback = CBID_STATION_LAND_SLOPE_CHECK;
+ object.callback_param1 = slope << 4 | slope ^ (axis == AXIS_Y && HasBit(slope, CORNER_W) != HasBit(slope, CORNER_E) ? SLOPE_EW : 0);
+ object.callback_param2 = numtracks << 24 | plat_len << 16 | (axis == AXIS_Y ? TileX(diff) << 8 | TileY(diff) : TileY(diff) << 8 | TileX(diff));
+ object.u.station.axis = axis;
+
+ const SpriteGroup *group = ResolveStation(&object);
+ uint16 cb_res = group != NULL ? group->GetCallbackResult() : CALLBACK_FAILED;
+
+ /* Failed callback means success. */
+ if (cb_res == CALLBACK_FAILED) return CommandCost();
+
+ /* The meaning of bit 10 is inverted in the result of this callback. */
+ return GetErrorMessageFromLocationCallbackResult(ToggleBit(cb_res, 10), statspec->grf_prop.grffile->grfid, STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
+}
+
/**
* Allocate a StationSpec to a Station. This is called once per build operation.
diff --git a/src/newgrf_station.h b/src/newgrf_station.h
index 82656ec04..7c9f80694 100644
--- a/src/newgrf_station.h
+++ b/src/newgrf_station.h
@@ -114,6 +114,7 @@ uint32 GetPlatformInfo(Axis axis, byte tile, int platforms, int length, int x, i
SpriteID GetCustomStationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint32 var10 = 0);
SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseStation *st, TileIndex tile, uint layout, uint edge_info);
uint16 GetStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile);
+CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, byte plat_len, byte numtracks);
/* Allocate a StationSpec to a Station. This is called once per build operation. */
int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec);
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 54f619fd8..3495f111d 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -749,22 +749,36 @@ CommandCost CheckFlatLand(TileArea tile_area, DoCommandFlag flags)
* Checks if a rail station can be built at the given area.
* @param tile_area Area to check.
* @param flags Operation to perform.
- * @param invalid_dirs Prohibited directions (set of #DiagDirection).
+ * @param axis Rail station axis.
* @param station StationID to be queried and returned if available.
* @param rt The rail type to check for (overbuilding rail stations over rail).
* @param affected_vehicles List of trains with PBS reservations on the tiles
+ * @param spec_class Station class.
+ * @param spec_index Index into the station class.
+ * @param plat_len Platform length.
+ * @param numtracks Number of platforms.
* @return The cost in case of success, or an error code if it failed.
*/
-static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, StationID *station, RailType rt, SmallVector<Train *, 4> &affected_vehicles)
+static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag flags, Axis axis, StationID *station, RailType rt, SmallVector<Train *, 4> &affected_vehicles, StationClassID spec_class, byte spec_index, byte plat_len, byte numtracks)
{
CommandCost cost(EXPENSES_CONSTRUCTION);
int allowed_z = -1;
+ uint invalid_dirs = 5 << axis;
+
+ const StationSpec *statspec = StationClass::Get(spec_class, spec_index);
+ bool slope_cb = statspec != NULL && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK);
TILE_AREA_LOOP(tile_cur, tile_area) {
CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z);
if (ret.Failed()) return ret;
cost.AddCost(ret);
+ if (slope_cb) {
+ /* Do slope check if requested. */
+ ret = PerformStationTileSlopeCheck(tile_area.tile, tile_cur, statspec, axis, plat_len, numtracks);
+ if (ret.Failed()) return ret;
+ }
+
/* if station is set, then we have special handling to allow building on top of already existing stations.
* so 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. */
@@ -1140,7 +1154,7 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
StationID est = INVALID_STATION;
SmallVector<Train *, 4> affected_vehicles;
/* Clear the land below the station. */
- CommandCost cost = CheckFlatLandRailStation(TileArea(tile_org, w_org, h_org), flags, 5 << axis, &est, rt, affected_vehicles);
+ CommandCost cost = CheckFlatLandRailStation(TileArea(tile_org, w_org, h_org), flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
if (cost.Failed()) return cost;
/* Add construction expenses. */
cost.AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len);