Tune redwoods cabins and chunk heightmaps
This commit is contained in:
@@ -426,7 +426,7 @@ static int is_cabin_structure_block(uint16_t block) {
|
||||
return block == BLOCK_SPRUCE_PLANKS || block == BLOCK_OAK_PLANKS ||
|
||||
block == BLOCK_OAK_LOG_X || block == BLOCK_OAK_LOG_Z ||
|
||||
block == BLOCK_SPRUCE_LOG_X || block == BLOCK_SPRUCE_LOG_Z ||
|
||||
block == BLOCK_GLASS_PANE || block == BLOCK_SPRUCE_STAIRS_E || block == BLOCK_SPRUCE_STAIRS_W ||
|
||||
block == BLOCK_GLASS_PANE || block == BLOCK_GLASS || block == BLOCK_SPRUCE_STAIRS_E || block == BLOCK_SPRUCE_STAIRS_W ||
|
||||
block == BLOCK_LADDER_N || block == BLOCK_LADDER_S || block == BLOCK_LADDER_E || block == BLOCK_LADDER_W ||
|
||||
block == BLOCK_SPRUCE_DOOR_N_LOWER || block == BLOCK_SPRUCE_DOOR_N_UPPER ||
|
||||
block == BLOCK_SPRUCE_DOOR_S_LOWER || block == BLOCK_SPRUCE_DOOR_S_UPPER ||
|
||||
@@ -1442,41 +1442,37 @@ static void build_maple_ancient(worldgen_ctx *ctx, int x, int y, int z, int heig
|
||||
|
||||
static void build_redwood_titan(worldgen_ctx *ctx, int x, int y, int z, int height, rng_state *rng, block_list *out, const tree_archetype *arch) {
|
||||
(void)ctx;
|
||||
int extra = rng_range_inclusive(rng, 20, 32);
|
||||
int core_height = height + extra;
|
||||
if (core_height < 60) core_height = 60;
|
||||
if (y + core_height + 16 >= CHUNK_HEIGHT) {
|
||||
core_height = CHUNK_HEIGHT - y - 16;
|
||||
if (core_height < 40) core_height = 40;
|
||||
int core_height = height + rng_range_inclusive(rng, 2, 7);
|
||||
if (core_height < 30) core_height = 30;
|
||||
if (core_height > 44) core_height = 44;
|
||||
if (y + core_height + 10 >= CHUNK_HEIGHT) {
|
||||
core_height = CHUNK_HEIGHT - y - 10;
|
||||
if (core_height < 24) core_height = 24;
|
||||
}
|
||||
int taper_start = core_height - 12;
|
||||
int taper_start = core_height - 6;
|
||||
for (int dy = 0; dy < core_height; ++dy) {
|
||||
int radius = 3;
|
||||
if (dy > taper_start) radius = 2;
|
||||
if (dy > taper_start + 6) radius = 1;
|
||||
int radius = (dy >= taper_start) ? 0 : 1;
|
||||
for (int dx = -radius; dx <= radius; ++dx) {
|
||||
for (int dz = -radius; dz <= radius; ++dz) {
|
||||
if (radius >= 3 && abs(dx) == radius && abs(dz) == radius && dy > 4) continue;
|
||||
if (radius == 2 && abs(dx) == 2 && abs(dz) == 2 && dy > taper_start) continue;
|
||||
block_list_push(out, x + dx, y + dy, z + dz, (uint16_t)arch->log_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
int spire = 6 + rng_range_inclusive(rng, 0, 3);
|
||||
int spire = 3 + rng_range_inclusive(rng, 0, 2);
|
||||
place_log_column(x, y + core_height, z, spire, arch->log_block, out);
|
||||
int canopy_base = y + core_height - 6;
|
||||
for (int ring = 0; ring < 5; ++ring) {
|
||||
int radius = 6 - ring;
|
||||
for (int ring = 0; ring < 4; ++ring) {
|
||||
int radius = 4 - ring;
|
||||
if (radius < 2) radius = 2;
|
||||
place_leaf_circle(x, canopy_base + ring, z, radius, arch->leaf_block, rng, 0.1, out);
|
||||
place_leaf_circle(x, canopy_base + ring + 1, z, radius - 1, arch->leaf_block, rng, 0.18, out);
|
||||
}
|
||||
place_leaf_circle(x, canopy_base + 6, z, 2, arch->leaf_block, rng, 0.0, out);
|
||||
place_leaf_circle(x, canopy_base + 7, z, 1, arch->leaf_block, rng, 0.0, out);
|
||||
place_leaf_circle(x, canopy_base + 5, z, 2, arch->leaf_block, rng, 0.0, out);
|
||||
place_leaf_circle(x, canopy_base + 6, z, 1, arch->leaf_block, rng, 0.0, out);
|
||||
const int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int buttress_height = 4 + rng_range_inclusive(rng, 0, 3);
|
||||
for (int step = 0; step < 4; ++step) {
|
||||
int buttress_height = 3 + rng_range_inclusive(rng, 0, 2);
|
||||
for (int step = 0; step < 2; ++step) {
|
||||
int px = x + dirs[i][0] * (2 + step);
|
||||
int pz = z + dirs[i][1] * (2 + step);
|
||||
int stack = buttress_height - step;
|
||||
@@ -1488,10 +1484,10 @@ static void build_redwood_titan(worldgen_ctx *ctx, int x, int y, int z, int heig
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int branch_y = canopy_base - 3 - rng_range_inclusive(rng, 0, 3);
|
||||
int branch_len = 5 + rng_range_inclusive(rng, 0, 3);
|
||||
place_branch_span(x, branch_y, z, dirs[i][0], dirs[i][1], branch_len, 3, arch->log_block, arch->leaf_block, rng, out);
|
||||
int branch_len = 3 + rng_range_inclusive(rng, 0, 2);
|
||||
place_branch_span(x, branch_y, z, dirs[i][0], dirs[i][1], branch_len, 2, arch->log_block, arch->leaf_block, rng, out);
|
||||
}
|
||||
place_leaf_blob(x, canopy_base - 2, z, 5, 4, arch->leaf_block, rng, out);
|
||||
place_leaf_blob(x, canopy_base - 2, z, 4, 3, arch->leaf_block, rng, out);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
@@ -1540,7 +1536,7 @@ static void build_redwood_titan(worldgen_ctx *ctx, int x, int y, int z, int heig
|
||||
[TREE_OAK_ANCIENT] = {"oak_ancient", TREE_SPECIES_OAK, BLOCK_OAK_LOG, BLOCK_OAK_LEAVES, 12, 16, 6, 7, build_oak_ancient},
|
||||
[TREE_SPRUCE_ANCIENT] = {"spruce_ancient", TREE_SPECIES_SPRUCE, BLOCK_OAK_LOG, BLOCK_OAK_LEAVES, 12, 16, 5, 7, build_spruce_ancient},
|
||||
[TREE_MAPLE_ANCIENT] = {"maple_ancient", TREE_SPECIES_MAPLE, BLOCK_OAK_LOG, BLOCK_OAK_LEAVES, 11, 15, 6, 6, build_maple_ancient},
|
||||
[TREE_REDWOOD_TITAN] = {"redwood_titan", TREE_SPECIES_PINE, BLOCK_OAK_LOG, BLOCK_OAK_LEAVES, 70, 86, 7, 24, build_redwood_titan},
|
||||
[TREE_REDWOOD_TITAN] = {"redwood_titan", TREE_SPECIES_PINE, BLOCK_OAK_LOG, BLOCK_OAK_LEAVES, 28, 38, 4, 10, build_redwood_titan},
|
||||
};
|
||||
|
||||
static const int TREE_VARIANTS_OAK[] = {TREE_OAK_ROUND, TREE_OAK_SPRAWL, TREE_OAK_COLUMNAR, TREE_OAK_ANCIENT};
|
||||
@@ -1871,7 +1867,7 @@ static const cabin_blueprint CABIN_BLUEPRINTS[] = {
|
||||
BLOCK_OAK_LOG,
|
||||
BLOCK_SPRUCE_STAIRS_E,
|
||||
BLOCK_SPRUCE_STAIRS_W,
|
||||
BLOCK_GLASS_PANE,
|
||||
BLOCK_GLASS,
|
||||
BLOCK_STONE,
|
||||
0.04,
|
||||
0.25,
|
||||
@@ -1893,7 +1889,7 @@ static const cabin_blueprint CABIN_BLUEPRINTS[] = {
|
||||
BLOCK_OAK_LOG,
|
||||
BLOCK_SPRUCE_STAIRS_E,
|
||||
BLOCK_SPRUCE_STAIRS_W,
|
||||
BLOCK_GLASS_PANE,
|
||||
BLOCK_GLASS,
|
||||
BLOCK_STONE,
|
||||
0.05,
|
||||
0.3,
|
||||
@@ -1915,7 +1911,7 @@ static const cabin_blueprint CABIN_BLUEPRINTS[] = {
|
||||
BLOCK_OAK_LOG,
|
||||
BLOCK_SPRUCE_STAIRS_E,
|
||||
BLOCK_SPRUCE_STAIRS_W,
|
||||
BLOCK_GLASS_PANE,
|
||||
BLOCK_GLASS,
|
||||
BLOCK_STONE,
|
||||
0.04,
|
||||
0.22,
|
||||
@@ -1967,6 +1963,39 @@ static void mark_rect_occupancy(unsigned char occupancy[CHUNK_SIZE][CHUNK_SIZE],
|
||||
}
|
||||
}
|
||||
|
||||
static int cabin_site_height_range(const cabin_blueprint *bp, int chunk_origin_x, int chunk_origin_z,
|
||||
column_data columns[CHUNK_SIZE][CHUNK_SIZE],
|
||||
int center_x, int center_z, int padding,
|
||||
int *out_min_h, int *out_max_h) {
|
||||
int min_h = INT_MAX;
|
||||
int max_h = INT_MIN;
|
||||
for (size_t i = 0; i < bp->rect_count; ++i) {
|
||||
const cabin_rect *rect = &bp->rects[i];
|
||||
int rcx = center_x + rect->offset_x;
|
||||
int rcz = center_z + rect->offset_z;
|
||||
int x0 = rcx - rect->half_w - padding;
|
||||
int x1 = rcx + rect->half_w + padding;
|
||||
int z0 = rcz - rect->half_l - padding;
|
||||
int z1 = rcz + rect->half_l + padding;
|
||||
if (x0 < chunk_origin_x || x1 >= chunk_origin_x + CHUNK_SIZE) return 0;
|
||||
if (z0 < chunk_origin_z || z1 >= chunk_origin_z + CHUNK_SIZE) return 0;
|
||||
for (int wz = z0; wz <= z1; ++wz) {
|
||||
for (int wx = x0; wx <= x1; ++wx) {
|
||||
int lx = wx - chunk_origin_x;
|
||||
int lz = wz - chunk_origin_z;
|
||||
column_data col = columns[lx][lz];
|
||||
if (col.has_water && col.height < col.water_surface) return 0;
|
||||
if (col.height < min_h) min_h = col.height;
|
||||
if (col.height > max_h) max_h = col.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (min_h == INT_MAX) return 0;
|
||||
*out_min_h = min_h;
|
||||
*out_max_h = max_h;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void build_cabin_roof(const cabin_blueprint *bp, int chunk_x, int chunk_z, chunk_data *chunk,
|
||||
int rect_center_x, int rect_center_z, int half_w, int half_l,
|
||||
int roof_base_y, rng_state *rng) {
|
||||
@@ -2302,7 +2331,11 @@ static int try_place_cabin(worldgen_ctx *ctx, int chunk_x, int chunk_z, chunk_da
|
||||
}
|
||||
}
|
||||
if (min_h == INT_MAX) return 0;
|
||||
if (max_h - min_h > 3) return 0;
|
||||
if (max_h - min_h > 1) return 0;
|
||||
int pad_min_h = INT_MAX;
|
||||
int pad_max_h = INT_MIN;
|
||||
if (!cabin_site_height_range(bp, chunk_origin_x, chunk_origin_z, columns, center_x, center_z, 2, &pad_min_h, &pad_max_h)) return 0;
|
||||
if (pad_max_h - pad_min_h > 2) return 0;
|
||||
int base_floor_y = min_h + 1;
|
||||
if (base_floor_y + bp->wall_height * bp->stories + 6 >= CHUNK_HEIGHT) return 0;
|
||||
|
||||
@@ -2364,7 +2397,7 @@ static void generate_chunk_cabins(worldgen_ctx *ctx, int chunk_x, int chunk_z, c
|
||||
size_t blueprint_count = sizeof(CABIN_BLUEPRINTS) / sizeof(CABIN_BLUEPRINTS[0]);
|
||||
unsigned char occupancy[CHUNK_SIZE][CHUNK_SIZE];
|
||||
memset(occupancy, 0, sizeof(occupancy));
|
||||
int attempts = 1 + (rng_next_f64(&rng) < 0.2 ? 1 : 0);
|
||||
int attempts = 3 + (rng_next_f64(&rng) < 0.35 ? 1 : 0);
|
||||
while (attempts-- > 0) {
|
||||
const cabin_blueprint *bp = &CABIN_BLUEPRINTS[rng_range_inclusive(&rng, 0, (int)blueprint_count - 1)];
|
||||
int min_local_x = 2;
|
||||
@@ -2386,13 +2419,22 @@ static void generate_chunk_cabins(worldgen_ctx *ctx, int chunk_x, int chunk_z, c
|
||||
int best_local_x = min_local_x;
|
||||
int best_local_z = min_local_z;
|
||||
double best_score = -1e9;
|
||||
const int samples = 12;
|
||||
const int samples = 24;
|
||||
for (int s = 0; s < samples; ++s) {
|
||||
int local_cx = rng_range_inclusive(&rng, min_local_x, max_local_x);
|
||||
int local_cz = rng_range_inclusive(&rng, min_local_z, max_local_z);
|
||||
int world_cx = chunk_x * CHUNK_SIZE + local_cx;
|
||||
int world_cz = chunk_z * CHUNK_SIZE + local_cz;
|
||||
double score = land_value(ctx, world_cx, world_cz);
|
||||
int flat_min_h = INT_MAX;
|
||||
int flat_max_h = INT_MIN;
|
||||
if (!cabin_site_height_range(bp, chunk_x * CHUNK_SIZE, chunk_z * CHUNK_SIZE, columns,
|
||||
world_cx, world_cz, 2, &flat_min_h, &flat_max_h)) {
|
||||
continue;
|
||||
}
|
||||
int flat_range = flat_max_h - flat_min_h;
|
||||
if (flat_range > 3) continue;
|
||||
score += 1.2 - (double)flat_range * 0.45;
|
||||
if (ctx->enable_trails) {
|
||||
double dist2 = nearest_trail_distance2(ctx, world_cx, world_cz, 1.0e12);
|
||||
double bonus = 0.0;
|
||||
@@ -3414,11 +3456,10 @@ void worldgen_generate_chunk(worldgen_ctx *ctx, int chunk_x, int chunk_z, chunk_
|
||||
}
|
||||
}
|
||||
|
||||
generate_chunk_cabins(ctx, chunk_x, chunk_z, columns, out);
|
||||
if (ctx->enable_trails) {
|
||||
generate_chunk_trails(ctx, chunk_x, chunk_z, columns, out);
|
||||
}
|
||||
|
||||
generate_chunk_cabins(ctx, chunk_x, chunk_z, columns, out);
|
||||
generate_chunk_redwood_floor(ctx, chunk_x, chunk_z, columns, out);
|
||||
generate_chunk_grass(ctx, chunk_x, chunk_z, columns, out);
|
||||
generate_chunk_flowers(ctx, chunk_x, chunk_z, columns, out);
|
||||
|
||||
Reference in New Issue
Block a user