mirror of https://github.com/OpenTTD/OpenTTD
(svn r12534) -Feature: Add a new type of town road layouts - random for each town
parent
4329223476
commit
584bbfd7e7
|
@ -1173,6 +1173,7 @@ STR_CONFIG_PATCHES_TOWN_LAYOUT_DEFAULT :default
|
||||||
STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS :better roads
|
STR_CONFIG_PATCHES_TOWN_LAYOUT_BETTER_ROADS :better roads
|
||||||
STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID :2x2 grid
|
STR_CONFIG_PATCHES_TOWN_LAYOUT_2X2_GRID :2x2 grid
|
||||||
STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID :3x3 grid
|
STR_CONFIG_PATCHES_TOWN_LAYOUT_3X3_GRID :3x3 grid
|
||||||
|
STR_CONFIG_PATCHES_TOWN_LAYOUT_RANDOM :random
|
||||||
|
|
||||||
STR_CONFIG_PATCHES_TOOLBAR_POS :{LTBLUE}Position of main toolbar: {ORANGE}{STRING1}
|
STR_CONFIG_PATCHES_TOOLBAR_POS :{LTBLUE}Position of main toolbar: {ORANGE}{STRING1}
|
||||||
STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT :Left
|
STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT :Left
|
||||||
|
|
49
src/town.h
49
src/town.h
|
@ -6,6 +6,7 @@
|
||||||
#define TOWN_H
|
#define TOWN_H
|
||||||
|
|
||||||
#include "oldpool.h"
|
#include "oldpool.h"
|
||||||
|
#include "core/bitmath_func.hpp"
|
||||||
#include "core/random_func.hpp"
|
#include "core/random_func.hpp"
|
||||||
#include "cargo_type.h"
|
#include "cargo_type.h"
|
||||||
#include "tile_type.h"
|
#include "tile_type.h"
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include "town_type.h"
|
#include "town_type.h"
|
||||||
#include "player_type.h"
|
#include "player_type.h"
|
||||||
#include "newgrf_string_type.h"
|
#include "newgrf_string_type.h"
|
||||||
|
#include "settings_type.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
HOUSE_NO_CLASS = 0,
|
HOUSE_NO_CLASS = 0,
|
||||||
|
@ -161,6 +163,9 @@ struct Town : PoolItem<Town, TownID, &_Town_pool> {
|
||||||
/* NOSAVE: The number of each type of building in the town. */
|
/* NOSAVE: The number of each type of building in the town. */
|
||||||
BuildingCounts building_counts;
|
BuildingCounts building_counts;
|
||||||
|
|
||||||
|
/* NOSAVE: The town specific road layout */
|
||||||
|
TownLayout layout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new town
|
* Creates a new town
|
||||||
*/
|
*/
|
||||||
|
@ -170,8 +175,21 @@ struct Town : PoolItem<Town, TownID, &_Town_pool> {
|
||||||
~Town();
|
~Town();
|
||||||
|
|
||||||
inline bool IsValid() const { return this->xy != 0; }
|
inline bool IsValid() const { return this->xy != 0; }
|
||||||
|
|
||||||
|
void InitializeLayout();
|
||||||
|
|
||||||
|
inline TownLayout GetActiveLayout() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current valid layout for the town
|
||||||
|
* @return the active layout for this town
|
||||||
|
*/
|
||||||
|
inline TownLayout Town::GetActiveLayout() const
|
||||||
|
{
|
||||||
|
return (_patches.town_layout == TL_RANDOM) ? this->layout : _patches.town_layout;
|
||||||
|
}
|
||||||
|
|
||||||
struct HouseSpec {
|
struct HouseSpec {
|
||||||
/* Standard properties */
|
/* Standard properties */
|
||||||
Year min_date; ///< introduction year of the house
|
Year min_date; ///< introduction year of the house
|
||||||
|
@ -314,7 +332,6 @@ extern const Town **_town_sort;
|
||||||
extern Town *_cleared_town;
|
extern Town *_cleared_town;
|
||||||
extern int _cleared_town_rating;
|
extern int _cleared_town_rating;
|
||||||
|
|
||||||
uint TileHash2Bit(uint x, uint y);
|
|
||||||
void ResetHouses();
|
void ResetHouses();
|
||||||
|
|
||||||
void ClearTownHouse(Town *t, TileIndex tile);
|
void ClearTownHouse(Town *t, TileIndex tile);
|
||||||
|
@ -327,4 +344,34 @@ void ChangeTownRating(Town *t, int add, int max);
|
||||||
HouseZonesBits GetTownRadiusGroup(const Town* t, TileIndex tile);
|
HouseZonesBits GetTownRadiusGroup(const Town* t, TileIndex tile);
|
||||||
void SetTownRatingTestMode(bool mode);
|
void SetTownRatingTestMode(bool mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a hash value from a tile position
|
||||||
|
*
|
||||||
|
* @param x The X coordinate
|
||||||
|
* @param y The Y coordinate
|
||||||
|
* @return The hash of the tile
|
||||||
|
*/
|
||||||
|
static inline uint TileHash(uint x, uint y)
|
||||||
|
{
|
||||||
|
uint hash = x >> 4;
|
||||||
|
hash ^= x >> 6;
|
||||||
|
hash ^= y >> 4;
|
||||||
|
hash -= y >> 6;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last two bits of the TileHash
|
||||||
|
* from a tile position.
|
||||||
|
*
|
||||||
|
* @see TileHash()
|
||||||
|
* @param x The X coordinate
|
||||||
|
* @param y The Y coordinate
|
||||||
|
* @return The last two bits from hash of the tile
|
||||||
|
*/
|
||||||
|
static inline uint TileHash2Bit(uint x, uint y)
|
||||||
|
{
|
||||||
|
return GB(TileHash(x, y), 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* TOWN_H */
|
#endif /* TOWN_H */
|
||||||
|
|
|
@ -107,6 +107,23 @@ Town::~Town()
|
||||||
this->xy = 0;
|
this->xy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random town road layout.
|
||||||
|
*
|
||||||
|
* The layout is based on the TileHash.
|
||||||
|
*/
|
||||||
|
void Town::InitializeLayout()
|
||||||
|
{
|
||||||
|
this->layout = (TownLayout)(TileHash(TileX(this->xy), TileY(this->xy)) % NUM_TLS);
|
||||||
|
|
||||||
|
/* Set invalid layouts to valid ones */
|
||||||
|
switch (this->layout) {
|
||||||
|
default: break;
|
||||||
|
case TL_RANDOM: this->layout = TL_ORIGINAL; break;
|
||||||
|
case TL_NO_ROADS: this->layout = TL_BETTER_ROADS; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Local
|
// Local
|
||||||
static int _grow_town_result;
|
static int _grow_town_result;
|
||||||
|
|
||||||
|
@ -129,23 +146,6 @@ static TownDrawTileProc * const _town_draw_tile_procs[1] = {
|
||||||
TownDrawHouseLift
|
TownDrawHouseLift
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate a hash value from a tile position
|
|
||||||
*
|
|
||||||
* @param x The X coordinate
|
|
||||||
* @param y The Y coordinate
|
|
||||||
* @return The hash of the tile
|
|
||||||
*/
|
|
||||||
uint TileHash2Bit(uint x, uint y)
|
|
||||||
{
|
|
||||||
uint hash = x >> 4;
|
|
||||||
hash ^= x >> 6;
|
|
||||||
hash ^= y >> 4;
|
|
||||||
hash -= y >> 6;
|
|
||||||
hash &= 3;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a random direction
|
* Return a random direction
|
||||||
*
|
*
|
||||||
|
@ -708,11 +708,12 @@ static bool IsNeighborRoadTile(TileIndex tile, const DiagDirection dir, uint dis
|
||||||
/**
|
/**
|
||||||
* Check if a Road is allowed on a given tile
|
* Check if a Road is allowed on a given tile
|
||||||
*
|
*
|
||||||
|
* @param t The current town
|
||||||
* @param tile The target tile
|
* @param tile The target tile
|
||||||
* @param dir The direction in which we want to extend the town
|
* @param dir The direction in which we want to extend the town
|
||||||
* @return true if it is allowed else false
|
* @return true if it is allowed else false
|
||||||
*/
|
*/
|
||||||
static bool IsRoadAllowedHere(TileIndex tile, DiagDirection dir)
|
static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir)
|
||||||
{
|
{
|
||||||
if (TileX(tile) < 2 || TileX(tile) >= MapMaxX() || TileY(tile) < 2 || TileY(tile) >= MapMaxY()) return false;
|
if (TileX(tile) < 2 || TileX(tile) >= MapMaxX() || TileY(tile) < 2 || TileY(tile) >= MapMaxY()) return false;
|
||||||
|
|
||||||
|
@ -733,7 +734,7 @@ static bool IsRoadAllowedHere(TileIndex tile, DiagDirection dir)
|
||||||
if (cur_slope == SLOPE_FLAT) {
|
if (cur_slope == SLOPE_FLAT) {
|
||||||
no_slope:
|
no_slope:
|
||||||
/* Tile has no slope */
|
/* Tile has no slope */
|
||||||
switch (_patches.town_layout) {
|
switch (t->GetActiveLayout()) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
case TL_ORIGINAL: // Disallow the road if any neighboring tile has a road (distance: 1)
|
case TL_ORIGINAL: // Disallow the road if any neighboring tile has a road (distance: 1)
|
||||||
|
@ -810,7 +811,7 @@ static RoadBits GetTownRoadGridElement(Town* t, TileIndex tile, DiagDirection di
|
||||||
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;
|
RoadBits rcmd = ROAD_NONE;
|
||||||
|
|
||||||
switch (_patches.town_layout) {
|
switch (t->GetActiveLayout()) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
case TL_2X2_GRID:
|
case TL_2X2_GRID:
|
||||||
|
@ -993,7 +994,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||||
LevelTownLand(tile);
|
LevelTownLand(tile);
|
||||||
|
|
||||||
/* Is a road allowed here? */
|
/* Is a road allowed here? */
|
||||||
switch (_patches.town_layout) {
|
switch (t1->GetActiveLayout()) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
case TL_NO_ROADS: /* Disallow Roads */
|
case TL_NO_ROADS: /* Disallow Roads */
|
||||||
|
@ -1007,7 +1008,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||||
|
|
||||||
case TL_BETTER_ROADS:
|
case TL_BETTER_ROADS:
|
||||||
case TL_ORIGINAL:
|
case TL_ORIGINAL:
|
||||||
if (!IsRoadAllowedHere(tile, target_dir)) return;
|
if (!IsRoadAllowedHere(t1, tile, target_dir)) return;
|
||||||
|
|
||||||
DiagDirection source_dir = ReverseDiagDir(target_dir);
|
DiagDirection source_dir = ReverseDiagDir(target_dir);
|
||||||
|
|
||||||
|
@ -1016,7 +1017,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||||
do target_dir = RandomDiagDir(); while (target_dir == source_dir);
|
do target_dir = RandomDiagDir(); while (target_dir == source_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsRoadAllowedHere(TileAddByDiagDir(tile, target_dir), target_dir)) {
|
if (!IsRoadAllowedHere(t1, TileAddByDiagDir(tile, target_dir), target_dir)) {
|
||||||
/* A road is not allowed to continue the randomized road,
|
/* A road is not allowed to continue the randomized road,
|
||||||
* return if the road we're trying to build is curved. */
|
* return if the road we're trying to build is curved. */
|
||||||
if (target_dir != ReverseDiagDir(source_dir)) return;
|
if (target_dir != ReverseDiagDir(source_dir)) return;
|
||||||
|
@ -1041,7 +1042,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||||
* the fitting RoadBits */
|
* the fitting RoadBits */
|
||||||
_grow_town_result = GROWTH_SEARCH_STOPPED;
|
_grow_town_result = GROWTH_SEARCH_STOPPED;
|
||||||
|
|
||||||
switch (_patches.town_layout) {
|
switch (t1->GetActiveLayout()) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
case TL_NO_ROADS: /* Disallow Roads */
|
case TL_NO_ROADS: /* Disallow Roads */
|
||||||
|
@ -1079,7 +1080,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||||
/* Don't walk into water. */
|
/* Don't walk into water. */
|
||||||
if (IsWaterTile(house_tile)) return;
|
if (IsWaterTile(house_tile)) return;
|
||||||
|
|
||||||
switch (_patches.town_layout) {
|
switch (t1->GetActiveLayout()) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
case TL_NO_ROADS:
|
case TL_NO_ROADS:
|
||||||
|
@ -1103,7 +1104,7 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
||||||
/* Allow a house at the edge. 60% chance or
|
/* Allow a house at the edge. 60% chance or
|
||||||
* always ok if no road allowed. */
|
* always ok if no road allowed. */
|
||||||
rcmd = DiagDirToRoadBits(target_dir);
|
rcmd = DiagDirToRoadBits(target_dir);
|
||||||
allow_house = (!IsRoadAllowedHere(house_tile, target_dir) || Chance16(6, 10));
|
allow_house = (!IsRoadAllowedHere(t1, house_tile, target_dir) || Chance16(6, 10));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,7 +1158,7 @@ static int GrowTownAtRoad(Town *t, TileIndex tile)
|
||||||
/* Number of times to search.
|
/* Number of times to search.
|
||||||
* Better roads, 2X2 and 3X3 grid grow quite fast so we give
|
* Better roads, 2X2 and 3X3 grid grow quite fast so we give
|
||||||
* them a little handicap. */
|
* them a little handicap. */
|
||||||
switch (_patches.town_layout) {
|
switch (t->GetActiveLayout()) {
|
||||||
case TL_BETTER_ROADS:
|
case TL_BETTER_ROADS:
|
||||||
_grow_town_result = 10 + t->num_houses * 2 / 9;
|
_grow_town_result = 10 + t->num_houses * 2 / 9;
|
||||||
break;
|
break;
|
||||||
|
@ -1447,6 +1448,8 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
|
||||||
UpdateTownVirtCoord(t);
|
UpdateTownVirtCoord(t);
|
||||||
_town_sort_dirty = true;
|
_town_sort_dirty = true;
|
||||||
|
|
||||||
|
t->InitializeLayout();
|
||||||
|
|
||||||
/* Random town size. */
|
/* Random town size. */
|
||||||
x = (Random() & 0xF) + 8;
|
x = (Random() & 0xF) + 8;
|
||||||
|
|
||||||
|
@ -1736,7 +1739,7 @@ static inline bool TownLayoutAllowsHouseHere(Town *t, TileIndex tile)
|
||||||
{
|
{
|
||||||
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile);
|
TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile);
|
||||||
|
|
||||||
switch (_patches.town_layout) {
|
switch (t->GetActiveLayout()) {
|
||||||
case TL_2X2_GRID:
|
case TL_2X2_GRID:
|
||||||
if ((grid_pos.x % 3) == 0 || (grid_pos.y % 3) == 0) return false;
|
if ((grid_pos.x % 3) == 0 || (grid_pos.y % 3) == 0) return false;
|
||||||
break;
|
break;
|
||||||
|
@ -1767,7 +1770,7 @@ static inline bool TownLayoutAllows2x2HouseHere(Town *t, TileIndex tile)
|
||||||
uint dx = MapSize() + TileX(t->xy) - TileX(tile);
|
uint dx = MapSize() + TileX(t->xy) - TileX(tile);
|
||||||
uint dy = MapSize() + TileY(t->xy) - TileY(tile);
|
uint dy = MapSize() + TileY(t->xy) - TileY(tile);
|
||||||
|
|
||||||
switch (_patches.town_layout) {
|
switch (t->GetActiveLayout()) {
|
||||||
case TL_2X2_GRID:
|
case TL_2X2_GRID:
|
||||||
if ((dx % 3) != 0 || (dy % 3) != 0) return false;
|
if ((dx % 3) != 0 || (dy % 3) != 0) return false;
|
||||||
break;
|
break;
|
||||||
|
@ -2700,6 +2703,9 @@ static void Load_TOWN()
|
||||||
void AfterLoadTown()
|
void AfterLoadTown()
|
||||||
{
|
{
|
||||||
_town_sort_dirty = true;
|
_town_sort_dirty = true;
|
||||||
|
|
||||||
|
Town *t;
|
||||||
|
FOR_ALL_TOWNS(t) t->InitializeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const ChunkHandler _town_chunk_handlers[] = {
|
extern const ChunkHandler _town_chunk_handlers[] = {
|
||||||
|
|
|
@ -66,6 +66,8 @@ enum TownLayout {
|
||||||
TL_2X2_GRID, ///< Geometric 2x2 grid algorithm
|
TL_2X2_GRID, ///< Geometric 2x2 grid algorithm
|
||||||
TL_3X3_GRID, ///< Geometric 3x3 grid algorithm
|
TL_3X3_GRID, ///< Geometric 3x3 grid algorithm
|
||||||
|
|
||||||
|
TL_RANDOM, ///< Random town layout
|
||||||
|
|
||||||
NUM_TLS, ///< Number of town layouts
|
NUM_TLS, ///< Number of town layouts
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue