From 9a41a3d0f1b5f2bcd16b61122f6a34434fea7a7d Mon Sep 17 00:00:00 2001 From: paramat Date: Mon, 9 Oct 2017 20:13:10 +0100 Subject: [PATCH] Simple decorations: Make 'place_offset_y' usable with simple decorations Necessary for placing the base cube of 'plantlike_rooted' drawtype in the seabed instead of on it. Useful for placing decorations sunk into, or buried in, the ground. --- doc/lua_api.txt | 29 +++++++++++++++++------------ src/mg_decoration.cpp | 10 ++++++++-- src/mg_decoration.h | 2 +- src/script/lua_api/l_mapgen.cpp | 15 +++++++-------- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 63c4bea48..c93f06c8a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4814,20 +4814,19 @@ Definition tables y_min = -31000 y_max = 31000 -- ^ Lower and upper limits for decoration. - -- ^ This parameter refers to the `y` position of the decoration base, so - -- the actual maximum height would be `height_max + size.Y`. + -- ^ These parameters refer to the Y co-ordinate of the 'place_on' node. spawn_by = "default:water", -- ^ Node (or list of nodes) that the decoration only spawns next to. -- ^ Checks two horizontal planes of neighbouring nodes (including diagonal neighbours), - -- ^ one plane at Y = surface and one plane at Y = surface = + 1. + -- ^ one plane level with the 'place_on' node and a plane one node above that. num_spawn_by = 1, -- ^ Number of spawn_by nodes that must be surrounding the decoration position to occur. -- ^ If absent or -1, decorations occur next to any nodes. flags = "liquid_surface, force_placement", -- ^ Flags for all decoration types. - -- ^ "liquid_surface": Instead of placement on the highest solid surface - -- ^ in a mapchunk column, placement is on the highest liquid surface. - -- ^ Placement is disabled if solid nodes are found above the liquid surface. + -- ^ "liquid_surface": Instead of placement on the highest solid surface in + -- ^ a mapchunk column, placement is on the highest liquid surface. Placement + -- ^ is disabled if solid nodes are found above the liquid surface. -- ^ "force_placement": Nodes other than "air" and "ignore" are replaced by the decoration. ----- Simple-type parameters @@ -4835,17 +4834,23 @@ Definition tables -- ^ The node name used as the decoration. -- ^ If instead a list of strings, a randomly selected node from the list is placed as the decoration. height = 1, - -- ^ Number of nodes high the decoration is made. - -- ^ If height_max is not 0, this is the lower bound of the randomly selected height. + -- ^ Decoration height in nodes. + -- ^ If height_max is not 0, this is the lower limit of a randomly selected height. height_max = 0, - -- ^ Number of nodes the decoration can be at maximum. + -- ^ Upper limit of the randomly selected height. -- ^ If absent, the parameter 'height' is used as a constant. param2 = 0, - -- ^ Param2 value of placed decoration node. - -- ^ If param2_max is not 0, this is the lower bound of the randomly selected param2. + -- ^ Param2 value of decoration nodes. + -- ^ If param2_max is not 0, this is the lower limit of a randomly selected param2. param2_max = 0, - -- ^ Upper bound of the randomly selected param2. + -- ^ Upper limit of the randomly selected param2. -- ^ If absent, the parameter 'param2' is used as a constant. + place_offset_y = 0, + -- ^ Y offset of the decoration base node relative to the standard + -- ^ base node position for simple decorations. + -- ^ Can be positive or negative. Default is 0. + -- ^ Ignored by 'y_min', 'y_max' and 'spawn_by' checks, which always refer + -- ^ to the 'place_on' node. ----- Schematic-type parameters schematic = "foobar.mts", diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index cb4705177..ada37bab4 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -219,6 +219,10 @@ size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) if (c_decos.empty()) return 0; + // Check for a negative place_offset_y causing placement below the voxelmanip + if (p.Y + 1 + place_offset_y < vm->m_area.MinEdge.Y) + return 0; + if (!canPlaceDecoration(vm, p)) return 0; @@ -234,9 +238,10 @@ size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) const v3s16 &em = vm->m_area.getExtent(); u32 vi = vm->m_area.index(p); + vm->m_area.add_y(em, vi, place_offset_y); + for (int i = 0; i < height; i++) { vm->m_area.add_y(em, vi, 1); - content_t c = vm->m_data[vi].getContent(); if (c != CONTENT_AIR && c != CONTENT_IGNORE && !force_placement) @@ -251,7 +256,8 @@ size_t DecoSimple::generate(MMVManip *vm, PcgRandom *pr, v3s16 p) int DecoSimple::getHeight() { - return (deco_height_max > 0) ? deco_height_max : deco_height; + return ((deco_height_max > 0) ? deco_height_max : deco_height) + + place_offset_y; } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index b63e62eff..9295d1a20 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -69,6 +69,7 @@ public: NoiseParams np; std::vector c_spawnby; s16 nspawnby; + s16 place_offset_y = 0; std::unordered_set biomes; }; @@ -96,7 +97,6 @@ public: virtual int getHeight(); Rotation rotation; - s16 place_offset_y = 0; Schematic *schematic = nullptr; }; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index f475a8f7f..9ec4d5002 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -906,12 +906,13 @@ int ModApiMapgen::l_register_decoration(lua_State *L) return 0; } - deco->name = getstringfield_default(L, index, "name", ""); - deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); - deco->y_min = getintfield_default(L, index, "y_min", -31000); - deco->y_max = getintfield_default(L, index, "y_max", 31000); - deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); - deco->sidelen = getintfield_default(L, index, "sidelen", 8); + deco->name = getstringfield_default(L, index, "name", ""); + deco->fill_ratio = getfloatfield_default(L, index, "fill_ratio", 0.02); + deco->y_min = getintfield_default(L, index, "y_min", -31000); + deco->y_max = getintfield_default(L, index, "y_max", 31000); + deco->nspawnby = getintfield_default(L, index, "num_spawn_by", -1); + deco->place_offset_y = getintfield_default(L, index, "place_offset_y", 0); + deco->sidelen = getintfield_default(L, index, "sidelen", 8); if (deco->sidelen <= 0) { errorstream << "register_decoration: sidelen must be " "greater than 0" << std::endl; @@ -1024,8 +1025,6 @@ bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic deco->rotation = (Rotation)getenumfield(L, index, "rotation", ModApiMapgen::es_Rotation, ROTATE_0); - deco->place_offset_y = getintfield_default(L, index, "place_offset_y", 0); - StringMap replace_names; lua_getfield(L, index, "replacements"); if (lua_istable(L, -1))