Skip to content

Commit

Permalink
Dungeongen: Add and improve parameters
Browse files Browse the repository at this point in the history
Add:
Bool for 'only_in_ground'.
Min and max corridor length.
Min and max room size with X, Y, Z components.
Min and max large room size with X, Y, Z components.

'only_in_ground = false' allows core mapgens to create structures
in air and water using dungeongen.
Corridor length parameters replace a fixed random range.
Room size parameters replace the former system where one parameter
'roomsize' was added to fixed random ranges.

All parameters are set for no change to current dungeon behaviour.

Remove some now-redundant and long-unused code.
  • Loading branch information
paramat committed Feb 26, 2017
1 parent 4d634ef commit a901a56
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 108 deletions.
94 changes: 45 additions & 49 deletions src/dungeongen.cpp
Expand Up @@ -52,6 +52,7 @@ DungeonGen::DungeonGen(INodeDefManager *ndef,
if (dparams) {
memcpy(&dp, dparams, sizeof(dp));
} else {
// Default dungeon parameters
dp.seed = 0;

dp.c_water = ndef->getId("mapgen_water_source");
Expand All @@ -63,14 +64,20 @@ DungeonGen::DungeonGen(INodeDefManager *ndef,
if (dp.c_river_water == CONTENT_IGNORE)
dp.c_river_water = ndef->getId("mapgen_water_source");

dp.diagonal_dirs = false;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0, 0, 0);
dp.rooms_min = 2;
dp.rooms_max = 16;
dp.y_min = -MAX_MAP_GENERATION_LIMIT;
dp.y_max = MAX_MAP_GENERATION_LIMIT;
dp.notifytype = GENNOTIFY_DUNGEON;
dp.diagonal_dirs = false;
dp.only_in_ground = true;
dp.holesize = v3s16(1, 2, 1);
dp.corridor_len_min = 1;
dp.corridor_len_max = 13;
dp.room_size_min = v3s16(4, 4, 4);
dp.room_size_max = v3s16(8, 6, 8);
dp.room_size_large_min = v3s16(8, 8, 8);
dp.room_size_large_max = v3s16(16, 16, 16);
dp.rooms_min = 2;
dp.rooms_max = 16;
dp.y_min = -MAX_MAP_GENERATION_LIMIT;
dp.y_max = MAX_MAP_GENERATION_LIMIT;
dp.notifytype = GENNOTIFY_DUNGEON;

dp.np_density = nparams_dungeon_density;
dp.np_alt_wall = nparams_dungeon_alt_wall;
Expand All @@ -97,16 +104,19 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax)
// Dungeon generator doesn't modify places which have this set
vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);

// Set all air and water to be untouchable
// to make dungeons open to caves and open air
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
u32 i = vm->m_area.index(nmin.X, y, z);
for (s16 x = nmin.X; x <= nmax.X; x++) {
content_t c = vm->m_data[i].getContent();
if (c == CONTENT_AIR || c == dp.c_water || c == dp.c_river_water)
vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
i++;
if (dp.only_in_ground) {
// Set all air and water to be untouchable
// to make dungeons open to caves and open air
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
u32 i = vm->m_area.index(nmin.X, y, z);
for (s16 x = nmin.X; x <= nmax.X; x++) {
content_t c = vm->m_data[i].getContent();
if (c == CONTENT_AIR || c == dp.c_water ||
c == dp.c_river_water)
vm->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
i++;
}
}
}
}
Expand Down Expand Up @@ -142,21 +152,25 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
v3s16 roomplace;

/*
Find place for first room
Find place for first room.
There is a 1 in 4 chance of the first room being 'large',
all other rooms are not 'large'.
*/
bool fits = false;
for (u32 i = 0; i < 100 && !fits; i++) {
bool is_large_room = ((random.next() & 3) == 1);
if (is_large_room) {
roomsize.Z = random.range(8, 16);
roomsize.Y = random.range(8, 16);
roomsize.X = random.range(8, 16);
roomsize.Z = random.range(
dp.room_size_large_min.Z, dp.room_size_large_max.Z);
roomsize.Y = random.range(
dp.room_size_large_min.Y, dp.room_size_large_max.Y);
roomsize.X = random.range(
dp.room_size_large_min.X, dp.room_size_large_max.X);
} else {
roomsize.Z = random.range(4, 8);
roomsize.Y = random.range(4, 6);
roomsize.X = random.range(4, 8);
roomsize.Z = random.range(dp.room_size_min.Z, dp.room_size_max.Z);
roomsize.Y = random.range(dp.room_size_min.Y, dp.room_size_max.Y);
roomsize.X = random.range(dp.room_size_min.X, dp.room_size_max.X);
}
roomsize += dp.roomsize;

// start_padding is used to disallow starting the generation of
// a dungeon in a neighboring generation chunk
Expand Down Expand Up @@ -246,10 +260,9 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir);

// Find a place for a random sized room
roomsize.Z = random.range(4, 8);
roomsize.Y = random.range(4, 6);
roomsize.X = random.range(4, 8);
roomsize += dp.roomsize;
roomsize.Z = random.range(dp.room_size_min.Z, dp.room_size_max.Z);
roomsize.Y = random.range(dp.room_size_min.Y, dp.room_size_max.Y);
roomsize.X = random.range(dp.room_size_min.X, dp.room_size_max.X);

m_pos = corridor_end;
m_dir = corridor_end_dir;
Expand Down Expand Up @@ -397,13 +410,8 @@ void DungeonGen::makeCorridor(v3s16 doorplace, v3s16 doordir,
makeHole(doorplace);
v3s16 p0 = doorplace;
v3s16 dir = doordir;
u32 length;
/*if (random.next() % 2)
length = random.range(1, 13);
else
length = random.range(1, 6);*/
length = random.range(1, 13);
u32 partlength = random.range(1, 13);
u32 length = random.range(dp.corridor_len_min, dp.corridor_len_max);
u32 partlength = random.range(dp.corridor_len_min, dp.corridor_len_max);
u32 partcount = 0;
s16 make_stairs = 0;

Expand Down Expand Up @@ -556,7 +564,6 @@ bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
continue;
v3s16 roomplace;
// X east, Z north, Y up
#if 1
if (doordir == v3s16(1, 0, 0)) // X+
roomplace = doorplace +
v3s16(0, -1, random.range(-roomsize.Z + 2, -2));
Expand All @@ -569,17 +576,6 @@ bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
if (doordir == v3s16(0, 0, -1)) // Z-
roomplace = doorplace +
v3s16(random.range(-roomsize.X + 2, -2), -1, -roomsize.Z + 1);
#endif
#if 0
if (doordir == v3s16(1, 0, 0)) // X+
roomplace = doorplace + v3s16(0, -1, -roomsize.Z / 2);
if (doordir == v3s16(-1, 0, 0)) // X-
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z / 2);
if (doordir == v3s16(0, 0, 1)) // Z+
roomplace = doorplace + v3s16(-roomsize.X / 2, -1, 0);
if (doordir == v3s16(0, 0, -1)) // Z-
roomplace = doorplace + v3s16(-roomsize.X / 2, -1, -roomsize.Z + 1);
#endif

// Check fit
bool fits = true;
Expand Down
8 changes: 7 additions & 1 deletion src/dungeongen.h
Expand Up @@ -48,8 +48,14 @@ struct DungeonParams {
content_t c_stair;

bool diagonal_dirs;
bool only_in_ground;
v3s16 holesize;
v3s16 roomsize;
u16 corridor_len_min;
u16 corridor_len_max;
v3s16 room_size_min;
v3s16 room_size_max;
v3s16 room_size_large_min;
v3s16 room_size_large_max;
u16 rooms_min;
u16 rooms_max;
s16 y_min;
Expand Down
80 changes: 47 additions & 33 deletions src/mapgen.cpp
Expand Up @@ -845,47 +845,61 @@ void MapgenBasic::generateDungeons(s16 max_stone_y, MgStoneType stone_type)

DungeonParams dp;

dp.seed = seed;
dp.c_water = c_water_source;
dp.c_river_water = c_river_water_source;
dp.rooms_min = 2;
dp.rooms_max = 16;
dp.y_min = -MAX_MAP_GENERATION_LIMIT;
dp.y_max = MAX_MAP_GENERATION_LIMIT;
dp.np_density = nparams_dungeon_density;
dp.np_alt_wall = nparams_dungeon_alt_wall;
dp.seed = seed;
dp.c_water = c_water_source;
dp.c_river_water = c_river_water_source;

dp.only_in_ground = true;
dp.corridor_len_min = 1;
dp.corridor_len_max = 13;
dp.rooms_min = 2;
dp.rooms_max = 16;
dp.y_min = -MAX_MAP_GENERATION_LIMIT;
dp.y_max = MAX_MAP_GENERATION_LIMIT;

dp.np_density = nparams_dungeon_density;
dp.np_alt_wall = nparams_dungeon_alt_wall;

switch (stone_type) {
default:
case MGSTONE_STONE:
dp.c_wall = c_cobble;
dp.c_alt_wall = c_mossycobble;
dp.c_stair = c_stair_cobble;

dp.diagonal_dirs = false;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0, 0, 0);
dp.notifytype = GENNOTIFY_DUNGEON;
dp.c_wall = c_cobble;
dp.c_alt_wall = c_mossycobble;
dp.c_stair = c_stair_cobble;

dp.diagonal_dirs = false;
dp.holesize = v3s16(1, 2, 1);
dp.room_size_min = v3s16(4, 4, 4);
dp.room_size_max = v3s16(8, 6, 8);
dp.room_size_large_min = v3s16(8, 8, 8);
dp.room_size_large_max = v3s16(16, 16, 16);
dp.notifytype = GENNOTIFY_DUNGEON;
break;
case MGSTONE_DESERT_STONE:
dp.c_wall = c_desert_stone;
dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_desert_stone;

dp.diagonal_dirs = true;
dp.holesize = v3s16(2, 3, 2);
dp.roomsize = v3s16(2, 5, 2);
dp.notifytype = GENNOTIFY_TEMPLE;
dp.c_wall = c_desert_stone;
dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_desert_stone;

dp.diagonal_dirs = true;
dp.holesize = v3s16(2, 3, 2);
dp.room_size_min = v3s16(6, 9, 6);
dp.room_size_max = v3s16(10, 11, 10);
dp.room_size_large_min = v3s16(10, 13, 10);
dp.room_size_large_max = v3s16(18, 21, 18);
dp.notifytype = GENNOTIFY_TEMPLE;
break;
case MGSTONE_SANDSTONE:
dp.c_wall = c_sandstonebrick;
dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_sandstonebrick;

dp.diagonal_dirs = false;
dp.holesize = v3s16(2, 2, 2);
dp.roomsize = v3s16(2, 0, 2);
dp.notifytype = GENNOTIFY_DUNGEON;
dp.c_wall = c_sandstonebrick;
dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_sandstonebrick;

dp.diagonal_dirs = false;
dp.holesize = v3s16(2, 2, 2);
dp.room_size_min = v3s16(6, 4, 6);
dp.room_size_max = v3s16(10, 6, 10);
dp.room_size_large_min = v3s16(10, 8, 10);
dp.room_size_large_max = v3s16(18, 16, 18);
dp.notifytype = GENNOTIFY_DUNGEON;
break;
}

Expand Down
63 changes: 38 additions & 25 deletions src/mapgen_v6.cpp
Expand Up @@ -564,34 +564,47 @@ void MapgenV6::makeChunk(BlockMakeData *data)
if ((flags & MG_DUNGEONS) && (stone_surface_max_y >= node_min.Y)) {
DungeonParams dp;

dp.seed = seed;
dp.c_water = c_water_source;
dp.c_river_water = c_water_source;
dp.rooms_min = 2;
dp.rooms_max = 16;
dp.y_min = -MAX_MAP_GENERATION_LIMIT;
dp.y_max = MAX_MAP_GENERATION_LIMIT;
dp.np_density = NoiseParams(0.9, 0.5, v3f(500.0, 500.0, 500.0), 0, 2, 0.8, 2.0);
dp.np_alt_wall = NoiseParams(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0);
dp.seed = seed;
dp.c_water = c_water_source;
dp.c_river_water = c_water_source;

dp.only_in_ground = true;
dp.corridor_len_min = 1;
dp.corridor_len_max = 13;
dp.rooms_min = 2;
dp.rooms_max = 16;
dp.y_min = -MAX_MAP_GENERATION_LIMIT;
dp.y_max = MAX_MAP_GENERATION_LIMIT;

dp.np_density
= NoiseParams(0.9, 0.5, v3f(500.0, 500.0, 500.0), 0, 2, 0.8, 2.0);
dp.np_alt_wall
= NoiseParams(-0.4, 1.0, v3f(40.0, 40.0, 40.0), 32474, 6, 1.1, 2.0);

if (getBiome(0, v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
dp.c_wall = c_desert_stone;
dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_desert_stone;

dp.diagonal_dirs = true;
dp.holesize = v3s16(2, 3, 2);
dp.roomsize = v3s16(2, 5, 2);
dp.notifytype = GENNOTIFY_TEMPLE;
dp.c_wall = c_desert_stone;
dp.c_alt_wall = CONTENT_IGNORE;
dp.c_stair = c_stair_desert_stone;

dp.diagonal_dirs = true;
dp.holesize = v3s16(2, 3, 2);
dp.room_size_min = v3s16(6, 9, 6);
dp.room_size_max = v3s16(10, 11, 10);
dp.room_size_large_min = v3s16(10, 13, 10);
dp.room_size_large_max = v3s16(18, 21, 18);
dp.notifytype = GENNOTIFY_TEMPLE;
} else {
dp.c_wall = c_cobble;
dp.c_alt_wall = c_mossycobble;
dp.c_stair = c_stair_cobble;

dp.diagonal_dirs = false;
dp.holesize = v3s16(1, 2, 1);
dp.roomsize = v3s16(0, 0, 0);
dp.notifytype = GENNOTIFY_DUNGEON;
dp.c_wall = c_cobble;
dp.c_alt_wall = c_mossycobble;
dp.c_stair = c_stair_cobble;

dp.diagonal_dirs = false;
dp.holesize = v3s16(1, 2, 1);
dp.room_size_min = v3s16(4, 4, 4);
dp.room_size_max = v3s16(8, 6, 8);
dp.room_size_large_min = v3s16(8, 8, 8);
dp.room_size_large_max = v3s16(16, 16, 16);
dp.notifytype = GENNOTIFY_DUNGEON;
}

DungeonGen dgen(ndef, &gennotify, &dp);
Expand Down

0 comments on commit a901a56

Please sign in to comment.