diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 34738974a..b0c1b41a3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1073,57 +1073,62 @@ methods: ^ clear all objects in the environments - spawn_tree (pos, {treedef}) ^ spawns L-System tree at given pos with definition in treedef table - treedef={ - axiom, - string initial tree axiom - rules_a, - string rules set A - rules_b, - string rules set B - rules_c, - string rules set C - rules_d, - string rules set D - trunk, - string trunk node name - leaves, - string leaves node name - angle, - num angle in deg - iterations, - num max # of iterations, usually 2 -5 - random_level, - num factor to lower nr of iterations, usually 0 - 3 - thin_trunks, - boolean true -> use thin trunks - fruit_tree, - boolean true -> is a fruit tree - fruit - string fruit node name +treedef={ + axiom, - string initial tree axiom + rules_a, - string rules set A + rules_b, - string rules set B + rules_c, - string rules set C + rules_d, - string rules set D + trunk, - string trunk node name + leaves, - string leaves node name + leaves2, - string secondary leaves node name + leaves2_chance,- num chance (0-100) to replace leaves with leaves2 + angle, - num angle in deg + iterations, - num max # of iterations, usually 2 -5 + random_level, - num factor to lower nr of iterations, usually 0 - 3 + trunk_type, - string single/double/crossed) type of trunk: 1 node, 2x2 nodes or 3x3 in cross shape + thin_branches, - boolean true -> use thin (1 node) branches + fruit, - string fruit node name + fruit_chance, - num chance (0-100) to replace leaves with fruit node } - Key for Special L-System Symbols used in Axioms - G - move forward one unit with the pin down - F - move forward one unit with the pin up - A - replace with rules set A - B - replace with rules set B - C - replace with rules set C - D - replace with rules set D - a - replace with rules set A, chance 90% - b - replace with rules set B, chance 80% - c - replace with rules set C, chance 70% - d - replace with rules set D, chance 60% - + - yaw the turtle right by angle parameter - - - yaw the turtle left by angle parameter - & - pitch the turtle down by angle parameter - ^ - pitch the turtle up by angle parameter - / - roll the turtle to the right by angle parameter - * - roll the turtle to the left by angle parameter - [ - save in stack current state info - ] - recover from stack state info +Key for Special L-System Symbols used in Axioms + G - move forward one unit with the pen up + F - move forward one unit with the pen down drawing trunks and branches + f - move forward one unit with the pen down drawing leaves + A - replace with rules set A + B - replace with rules set B + C - replace with rules set C + D - replace with rules set D + a - replace with rules set A, chance 90% + b - replace with rules set B, chance 80% + c - replace with rules set C, chance 70% + d - replace with rules set D, chance 60% + + - yaw the turtle right by angle parameter + - - yaw the turtle left by angle parameter + & - pitch the turtle down by angle parameter + ^ - pitch the turtle up by angle parameter + / - roll the turtle to the right by angle parameter + * - roll the turtle to the left by angle parameter + [ - save in stack current state info + ] - recover from stack state info - Example usage: spawn small apple tree - apple_tree={ - axiom="FFFFFAFFBF", - rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]", - rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]", - trunk="default:tree", - leaves="default:leaves", - angle=30, - iterations=2, - random_level=0, - thin_trunks=true, - fruit_tree=true, - fruit="default:apple" +Example usage: spawn small apple tree +apple_tree={ + axiom="FFFFFAFFBF", + rules_a="[&&&FFFFF&&FFFF][&&&++++FFFFF&&FFFF][&&&----FFFFF&&FFFF]", + rules_b="[&&&++FFFFF&&FFFF][&&&--FFFFF&&FFFF][&&&------FFFFF&&FFFF]", + trunk="default:tree", + leaves="default:leaves", + angle=30, + iterations=2, + random_level=0, + trunk_type="single", + thin_branches=true, + fruit_chance=10, + fruit="default:apple" } - minetest.env:spawn_tree(pos,apple_tree) +minetest.env:spawn_tree(pos,apple_tree) Deprecated: - add_rat(pos): Add C++ rat object (no-op) diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 04f741ad3..60e5b55f4 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -4034,21 +4034,30 @@ private: getstringfield(L, 3, "axiom", tree_def.initial_axiom); getstringfield(L, 3, "rules_a", tree_def.rules_a); getstringfield(L, 3, "rules_b", tree_def.rules_b); - getstringfield(L, 3, "rules_c", tree_def.rules_a); - getstringfield(L, 3, "rules_d", tree_def.rules_b); + getstringfield(L, 3, "rules_c", tree_def.rules_c); + getstringfield(L, 3, "rules_d", tree_def.rules_d); getstringfield(L, 3, "trunk", trunk); tree_def.trunknode=ndef->getId(trunk); getstringfield(L, 3, "leaves", leaves); tree_def.leavesnode=ndef->getId(leaves); + tree_def.leaves2_chance=0; + getstringfield(L, 3, "leaves2", leaves); + if (leaves !="") + { + tree_def.leaves2node=ndef->getId(leaves); + getintfield(L, 3, "leaves2_chance", tree_def.leaves2_chance); + } getintfield(L, 3, "angle", tree_def.angle); getintfield(L, 3, "iterations", tree_def.iterations); getintfield(L, 3, "random_level", tree_def.iterations_random_level); - getboolfield(L, 3, "thin_trunks", tree_def.thin_trunks); - getboolfield(L, 3, "fruit_tree", tree_def.fruit_tree); - if (tree_def.fruit_tree) + getstringfield(L, 3, "trunk_type", tree_def.trunk_type); + getboolfield(L, 3, "thin_branches", tree_def.thin_branches); + tree_def.fruit_chance=0; + getstringfield(L, 3, "fruit", fruit); + if (fruit != "") { - getstringfield(L, 3, "fruit", fruit); tree_def.fruitnode=ndef->getId(fruit); + getintfield(L, 3, "fruit_chance",tree_def.fruit_chance); } } else diff --git a/src/treegen.cpp b/src/treegen.cpp index 54cee0fef..49f0666bc 100644 --- a/src/treegen.cpp +++ b/src/treegen.cpp @@ -118,7 +118,7 @@ void spawn_ltree (ServerEnvironment *env, v3s16 p0, INodeDefManager *ndef, TreeD core::map modified_blocks; ManualMapVoxelManipulator vmanip(map); v3s16 tree_blockp = getNodeBlockPos(p0); - vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); + vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,2,1)); make_ltree (vmanip, p0, ndef, tree_definition); vmanip.blitBackAll(&modified_blocks); @@ -221,7 +221,13 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd } //make sure tree is not floating in the air - if (tree_definition.thin_trunks == false) + if (tree_definition.trunk_type == "double") + { + make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); + make_tree_node_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode); + make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z+1),dirtnode); + } + if (tree_definition.trunk_type == "crossed") { make_tree_node_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); make_tree_node_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y-1,p0.Z+position.Z),dirtnode); @@ -233,8 +239,9 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd Key for Special L-System Symbols used in Axioms - G - move forward one unit with the pin down - F - move forward one unit with the pin up + G - move forward one unit with the pen up + F - move forward one unit with the pen down drawing trunks and branches + f - move forward one unit with the pen down drawing leaves A - replace with rules set A B - replace with rules set B C - replace with rules set C @@ -264,13 +271,21 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd switch (axiom_char) { case 'G': - dir = v3f(-1,0,0); + dir = v3f(1,0,0); dir = transposeMatrix(rotation,dir); position+=dir; break; case 'F': make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z),tree_definition); - if (tree_definition.thin_trunks == false) + if ((stack_orientation.empty() && tree_definition.trunk_type == "double") || + (!stack_orientation.empty() && tree_definition.trunk_type == "double" && !tree_definition.thin_branches)) + { + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition); + make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z+1),tree_definition); + } + if ((stack_orientation.empty() && tree_definition.trunk_type == "crossed") || + (!stack_orientation.empty() && tree_definition.trunk_type == "crossed" && !tree_definition.thin_branches)) { make_tree_trunk_placement(vmanip,v3f(p0.X+position.X+1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); make_tree_trunk_placement(vmanip,v3f(p0.X+position.X-1,p0.Y+position.Y,p0.Z+position.Z),tree_definition); @@ -295,6 +310,12 @@ void make_ltree(ManualMapVoxelManipulator &vmanip, v3s16 p0, INodeDefManager *nd dir = transposeMatrix(rotation,dir); position+=dir; break; + case 'f': + make_tree_leaves_placement(vmanip,v3f(p0.X+position.X,p0.Y+position.Y,p0.Z+position.Z),tree_definition); + dir = v3f(1,0,0); + dir = transposeMatrix(rotation,dir); + position+=dir; + break; // turtle commands case '[': stack_orientation.push(rotation); @@ -371,6 +392,9 @@ void make_tree_trunk_placement(ManualMapVoxelManipulator &vmanip, v3f p0, void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0, TreeDef &tree_definition) { + MapNode leavesnode=tree_definition.leavesnode; + if (myrand_range(1,100) > 100-tree_definition.leaves2_chance) + leavesnode=tree_definition.leaves2node; v3s16 p1 = v3s16(myround(p0.X),myround(p0.Y),myround(p0.Z)); if(vmanip.m_area.contains(p1) == false) return; @@ -378,15 +402,15 @@ void make_tree_leaves_placement(ManualMapVoxelManipulator &vmanip, v3f p0, if(vmanip.m_data[vi].getContent() != CONTENT_AIR && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) return; - if (tree_definition.fruit_tree) + if (tree_definition.fruit_chance>0) { - if (myrand_range(1,100) > 90+tree_definition.iterations) + if (myrand_range(1,100) > 100-tree_definition.fruit_chance) vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.fruitnode; else - vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; + vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; } else if (myrand_range(1,100) > 20) - vmanip.m_data[vmanip.m_area.index(p1)] = tree_definition.leavesnode; + vmanip.m_data[vmanip.m_area.index(p1)] = leavesnode; } irr::core::matrix4 setRotationAxisRadians(irr::core::matrix4 M, double angle, v3f axis) @@ -517,4 +541,4 @@ static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0, } #endif -}; // namespace treegen \ No newline at end of file +}; // namespace treegen diff --git a/src/treegen.h b/src/treegen.h index 62a220ee2..1435d6bb2 100644 --- a/src/treegen.h +++ b/src/treegen.h @@ -38,12 +38,15 @@ std::string rules_c; std::string rules_d; MapNode trunknode; MapNode leavesnode; +MapNode leaves2node; +int leaves2_chance; int angle; int iterations; int iterations_random_level; -bool thin_trunks; -bool fruit_tree; +std::string trunk_type; +bool thin_branches; MapNode fruitnode; +int fruit_chance; }; // Add default tree