MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / CmdLevelLand

Function CmdLevelLand

src/terraform_cmd.cpp:315–387  ·  view source on GitHub ↗

* Levels a selected (rectangle) area of land * @param flags for this command type * @param tile end tile of area-drag * @param start_tile start tile of area drag * @param diagonal Whether to use the Orthogonal (false) or Diagonal (true) iterator. * @param LevelMode Mode of leveling \c LevelMode. * @return the cost of this operation or an error */

Source from the content-addressed store, hash-verified

313 * @return the cost of this operation or an error
314 */
315std::tuple<CommandCost, Money, TileIndex> CmdLevelLand(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal, LevelMode lm)
316{
317 if (start_tile >= Map::Size()) return { CMD_ERROR, 0, INVALID_TILE };
318
319 /* remember level height */
320 uint oldh = TileHeight(start_tile);
321
322 /* compute new height */
323 uint h = oldh;
324 switch (lm) {
325 case LM_LEVEL: break;
326 case LM_RAISE: h++; break;
327 case LM_LOWER: h--; break;
328 default: return { CMD_ERROR, 0, INVALID_TILE };
329 }
330
331 /* Check range of destination height */
332 if (h > _settings_game.construction.map_height_limit) return { CommandCost(oldh == 0 ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH), 0, INVALID_TILE };
333
334 Money money = GetAvailableMoneyForCommand();
335 CommandCost cost(EXPENSES_CONSTRUCTION);
336 CommandCost last_error(lm == LM_LEVEL ? STR_ERROR_ALREADY_LEVELLED : INVALID_STRING_ID);
337 bool had_success = false;
338
339 const Company *c = Company::GetIfValid(_current_company);
340 int limit = (c == nullptr ? INT32_MAX : GB(c->terraform_limit, 16, 16));
341 if (limit == 0) return { CommandCost(STR_ERROR_TERRAFORM_LIMIT_REACHED), 0, INVALID_TILE };
342
343 TileIndex error_tile = INVALID_TILE;
344 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
345 for (; *iter != INVALID_TILE; ++(*iter)) {
346 TileIndex t = *iter;
347 uint curh = TileHeight(t);
348 while (curh != h) {
349 CommandCost ret;
350 std::tie(ret, std::ignore, error_tile) = Command<CMD_TERRAFORM_LAND>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), t, SLOPE_N, curh <= h);
351 if (ret.Failed()) {
352 last_error = std::move(ret);
353
354 /* Did we reach the limit? */
355 if (last_error.GetErrorMessage() == STR_ERROR_TERRAFORM_LIMIT_REACHED) limit = 0;
356 break;
357 }
358
359 if (flags.Test(DoCommandFlag::Execute)) {
360 money -= ret.GetCost();
361 if (money < 0) {
362 return { cost, ret.GetCost(), error_tile };
363 }
364 Command<CMD_TERRAFORM_LAND>::Do(flags, t, SLOPE_N, curh <= h);
365 } else {
366 /* When we're at the terraform limit we better bail (unneeded) testing as well.
367 * This will probably cause the terraforming cost to be underestimated, but only
368 * when it's near the terraforming limit. Even then, the estimation is
369 * completely off due to it basically counting terraforming double, so it being
370 * cut off earlier might even give a better estimate in some cases. */
371 if (--limit <= 0) {
372 had_success = true;

Callers

nothing calls this directly

Calls 11

TileHeightFunction · 0.85
CommandCostClass · 0.85
GBFunction · 0.85
FailedMethod · 0.80
GetErrorMessageMethod · 0.80
TestMethod · 0.80
SucceededMethod · 0.80
ResetMethod · 0.45
GetCostMethod · 0.45
AddCostMethod · 0.45

Tested by

no test coverage detected