Skip to content

Commit bbae8eb

Browse files
committed
Dungeongen: Create dungeon gen tuneables; add desert temples for Mapgen V6
1 parent a0dce51 commit bbae8eb

File tree

5 files changed

+158
-110
lines changed

5 files changed

+158
-110
lines changed

src/dungeongen.cpp

Lines changed: 84 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2929
#include "settings.h" // For g_settings
3030
#include "main.h" // For g_profiler
3131

32+
//#define DGEN_USE_TORCHES
33+
3234
NoiseParams nparams_dungeon_rarity =
3335
{0.0, 1.0, v3f(500.0, 500.0, 500.0), 0, 2, 0.8};
3436
NoiseParams nparams_dungeon_wetness =
@@ -40,42 +42,49 @@ NoiseParams nparams_dungeon_density =
4042
///////////////////////////////////////////////////////////////////////////////
4143

4244

43-
DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel) {
45+
DungeonGen::DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel,
46+
DungeonParams *dparams) {
4447
this->ndef = ndef;
4548
this->mapseed = seed;
4649
this->water_level = waterlevel;
50+
51+
#ifdef DGEN_USE_TORCHES
52+
c_torch = ndef->getId("default:torch");
53+
#endif
4754

48-
np_rarity = &nparams_dungeon_rarity;
49-
np_wetness = &nparams_dungeon_wetness;
50-
np_density = &nparams_dungeon_density;
51-
/*
52-
cid_water_source = ndef->getId("mapgen_water_source");
53-
cid_cobble = ndef->getId("mapgen_cobble");
54-
cid_mossycobble = ndef->getId("mapgen_mossycobble");
55-
cid_torch = ndef->getId("default:torch");
56-
*/
55+
if (dparams) {
56+
memcpy(&dp, dparams, sizeof(dp));
57+
} else {
58+
dp.c_water = ndef->getId("mapgen_water_source");
59+
dp.c_cobble = ndef->getId("mapgen_cobble");
60+
dp.c_moss = ndef->getId("mapgen_mossycobble");
61+
dp.c_stair = ndef->getId("mapgen_stair_cobble");
62+
63+
dp.diagonal_dirs = false;
64+
dp.mossratio = 3.0;
65+
dp.holesize = v3s16(1, 2, 1);
66+
dp.roomsize = v3s16(0,0,0);
67+
68+
dp.np_rarity = nparams_dungeon_rarity;
69+
dp.np_wetness = nparams_dungeon_wetness;
70+
dp.np_density = nparams_dungeon_density;
71+
}
5772
}
5873

5974

6075
void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
61-
v3s16 nmin, v3s16 nmax) {
76+
v3s16 nmin, v3s16 nmax) {
6277
//TimeTaker t("gen dungeons");
6378
int approx_groundlevel = 10 + water_level;
6479

6580
if ((nmin.Y + nmax.Y) / 2 >= approx_groundlevel ||
66-
NoisePerlin3D(np_rarity, nmin.X, nmin.Y, nmin.Z, mapseed) < 0.2)
81+
NoisePerlin3D(&dp.np_rarity, nmin.X, nmin.Y, nmin.Z, mapseed) < 0.2)
6782
return;
6883

6984
this->vmanip = vm;
7085
this->blockseed = bseed;
7186
random.seed(bseed + 2);
7287

73-
cid_water_source = ndef->getId("mapgen_water_source");
74-
cid_cobble = ndef->getId("mapgen_cobble");
75-
cid_mossycobble = ndef->getId("mapgen_mossycobble");
76-
//cid_torch = ndef->getId("default:torch");
77-
cid_cobblestair = ndef->getId("mapgen_stair_cobble");
78-
7988
// Dungeon generator doesn't modify places which have this set
8089
vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
8190

@@ -86,7 +95,7 @@ void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
8695
u32 i = vmanip->m_area.index(nmin.X, y, z);
8796
for (s16 x = nmin.X; x <= nmax.X; x++) {
8897
content_t c = vmanip->m_data[i].getContent();
89-
if (c == CONTENT_AIR || c == cid_water_source)
98+
if (c == CONTENT_AIR || c == dp.c_water)
9099
vmanip->m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
91100
i++;
92101
}
@@ -95,17 +104,18 @@ void DungeonGen::generate(ManualMapVoxelManipulator *vm, u32 bseed,
95104

96105
// Add it
97106
makeDungeon(v3s16(1,1,1) * MAP_BLOCKSIZE);
98-
107+
99108
// Convert some cobble to mossy cobble
100-
for (s16 z = nmin.Z; z <= nmax.Z; z++) {
109+
if (dp.mossratio != 0.0) {
110+
for (s16 z = nmin.Z; z <= nmax.Z; z++)
101111
for (s16 y = nmin.Y; y <= nmax.Y; y++) {
102112
u32 i = vmanip->m_area.index(nmin.X, y, z);
103113
for (s16 x = nmin.X; x <= nmax.X; x++) {
104-
if (vmanip->m_data[i].getContent() == cid_cobble) {
105-
float wetness = NoisePerlin3D(np_wetness, x, y, z, mapseed);
106-
float density = NoisePerlin3D(np_density, x, y, z, blockseed);
107-
if (density < wetness / 3.0)
108-
vmanip->m_data[i].setContent(cid_mossycobble);
114+
if (vmanip->m_data[i].getContent() == dp.c_cobble) {
115+
float wetness = NoisePerlin3D(&dp.np_wetness, x, y, z, mapseed);
116+
float density = NoisePerlin3D(&dp.np_density, x, y, z, blockseed);
117+
if (density < wetness / dp.mossratio)
118+
vmanip->m_data[i].setContent(dp.c_moss);
109119
}
110120
i++;
111121
}
@@ -132,7 +142,8 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
132142
roomsize = is_large_room ?
133143
v3s16(random.range(8, 16),random.range(8, 16),random.range(8, 16)) :
134144
v3s16(random.range(4, 8),random.range(4, 6),random.range(4, 8));
135-
145+
roomsize += dp.roomsize;
146+
136147
// start_padding is used to disallow starting the generation of
137148
// a dungeon in a neighboring generation chunk
138149
roomplace = vmanip->m_area.MinEdge + start_padding + v3s16(
@@ -184,8 +195,10 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
184195

185196
v3s16 room_center = roomplace + v3s16(roomsize.X / 2, 1, roomsize.Z / 2);
186197

198+
#ifdef DGEN_USE_TORCHES
187199
// Place torch at room center (for testing)
188-
//vmanip->m_data[vmanip->m_area.index(room_center)] = MapNode(cid_torch);
200+
vmanip->m_data[vmanip->m_area.index(room_center)] = MapNode(c_torch);
201+
#endif
189202

190203
// Quit if last room
191204
if (i == room_count - 1)
@@ -231,6 +244,8 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
231244

232245
// Find a place for a random sized room
233246
roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
247+
roomsize += dp.roomsize;
248+
234249
m_pos = corridor_end;
235250
m_dir = corridor_end_dir;
236251
r = findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace);
@@ -250,7 +265,7 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
250265

251266
void DungeonGen::makeRoom(v3s16 roomsize, v3s16 roomplace)
252267
{
253-
MapNode n_cobble(cid_cobble);
268+
MapNode n_cobble(dp.c_cobble);
254269
MapNode n_air(CONTENT_AIR);
255270

256271
// Make +-X walls
@@ -361,16 +376,19 @@ void DungeonGen::makeFill(v3s16 place, v3s16 size,
361376

362377
void DungeonGen::makeHole(v3s16 place)
363378
{
364-
makeFill(place, v3s16(1, 2, 1), 0, MapNode(CONTENT_AIR),
365-
VMANIP_FLAG_DUNGEON_INSIDE);
379+
makeFill(place, dp.holesize, 0,
380+
MapNode(CONTENT_AIR), VMANIP_FLAG_DUNGEON_INSIDE);
366381
}
367382

368383

369384
void DungeonGen::makeDoor(v3s16 doorplace, v3s16 doordir)
370385
{
371386
makeHole(doorplace);
387+
388+
#ifdef DGEN_USE_TORCHES
372389
// Place torch (for testing)
373-
//vmanip->m_data[vmanip->m_area.index(doorplace)] = MapNode(cid_torch);
390+
vmanip->m_data[vmanip->m_area.index(doorplace)] = MapNode(c_torch);
391+
#endif
374392
}
375393

376394

@@ -401,30 +419,32 @@ void DungeonGen::makeCorridor(v3s16 doorplace,
401419
if (vmanip->m_area.contains(p) == true &&
402420
vmanip->m_area.contains(p + v3s16(0, 1, 0)) == true) {
403421
if (make_stairs) {
404-
makeFill(p + v3s16(-1, -1, -1), v3s16(3, 5, 3),
405-
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(cid_cobble), 0);
422+
makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 3, 2),
423+
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(dp.c_cobble), 0);
406424
makeHole(p);
407425
makeHole(p - dir);
408426

409427
// TODO: fix stairs code so it works 100% (quite difficult)
410428

411429
// exclude stairs from the bottom step
412-
if (((make_stairs == 1) && i != 0) ||
413-
((make_stairs == -1) && i != length - 1)) {
430+
// exclude stairs from diagonal steps
431+
if (((dir.X ^ dir.Z) & 1) &&
432+
(((make_stairs == 1) && i != 0) ||
433+
((make_stairs == -1) && i != length - 1))) {
414434
// rotate face 180 deg if making stairs backwards
415435
int facedir = dir_to_facedir(dir * make_stairs);
416436

417437
u32 vi = vmanip->m_area.index(p.X - dir.X, p.Y - 1, p.Z - dir.Z);
418-
if (vmanip->m_data[vi].getContent() == cid_cobble)
419-
vmanip->m_data[vi] = MapNode(cid_cobblestair, 0, facedir);
438+
if (vmanip->m_data[vi].getContent() == dp.c_cobble)
439+
vmanip->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
420440

421441
vi = vmanip->m_area.index(p.X, p.Y, p.Z);
422-
if (vmanip->m_data[vi].getContent() == cid_cobble)
423-
vmanip->m_data[vi] = MapNode(cid_cobblestair, 0, facedir);
442+
if (vmanip->m_data[vi].getContent() == dp.c_cobble)
443+
vmanip->m_data[vi] = MapNode(dp.c_stair, 0, facedir);
424444
}
425445
} else {
426-
makeFill(p + v3s16(-1, -1, -1), v3s16(3, 4, 3),
427-
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(cid_cobble), 0);
446+
makeFill(p + v3s16(-1, -1, -1), dp.holesize + v3s16(2, 2, 2),
447+
VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(dp.c_cobble), 0);
428448
makeHole(p);
429449
}
430450

@@ -469,8 +489,8 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
469489
randomizeDir();
470490
continue;
471491
}
472-
if (vmanip->getNodeNoExNoEmerge(p).getContent() == cid_cobble
473-
&& vmanip->getNodeNoExNoEmerge(p1).getContent() == cid_cobble)
492+
if (vmanip->getNodeNoExNoEmerge(p).getContent() == dp.c_cobble
493+
&& vmanip->getNodeNoExNoEmerge(p1).getContent() == dp.c_cobble)
474494
{
475495
// Found wall, this is a good place!
476496
result_place = p;
@@ -483,12 +503,12 @@ bool DungeonGen::findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
483503
Determine where to move next
484504
*/
485505
// Jump one up if the actual space is there
486-
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == cid_cobble
506+
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == dp.c_cobble
487507
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR
488508
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR)
489509
p += v3s16(0,1,0);
490510
// Jump one down if the actual space is there
491-
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == cid_cobble
511+
if (vmanip->getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == dp.c_cobble
492512
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR
493513
&& vmanip->getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR)
494514
p += v3s16(0,-1,0);
@@ -577,12 +597,25 @@ bool DungeonGen::findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
577597
}
578598

579599

580-
v3s16 rand_ortho_dir(PseudoRandom &random)
600+
v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs)
581601
{
582-
if (random.next() % 2 == 0)
583-
return random.next() % 2 ? v3s16(-1, 0, 0) : v3s16(1, 0, 0);
584-
else
585-
return random.next() % 2 ? v3s16(0, 0, -1) : v3s16(0, 0, 1);
602+
// Make diagonal directions somewhat rare
603+
if (diagonal_dirs && (random.next() % 4 == 0)) {
604+
v3s16 dir;
605+
int trycount = 0;
606+
607+
do {
608+
trycount++;
609+
dir = v3s16(random.next() % 3 - 1, 0, random.next() % 3 - 1);
610+
} while ((dir.X == 0 && dir.Z == 0) && trycount < 10);
611+
612+
return dir;
613+
} else {
614+
if (random.next() % 2 == 0)
615+
return random.next() % 2 ? v3s16(-1, 0, 0) : v3s16(1, 0, 0);
616+
else
617+
return random.next() % 2 ? v3s16(0, 0, -1) : v3s16(0, 0, 1);
618+
}
586619
}
587620

588621

src/dungeongen.h

Lines changed: 28 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,29 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3131
class ManualMapVoxelManipulator;
3232
class INodeDefManager;
3333

34-
v3s16 rand_ortho_dir(PseudoRandom &random);
34+
35+
v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs);
3536
v3s16 turn_xz(v3s16 olddir, int t);
3637
v3s16 random_turn(PseudoRandom &random, v3s16 olddir);
3738
int dir_to_facedir(v3s16 d);
3839

40+
41+
struct DungeonParams {
42+
content_t c_water;
43+
content_t c_cobble;
44+
content_t c_moss;
45+
content_t c_stair;
46+
47+
bool diagonal_dirs;
48+
float mossratio;
49+
v3s16 holesize;
50+
v3s16 roomsize;
51+
52+
NoiseParams np_rarity;
53+
NoiseParams np_wetness;
54+
NoiseParams np_density;
55+
};
56+
3957
class DungeonGen {
4058
public:
4159
u32 blockseed;
@@ -45,25 +63,17 @@ class DungeonGen {
4563
PseudoRandom random;
4664
v3s16 csize;
4765
s16 water_level;
48-
49-
NoiseParams *np_rarity;
50-
NoiseParams *np_wetness;
51-
NoiseParams *np_density;
52-
53-
content_t cid_water_source;
54-
content_t cid_cobble;
55-
content_t cid_mossycobble;
56-
content_t cid_torch;
57-
content_t cid_cobblestair;
66+
67+
content_t c_torch;
68+
DungeonParams dp;
5869

5970
//RoomWalker
6071
v3s16 m_pos;
6172
v3s16 m_dir;
6273

63-
DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel);
74+
DungeonGen(INodeDefManager *ndef, u64 seed, s16 waterlevel, DungeonParams *dparams);
6475
void generate(ManualMapVoxelManipulator *vm, u32 bseed,
65-
v3s16 full_node_min, v3s16 full_node_max);
66-
//void generate(v3s16 full_node_min, v3s16 full_node_max, u32 bseed);
76+
v3s16 full_node_min, v3s16 full_node_max);
6777

6878
void makeDungeon(v3s16 start_padding);
6979
void makeRoom(v3s16 roomsize, v3s16 roomplace);
@@ -79,50 +89,12 @@ class DungeonGen {
7989

8090
void randomizeDir()
8191
{
82-
m_dir = rand_ortho_dir(random);
83-
}
84-
};
85-
86-
class RoomWalker
87-
{
88-
public:
89-
90-
RoomWalker(VoxelManipulator &vmanip_, v3s16 pos, PseudoRandom &random,
91-
INodeDefManager *ndef):
92-
vmanip(vmanip_),
93-
m_pos(pos),
94-
m_random(random),
95-
m_ndef(ndef)
96-
{
97-
randomizeDir();
92+
m_dir = rand_ortho_dir(random, dp.diagonal_dirs);
9893
}
99-
100-
void randomizeDir()
101-
{
102-
m_dir = rand_ortho_dir(m_random);
103-
}
104-
105-
void setPos(v3s16 pos)
106-
{
107-
m_pos = pos;
108-
}
109-
110-
void setDir(v3s16 dir)
111-
{
112-
m_dir = dir;
113-
}
114-
115-
//bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir);
116-
//bool findPlaceForRoomDoor(v3s16 roomsize, v3s16 &result_doorplace,
117-
// v3s16 &result_doordir, v3s16 &result_roomplace);
118-
119-
private:
120-
VoxelManipulator &vmanip;
121-
v3s16 m_pos;
122-
v3s16 m_dir;
123-
PseudoRandom &m_random;
124-
INodeDefManager *m_ndef;
12594
};
12695

96+
extern NoiseParams nparams_dungeon_rarity;
97+
extern NoiseParams nparams_dungeon_wetness;
98+
extern NoiseParams nparams_dungeon_density;
12799

128100
#endif

0 commit comments

Comments
 (0)