changeset 15976:5bc7f30fcc56 draft

(svn r20664) -Codechange: implement the land slope callback for objects
author rubidium <rubidium@openttd.org>
date Sat, 28 Aug 2010 18:55:20 +0000
parents abda7bdf71bc
children 9bdda4be4c9a
files src/newgrf_callbacks.h src/object_cmd.cpp
diffstat 2 files changed, 39 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_callbacks.h
+++ b/src/newgrf_callbacks.h
@@ -253,7 +253,7 @@
 	CBID_AIRPORT_LAYOUT_NAME             = 0x156, // 15 bit callback
 
 	/** Callback done for each tile of an object to check the slope. */
-	CBID_OBJECT_LAND_SLOPE_CHECK         = 0x157, // 15 bit callback, not implemented
+	CBID_OBJECT_LAND_SLOPE_CHECK         = 0x157, // 15 bit callback
 
 	/** Determine the next animation frame for a house. */
 	CBID_OBJECT_ANIMATION_NEXT_FRAME     = 0x158, // 15 bit callback
--- a/src/object_cmd.cpp
+++ b/src/object_cmd.cpp
@@ -127,7 +127,7 @@
 	}
 }
 
-extern CommandCost CheckFlatLand(TileArea tile_area, DoCommandFlag flags);
+extern CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z);
 static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlag flags);
 
 /**
@@ -161,7 +161,37 @@
 		/* Owned land is special as it can be placed on any slope. */
 		cost.AddCost(DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR));
 	} else {
-		cost.AddCost(CheckFlatLand(ta, flags));
+		/* Check the surface to build on. */
+		bool allow_water = (spec->flags & OBJECT_FLAG_BUILT_ON_WATER) != 0;
+		bool allow_ground = (spec->flags & OBJECT_FLAG_NOT_ON_LAND) == 0;
+		TILE_AREA_LOOP(t, ta) {
+			if (IsWaterTile(t)) {
+				if (!allow_water) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
+				/* For water tiles we want to "just" check whether the tile is water and
+				 * can be cleared, i.e. it's not filled. We won't be paying though. */
+				CommandCost ret = DoCommand(t, 0, 0, flags & ~(DC_EXEC | DC_NO_WATER), CMD_LANDSCAPE_CLEAR);
+				if (ret.Failed()) return ret;
+			} else {
+				if (!allow_ground) return_cmd_error(STR_ERROR_MUST_BE_BUILT_ON_WATER);
+				/* For non-water tiles, we'll have to clear it before building. */
+				cost.AddCost(DoCommand(t, 0, 0, flags, CMD_LANDSCAPE_CLEAR));
+			}
+		}
+
+		/* So, now the surface is checked... check the slope of said surface. */
+		if (spec->callback_mask & CBM_OBJ_SLOPE_CHECK) {
+			TILE_AREA_LOOP(t, ta) {
+				TileIndex diff = t - tile;
+				uint16 callback = GetObjectCallback(CBID_OBJECT_LAND_SLOPE_CHECK, GetTileSlope(t, NULL), TileY(diff) << 4 | TileX(diff), spec, NULL, t);
+				if (callback != 0) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
+			}
+		} else {
+			/* Check whether the ground is flat enough. */
+			int allowed_z = -1;
+			TILE_AREA_LOOP(t, ta) {
+				cost.AddCost(CheckBuildableTile(t, 0, allowed_z));
+			}
+		}
 	}
 	if (cost.Failed()) return cost;
 
@@ -197,7 +227,12 @@
 			break;
 		}
 
-		default: break;
+		case OBJECT_STATUE:
+			/* This may never be constructed using this method. */
+			return CMD_ERROR;
+
+		default: // i.e. NewGRF provided.
+			break;
 	}
 
 	if (flags & DC_EXEC) {