Thanks planetmaker, though I can't figure out a way to "deconstruct" the bitmask result (or related numerical value), or find an API approach to use them directly.
I settled on a large switch, for each slope type and some arrays linking the bits, but its just seems like there is a better way somewhere...
Code: Select all
/**
* Perform landscapeing on a single tile to get a specific slope.
* @param tile The tile to landscape.
* @param desired_slope The slope to try get.
* @param desired_height The desired AITile.GetMinHeight of the resulting tile.
* @return True if completed, false if fail.
*/
function MapBuilder::LandscapeSlope(tile, desired_slope, desired_height) {
// Validate.
if (!AIMap.IsValidTile(tile)) throw("Must be valid tile!");
if (typeof(desired_slope) != "integer" || desired_slope == AITile.SLOPE_INVALID) throw("Must be valid slope!");
if (typeof(desired_height) != "integer") throw("Argument is invalid height!");
// Check if not required.
if (AITile.GetSlope(tile) == desired_slope && AITile.GetMinHeight(tile) == desired_height) return true;
// Get desired corner height.
local corners_to_set = null; // Delta from tile min height for each corner [N, E, W, S];
switch (desired_slope) {
case AITile.SLOPE_FLAT: corners_to_set = [0, 0, 0, 0]; break;
case AITile.SLOPE_W: corners_to_set = [0, 0, 1, 0]; break;
case AITile.SLOPE_S: corners_to_set = [0, 0, 0, 1]; break;
case AITile.SLOPE_E: corners_to_set = [0, 1, 0, 0]; break;
case AITile.SLOPE_N: corners_to_set = [1, 0, 0, 0]; break;
case AITile.SLOPE_STEEP: throw("Steep slope not valid!"); break;
case AITile.SLOPE_NW: corners_to_set = [1, 0, 1, 0]; break;
case AITile.SLOPE_SW: corners_to_set = [0, 0, 1, 1]; break;
case AITile.SLOPE_SE: corners_to_set = [0, 1, 0, 1]; break;
case AITile.SLOPE_NE: corners_to_set = [1, 1, 0, 0]; break;
case AITile.SLOPE_EW: corners_to_set = [0, 1, 1, 0]; break;
case AITile.SLOPE_NS: corners_to_set = [1, 0, 0, 1]; break;
case AITile.SLOPE_ELEVATED: throw("Elevated slope not valid!"); break;
case AITile.SLOPE_NWS: corners_to_set = [1, 0, 1, 1]; break;
case AITile.SLOPE_WSE: corners_to_set = [0, 1, 1, 1]; break;
case AITile.SLOPE_SEN: corners_to_set = [1, 1, 0, 1]; break;
case AITile.SLOPE_ENW: corners_to_set = [1, 1, 1, 0]; break;
case AITile.SLOPE_STEEP_W: corners_to_set = [0, 0, 2, 0]; break;
case AITile.SLOPE_STEEP_S: corners_to_set = [0, 0, 0, 2]; break;
case AITile.SLOPE_STEEP_E: corners_to_set = [0, 2, 0, 0]; break;
case AITile.SLOPE_STEEP_N: corners_to_set = [2, 0, 0, 0]; break;
case AITile.SLOPE_INVALID: throw("Invalid slope!"); break;
default: throw("Unhandled slope!"); break;
}
// Create mirror corner and slope arrays.
// Has to match above SWITCH array.
local corner_array = [AITile.CORNER_N, AITile.CORNER_E, AITile.CORNER_W, AITile.CORNER_S];
local slope_array = [AITile.SLOPE_N, AITile.SLOPE_E, AITile.SLOPE_W, AITile.SLOPE_S];
local build_mode = AIExecMode();
// Loop for each corner.
foreach (corner_index, corner in corner_array) {
// Loop landscape each corner till desired height or fail.
local corner_height = null;
local desired_corner_height = desired_height + corners_to_set[corner_index];
while((corner_height = AITile.GetCornerHeight(tile, corner)) != desired_corner_height) {
// Raise if lower.
if (corner_height < desired_corner_height)
if(!AITile.RaiseTile(tile, slope_array[corner_index])) return false;
// Lower if higher.
else if (corner_height > desired_corner_height)
if(!AITile.LowerTile(tile, slope_array[corner_index])) return false;
}
}
return true;
}