This commit is contained in:
SamuXarick 2024-04-19 13:25:41 +01:00 committed by GitHub
commit 1db1f5bce9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 56 additions and 10 deletions

View File

@ -15,6 +15,7 @@
#include "viewport_func.h"
#include "core/random_func.hpp"
#include "newgrf_generic.h"
#include "town.h"
#include "landscape_cmd.h"
#include "table/strings.h"
@ -369,8 +370,14 @@ static void ChangeTileOwner_Clear(TileIndex, Owner, Owner)
return;
}
static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, int, Slope)
static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
{
if (flags & DC_NO_TERRAFORM_FLOOD) {
if (!CanTownTerraformTileWithoutFlooding(tile, z_new, tileh_new)) {
return CMD_ERROR;
}
}
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
}

View File

@ -372,7 +372,7 @@ enum DoCommandFlag {
DC_AUTO = 0x002, ///< don't allow building on structures
DC_QUERY_COST = 0x004, ///< query cost only, don't build.
DC_NO_WATER = 0x008, ///< don't allow building on water
// 0x010 is unused
DC_NO_TERRAFORM_FLOOD = 0x010, ///< don't allow terraforming on tiles with a flooding behaviour (used for town growth)
DC_NO_TEST_TOWN_RATING = 0x020, ///< town rating does not disallow you from building
DC_BANKRUPT = 0x040, ///< company bankrupts, skip money check, skip vehicle on tile check in some cases
DC_AUTOREPLACE = 0x080, ///< autoreplace/autorenew is in progress, this shall disable vehicle limits when building, and ignore certain restrictions when undoing things (like vehicle attach callback)

View File

@ -317,7 +317,7 @@ inline uint16_t TownTicksToGameTicks(uint16_t ticks)
return (std::min(ticks, MAX_TOWN_GROWTH_TICKS) + 1) * Ticks::TOWN_GROWTH_TICKS - 1;
}
bool CanTownTerraformTileWithoutFlooding(TileIndex tile, int z_new, Slope tileh_new);
RoadType GetTownRoadType();
bool CheckTownRoadTypes();

View File

@ -48,6 +48,7 @@
#include "object_base.h"
#include "ai/ai.hpp"
#include "game/game.hpp"
#include "water.h"
#include "town_cmd.h"
#include "landscape_cmd.h"
#include "road_cmd.h"
@ -1054,7 +1055,7 @@ static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir)
CommandCost res = CMD_ERROR;
if (!_generating_world && Chance16(1, 10)) {
/* Note: Do not replace "^ SLOPE_ELEVATED" with ComplementSlope(). The slope might be steep. */
res = std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(DC_EXEC | DC_AUTO | DC_NO_WATER,
res = std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(DC_EXEC | DC_AUTO | DC_NO_WATER | DC_NO_TERRAFORM_FLOOD,
tile, Chance16(1, 16) ? cur_slope : cur_slope ^ SLOPE_ELEVATED, false));
}
if (res.Failed() && Chance16(1, 3)) {
@ -1071,9 +1072,9 @@ static bool TerraformTownTile(TileIndex tile, Slope edges, bool dir)
{
assert(tile < Map::Size());
CommandCost r = std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(DC_AUTO | DC_NO_WATER, tile, edges, dir));
CommandCost r = std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(DC_AUTO | DC_NO_WATER | DC_NO_TERRAFORM_FLOOD, tile, edges, dir));
if (r.Failed() || r.GetCost() >= (_price[PR_TERRAFORM] + 2) * 8) return false;
Command<CMD_TERRAFORM_LAND>::Do(DC_AUTO | DC_NO_WATER | DC_EXEC, tile, edges, dir);
Command<CMD_TERRAFORM_LAND>::Do(DC_AUTO | DC_NO_WATER | DC_NO_TERRAFORM_FLOOD | DC_EXEC, tile, edges, dir);
return true;
}
@ -1092,6 +1093,31 @@ static void LevelTownLand(TileIndex tile)
}
}
/**
* Check if a town can safely terraform a tile without it being flooded by the ocean.
*
* @param tile Tile to check.
* @param z_new The new height the tile would get after being terraformed.
* @param tileh_new The new slope type the tile would get after being terraformed.
* @return true iff a tile with or without a flooding behaviour can be terraformed.
* @note This function is intended to be used for the town growth algorithm using the terraform command.
*/
bool CanTownTerraformTileWithoutFlooding(TileIndex tile, int z_new, Slope tileh_new)
{
/* This function is intended to be used for the town growth algorithm using the terraform command. */
assert(_current_company == OWNER_TOWN);
if (GetFloodingBehaviour(tile) != FLOOD_NONE) {
return z_new != 0 || (!IsSlopeWithOneCornerRaised(tileh_new) && tileh_new != SLOPE_FLAT);
}
if (_settings_game.construction.freeform_edges && DistanceFromEdge(tile) == 1) {
return tileh_new != SLOPE_FLAT;
}
return true;
}
/**
* Generate the RoadBits of a grid tile.
*
@ -1417,8 +1443,8 @@ static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDi
/* Attempt to build the tunnel. Return false if it fails to let the town build a road instead. */
RoadType rt = GetTownRoadType();
if (Command<CMD_BUILD_TUNNEL>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, TRANSPORT_ROAD, rt).Succeeded()) {
Command<CMD_BUILD_TUNNEL>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, TRANSPORT_ROAD, rt);
if (Command<CMD_BUILD_TUNNEL>::Do(DC_NO_TERRAFORM_FLOOD | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, TRANSPORT_ROAD, rt).Succeeded()) {
Command<CMD_BUILD_TUNNEL>::Do(DC_EXEC | DC_NO_TERRAFORM_FLOOD | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, TRANSPORT_ROAD, rt);
_grow_town_result = GROWTH_SUCCEED;
return true;
}

View File

@ -878,8 +878,14 @@ void InitializeTrees()
_trees_tick_ctr = 0;
}
static CommandCost TerraformTile_Trees(TileIndex tile, DoCommandFlag flags, int, Slope)
static CommandCost TerraformTile_Trees(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
{
if (flags & DC_NO_TERRAFORM_FLOOD) {
if (!CanTownTerraformTileWithoutFlooding(tile, z_new, tileh_new)) {
return CMD_ERROR;
}
}
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
}

View File

@ -37,6 +37,7 @@
#include "company_gui.h"
#include "newgrf_generic.h"
#include "industry.h"
#include "town.h"
#include "water_cmd.h"
#include "landscape_cmd.h"
#include "pathfinder/water_regions.h"
@ -1381,11 +1382,17 @@ static VehicleEnterTileStatus VehicleEnter_Water(Vehicle *, TileIndex, int, int)
return VETSB_CONTINUE;
}
static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, int, Slope)
static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
{
/* Canals can't be terraformed */
if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
if (flags & DC_NO_TERRAFORM_FLOOD) {
if (!CanTownTerraformTileWithoutFlooding(tile, z_new, tileh_new)) {
return CMD_ERROR;
}
}
return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
}