mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-05 22:04:57 +00:00
(svn r11172) -Codechange: rewrite of town road building and addition of the possibility to clean up unconnected road bits during the local road reconstructions. Based on a patch by skidd13.
This commit is contained in:
parent
a85e18c922
commit
01edaeec57
@ -326,6 +326,9 @@
|
||||
<File
|
||||
RelativePath=".\..\src\rev.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\road.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\saveload.cpp">
|
||||
</File>
|
||||
|
@ -667,6 +667,10 @@
|
||||
RelativePath=".\..\src\rev.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\road.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\saveload.cpp"
|
||||
>
|
||||
|
@ -58,6 +58,7 @@ players.cpp
|
||||
queue.cpp
|
||||
rail.cpp
|
||||
rev.cpp
|
||||
road.cpp
|
||||
saveload.cpp
|
||||
screenshot.cpp
|
||||
#if SDL
|
||||
|
@ -165,6 +165,9 @@ enum DiagDirDiff {
|
||||
DIAGDIRDIFF_90LEFT = 3 ///< 90 degrees left
|
||||
};
|
||||
|
||||
/** Allow incrementing of DiagDirDiff variables */
|
||||
DECLARE_POSTFIX_INCREMENT(DiagDirDiff);
|
||||
|
||||
/**
|
||||
* Applies a difference on a DiagDirection
|
||||
*
|
||||
|
@ -1187,6 +1187,7 @@ STR_CONFIG_PATCHES_TOWN_GROWTH_VERY_FAST :Very fast
|
||||
STR_CONFIG_PATCHES_LARGER_TOWNS :{LTBLUE}Proportion of towns that will become cities: {ORANGE}1 in {STRING1}
|
||||
STR_CONFIG_PATCHES_LARGER_TOWNS_DISABLED :{LTBLUE}Proportion of towns that will become cities: {ORANGE}None
|
||||
STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER :{LTBLUE}Initial city size multiplier: {ORANGE}{STRING1}
|
||||
STR_CONFIG_MODIFIED_ROAD_REBUILD :{LTBLUE}Remove absurd road-elements during the road construction
|
||||
|
||||
STR_CONFIG_PATCHES_GUI :{BLACK}Interface
|
||||
STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction
|
||||
|
12
src/map.h
12
src/map.h
@ -389,6 +389,18 @@ static inline TileIndexDiff TileOffsByDir(Direction dir)
|
||||
return ToTileIndexDiff(_tileoffs_by_dir[dir]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DiagDir to a tile.
|
||||
*
|
||||
* @param tile The current tile
|
||||
* @param dir The direction in which we want to step
|
||||
* @return the moved tile
|
||||
*/
|
||||
static inline TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
|
||||
{
|
||||
return TILE_ADD(tile, TileOffsByDiagDir(dir));
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback function type for searching tiles.
|
||||
*
|
||||
|
69
src/road.cpp
Normal file
69
src/road.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "stdafx.h"
|
||||
#include "openttd.h"
|
||||
#include "functions.h"
|
||||
#include "rail_map.h"
|
||||
#include "road.h"
|
||||
#include "road_map.h"
|
||||
#include "water_map.h"
|
||||
#include "macros.h"
|
||||
|
||||
bool IsPossibleCrossing(const TileIndex tile, Axis ax)
|
||||
{
|
||||
return (IsTileType(tile, MP_RAILWAY) &&
|
||||
!HasSignals(tile) &&
|
||||
GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) &&
|
||||
GetTileSlope(tile, NULL) == SLOPE_FLAT);
|
||||
}
|
||||
|
||||
RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
|
||||
{
|
||||
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
|
||||
const TileIndex neighbor_tile = TileAddByDiagDir(tile, dir);
|
||||
|
||||
/* Get the Roadbit pointing to the neighbor_tile */
|
||||
const RoadBits target_rb = DiagDirToRoadBits(dir);
|
||||
|
||||
/* If the roadbit is in the current plan */
|
||||
if (org_rb & target_rb) {
|
||||
bool connective = false;
|
||||
const RoadBits mirrored_rb = MirrorRoadBits(target_rb);
|
||||
|
||||
switch (GetTileType(neighbor_tile)) {
|
||||
/* Allways connective ones */
|
||||
case MP_CLEAR: case MP_TREES:
|
||||
connective = true;
|
||||
break;
|
||||
|
||||
/* The conditionaly connective ones */
|
||||
case MP_TUNNELBRIDGE:
|
||||
case MP_STATION:
|
||||
case MP_ROAD: {
|
||||
const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM);
|
||||
|
||||
/* Accept only connective tiles */
|
||||
connective = (neighbor_rb & mirrored_rb) || // Neighbor has got the fitting RoadBit
|
||||
COUNTBITS(neighbor_rb) == 1; // Neighbor has got only one Roadbit
|
||||
|
||||
} break;
|
||||
|
||||
case MP_RAILWAY:
|
||||
connective = IsPossibleCrossing(neighbor_tile, DiagDirToAxis(dir));
|
||||
break;
|
||||
|
||||
case MP_WATER:
|
||||
/* Check for real water tile */
|
||||
connective = !IsWater(neighbor_tile);
|
||||
break;
|
||||
|
||||
/* The defentetly not connective ones */
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* If the neighbor tile is inconnective remove the planed road connection to it */
|
||||
if (!connective) org_rb ^= target_rb;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return org_rb;
|
||||
}
|
48
src/road.h
48
src/road.h
@ -115,6 +115,36 @@ static inline RoadBits ComplementRoadBits(RoadBits r)
|
||||
return (RoadBits)(ROAD_ALL ^ r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the mirrored RoadBits
|
||||
*
|
||||
* Simply move the bits to their new position.
|
||||
*
|
||||
* @param r The given RoadBits value
|
||||
* @return the mirrored
|
||||
*/
|
||||
static inline RoadBits MirrorRoadBits(RoadBits r)
|
||||
{
|
||||
return (RoadBits)(GB(r, 0, 2) << 2 | GB(r, 2, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate rotated RoadBits
|
||||
*
|
||||
* Move the Roadbits clockwise til they are in their final position.
|
||||
*
|
||||
* @param r The given RoadBits value
|
||||
* @param rot The given Rotation angle
|
||||
* @return the rotated
|
||||
*/
|
||||
static inline RoadBits RotateRoadBits(RoadBits r, DiagDirDiff rot)
|
||||
{
|
||||
for (; rot > (DiagDirDiff)0; rot--){
|
||||
r = (RoadBits)(GB(r, 0, 1) << 3 | GB(r, 1, 3));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the road-part which belongs to the given DiagDirection
|
||||
*
|
||||
@ -129,6 +159,16 @@ static inline RoadBits DiagDirToRoadBits(DiagDirection d)
|
||||
return (RoadBits)(ROAD_NW << (3 ^ d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the tile is a valid tile for a crossing.
|
||||
*
|
||||
* @note function is overloaded
|
||||
* @param tile the curent tile
|
||||
* @param ax the axis of the road over the rail
|
||||
* @return true if it is a valid tile
|
||||
*/
|
||||
bool IsPossibleCrossing(const TileIndex tile, Axis ax);
|
||||
|
||||
/**
|
||||
* Checks whether the trackdir means that we are reversing.
|
||||
* @param dir the trackdir to check
|
||||
@ -149,6 +189,14 @@ static inline bool IsStraightRoadTrackdir(Trackdir dir)
|
||||
return (dir & 0x06) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up unneccesary RoadBits of a planed tile.
|
||||
* @param tile current tile
|
||||
* @param org_rb planed RoadBits
|
||||
* @return optimised RoadBits
|
||||
*/
|
||||
RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb);
|
||||
|
||||
/**
|
||||
* Is it allowed to remove the given road bits from the given tile?
|
||||
* @param tile the tile to remove the road from
|
||||
|
138
src/road_cmd.cpp
138
src/road_cmd.cpp
@ -259,70 +259,121 @@ CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
static const RoadBits _valid_tileh_slopes_road[][15] = {
|
||||
/* set of normal ones */
|
||||
{
|
||||
ROAD_ALL, ROAD_NONE, ROAD_NONE,
|
||||
ROAD_X, ROAD_NONE, ROAD_NONE, // 3, 4, 5
|
||||
ROAD_Y, ROAD_NONE, ROAD_NONE,
|
||||
ROAD_Y, ROAD_NONE, ROAD_NONE, // 9, 10, 11
|
||||
ROAD_X, ROAD_NONE, ROAD_NONE
|
||||
ROAD_ALL, // SLOPE_FLAT
|
||||
ROAD_NONE, // SLOPE_W
|
||||
ROAD_NONE, // SLOPE_S
|
||||
|
||||
ROAD_X, // SLOPE_SW
|
||||
ROAD_NONE, // SLOPE_E
|
||||
ROAD_NONE, // SLOPE_EW
|
||||
|
||||
ROAD_Y, // SLOPE_SE
|
||||
ROAD_NONE, // SLOPE_WSE
|
||||
ROAD_NONE, // SLOPE_N
|
||||
|
||||
ROAD_Y, // SLOPE_NW
|
||||
ROAD_NONE, // SLOPE_NS
|
||||
ROAD_NONE, // SLOPE_NE
|
||||
|
||||
ROAD_X, // SLOPE_ENW
|
||||
ROAD_NONE, // SLOPE_SEN
|
||||
ROAD_NONE // SLOPE_ELEVATED
|
||||
},
|
||||
/* allowed road for an evenly raised platform */
|
||||
{
|
||||
ROAD_NONE,
|
||||
ROAD_SW | ROAD_NW,
|
||||
ROAD_SW | ROAD_SE,
|
||||
ROAD_Y | ROAD_SW,
|
||||
ROAD_NONE, // SLOPE_FLAT
|
||||
ROAD_SW | ROAD_NW, // SLOPE_W
|
||||
ROAD_SW | ROAD_SE, // SLOPE_S
|
||||
|
||||
ROAD_SE | ROAD_NE, // 4
|
||||
ROAD_ALL,
|
||||
ROAD_X | ROAD_SE,
|
||||
ROAD_ALL,
|
||||
ROAD_Y | ROAD_SW, // SLOPE_SW
|
||||
ROAD_SE | ROAD_NE, // SLOPE_E
|
||||
ROAD_ALL, // SLOPE_EW
|
||||
|
||||
ROAD_NW | ROAD_NE, // 8
|
||||
ROAD_X | ROAD_NW,
|
||||
ROAD_ALL,
|
||||
ROAD_ALL,
|
||||
ROAD_X | ROAD_SE, // SLOPE_SE
|
||||
ROAD_ALL, // SLOPE_WSE
|
||||
ROAD_NW | ROAD_NE, // SLOPE_N
|
||||
|
||||
ROAD_Y | ROAD_NE, // 12
|
||||
ROAD_ALL,
|
||||
ROAD_ALL
|
||||
ROAD_X | ROAD_NW, // SLOPE_NW
|
||||
ROAD_ALL, // SLOPE_NS
|
||||
ROAD_ALL, // SLOPE_NE
|
||||
|
||||
ROAD_Y | ROAD_NE, // SLOPE_ENW
|
||||
ROAD_ALL, // SLOPE_SEN
|
||||
ROAD_ALL // SLOPE_ELEVATED
|
||||
},
|
||||
/* Singe bits on slopes */
|
||||
{
|
||||
ROAD_ALL, // SLOPE_FLAT
|
||||
ROAD_NE | ROAD_SE, // SLOPE_W
|
||||
ROAD_NE | ROAD_NW, // SLOPE_S
|
||||
|
||||
ROAD_NE, // SLOPE_SW
|
||||
ROAD_NW | ROAD_SW, // SLOPE_E
|
||||
ROAD_ALL, // SLOPE_EW
|
||||
|
||||
ROAD_NW, // SLOPE_SE
|
||||
ROAD_ALL, // SLOPE_WSE
|
||||
ROAD_SE | ROAD_SW, // SLOPE_N
|
||||
|
||||
ROAD_SE, // SLOPE_NW
|
||||
ROAD_ALL, // SLOPE_NS
|
||||
ROAD_ALL, // SLOPE_NE
|
||||
|
||||
ROAD_SW, // SLOPE_ENW
|
||||
ROAD_ALL, // SLOPE_SEN
|
||||
ROAD_ALL, // SLOPE_ELEVATED
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the costs for roads on slopes
|
||||
* Aside modify the RoadBits to fit on the slopes
|
||||
*
|
||||
* @note The RoadBits are modified too!
|
||||
* @param tileh The current slope
|
||||
* @param pieces The RoadBits we want to add
|
||||
* @param existing The existent RoadBits
|
||||
* @return The costs for these RoadBits on this slope
|
||||
*/
|
||||
static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing)
|
||||
{
|
||||
RoadBits road_bits;
|
||||
|
||||
if (IsSteepSlope(tileh)) {
|
||||
/* force full pieces. */
|
||||
*pieces |= (RoadBits)((*pieces & 0xC) >> 2);
|
||||
*pieces |= (RoadBits)((*pieces & 0x3) << 2);
|
||||
/* Force straight roads. */
|
||||
*pieces |= MirrorRoadBits(*pieces);
|
||||
|
||||
if (existing == 0 || existing == *pieces) {
|
||||
if (existing == ROAD_NONE || existing == *pieces) {
|
||||
if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform;
|
||||
}
|
||||
return CMD_ERROR;
|
||||
}
|
||||
road_bits = *pieces | existing;
|
||||
|
||||
RoadBits road_bits = *pieces | existing;
|
||||
|
||||
/* Single bits on slopes.
|
||||
* We check for the roads that need at least 2 bits */
|
||||
if (_patches.build_on_slopes && !_is_old_ai_player &&
|
||||
existing == ROAD_NONE && COUNTBITS(*pieces) == 1 &&
|
||||
(_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) {
|
||||
return CommandCost(_price.terraform);
|
||||
}
|
||||
|
||||
/* no special foundation */
|
||||
if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) {
|
||||
if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == ROAD_NONE) {
|
||||
/* force that all bits are set when we have slopes */
|
||||
if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh];
|
||||
return CommandCost(); // no extra cost
|
||||
}
|
||||
|
||||
/* foundation is used. Whole tile is leveled up */
|
||||
if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) {
|
||||
return CommandCost(existing != 0 ? 0 : _price.terraform);
|
||||
if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) {
|
||||
return CommandCost(existing != ROAD_NONE ? 0 : _price.terraform);
|
||||
}
|
||||
|
||||
*pieces |= (RoadBits)((*pieces & 0xC) >> 2);
|
||||
*pieces |= (RoadBits)((*pieces & 0x3) << 2);
|
||||
/* Force straight roads. */
|
||||
*pieces |= MirrorRoadBits(*pieces);
|
||||
|
||||
/* partly leveled up tile, only if there's no road on that tile */
|
||||
if ((existing == 0 || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) {
|
||||
/* force full pieces. */
|
||||
if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) {
|
||||
if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform;
|
||||
}
|
||||
return CMD_ERROR;
|
||||
@ -1182,8 +1233,8 @@ static void TileLoop_Road(TileIndex tile)
|
||||
|
||||
if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) return;
|
||||
|
||||
const Town* t = ClosestTownFromTile(tile, (uint)-1);
|
||||
if (!HasRoadWorks(tile)) {
|
||||
const Town* t = ClosestTownFromTile(tile, (uint)-1);
|
||||
int grp = 0;
|
||||
|
||||
if (t != NULL) {
|
||||
@ -1192,8 +1243,8 @@ static void TileLoop_Road(TileIndex tile)
|
||||
/* Show an animation to indicate road work */
|
||||
if (t->road_build_months != 0 &&
|
||||
(DistanceManhattan(t->xy, tile) < 8 || grp != 0) &&
|
||||
GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) {
|
||||
if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) {
|
||||
GetRoadTileType(tile) == ROAD_TILE_NORMAL && COUNTBITS(GetAllRoadBits(tile)) > 1 ) {
|
||||
if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) {
|
||||
StartRoadWorks(tile);
|
||||
|
||||
SndPlayTileFx(SND_21_JACKHAMMER, tile);
|
||||
@ -1231,6 +1282,17 @@ static void TileLoop_Road(TileIndex tile)
|
||||
}
|
||||
} else if (IncreaseRoadWorksCounter(tile)) {
|
||||
TerminateRoadWorks(tile);
|
||||
|
||||
if (_patches.mod_road_rebuild) {
|
||||
/* Generate a nicer town surface */
|
||||
const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
|
||||
const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
|
||||
|
||||
if (old_rb != new_rb) {
|
||||
DoCommand(tile, (old_rb ^ new_rb), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_REMOVE_ROAD);
|
||||
}
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "strings.h"
|
||||
#include <list>
|
||||
|
||||
extern const uint16 SAVEGAME_VERSION = 76;
|
||||
extern const uint16 SAVEGAME_VERSION = 77;
|
||||
uint16 _sl_version; ///< the major savegame version identifier
|
||||
byte _sl_minor_version; ///< the minor savegame version, DO NOT USE!
|
||||
|
||||
|
@ -1438,6 +1438,7 @@ const SettingDesc _patch_settings[] = {
|
||||
SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0, 4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH, NULL),
|
||||
SDT_CONDVAR(Patches, larger_towns, SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL),
|
||||
SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0, 2, 1, 10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL),
|
||||
SDT_CONDBOOL(Patches, mod_road_rebuild, 77, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_MODIFIED_ROAD_REBUILD, NULL),
|
||||
|
||||
/***************************************************************************/
|
||||
/* AI section of the GUI-configure patches window */
|
||||
|
@ -672,7 +672,6 @@ static const char *_patches_construction[] = {
|
||||
"drag_signals_density",
|
||||
"oil_refinery_limit",
|
||||
"semaphore_build_before",
|
||||
"town_layout",
|
||||
};
|
||||
|
||||
static const char *_patches_stations[] = {
|
||||
@ -700,6 +699,8 @@ static const char *_patches_economy[] = {
|
||||
"ending_year",
|
||||
"smooth_economy",
|
||||
"allow_shares",
|
||||
"town_layout",
|
||||
"mod_road_rebuild",
|
||||
"town_growth_rate",
|
||||
"larger_towns",
|
||||
"initial_city_size",
|
||||
|
256
src/town_cmd.cpp
256
src/town_cmd.cpp
@ -132,18 +132,6 @@ static inline DiagDirection RandomDiagDir()
|
||||
return (DiagDirection)(3 & Random());
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a TileIndex into a diagonal direction.
|
||||
*
|
||||
* @param tile The current tile
|
||||
* @param dir The direction in which we want to step
|
||||
* @return the moved tile
|
||||
*/
|
||||
static inline TileIndex AddDiagDirToTileIndex(TileIndex tile, DiagDirection dir)
|
||||
{
|
||||
return TILE_ADD(tile, TileOffsByDiagDir(dir));
|
||||
}
|
||||
|
||||
/**
|
||||
* House Tile drawing handler.
|
||||
* Part of the tile loop process
|
||||
@ -661,7 +649,7 @@ static RoadBits GetTownRoadBits(TileIndex tile)
|
||||
*/
|
||||
static bool IsNeighborRoadTile(TileIndex tile, DiagDirection dir, uint dist_multi)
|
||||
{
|
||||
static TileIndexDiff tid_lt[3]; ///< lookup table for the used diff values
|
||||
static TileIndexDiff tid_lt[3]; // lookup table for the used diff values
|
||||
tid_lt[0] = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90RIGHT));
|
||||
tid_lt[1] = TileOffsByDiagDir(ChangeDiagDir(dir, DIAGDIRDIFF_90LEFT));
|
||||
tid_lt[2] = TileOffsByDiagDir(ReverseDiagDir(dir));
|
||||
@ -681,7 +669,7 @@ static bool IsNeighborRoadTile(TileIndex tile, DiagDirection dir, uint dist_mult
|
||||
cur += tid_lt[(pos & 1) ? 0 : 1];
|
||||
if (pos & 2) cur += tid_lt[2];
|
||||
|
||||
cur = (uint)(pos / 4) * cur; ///< Multiply for the fitting distance
|
||||
cur = (uint)(pos / 4) * cur; // Multiply for the fitting distance
|
||||
if (GetTownRoadBits(TILE_ADD(tile, cur)) & DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir))) return true;
|
||||
}
|
||||
return false;
|
||||
@ -797,7 +785,7 @@ static void LevelTownLand(TileIndex tile)
|
||||
static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile, DiagDirection dir)
|
||||
{
|
||||
/* align the grid to the downtown */
|
||||
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); ///< Vector from downtown to the tile
|
||||
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); // Vector from downtown to the tile
|
||||
RoadBits rcmd = ROAD_NONE;
|
||||
|
||||
switch (_patches.town_layout) {
|
||||
@ -849,32 +837,110 @@ static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile, DiagDirection di
|
||||
}
|
||||
|
||||
/**
|
||||
* Check there are enough neighbor house tiles next to the current tile
|
||||
* Grows the town with an extra house.
|
||||
* Check if there are enough neighbor house tiles
|
||||
* next to the current tile. If there are enough
|
||||
* add another house.
|
||||
*
|
||||
* @param tile current tile
|
||||
* @return true if there are more than 2 house tiles next
|
||||
* to the current one
|
||||
* @param t The current town
|
||||
* @param tile The target tile for the extra house
|
||||
* @return true if an extra house has been added
|
||||
*/
|
||||
static bool AreNeighborsHouseTiles(TileIndex tile)
|
||||
static bool GrowTownWithExtraHouse(Town *t, TileIndex tile)
|
||||
{
|
||||
uint counter = 0; ///< counts the house neighbor tiles
|
||||
|
||||
/* We can't look further than that. */
|
||||
if (TileX(tile) < 1 || TileY(tile) < 1) {
|
||||
return false;
|
||||
if (TileX(tile) < 2 || TileY(tile) < 2 || MapMaxX() <= TileX(tile) || MapMaxY() <= TileY(tile)) return false;
|
||||
|
||||
uint counter = 0; // counts the house neighbor tiles
|
||||
|
||||
/* Check the tiles E,N,W and S of the current tile for houses */
|
||||
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
|
||||
|
||||
if (IsTileType(TileAddByDiagDir(tile, dir), MP_HOUSE)) counter++;
|
||||
|
||||
/* If there are enough neighbors stop here */
|
||||
if (counter >= 3) {
|
||||
if (BuildTownHouse(t, tile)) {
|
||||
_grow_town_result = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the town with a road piece.
|
||||
*
|
||||
* @param t The current town
|
||||
* @param tile The current tile
|
||||
* @param rcmd The RoadBits we want to build on the tile
|
||||
* @return true if the RoadBits have been added else false
|
||||
*/
|
||||
static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd)
|
||||
{
|
||||
if (CmdSucceeded(DoCommand(tile, rcmd, t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) {
|
||||
_grow_town_result = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the town with a bridge.
|
||||
* At first we check if a bridge is reasonable.
|
||||
* If so we check if we are able to build it.
|
||||
*
|
||||
* @param t The current town
|
||||
* @param tile The current tile
|
||||
* @param rcmd The RoadBits which are possible on this tile
|
||||
* @return true if a bridge has been build else false
|
||||
*/
|
||||
static bool GrowTownWithBridge(const Town *t, TileIndex tile, RoadBits rcmd)
|
||||
{
|
||||
DiagDirection bridge_dir; // The direction of a bridge we maybe want to build
|
||||
|
||||
/* Determine direction of slope,
|
||||
* and build a road if not a special slope. */
|
||||
switch (GetTileSlope(tile, NULL)) {
|
||||
case SLOPE_SW: bridge_dir = DIAGDIR_NE; break;
|
||||
case SLOPE_SE: bridge_dir = DIAGDIR_NW; break;
|
||||
case SLOPE_NW: bridge_dir = DIAGDIR_SE; break;
|
||||
case SLOPE_NE: bridge_dir = DIAGDIR_SW; break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
|
||||
/* Check the tiles E,N,W and S of the current tile. */
|
||||
for (DiagDirection i = DIAGDIR_BEGIN; i < DIAGDIR_END; i++) {
|
||||
if (IsTileType(AddDiagDirToTileIndex(tile, i), MP_HOUSE)) {
|
||||
counter++;
|
||||
}
|
||||
/* Check if the bridge will be compatible to the RoadBits */
|
||||
if (!(rcmd & DiagDirToRoadBits(ReverseDiagDir(bridge_dir)))) return false;
|
||||
|
||||
/* If there are enougth neighbor's stop it here */
|
||||
if (counter >= 3) {
|
||||
/* We are in the right direction */
|
||||
uint32 bridge_length = 0; // This value stores the length of the possible bridge
|
||||
TileIndex bridge_tile = tile; // Used to store the other waterside
|
||||
|
||||
do {
|
||||
if (bridge_length++ >= 11) {
|
||||
/* Max 11 tile long bridges */
|
||||
return false;
|
||||
}
|
||||
bridge_tile = TILE_MASK(bridge_tile + TileOffsByDiagDir(bridge_dir));
|
||||
} while (IsClearWaterTile(bridge_tile));
|
||||
|
||||
/* no water tiles in between? */
|
||||
if (bridge_length == 1) return false;
|
||||
|
||||
for (uint8 times = 0; times <= 22; times++) {
|
||||
byte bridge_type = RandomRange(MAX_BRIDGES - 1);
|
||||
|
||||
/* Can we actually build the bridge? */
|
||||
if (CmdSucceeded(DoCommand(tile, bridge_tile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE))) {
|
||||
DoCommand(tile, bridge_tile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
_grow_town_result--;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* Quit if it selecting an appropiate bridge type fails a large number of times. */
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -882,25 +948,24 @@ static bool AreNeighborsHouseTiles(TileIndex tile)
|
||||
* Grows the given town.
|
||||
* There are at the moment 3 possible way's for
|
||||
* the town expansion:
|
||||
* @li Generate a random tile and check if there is a road allowed
|
||||
* @li TL_ORIGINAL
|
||||
* @li TL_BETTER_ROADS
|
||||
* @li Check if the town geometry allows a road and which one
|
||||
* @li TL_2X2_GRID
|
||||
* @li TL_3X3_GRID
|
||||
* @li Forbid roads, only build houses
|
||||
* @li TL_NO_ROADS
|
||||
* @li Generate a random tile and check if there is a road allowed
|
||||
* @li TL_ORIGINAL
|
||||
* @li TL_BETTER_ROADS
|
||||
* @li Check if the town geometry allows a road and which one
|
||||
* @li TL_2X2_GRID
|
||||
* @li TL_3X3_GRID
|
||||
* @li Forbid roads, only build houses
|
||||
* @li TL_NO_ROADS
|
||||
*
|
||||
* @param tile_ptr The current tile
|
||||
* @param cur_rb The current tiles RoadBits
|
||||
* @param target_dir The target road dir
|
||||
* @param t1 The current town
|
||||
*/
|
||||
static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town* t1)
|
||||
static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town *t1)
|
||||
{
|
||||
RoadBits rcmd = ROAD_NONE; ///< RoadBits for the road construction command
|
||||
TileIndex tmptile; ///< Dummy tile for various things
|
||||
TileIndex tile = *tile_ptr; ///< The main tile on which we base our growth
|
||||
RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command
|
||||
TileIndex tile = *tile_ptr; // The main tile on which we base our growth
|
||||
|
||||
TILE_ASSERT(tile);
|
||||
|
||||
@ -936,14 +1001,14 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||
do target_dir = RandomDiagDir(); while (target_dir == source_dir);
|
||||
}
|
||||
|
||||
if (!IsRoadAllowedHere(AddDiagDirToTileIndex(tile, target_dir), target_dir)) {
|
||||
if (!IsRoadAllowedHere(TileAddByDiagDir(tile, target_dir), target_dir)) {
|
||||
/* A road is not allowed to continue the randomized road,
|
||||
* return if the road we're trying to build is curved. */
|
||||
if (target_dir != ReverseDiagDir(source_dir)) return;
|
||||
|
||||
/* Return if neither side of the new road is a house */
|
||||
if (!IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) &&
|
||||
!IsTileType(AddDiagDirToTileIndex(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) {
|
||||
if (!IsTileType(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90RIGHT)), MP_HOUSE) &&
|
||||
!IsTileType(TileAddByDiagDir(tile, ChangeDiagDir(target_dir, DIAGDIRDIFF_90LEFT)), MP_HOUSE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -955,7 +1020,7 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (target_dir < (DiagDirection)5 && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) {
|
||||
} else if (target_dir < DIAGDIR_END && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) {
|
||||
/* Continue building on a partial road.
|
||||
* Should be allways OK, so we only generate
|
||||
* the fitting RoadBits */
|
||||
@ -978,8 +1043,7 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bool allow_house = false; ///< Value which decides if we want to construct a house
|
||||
TileIndex tmptile2; ///< Yet another dummy tile
|
||||
bool allow_house = false; // Value which decides if we want to construct a house
|
||||
|
||||
/* Reached a tunnel/bridge? Then continue at the other side of it. */
|
||||
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
||||
@ -997,10 +1061,10 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||
if (cur_rb & DiagDirToRoadBits(target_dir)) return;
|
||||
|
||||
/* This is the tile we will reach if we extend to this direction. */
|
||||
tmptile = AddDiagDirToTileIndex(tile, target_dir);
|
||||
TileIndex house_tile = TileAddByDiagDir(tile, target_dir); // position of a possible house
|
||||
|
||||
/* Don't walk into water. */
|
||||
if (IsClearWaterTile(tmptile)) return;
|
||||
if (IsClearWaterTile(house_tile)) return;
|
||||
|
||||
switch (_patches.town_layout) {
|
||||
default: NOT_REACHED();
|
||||
@ -1010,41 +1074,35 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||
break;
|
||||
|
||||
case TL_3X3_GRID: /* Use 2x2 grid afterwards! */
|
||||
/* Fill gap if house has enougth neighbors */
|
||||
tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir);
|
||||
if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) {
|
||||
_grow_town_result = -1;
|
||||
}
|
||||
GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir));
|
||||
/* FALL THROUGH */
|
||||
|
||||
case TL_2X2_GRID:
|
||||
rcmd = GetTownRoadGridElement(t1, tmptile, target_dir);
|
||||
rcmd = GetTownRoadGridElement(t1, house_tile, target_dir);
|
||||
allow_house = (rcmd == ROAD_NONE);
|
||||
break;
|
||||
|
||||
case TL_BETTER_ROADS: /* Use original afterwards! */
|
||||
/* Fill gap if house has enougth neighbors */
|
||||
tmptile2 = AddDiagDirToTileIndex(tmptile, target_dir);
|
||||
if (AreNeighborsHouseTiles(tmptile2) && BuildTownHouse(t1, tmptile2)) {
|
||||
_grow_town_result = -1;
|
||||
}
|
||||
GrowTownWithExtraHouse(t1, TileAddByDiagDir(house_tile, target_dir));
|
||||
/* FALL THROUGH */
|
||||
|
||||
case TL_ORIGINAL:
|
||||
/* Allow a house at the edge. 60% chance or
|
||||
* always ok if no road allowed. */
|
||||
rcmd = DiagDirToRoadBits(target_dir);
|
||||
allow_house = (!IsRoadAllowedHere(tmptile, target_dir) || CHANCE16(6, 10));
|
||||
allow_house = (!IsRoadAllowedHere(house_tile, target_dir) || CHANCE16(6, 10));
|
||||
break;
|
||||
}
|
||||
|
||||
if (allow_house) {
|
||||
/* Build a house, but not if there already is a house there. */
|
||||
if (!IsTileType(tmptile, MP_HOUSE)) {
|
||||
if (!IsTileType(house_tile, MP_HOUSE)) {
|
||||
/* Level the land if possible */
|
||||
LevelTownLand(tmptile);
|
||||
LevelTownLand(house_tile);
|
||||
|
||||
/* And build a house.
|
||||
* Set result to -1 if we managed to build it. */
|
||||
if (BuildTownHouse(t1, tmptile)) {
|
||||
if (BuildTownHouse(t1, house_tile)) {
|
||||
_grow_town_result = -1;
|
||||
}
|
||||
}
|
||||
@ -1057,51 +1115,13 @@ static void GrowTownInTile(TileIndex* tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||
/* Return if a water tile */
|
||||
if (IsClearWaterTile(tile)) return;
|
||||
|
||||
DiagDirection bridge_dir; ///< The direction of a bridge we maybe want to build
|
||||
/* Determine direction of slope,
|
||||
* and build a road if not a special slope. */
|
||||
switch (GetTileSlope(tile, NULL)) {
|
||||
case SLOPE_SW: bridge_dir = DIAGDIR_NE; break;
|
||||
case SLOPE_SE: bridge_dir = DIAGDIR_NW; break;
|
||||
case SLOPE_NW: bridge_dir = DIAGDIR_SE; break;
|
||||
case SLOPE_NE: bridge_dir = DIAGDIR_SW; break;
|
||||
/* Make the roads look nicer */
|
||||
rcmd = CleanUpRoadBits(tile, rcmd);
|
||||
if (rcmd == ROAD_NONE) return;
|
||||
|
||||
default:
|
||||
build_road_and_exit:
|
||||
if (CmdSucceeded(DoCommand(tile, rcmd, t1->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD))) {
|
||||
_grow_town_result = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (GrowTownWithBridge(t1, tile, rcmd)) return;
|
||||
|
||||
/* Check if the bridge is in the right direction */
|
||||
if (!(rcmd & DiagDirToRoadBits(bridge_dir))) goto build_road_and_exit;
|
||||
|
||||
/* We are in the right direction */
|
||||
uint32 bridge_length = 0; ///< This value stores the length of the possible bridge
|
||||
tmptile = tile; ///< Now we use this dummy to store the other waterside
|
||||
do {
|
||||
if (bridge_length++ >= 11) {
|
||||
/* Max 11 tile long bridges */
|
||||
goto build_road_and_exit;
|
||||
}
|
||||
tmptile = TILE_MASK(tmptile + TileOffsByDiagDir(bridge_dir));
|
||||
} while (IsClearWaterTile(tmptile));
|
||||
|
||||
/* no water tiles in between? */
|
||||
if (bridge_length == 1) goto build_road_and_exit;
|
||||
|
||||
for (uint times = 0; times <= 22; times++) {
|
||||
byte bridge_type = RandomRange(MAX_BRIDGES - 1);
|
||||
|
||||
/* Can we actually build the bridge? */
|
||||
if (CmdSucceeded(DoCommand(tile, tmptile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE))) {
|
||||
DoCommand(tile, tmptile, bridge_type | ((0x80 | ROADTYPES_ROAD) << 8), DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE);
|
||||
_grow_town_result = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Quit if it selecting an appropiate bridge type fails a large number of times. */
|
||||
GrowTownWithRoad(t1, tile, rcmd);
|
||||
}
|
||||
|
||||
/** Returns "growth" if a house was built, or no if the build failed.
|
||||
@ -1114,7 +1134,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile)
|
||||
/* Special case.
|
||||
* @see GrowTownInTile Check the else if
|
||||
*/
|
||||
DiagDirection target_dir = (DiagDirection)5; ///< The direction in which we want to extend the town
|
||||
DiagDirection target_dir = DIAGDIR_END; // The direction in which we want to extend the town
|
||||
|
||||
TILE_ASSERT(tile);
|
||||
|
||||
@ -1137,7 +1157,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile)
|
||||
}
|
||||
|
||||
do {
|
||||
RoadBits cur_rb = GetTownRoadBits(tile); ///< The RoadBits of the current tile
|
||||
RoadBits cur_rb = GetTownRoadBits(tile); // The RoadBits of the current tile
|
||||
|
||||
/* Try to grow the town from this point */
|
||||
GrowTownInTile(&tile, cur_rb, target_dir, t);
|
||||
@ -1151,7 +1171,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile)
|
||||
/* Select a random bit from the blockmask, walk a step
|
||||
* and continue the search from there. */
|
||||
do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir)));
|
||||
tile = AddDiagDirToTileIndex(tile, target_dir);
|
||||
tile = TileAddByDiagDir(tile, target_dir);
|
||||
|
||||
if (IsTileType(tile, MP_ROAD)) {
|
||||
/* Don't allow building over roads of other cities */
|
||||
@ -1220,7 +1240,7 @@ static bool GrowTown(Town *t)
|
||||
PlayerID old_player = _current_player;
|
||||
_current_player = OWNER_TOWN;
|
||||
|
||||
TileIndex tile = t->xy; ///< The tile we are working with ATM
|
||||
TileIndex tile = t->xy; // The tile we are working with ATM
|
||||
|
||||
/* Find a road that we can base the construction on. */
|
||||
for (ptr = _town_coord_mod; ptr != endof(_town_coord_mod); ++ptr) {
|
||||
@ -2110,8 +2130,8 @@ static void UpdateTownGrowRate(Town *t)
|
||||
/** Towns are processed every TOWN_GROWTH_FREQUENCY ticks, and this is the
|
||||
* number of times towns are processed before a new building is built. */
|
||||
static const uint16 _grow_count_values[2][6] = {
|
||||
{ 120, 120, 120, 100, 80, 60 }, ///< Fund new buildings has been activated
|
||||
{ 320, 420, 300, 220, 160, 100 } ///< Normal values
|
||||
{ 120, 120, 120, 100, 80, 60 }, // Fund new buildings has been activated
|
||||
{ 320, 420, 300, 220, 160, 100 } // Normal values
|
||||
};
|
||||
|
||||
if (t->fund_buildings_months != 0) {
|
||||
@ -2252,9 +2272,9 @@ void ChangeTownRating(Town *t, int add, int max)
|
||||
/* penalty for removing town-owned stuff */
|
||||
static const int _default_rating_settings [3][3] = {
|
||||
/* ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE */
|
||||
{ 0, 128, 384}, ///< Permissive
|
||||
{ 48, 192, 480}, ///< Neutral
|
||||
{ 96, 384, 768}, ///< Hostile
|
||||
{ 0, 128, 384}, // Permissive
|
||||
{ 48, 192, 480}, // Neutral
|
||||
{ 96, 384, 768}, // Hostile
|
||||
};
|
||||
|
||||
bool CheckforTownRating(uint32 flags, Town *t, byte type)
|
||||
|
@ -242,6 +242,8 @@ struct Patches {
|
||||
bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days.
|
||||
|
||||
bool autoslope; ///< Allow terraforming under things.
|
||||
|
||||
bool mod_road_rebuild; ///< Roadworks remove unneccesary RoadBits
|
||||
};
|
||||
|
||||
VARDEF Patches _patches;
|
||||
|
Loading…
Reference in New Issue
Block a user