Compare commits
370 commits
Author | SHA1 | Date | |
---|---|---|---|
|
133e66ad38 | ||
|
f1f0abcc16 | ||
|
2186b24632 | ||
|
bdca26220d | ||
|
297b41a055 | ||
|
b568e8b96f | ||
|
1e78532144 | ||
|
6cb7f1da1d | ||
|
e5e7475476 | ||
|
3f8a2de971 | ||
|
b3c4e26027 | ||
|
d0149162c0 | ||
|
be7d7a1976 | ||
|
77a6129e00 | ||
|
5ae6e9f89c | ||
|
678b025cb0 | ||
|
f182dd902a | ||
|
3244b2f1ff | ||
|
f91d3d1070 | ||
|
2bbf9ab957 | ||
|
232fac6361 | ||
|
e64d458359 | ||
|
7c0b4affe5 | ||
|
35e52b1a7b | ||
|
04ecb1bd5c | ||
|
5f3d97ab0c | ||
|
c1c60d1f8b | ||
|
a0fa05a60f | ||
|
8eab778a39 | ||
|
fb45d350b3 | ||
|
2f9d41c11e | ||
|
cbf8994755 | ||
|
323bf1d0ca | ||
|
8f4c8f7668 | ||
|
366a2125b8 | ||
|
4141dce691 | ||
|
ab1fc810a9 | ||
|
69feb6f994 | ||
|
aa379d0701 | ||
|
2ae0d2f2a1 | ||
|
3fe63e8fd8 | ||
|
0405fb8448 | ||
|
8817fd38d6 | ||
|
2270e87a71 | ||
|
61c3cb0edd | ||
|
5abe211fb6 | ||
|
138858c2a2 | ||
|
92bb8a6c8e | ||
|
aefc390cc9 | ||
|
4575c5c0e6 | ||
|
dfddba270c | ||
|
9c121b4c09 | ||
|
7b6de7195c | ||
|
6119dba871 | ||
|
df1e490a9e | ||
|
14774dfe3f | ||
|
26e671d600 | ||
|
394e5cd8c2 | ||
|
d32ca7788f | ||
|
10d8a0cc5c | ||
|
57ef1744c5 | ||
|
d5c3a8f971 | ||
|
5dba3b99ec | ||
|
52d4311071 | ||
|
e9765fabfc | ||
|
212511b754 | ||
|
8e7e1f2d46 | ||
|
a1a5fb0a7f | ||
|
b2c104d53a | ||
|
ae0886a397 | ||
|
ee4ca10d61 | ||
|
538243d697 | ||
|
01cef3d1bd | ||
|
193ad7e7ac | ||
|
357be42a0a | ||
|
812dcca7b9 | ||
|
89627afc78 | ||
|
39a38703a8 | ||
|
de4d2b7b52 | ||
|
ae3e8eff08 | ||
|
1648bc459f | ||
|
bf26b8bee1 | ||
|
aa999e2ed5 | ||
|
e1e7745a15 | ||
|
9efa81d1fe | ||
|
ddd97bc66a | ||
|
73354d3a96 | ||
|
28c3d82cfa | ||
|
6daa9ee815 | ||
|
992fdbf9e9 | ||
|
b138bad822 | ||
|
05dab8ff81 | ||
|
410259de35 | ||
|
b6e66def05 | ||
|
dd81a5777a | ||
|
e6a1a158ed | ||
|
1caf0fba61 | ||
|
8eedc5afc3 | ||
|
4ad818a922 | ||
|
278bfadb17 | ||
|
eb6b544926 | ||
|
a5906f635b | ||
|
34ffc77540 | ||
|
4ed95b93af | ||
|
159083227d | ||
|
534d48a0bd | ||
|
4cfa301cea | ||
|
186abc20f3 | ||
|
d1fda5aa30 | ||
|
fdc3a6ed19 | ||
|
5bb654be93 | ||
|
927c4b1f77 | ||
|
0d33ff5b0b | ||
|
c8c107b300 | ||
|
aa9c21bc93 | ||
|
d18e98bfa2 | ||
|
d820a49197 | ||
|
2e978e540c | ||
|
5763c4888e | ||
|
71b6f4b168 | ||
|
8d70e7a7cb | ||
|
14b38a868b | ||
|
f693268c75 | ||
|
518a8384fc | ||
|
5d2bdcdaba | ||
|
f75e5fe6e4 | ||
|
fcee06b6e1 | ||
|
419fc2f583 | ||
|
a23782fbf2 | ||
|
2248d65591 | ||
|
ededbd5a78 | ||
|
943977949b | ||
|
4a63066b7d | ||
|
0fd901dcca | ||
|
970dd3fab2 | ||
|
26622dd1dd | ||
|
4de7c7ab68 | ||
|
d033bcf7b5 | ||
|
801b11bf67 | ||
|
6286a4e829 | ||
|
70c39c6c0e | ||
|
7c6f09db63 | ||
|
91de8b0abf | ||
|
0b1e15bf4d | ||
|
ee590db95e | ||
|
1eb6658a15 | ||
|
396d149ab4 | ||
|
f44735e032 | ||
|
955d4db7ad | ||
|
e9ae30dfc9 | ||
|
b486af8627 | ||
|
e5005dd8d6 | ||
|
9a7f058659 | ||
|
d94847072f | ||
|
6a68d3c616 | ||
|
f860bfa6b7 | ||
|
925378daa1 | ||
|
dc1b4544c1 | ||
|
e2d29e0dd9 | ||
|
695316ea2a | ||
|
163d75ae74 | ||
|
e5395a69ff | ||
|
fb8fcab31a | ||
|
2e1a49cd6e | ||
|
ad330c2f9e | ||
|
ada9d80bc6 | ||
|
04ade2f8ff | ||
|
25ad0e3200 | ||
|
3c41fa6a3f | ||
|
c2ac5a93be | ||
|
6bea364511 | ||
|
eea51cd260 | ||
|
d1443e1d09 | ||
|
cca6f2ae1c | ||
|
09017179fc | ||
|
95c3acbe11 | ||
|
a8a058ac8b | ||
|
3938e81fe5 | ||
|
4704b4cf2b | ||
|
a0fac75def | ||
|
82f226a0aa | ||
|
fbcd651651 | ||
|
02337a1187 | ||
|
dffcc72cbd | ||
|
9333788d8e | ||
|
fc9e303c0c | ||
|
394b046bed | ||
|
5568b5c893 | ||
|
e43aa31279 | ||
|
fdd130c1a5 | ||
|
af524bf009 | ||
|
36af3b1d92 | ||
|
aac2db0da4 | ||
|
c8ad6d4fec | ||
|
99c9c18ed8 | ||
|
9325a474b5 | ||
|
3e3e0c17d6 | ||
|
1aebdf3b47 | ||
|
d29d7e4e0b | ||
|
7b157a1029 | ||
|
de4874c3ce | ||
|
ada2231dbf | ||
|
42916c4666 | ||
|
e6f482c9d5 | ||
|
f438090899 | ||
|
48847cc7e0 | ||
|
72efe71560 | ||
|
ef9e69eb07 | ||
|
d8c6550127 | ||
|
53b31526f4 | ||
|
d569dc3ce4 | ||
|
c5357b51fc | ||
|
abffeb54d9 | ||
|
3de24bde95 | ||
|
d8dbf6a4af | ||
|
ab14e3b2aa | ||
|
11c4a7d7d0 | ||
|
2b8b604162 | ||
|
3d57691431 | ||
|
50ce118087 | ||
|
9ef29d3feb | ||
|
1ddb0c02a7 | ||
|
f93da354d9 | ||
|
35c08b1aa4 | ||
|
67266afceb | ||
|
9193317ca6 | ||
|
04c6051e8a | ||
|
2aa15f20a9 | ||
|
6cbfcde873 | ||
|
6c764f0c3b | ||
|
fa86013731 | ||
|
37c7275a07 | ||
|
6a793059f2 | ||
|
17fc19f787 | ||
|
f1db3a156e | ||
|
306591f082 | ||
|
edd4baf418 | ||
|
0696a64673 | ||
|
4f66ec44bd | ||
|
cd42c129c3 | ||
|
508adfc281 | ||
|
09bbe2132b | ||
|
e5cd050121 | ||
|
3f0b5d08b2 | ||
|
9cb5aef679 | ||
|
3d6bc4451e | ||
|
68e8671235 | ||
|
99eb220fef | ||
|
48089a51c6 | ||
|
9034b560f1 | ||
|
d3480acde2 | ||
|
37a5474570 | ||
|
7ec0eae568 | ||
|
241fef9f79 | ||
|
e144b2b300 | ||
|
1da72bfa40 | ||
|
c4dd513d88 | ||
|
dc05865839 | ||
|
03f29b1cd8 | ||
|
30d5f9ce96 | ||
|
b5d48307cb | ||
|
ac2096246e | ||
|
f3393d36fc | ||
|
9fedc6c52a | ||
|
43176144f9 | ||
|
65a11345a8 | ||
|
8912eb85cd | ||
|
a6497392bd | ||
|
3ddce086ca | ||
|
e447a3f506 | ||
|
10bb057f61 | ||
|
d22195be27 | ||
|
f0aeb4855e | ||
|
fd2b4d8389 | ||
|
6296eafcd9 | ||
|
87c065153a | ||
|
5ea5f54a7d | ||
|
ca5b481ecd | ||
|
0f09bd5cc8 | ||
|
0c788eb537 | ||
|
0edc007f47 | ||
|
d7c16bbae9 | ||
|
35e6699a56 | ||
|
9bb660983e | ||
|
88fd2e6a1b | ||
|
858130fb88 | ||
|
75fdb61c25 | ||
|
22b96c7ff9 | ||
|
57ab4c49fd | ||
|
865733cec7 | ||
|
c8d70f4b34 | ||
|
326d3d5613 | ||
|
1cf1f3856c | ||
|
503d966733 | ||
|
762dbfa595 | ||
|
245381aafa | ||
|
301249f9d2 | ||
|
2bc38a79a3 | ||
|
729079cff4 | ||
|
10ea16bc7e | ||
|
70a706e6be | ||
|
c9c3153f1d | ||
|
aa44226a4e | ||
|
85353e0ce6 | ||
|
4a5950721e | ||
|
16983356c8 | ||
|
558e778861 | ||
|
02d6c44638 | ||
|
285387f1b3 | ||
|
67c19e3ee8 | ||
|
b5088cbffb | ||
|
7172568615 | ||
|
bde0274123 | ||
|
0f684a76d0 | ||
|
fac68f46a5 | ||
|
65a6df1e44 | ||
|
942d6c6a9c | ||
|
f76f554d1f | ||
|
6225566875 | ||
|
d02f04504b | ||
|
a117583db6 | ||
|
f5ed9d1cb2 | ||
|
660023553b | ||
|
68397c7fca | ||
|
58ed1a5e1c | ||
|
234b71064c | ||
|
f8678a3d44 | ||
|
0285d39793 | ||
|
5e5aa5f610 | ||
|
7f031350a9 | ||
|
1a9afc9ede | ||
|
26d4d7cc86 | ||
|
ba83b79a9c | ||
|
f4e6c52f2f | ||
|
7b969e0009 | ||
|
c93090b4e8 | ||
|
11e404c23a | ||
|
689548aa9b | ||
|
26af8d805c | ||
|
061576fcc3 | ||
|
61f3bd007d | ||
|
d65c6acdf4 | ||
|
011affc46f | ||
|
f8a5339f57 | ||
|
d648e1a178 | ||
|
b4e2db7f3c | ||
|
007fb4e38e | ||
|
1ca35fe367 | ||
|
4821c4e912 | ||
|
a46641fcac | ||
|
6f25d3c388 | ||
|
0ad60d974b | ||
|
36597871fb | ||
|
54cff8252b | ||
|
5f09951a56 | ||
|
a595c7952a | ||
|
fb8b9eb68d | ||
|
18b8401334 | ||
|
0780d8dd67 | ||
|
87fbc5256c | ||
|
12b65b8fb6 | ||
|
80c2d32129 | ||
|
1571108cf3 | ||
|
b89e40e092 | ||
|
7ec34577c4 | ||
|
24412d94be | ||
|
eebddeb1a4 | ||
|
303655e06c | ||
|
182e32d231 | ||
|
6097e844cf |
34
LICENSE
|
@ -6,9 +6,9 @@
|
|||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
(This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
the version number 2.1.)
|
||||
|
||||
Preamble
|
||||
|
||||
|
@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
|
|||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
|
@ -111,7 +111,7 @@ modification follow. Pay close attention to the difference between a
|
|||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
|
@ -158,7 +158,7 @@ Library.
|
|||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
|
@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
|
|||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
@ -267,7 +267,7 @@ Library will still fall under Section 6.)
|
|||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
|
@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
|
|||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
|
@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
|
|||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
|
@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
|
|||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
|
@ -456,7 +456,7 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
|
@ -470,8 +470,8 @@ safest to attach them to the start of each source file to most effectively
|
|||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -485,7 +485,8 @@ convey the exclusion of warranty; and each file should have at least the
|
|||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
@ -494,9 +495,10 @@ school, if any, to sign a "copyright disclaimer" for the library, if
|
|||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
library `Frob' (a library for tweaking knobs) written by James Random
|
||||
Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
{signature of Ty Coon}, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# fun_caves
|
||||
|
||||
Fun Caves is an attempt to convert the mapgen V6 caves into a lua mod, so they can be used with any mapgen. I've translated the C++ code into lua in the most mechanical way possible. I honestly have no idea how half of it works, and I don't intend to spend a lot of time on it in the future, so anyone who likes this mod is encouraged to fork and/or tinker with it and submit pull requests.
|
||||
Fun Caves replaces the default caves with a dense system of mostly flat (and easier to navigate) caverns, with biomes owing much to caverealms. Once you go underground, you should find everything you need to survive without ever returning to the surface.
|
||||
|
||||

|
||||
#
|
||||
|
||||
The source is available on github.
|
||||
|
||||
Code: LGPL2, textures: none
|
||||
Code: LGPL2, textures: CC-BY-SA and CC0
|
||||
|
||||
Mod dependencies: default
|
||||
Mod dependencies: default, dye, flowers, vessels
|
||||
|
||||
Download: https://github.com/duane-r/fun_caves/archive/master.zip
|
||||
|
|
659
abms.lua
Normal file
|
@ -0,0 +1,659 @@
|
|||
-- Fun_Caves abms.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Abms
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- player surface damage
|
||||
local dps_delay = 3
|
||||
local last_dps_check = 0
|
||||
local cold_delay = 5
|
||||
local dps_count = cold_delay
|
||||
local mushrooms = {"flowers:mushroom_brown", "flowers:mushroom_red"}
|
||||
local time_factor = (fun_caves_mod.time_factor or 10)
|
||||
local light_max = (fun_caves_mod.light_max or 10)
|
||||
|
||||
|
||||
-- fungal tree nodes
|
||||
local fungal_tree_leaves = {}
|
||||
for i = 1, 4 do
|
||||
fungal_tree_leaves[#fungal_tree_leaves+1] = "fun_caves:fungal_tree_leaves_"..i
|
||||
end
|
||||
|
||||
local is_fungal_leaf = {}
|
||||
for _, leaf in ipairs(fungal_tree_leaves) do
|
||||
is_fungal_leaf[leaf] = true
|
||||
end
|
||||
|
||||
local fungal_nodes = {}
|
||||
for _, leaf in pairs(fungal_tree_leaves) do
|
||||
fungal_nodes[#fungal_nodes+1] = {name = leaf}
|
||||
end
|
||||
fungal_nodes[#fungal_nodes+1] = {name = 'fun_caves:fungal_tree_fruit'}
|
||||
|
||||
local fungi_to_explode = {} -- see below
|
||||
local exploding_fungi = fun_caves_mod.exploding_fungi
|
||||
if not exploding_fungi then
|
||||
exploding_fungi = {}
|
||||
end
|
||||
|
||||
|
||||
-- hot spike parameters
|
||||
local spike_air = {}
|
||||
spike_air['default:lava_source'] = true
|
||||
spike_air['default:lava_source'] = true
|
||||
spike_air['default:lava_flowing'] = true
|
||||
|
||||
local spike_soil = {}
|
||||
spike_soil['fun_caves:hot_cobble'] = true
|
||||
spike_soil['fun_caves:black_sand'] = true
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- all the fun_caves globalstep functions
|
||||
------------------------------------------------------------
|
||||
local hot_stuff = {"group:surface_hot"}
|
||||
local cold_stuff = {"group:surface_cold"}
|
||||
local poison_stuff = {"group:poison"}
|
||||
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if not (dtime and type(dtime) == 'number') then
|
||||
return
|
||||
end
|
||||
|
||||
local time = minetest.get_gametime()
|
||||
if not (time and type(time) == 'number') then
|
||||
return
|
||||
end
|
||||
|
||||
-- Execute only after an interval.
|
||||
if not last_dps_check or time - last_dps_check < dps_delay then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local players = minetest.get_connected_players()
|
||||
if not (players and type(players) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, #players do
|
||||
local player = players[i]
|
||||
local pos = player:getpos()
|
||||
pos = vector.round(pos)
|
||||
local player_name = player:get_player_name()
|
||||
|
||||
-- environmental damage
|
||||
if fun_caves_mod.DEBUG and player:get_hp() < 20 then
|
||||
-- Regenerate the player while testing.
|
||||
print("HP: "..player:get_hp())
|
||||
player:set_hp(20)
|
||||
return
|
||||
else
|
||||
local minp = vector.subtract(pos, 0.5)
|
||||
local maxp = vector.add(pos, 0.5)
|
||||
|
||||
-- ... from standing on or near hot objects.
|
||||
local counts = minetest_find_nodes_in_area(minp, maxp, hot_stuff)
|
||||
if not (counts and type(counts) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
if #counts > 1 then
|
||||
player:set_hp(player:get_hp() - 1)
|
||||
end
|
||||
|
||||
-- ... from standing on or near poison.
|
||||
local counts = minetest_find_nodes_in_area(minp, maxp, poison_stuff)
|
||||
if not (counts and type(counts) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
if #counts > 1 then
|
||||
player:set_hp(player:get_hp() - 1)
|
||||
end
|
||||
|
||||
-- ... from standing on or near cold objects (less often).
|
||||
if dps_count % cold_delay == 0 then
|
||||
counts = minetest_find_nodes_in_area(minp, maxp, cold_stuff)
|
||||
if not (counts and type(counts) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
if #counts > 1 then
|
||||
player:set_hp(player:get_hp() - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Set this outside of the player loop, to affect everyone.
|
||||
if dps_count % cold_delay < 1 then
|
||||
dps_count = cold_delay
|
||||
end
|
||||
|
||||
last_dps_check = minetest.get_gametime()
|
||||
if not (last_dps_check and type(last_dps_check) == 'number') then
|
||||
last_dps_check = 0
|
||||
end
|
||||
dps_count = dps_count - 1
|
||||
end)
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- destruction
|
||||
------------------------------------------------------------
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"fun_caves:hot_cobble",},
|
||||
neighbors = {"group:water"},
|
||||
interval = time_factor,
|
||||
chance = 30,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
if not (pos and node) then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.set_node(pos, {name = "default:cobble"})
|
||||
minetest.sound_play("default_cool_lava",
|
||||
{pos = pos, max_hear_distance = 16, gain = 0.25})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Exploding fungal fruit
|
||||
minetest.register_abm({
|
||||
nodenames = {"fun_caves:fungal_tree_fruit"},
|
||||
interval = 12 * time_factor,
|
||||
chance = 400,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
if not (pos and node) then
|
||||
return
|
||||
end
|
||||
|
||||
fun_caves_mod.soft_boom(pos)
|
||||
end
|
||||
})
|
||||
|
||||
-- Destroy mushroom caps in the light.
|
||||
minetest.register_abm({
|
||||
nodenames = {"fun_caves:giant_mushroom_cap", "fun_caves:huge_mushroom_cap"},
|
||||
interval = 3 * time_factor,
|
||||
chance = 200,
|
||||
action = function(pos, node)
|
||||
if not (pos and node) then
|
||||
return
|
||||
end
|
||||
|
||||
if (minetest.get_node_light(pos, nil) or 99) >= light_max + 2 then
|
||||
minetest.remove_node(pos)
|
||||
return
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
-- * Replace this with an after_destruct call *
|
||||
--minetest.register_abm({
|
||||
-- nodenames = {"fun_caves:giant_mushroom_cap", "fun_caves:huge_mushroom_cap"},
|
||||
-- interval = time_factor,
|
||||
-- chance = 20,
|
||||
-- action = function(pos, node)
|
||||
-- if not (pos and node) then
|
||||
-- return
|
||||
-- end
|
||||
--
|
||||
-- pos.y = pos.y - 1
|
||||
-- local node_below = minetest.get_node_or_nil(pos)
|
||||
-- if not (node_below and node_below.name == 'fun_caves:giant_mushroom_stem') then
|
||||
-- pos.y = pos.y + 1
|
||||
-- minetest.remove_node(pos)
|
||||
-- return
|
||||
-- end
|
||||
-- end
|
||||
--})
|
||||
|
||||
--minetest.register_abm({
|
||||
-- nodenames = {"fire:basic_flame"},
|
||||
-- interval = 2 * time_factor,
|
||||
-- chance = 50,
|
||||
-- action = function(p0, node, _, _)
|
||||
-- minetest.remove_node(p0)
|
||||
-- end,
|
||||
--})
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- creation
|
||||
------------------------------------------------------------
|
||||
|
||||
-- fungal spread
|
||||
minetest.register_abm({
|
||||
nodenames = fungal_tree_leaves,
|
||||
neighbors = {"air", "group:liquid"},
|
||||
interval = 4 * time_factor,
|
||||
chance = 200,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
if not (pos and node) then
|
||||
return
|
||||
end
|
||||
|
||||
if (minetest.get_node_light(pos, nil) or 99) >= light_max + 2 then
|
||||
minetest.remove_node(pos)
|
||||
return
|
||||
end
|
||||
|
||||
if math.random(40) == 1 then
|
||||
minetest.set_node(pos, fungal_nodes[#fungal_nodes])
|
||||
return
|
||||
end
|
||||
|
||||
if math.random(100) == 1 then
|
||||
minetest.set_node(pos, fungal_nodes[math.random(#fungal_nodes - 1)])
|
||||
return
|
||||
end
|
||||
|
||||
pos.y = pos.y - 1
|
||||
local grow_node = minetest.get_node_or_nil(pos)
|
||||
if grow_node and grow_node.name == "air" then
|
||||
minetest.set_node(pos, node)
|
||||
return
|
||||
end
|
||||
|
||||
pos.x = pos.x + math.random(-1, 1)
|
||||
pos.y = pos.y + math.random(-1, 1) + 1
|
||||
pos.z = pos.z + math.random(-1, 1)
|
||||
grow_node = minetest.get_node_or_nil(pos)
|
||||
if grow_node and grow_node.name == "air" and (minetest.get_node_light(pos, nil) or 99) <= light_max then
|
||||
minetest.set_node(pos, node)
|
||||
return
|
||||
elseif grow_node and is_fungal_leaf[grow_node.name] and grow_node.name ~= node.name then
|
||||
minetest.remove_node(pos)
|
||||
return
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
-- mushroom growth -- caps regenerate in time
|
||||
local huge_mushroom_cap_node = {name = 'fun_caves:huge_mushroom_cap'}
|
||||
minetest.register_abm({
|
||||
nodenames = {"fun_caves:giant_mushroom_stem"},
|
||||
neighbors = {'air'},
|
||||
interval = 4 * time_factor,
|
||||
chance = 200,
|
||||
action = function(pos, node)
|
||||
if not (pos and node) then
|
||||
return
|
||||
end
|
||||
|
||||
pos.y = pos.y + 1
|
||||
local node_up = minetest.get_node_or_nil(pos)
|
||||
if not node_up or node_up.name ~= "air" then
|
||||
return
|
||||
end
|
||||
|
||||
if (minetest.get_node_light(pos, nil) or 99) <= light_max then
|
||||
minetest.set_node(pos, huge_mushroom_cap_node)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
-- new fungi
|
||||
local mushroom_nodes = {}
|
||||
for _, mushroom in pairs(mushrooms) do
|
||||
mushroom_nodes[#mushroom_nodes+1] = {name = mushroom}
|
||||
end
|
||||
minetest.register_abm({
|
||||
nodenames = {"default:dirt"},
|
||||
neighbors = {'fun_caves:stone_with_lichen', 'fun_caves:stone_with_algae', 'fun_caves:giant_mushroom_stem'},
|
||||
interval = 10 * time_factor,
|
||||
chance = 500,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
if not (pos and node and pos.y < 0) then
|
||||
return
|
||||
end
|
||||
|
||||
pos.y = pos.y + 1
|
||||
local grow_node = minetest.get_node_or_nil(pos)
|
||||
if grow_node and grow_node.name == "air"
|
||||
and (minetest.get_node_light(pos, nil) or 99) <= light_max then
|
||||
if math.random(4) == 1 then
|
||||
minetest.set_node(pos, fungal_nodes[math.random(#fungal_nodes - 1)])
|
||||
else
|
||||
minetest.set_node(pos, mushroom_nodes[math.random(#mushroom_nodes)])
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
-- mushroom growth -- small into huge
|
||||
local giant_mushroom_stem_node = {name = 'fun_caves:giant_mushroom_stem'}
|
||||
minetest.register_abm({
|
||||
nodenames = mushrooms,
|
||||
interval = 20 * time_factor,
|
||||
chance = 700,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
if not (pos and node and pos.y < 0) then
|
||||
return
|
||||
end
|
||||
|
||||
local pos_up = {x=pos.x,y=pos.y+1,z=pos.z}
|
||||
local node_up = minetest.get_node_or_nil(pos_up)
|
||||
if not node_up or node_up.name ~= "air" then
|
||||
return
|
||||
end
|
||||
|
||||
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
if not node_under
|
||||
or minetest.get_item_group(node_under.name, "soil") == 0
|
||||
or (minetest.get_node_light(pos_up, nil) or 99) > light_max then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.set_node(pos_up, huge_mushroom_cap_node)
|
||||
minetest.set_node(pos, giant_mushroom_stem_node)
|
||||
end
|
||||
})
|
||||
|
||||
-- mushroom growth -- huge into giant
|
||||
local giant_mushroom_cap_node = {name = "fun_caves:giant_mushroom_cap"}
|
||||
minetest.register_abm({
|
||||
nodenames = {"fun_caves:huge_mushroom_cap"},
|
||||
interval = 40 * time_factor,
|
||||
chance = 2000,
|
||||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
if not (pos and node) then
|
||||
return
|
||||
end
|
||||
|
||||
local pos_up = {x=pos.x,y=pos.y+1,z=pos.z}
|
||||
local node_up = minetest.get_node_or_nil(pos_up)
|
||||
if not node_up or node_up.name ~= "air" then
|
||||
return
|
||||
end
|
||||
|
||||
-- Check for soil.
|
||||
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 2, z = pos.z})
|
||||
if not node_under
|
||||
or minetest.get_item_group(node_under.name, "soil") == 0
|
||||
or (minetest.get_node_light(pos_up, nil) or 99) > light_max then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.set_node(pos_up, giant_mushroom_cap_node)
|
||||
minetest.set_node(pos, {name = "fun_caves:giant_mushroom_stem"})
|
||||
end
|
||||
})
|
||||
|
||||
-- Spike spread and death
|
||||
minetest.register_abm({
|
||||
nodenames = fun_caves_mod.hot_spikes,
|
||||
interval = 40 * time_factor,
|
||||
chance = 2000,
|
||||
action = function(pos, node)
|
||||
if not (pos and node and pos.y < 0) then
|
||||
return
|
||||
end
|
||||
|
||||
if not (fun_caves_mod.hot_spike and fun_caves_mod.hot_spikes) then
|
||||
return
|
||||
end
|
||||
|
||||
local spike_num = fun_caves_mod.hot_spike[node.name]
|
||||
if not spike_num then
|
||||
return
|
||||
end
|
||||
|
||||
if spike_num < #fun_caves_mod.hot_spikes then
|
||||
minetest.set_node(pos, {name=fun_caves_mod.hot_spikes[spike_num+1]})
|
||||
return
|
||||
end
|
||||
|
||||
pos.x = pos.x + math.random(-2, 2)
|
||||
pos.y = pos.y + math.random(-1, 1)
|
||||
pos.z = pos.z + math.random(-2, 2)
|
||||
local new_node = minetest.get_node_or_nil(pos)
|
||||
if not (new_node and spike_air[new_node.name]) then
|
||||
return
|
||||
end
|
||||
|
||||
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
if not (node_under and spike_soil[node_under.name]) then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.set_node(pos, {name = fun_caves_mod.hot_spikes[1]})
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- explosive functions
|
||||
------------------------------------------------------------
|
||||
|
||||
-- All of this is copied from TNT, but modified to leave stone intact.
|
||||
|
||||
-- Fill a list with data for content IDs, after all nodes are registered
|
||||
local cid_data = {}
|
||||
minetest.after(0, function()
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
cid_data[minetest.get_content_id(name)] = {
|
||||
name = name,
|
||||
--drops = def.drops,
|
||||
flammable = def.groups.flammable,
|
||||
choppy = def.groups.choppy,
|
||||
fleshy = def.groups.fleshy,
|
||||
snappy = def.groups.snappy,
|
||||
on_blast = def.on_blast,
|
||||
}
|
||||
end
|
||||
|
||||
-- This also has to be done after content ids are established.
|
||||
for i = 1, 4 do
|
||||
fungi_to_explode[minetest.get_content_id("fun_caves:fungal_tree_leaves_"..i)] = true
|
||||
end
|
||||
fungi_to_explode[minetest.get_content_id('fun_caves:fungal_tree_fruit')] = true
|
||||
fungi_to_explode[minetest.get_content_id('fun_caves:giant_mushroom_cap')] = true
|
||||
fungi_to_explode[minetest.get_content_id('fun_caves:giant_mushroom_stem')] = true
|
||||
fungi_to_explode[minetest.get_content_id('fun_caves:huge_mushroom_cap')] = true
|
||||
end)
|
||||
|
||||
local function add_effects(pos, radius)
|
||||
if not (pos and radius and type(radius) == 'number') then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.add_particlespawner({
|
||||
amount = 128,
|
||||
time = 1,
|
||||
minpos = vector.subtract(pos, radius / 2),
|
||||
maxpos = vector.add(pos, radius / 2),
|
||||
minvel = {x=-20, y=-20, z=-20},
|
||||
maxvel = {x=20, y=20, z=20},
|
||||
minacc = vector.new(),
|
||||
maxacc = vector.new(),
|
||||
minexptime = 1,
|
||||
maxexptime = 3,
|
||||
minsize = 8,
|
||||
maxsize = 16,
|
||||
texture = "tnt_smoke.png",
|
||||
})
|
||||
end
|
||||
|
||||
local function destroy(pos, cid)
|
||||
if not (pos and cid) then
|
||||
return
|
||||
end
|
||||
|
||||
local def = cid_data[cid]
|
||||
if not (def and def.flammable and def.flammable > 0 and not minetest.is_protected(pos, "")) then
|
||||
return
|
||||
end
|
||||
|
||||
if def.on_blast then
|
||||
def.on_blast(vector.new(pos), 1)
|
||||
return
|
||||
end
|
||||
|
||||
if def.snappy == nil and def.choppy == nil and def.fleshy == nil and def.name ~= "fire:basic_flame" then
|
||||
return
|
||||
end
|
||||
|
||||
if exploding_fungi or fungi_to_explode[cid] then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local math_random = math.random
|
||||
local function explode(pos, radius)
|
||||
if not (pos and radius and type(radius) == 'number') then
|
||||
return
|
||||
end
|
||||
|
||||
local pos = vector.round(pos)
|
||||
local vm = VoxelManip()
|
||||
local p1 = vector.subtract(pos, radius)
|
||||
local p2 = vector.add(pos, radius)
|
||||
local minp, maxp = vm:read_from_map(p1, p2)
|
||||
local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp})
|
||||
local data = vm:get_data()
|
||||
|
||||
local p = {}
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
|
||||
for z = -radius, radius do
|
||||
for y = -radius, 4*radius do
|
||||
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
|
||||
for x = -radius, radius do
|
||||
if (x * x) + (y * y / 4) + (z * z) <=
|
||||
(radius * radius) + math_random(-radius, radius) then
|
||||
local cid = data[vi]
|
||||
p.x = pos.x + x
|
||||
p.y = pos.y + y
|
||||
p.z = pos.z + z
|
||||
if cid ~= c_air then
|
||||
destroy(p, cid)
|
||||
end
|
||||
end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function calc_velocity(pos1, pos2, old_vel, power)
|
||||
if not (pos1 and pos2 and old_vel and power) then
|
||||
return
|
||||
end
|
||||
|
||||
local vel = vector.direction(pos1, pos2)
|
||||
vel = vector.normalize(vel)
|
||||
vel = vector.multiply(vel, power)
|
||||
|
||||
-- Divide by distance
|
||||
local dist = vector.distance(pos1, pos2)
|
||||
dist = math.max(dist, 1)
|
||||
vel = vector.divide(vel, dist)
|
||||
|
||||
-- Add old velocity
|
||||
vel = vector.add(vel, old_vel)
|
||||
return vel
|
||||
end
|
||||
|
||||
local function entity_physics(pos, radius)
|
||||
if not (pos and radius and type(radius) == 'number') then
|
||||
return
|
||||
end
|
||||
|
||||
-- Make the damage radius larger than the destruction radius
|
||||
radius = radius * 2
|
||||
local objs = minetest.get_objects_inside_radius(pos, radius)
|
||||
if not (objs and type(objs) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
local math_max = math.max
|
||||
local vector_distance = vector.distance
|
||||
for _, obj in pairs(objs) do
|
||||
local obj_pos = obj:getpos()
|
||||
local obj_vel = obj:getvelocity()
|
||||
local dist = math_max(1, vector_distance(pos, obj_pos))
|
||||
|
||||
if obj_vel ~= nil then
|
||||
obj:setvelocity(calc_velocity(pos, obj_pos,
|
||||
obj_vel, radius * 10))
|
||||
end
|
||||
|
||||
local damage = (4 / dist) * radius
|
||||
obj:set_hp(obj:get_hp() - damage)
|
||||
end
|
||||
end
|
||||
|
||||
fun_caves_mod.soft_boom = function(pos)
|
||||
if not pos then
|
||||
return
|
||||
end
|
||||
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
|
||||
if exploding_fungi then
|
||||
minetest.sound_play("tnt_explode", {pos=pos, gain=1.5, max_hear_distance=2*64})
|
||||
end
|
||||
local radius = 5
|
||||
minetest.remove_node(pos)
|
||||
explode(pos, radius)
|
||||
if exploding_fungi then
|
||||
entity_physics(pos, radius)
|
||||
add_effects(pos, radius)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------
|
||||
-- testing only -- remove before distribution
|
||||
-----------------------------------------------
|
||||
-- Mushroom spread and death
|
||||
--minetest.register_abm({
|
||||
-- nodenames = mushrooms,
|
||||
-- interval = 1 * time_factor,
|
||||
-- chance = 50,
|
||||
-- action = function(pos, node)
|
||||
-- if minetest.get_node_light(pos, nil) >= light_max + 2 then
|
||||
-- minetest.remove_node(pos)
|
||||
-- return
|
||||
-- end
|
||||
-- local random = {
|
||||
-- x = pos.x + math.random(-2, 2),
|
||||
-- y = pos.y + math.random(-1, 1),
|
||||
-- z = pos.z + math.random(-2, 2)
|
||||
-- }
|
||||
-- local random_node = minetest.get_node_or_nil(random)
|
||||
-- if not random_node or random_node.name ~= "air" then
|
||||
-- return
|
||||
-- end
|
||||
-- local node_under = minetest.get_node_or_nil({x = random.x,
|
||||
-- y = random.y - 1, z = random.z})
|
||||
-- if not node_under then
|
||||
-- return
|
||||
-- end
|
||||
--
|
||||
-- if (minetest.get_item_group(node_under.name, "soil") ~= 0 or
|
||||
-- minetest.get_item_group(node_under.name, "tree") ~= 0) and
|
||||
-- minetest.get_node_light(pos, 0.5) <= light_max and
|
||||
-- minetest.get_node_light(random, 0.5) <= light_max then
|
||||
-- minetest.set_node(random, {name = node.name})
|
||||
-- end
|
||||
-- end
|
||||
--})
|
69
cavegen.lua
Normal file
|
@ -0,0 +1,69 @@
|
|||
-- Fun_Caves cavegen.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
fun_caves_mod.cave_width = 0.05 -- figurative width
|
||||
local max_depth = -28000
|
||||
|
||||
|
||||
fun_caves_mod.cave_noise_1 = {offset = 0, scale = 1, seed = 3901, spread = {x = 40, y = 10, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
|
||||
fun_caves_mod.cave_noise_2 = {offset = 0, scale = 1, seed = -8402, spread = {x = 40, y = 20, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
|
||||
local cave_noise_3 = {offset = 15, scale = 10, seed = 3721, spread = {x = 40, y = 40, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
|
||||
|
||||
|
||||
fun_caves_mod.cavegen = function(minp, maxp, data, area, node, heightmap)
|
||||
if not (minp and maxp and data and area and node and type(data) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
local temp_y = (minp.y+maxp.y)/2
|
||||
if temp_y > -28000 or temp_y < -30999 then return end
|
||||
|
||||
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
||||
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
|
||||
local map_min = {x = minp.x, y = minp.y - 1, z = minp.z}
|
||||
|
||||
local cave_1, cave_2, cave_3
|
||||
cave_1 = minetest.get_perlin_map(fun_caves_mod.cave_noise_1, map_max):get3dMap_flat(map_min)
|
||||
cave_2 = minetest.get_perlin_map(fun_caves_mod.cave_noise_2, map_max):get3dMap_flat(map_min)
|
||||
cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
|
||||
|
||||
if not (cave_1 and cave_2 and cave_3) then
|
||||
return
|
||||
end
|
||||
|
||||
local index = 0
|
||||
local index3d = 0
|
||||
local cave_width = fun_caves_mod.cave_width
|
||||
local write
|
||||
for z = minp.z, maxp.z do
|
||||
for x = minp.x, maxp.x do
|
||||
index = index + 1
|
||||
index3d = (z - minp.z) * (csize.y + 2) * csize.x + (x - minp.x) + 1
|
||||
local ivm = area:index(x, minp.y, z)
|
||||
local height = heightmap[index]
|
||||
for y = minp.y, maxp.y do
|
||||
if ((y <= maxp.y and y >= minp.y) or (data[ivm] == node['default:stone'])) and y < height - cave_3[index] and cave_1[index3d] * cave_2[index3d] > cave_width then
|
||||
data[ivm] = node["air"]
|
||||
write = true
|
||||
if y > 0 and cave_3[index] < 1 and y == height then
|
||||
-- Clear the air above a cave mouth.
|
||||
local ivm2 = ivm
|
||||
for y2 = y + 1, maxp.y + 8 do
|
||||
ivm2 = ivm2 + area.ystride
|
||||
if data[ivm2] ~= node["default:water_source"] then
|
||||
data[ivm2] = node["air"]
|
||||
write = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ivm = ivm + area.ystride
|
||||
index3d = index3d + csize.x
|
||||
end
|
||||
end
|
||||
end
|
||||
return write
|
||||
end
|
222
deco.lua
Normal file
|
@ -0,0 +1,222 @@
|
|||
-- Fun_Caves deco.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
dofile(fun_caves_mod.path .. "/nodes.lua")
|
||||
dofile(fun_caves_mod.path .. "/fungal_tree.lua")
|
||||
|
||||
|
||||
local deco_depth = -5 -- place cave stuff this far beneath the surface
|
||||
local water_level = 1
|
||||
local fluid_compression = -22000 -- the depth to start planting lava/water
|
||||
local max_depth = -27960
|
||||
|
||||
local csize
|
||||
local node_match_cache = {}
|
||||
|
||||
|
||||
local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = 903, octaves = 3, persist = 0.5, lacunarity = 2.0}
|
||||
|
||||
|
||||
-- Air needs to be placed prior to decorations.
|
||||
fun_caves_mod.decogen = function(minp, maxp, data, area, node, heightmap)
|
||||
if not (minp and maxp and data and area and node and type(data) == 'table' and fun_caves_mod.cave_biomes and fun_caves_mod.make_fungal_tree) then
|
||||
return
|
||||
end
|
||||
local temp_y = (minp.y+maxp.y)/2
|
||||
if temp_y > -28000 or temp_y < -30999 then return end
|
||||
|
||||
csize = vector.add(vector.subtract(maxp, minp), 1)
|
||||
|
||||
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
|
||||
local map_min = {x = minp.x, y = minp.y - 1, z = minp.z}
|
||||
|
||||
local biome_n = minetest.get_perlin_map(biome_noise, map_max):get3dMap_flat(map_min)
|
||||
|
||||
local write
|
||||
local index = 0
|
||||
local index3d = 0
|
||||
local math_max = math.max
|
||||
local math_min = math.min
|
||||
local math_log = math.log
|
||||
local math_random = math.random
|
||||
|
||||
for z = minp.z, maxp.z do
|
||||
for x = minp.x, maxp.x do
|
||||
index = index + 1
|
||||
index3d = (z - minp.z) * (csize.y + 2) * csize.x + (x - minp.x) + 1
|
||||
local ivm = area:index(x, minp.y, z)
|
||||
local height = heightmap[index]
|
||||
|
||||
for y = minp.y-1, maxp.y+1 do
|
||||
if y <= height + deco_depth and (height < max_depth or y < 0) then
|
||||
for deco_non_loop = 1, 1 do
|
||||
if not (data[ivm] == node["air"] or data[ivm] == node["default:stone"]) then
|
||||
break
|
||||
end
|
||||
|
||||
local biome
|
||||
local biome_val = biome_n[index3d]
|
||||
|
||||
-- Compress biomes at the surface to avoid fluids.
|
||||
if y > fluid_compression then
|
||||
biome_val = biome_val / math_max(1, math_log(y - fluid_compression))
|
||||
end
|
||||
|
||||
for _, bi in pairs(fun_caves_mod.cave_biomes) do
|
||||
if biome_val >= bi.biome_val_low and biome_val < bi.biome_val_high then
|
||||
biome = bi
|
||||
end
|
||||
end
|
||||
--biome = fun_caves_mod.cave_biomes['salt']
|
||||
|
||||
if not biome then
|
||||
print(("* Fun Caves: Error in biome selection: %s"):format(biome_val))
|
||||
biome = fun_caves_mod.cave_biomes['algae']
|
||||
end
|
||||
|
||||
|
||||
local node_below
|
||||
if y > minp.y then
|
||||
node_below = data[ivm - area.ystride]
|
||||
end
|
||||
local node_above = data[ivm + area.ystride]
|
||||
|
||||
if data[ivm] == node["default:stone"] then
|
||||
if node_above == node["air"] and biome and biome.dirt and math_random(biome.dirt_chance) == 1 then
|
||||
data[ivm] = node[biome.dirt]
|
||||
write = true
|
||||
break
|
||||
end
|
||||
|
||||
local air_above = false
|
||||
for i = 1, biome.stone_depth do
|
||||
if data[ivm + area.ystride * i] == node["air"] then
|
||||
air_above = true
|
||||
end
|
||||
end
|
||||
|
||||
if air_above then
|
||||
if biome and biome.deco and math_random(biome.deco_chance) == 1 then
|
||||
data[ivm] = node[biome.deco]
|
||||
write = true
|
||||
break
|
||||
else
|
||||
data[ivm] = node[biome.floor_node]
|
||||
write = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local air_below = false
|
||||
for i = 1, biome.stone_depth do
|
||||
if data[ivm - area.ystride * i] == node["air"] then
|
||||
air_below = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Prevent server-crashing sandslides.
|
||||
if not air_above and biome.floor_node == "default:sand" then
|
||||
data[ivm] = node["default:sandstone"]
|
||||
write = true
|
||||
break
|
||||
end
|
||||
|
||||
if air_below then
|
||||
if biome and biome.deco and math_random(biome.deco_chance) == 1 then
|
||||
data[ivm] = node[biome.deco]
|
||||
write = true
|
||||
break
|
||||
else
|
||||
data[ivm] = node[biome.ceiling_node]
|
||||
write = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if data[ivm] == node["air"] and y < maxp.y then
|
||||
-- hanging down
|
||||
-- stone hasn't yet been changed
|
||||
if biome and biome.stalactite and node_above == node["default:stone"] and math_random(biome.stalactite_chance) == 1 then
|
||||
data[ivm] = node[biome.stalactite]
|
||||
write = true
|
||||
break
|
||||
end
|
||||
|
||||
-- fluids
|
||||
if y > minp.y and biome and biome.fluid and node_below == node[biome.floor_node] and math_random(biome.fluid_chance) == 1 then
|
||||
data[ivm] = node[biome.fluid]
|
||||
write = true
|
||||
break
|
||||
|
||||
-- standing up
|
||||
elseif node_below == node[biome.floor_node] and biome and biome.stalagmite and math_random(biome.stalagmite_chance) == 1 then
|
||||
if type(biome.stalagmite) == 'table' then
|
||||
data[ivm] = node[biome.stalagmite[math_random(#biome.stalagmite)]]
|
||||
else
|
||||
data[ivm] = node[biome.stalagmite]
|
||||
end
|
||||
write = true
|
||||
break
|
||||
|
||||
-- vegetation
|
||||
elseif node_below == node["default:dirt"] and biome and biome.fungi then
|
||||
if math_random(10) == 1 then
|
||||
data[ivm] = node["flowers:mushroom_red"]
|
||||
write = true
|
||||
break
|
||||
elseif math_random(10) == 1 then
|
||||
data[ivm] = node["flowers:mushroom_brown"]
|
||||
write = true
|
||||
break
|
||||
elseif node_above == node["air"] and math_random(10) == 1 then
|
||||
data[ivm] = node["fun_caves:giant_mushroom_stem"]
|
||||
write = true
|
||||
break
|
||||
elseif math_random(30) == 1 then
|
||||
local air_count = 0
|
||||
local j
|
||||
for i = 1, 12 do
|
||||
j = ivm + area.ystride * i
|
||||
if j <= #data and data[j] == node["air"] then
|
||||
air_count = air_count + 1
|
||||
end
|
||||
end
|
||||
if air_count > 5 then
|
||||
fun_caves_mod.make_fungal_tree(data, area, ivm, math_random(2, math_min(air_count, 12)))
|
||||
end
|
||||
end
|
||||
elseif node_below == node["fun_caves:giant_mushroom_stem"] and data[ivm - area.ystride * 2] == node["fun_caves:giant_mushroom_stem"] then
|
||||
data[ivm] = node["fun_caves:giant_mushroom_cap"]
|
||||
write = true
|
||||
break
|
||||
elseif node_below == node["fun_caves:giant_mushroom_stem"] then
|
||||
if node_above == node["air"] and math_random(3) == 1 then
|
||||
data[ivm] = node["fun_caves:giant_mushroom_stem"]
|
||||
write = true
|
||||
break
|
||||
else
|
||||
data[ivm] = node["fun_caves:huge_mushroom_cap"]
|
||||
write = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif y < height and data[ivm] == node["air"] and (data[ivm - area.ystride] == node['default:stone'] or data[ivm - area.ystride] == node['default:sandstone']) then
|
||||
-- This just places non-abm dirt inside caves.
|
||||
-- Its value is questionable.
|
||||
data[ivm - area.ystride] = node["fun_caves:dirt"]
|
||||
write = true
|
||||
end
|
||||
|
||||
ivm = ivm + area.ystride
|
||||
index3d = index3d + csize.x
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return write
|
||||
end
|
|
@ -1 +1,9 @@
|
|||
default
|
||||
bucket?
|
||||
dye
|
||||
flowers
|
||||
mobs?
|
||||
ramoid?
|
||||
underworlds?
|
||||
vessels
|
||||
wooden_bucket?
|
||||
|
|
188
fungal_tree.lua
Normal file
|
@ -0,0 +1,188 @@
|
|||
-- Fun_Caves fungal_tree.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
local colors = {}
|
||||
colors["^[colorize:#FF00FF:60"] = "dye:violet"
|
||||
colors["^[colorize:#0000FF:60"] = "dye:blue"
|
||||
colors["^[colorize:#FF4500:80"] = "dye:green"
|
||||
colors[""] = "dye:white"
|
||||
local fungal_tree_leaves = {}
|
||||
|
||||
local newnode = fun_caves_mod.clone_node("farming:straw")
|
||||
newnode.description = "Dry Fiber"
|
||||
minetest.register_node("fun_caves:dry_fiber", newnode)
|
||||
|
||||
|
||||
minetest.register_node("fun_caves:fungal_tree_fruit", {
|
||||
description = "Fungal tree fruit",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 0.75,
|
||||
tiles = {"fun_caves_fungal_tree_fruit.png"},
|
||||
--inventory_image = ".png",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
light_source = 6,
|
||||
walkable = false,
|
||||
is_ground_content = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}
|
||||
},
|
||||
groups = {fleshy = 3, dig_immediate = 3, flammable = 2},
|
||||
--on_use = minetest.item_eat(2),
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
on_timer = fun_caves_mod.soft_boom,
|
||||
on_punch = fun_caves_mod.soft_boom,
|
||||
})
|
||||
|
||||
local fruit = minetest.get_content_id("fun_caves:fungal_tree_fruit")
|
||||
|
||||
function fun_caves_mod.make_fungal_tree(data, area, ivm, height)
|
||||
if not (data and area and ivm and height and type(data) == 'table' and type(ivm) == 'number' and type(height) == 'number') then
|
||||
return
|
||||
end
|
||||
|
||||
local leaf = minetest.get_content_id(fungal_tree_leaves[math.random(#fungal_tree_leaves)])
|
||||
local air = minetest.get_content_id('air')
|
||||
for y = 0, height do
|
||||
local radius = 1
|
||||
if y > 1 and y < height - 2 then
|
||||
radius = 2
|
||||
end
|
||||
for z = -radius,radius do
|
||||
for x = -radius,radius do
|
||||
local sr = math.random(1,100)
|
||||
local i = ivm + z*area.zstride + y*area.ystride + x
|
||||
if data[i] == air then
|
||||
if x == 0 and y == 0 and z == 0 then
|
||||
data[i] = leaf
|
||||
elseif sr == 1 then
|
||||
data[i] = fruit
|
||||
elseif sr < 50 then
|
||||
data[i] = leaf
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- multicolored growths
|
||||
local count = 0
|
||||
for color, dye in pairs(colors) do
|
||||
count = count + 1
|
||||
local name = "fun_caves:fungal_tree_leaves_"..count
|
||||
fungal_tree_leaves[#fungal_tree_leaves+1] = name
|
||||
|
||||
minetest.register_node(name, {
|
||||
description = "Fungal tree growths",
|
||||
drawtype = "allfaces_optional",
|
||||
waving = 1,
|
||||
visual_scale = 1.3,
|
||||
tiles = {"fun_caves_fungal_tree_leaves.png"..color},
|
||||
paramtype = "light",
|
||||
is_ground_content = false,
|
||||
groups = {snappy=3, flammable=3, plant=1},
|
||||
drop = {
|
||||
max_items = 1,
|
||||
items = {
|
||||
--{items = {"fun_caves:"..tree.name.."_sapling"}, rarity = tree.drop_rarity },
|
||||
{items = {name} }
|
||||
}
|
||||
},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
after_place_node = default.after_place_leaves,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "fun_caves:dry_fiber",
|
||||
recipe = name,
|
||||
cooktime = 2,
|
||||
})
|
||||
|
||||
if dye then
|
||||
minetest.register_craft({
|
||||
output = dye,
|
||||
recipe = {
|
||||
{name}
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "fun_caves:dry_fiber",
|
||||
burntime = 5,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "dye:yellow",
|
||||
recipe = {
|
||||
{"flowers:mushroom_brown"}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("fun_caves:wooden_bowl", {
|
||||
description = "Wooden Bowl",
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
tiles = {"fun_caves_wooden_bowl.png"},
|
||||
inventory_image = "fun_caves_wooden_bowl.png",
|
||||
groups = {bowl = 1, dig_immediate = 3},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'fun_caves:wooden_bowl 20',
|
||||
recipe = {
|
||||
{'group:wood', '', 'group:wood'},
|
||||
{'group:wood', '', 'group:wood'},
|
||||
{'', 'group:wood', ''},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craftitem("fun_caves:disgusting_gruel", {
|
||||
description = "Disgusting Gruel",
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
tiles = {"fun_caves_disgusting_gruel.png"},
|
||||
inventory_image = "fun_caves_disgusting_gruel.png",
|
||||
on_use = minetest.item_eat(2),
|
||||
groups = {dig_immediate = 3},
|
||||
})
|
||||
|
||||
minetest.register_craftitem("fun_caves:disgusting_gruel_raw", {
|
||||
description = "Bowl Of Gluey Paste",
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
tiles = {"fun_caves_disgusting_gruel_raw.png"},
|
||||
inventory_image = "fun_caves_disgusting_gruel_raw.png",
|
||||
groups = {dig_immediate = 3},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "fun_caves:disgusting_gruel",
|
||||
recipe = 'fun_caves:disgusting_gruel_raw',
|
||||
cooktime = 2,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "fun_caves:disgusting_gruel_raw",
|
||||
type = 'shapeless',
|
||||
recipe = {
|
||||
'fun_caves:dry_fiber',
|
||||
'group:water_bucket',
|
||||
'group:bowl',
|
||||
},
|
||||
replacements = {
|
||||
{'bucket:bucket_water', 'bucket:bucket_water'},
|
||||
{'bucket:bucket_river_water', 'bucket:bucket_river_water'},
|
||||
{'wooden_bucket:bucket_wood_water', 'wooden_bucket:bucket_wood_water'},
|
||||
{'wooden_bucket:bucket_wood_river_water', 'wooden_bucket:bucket_wood_river_water'},
|
||||
},
|
||||
})
|
88
init.lua
|
@ -1,84 +1,32 @@
|
|||
fun_caves = {}
|
||||
fun_caves.version = "1.0"
|
||||
fun_caves.path = minetest.get_modpath(minetest.get_current_modname())
|
||||
fun_caves.world = false
|
||||
-- Fun_Caves init.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
if fun_caves.world then
|
||||
minetest.register_on_mapgen_init(function(mgparams)
|
||||
minetest.set_mapgen_params({mgname="singlenode", flags="nolight"})
|
||||
end)
|
||||
|
||||
if default then
|
||||
if default.register_ores then
|
||||
default.register_ores()
|
||||
end
|
||||
if default.register_blobs then
|
||||
default.register_blobs()
|
||||
end
|
||||
if default.register_biomes then
|
||||
default.register_biomes()
|
||||
end
|
||||
if default.register_decorations then
|
||||
default.register_decorations()
|
||||
end
|
||||
if flowers.register_decorations then
|
||||
flowers.register_decorations()
|
||||
end
|
||||
end
|
||||
else
|
||||
minetest.set_mapgen_params({flags="nocaves"})
|
||||
end
|
||||
fun_caves_mod = {}
|
||||
fun_caves_mod.version = "2.0"
|
||||
fun_caves_mod.time_factor = 1 -- affects growth abms
|
||||
fun_caves_mod.light_max = 8 -- light intensity for mushroom growth
|
||||
fun_caves_mod.path = minetest.get_modpath(minetest.get_current_modname())
|
||||
fun_caves_mod.world = minetest.get_worldpath()
|
||||
|
||||
|
||||
-- Modify a node to add a group
|
||||
function minetest.add_group(node, groups)
|
||||
local def = minetest.registered_items[node]
|
||||
if not def then
|
||||
return false
|
||||
end
|
||||
local def_groups = def.groups or {}
|
||||
for group, value in pairs(groups) do
|
||||
if value ~= 0 then
|
||||
def_groups[group] = value
|
||||
else
|
||||
def_groups[group] = nil
|
||||
end
|
||||
end
|
||||
minetest.override_item(node, {groups = def_groups})
|
||||
return true
|
||||
function fun_caves_mod.clone_node(name)
|
||||
if not (name and type(name) == 'string') then
|
||||
return
|
||||
end
|
||||
|
||||
function fun_caves.clone_node(name)
|
||||
local node = minetest.registered_nodes[name]
|
||||
local node2 = table.copy(node)
|
||||
return node2
|
||||
end
|
||||
|
||||
function fun_caves.node(name)
|
||||
if not fun_caves.node_cache then
|
||||
fun_caves.node_cache = {}
|
||||
end
|
||||
|
||||
if not fun_caves.node_cache[name] then
|
||||
fun_caves.node_cache[name] = minetest.get_content_id(name)
|
||||
if name ~= "ignore" and fun_caves.node_cache[name] == 127 then
|
||||
print("*** Failure to find node: "..name)
|
||||
end
|
||||
end
|
||||
|
||||
return fun_caves.node_cache[name]
|
||||
end
|
||||
minetest.register_on_mapgen_init(function(mgparams)
|
||||
--minetest.set_mapgen_setting('mg_flags', "nocaves, nodungeons", true)
|
||||
--minetest.set_mapgen_setting('mg_flags', "nocaves", true)
|
||||
end)
|
||||
|
||||
|
||||
--dofile(fun_caves.path .. "/nodes.lua")
|
||||
dofile(fun_caves.path .. "/mapgen.lua")
|
||||
|
||||
|
||||
if fun_caves.world then
|
||||
minetest.register_on_newplayer(fun_caves.respawn)
|
||||
minetest.register_on_respawnplayer(fun_caves.respawn)
|
||||
end
|
||||
|
||||
-- Inserting helps to ensure that fun_caves operates first.
|
||||
table.insert(minetest.registered_on_generateds, 1, fun_caves.generate)
|
||||
dofile(fun_caves_mod.path .. "/mapgen.lua")
|
||||
dofile(fun_caves_mod.path .. "/abms.lua")
|
||||
|
|
772
mapgen.lua
|
@ -1,545 +1,279 @@
|
|||
-- Much of this code is translated directly from the Minetest
|
||||
-- cavegen.cpp, and is likewise distributed under the LGPL2.1
|
||||
-- Fun_Caves mapgen.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
--local DEBUG = true
|
||||
local node = fun_caves.node
|
||||
local DEBUG
|
||||
local max_depth = -28000
|
||||
local seed_noise = {offset = 0, scale = 32768, seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2, persist = 0.4, lacunarity = 2}
|
||||
fun_caves_mod.use_bi_hi = true
|
||||
|
||||
|
||||
local ground_nodes = {}
|
||||
ground_nodes[minetest.get_content_id('default:stone')] = true
|
||||
ground_nodes[minetest.get_content_id('default:desert_stone')] = true
|
||||
ground_nodes[minetest.get_content_id('default:sandstone')] = true
|
||||
ground_nodes[minetest.get_content_id('default:dirt')] = true
|
||||
ground_nodes[minetest.get_content_id('default:sand')] = true
|
||||
ground_nodes[minetest.get_content_id('default:dirt_with_grass')] = true
|
||||
ground_nodes[minetest.get_content_id('default:dirt_with_snow')] = true
|
||||
ground_nodes[minetest.get_content_id('default:dirt_with_dry_grass')] = true
|
||||
|
||||
|
||||
-- This tables looks up nodes that aren't already stored.
|
||||
local node = setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
if not (t and k and type(t) == 'table') then
|
||||
return
|
||||
end
|
||||
|
||||
t[k] = minetest.get_content_id(k)
|
||||
return t[k]
|
||||
end
|
||||
})
|
||||
|
||||
local data = {}
|
||||
local p2data = {} -- vm rotation data buffer
|
||||
local lightmap = {}
|
||||
local vm, emin, emax, a, csize, heightmap, biomemap
|
||||
local div_sz_x, div_sz_z, minp, maxp, terrain, cave
|
||||
|
||||
local terrain_noise = {offset = 0,
|
||||
scale = 20, seed = 8829, spread = {x = 40, y = 40, z = 40},
|
||||
octaves = 6, persist = 0.4, lacunarity = 2}
|
||||
|
||||
local cave_noise = {offset = 0, scale = 1,
|
||||
seed = -3977, spread = {x = 30, y = 30, z = 30}, octaves = 3,
|
||||
persist = 0.8, lacunarity = 2}
|
||||
|
||||
local seed_noise = {offset = 0, scale = 32768,
|
||||
seed = 5202, spread = {x = 80, y = 80, z = 80}, octaves = 2,
|
||||
persist = 0.4, lacunarity = 2}
|
||||
|
||||
if fun_caves.world then
|
||||
fun_caves.biomes = {}
|
||||
local biomes = fun_caves.biomes
|
||||
local biome_names = {}
|
||||
biome_names["common"] = {}
|
||||
biome_names["uncommon"] = {}
|
||||
do
|
||||
local biome_terrain_scale = {}
|
||||
biome_terrain_scale["coniferous_forest"] = 0.75
|
||||
biome_terrain_scale["rainforest"] = 0.33
|
||||
biome_terrain_scale["underground"] = 1.5
|
||||
|
||||
local tree_biomes = {}
|
||||
tree_biomes["deciduous_forest"] = {"deciduous_trees"}
|
||||
tree_biomes["coniferous_forest"] = {"conifer_trees"}
|
||||
tree_biomes["taiga"] = {"conifer_trees"}
|
||||
tree_biomes["rainforest"] = {"jungle_trees"}
|
||||
tree_biomes["rainforest_swamp"] = {"jungle_trees"}
|
||||
tree_biomes["coniferous_forest"] = {"conifer_trees"}
|
||||
tree_biomes["savanna"] = {"acacia_trees"}
|
||||
|
||||
for i, obiome in pairs(minetest.registered_biomes) do
|
||||
local biome = table.copy(obiome)
|
||||
biome.special_tree_prob = 2
|
||||
if biome.name == "savanna" then
|
||||
biome.special_tree_prob = 30
|
||||
end
|
||||
local rarity = "common"
|
||||
biome.terrain_scale = biome_terrain_scale[biome] or 0.5
|
||||
if string.find(biome.name, "ocean") then
|
||||
biome.terrain_scale = 1
|
||||
rarity = "uncommon"
|
||||
end
|
||||
if string.find(biome.name, "swamp") then
|
||||
biome.terrain_scale = 0.25
|
||||
rarity = "uncommon"
|
||||
end
|
||||
if string.find(biome.name, "beach") then
|
||||
biome.terrain_scale = 0.25
|
||||
rarity = "uncommon"
|
||||
end
|
||||
if string.find(biome.name, "^underground$") then
|
||||
biome.node_top = "default:stone"
|
||||
rarity = "uncommon"
|
||||
end
|
||||
biome.special_trees = tree_biomes[biome.name]
|
||||
biomes[biome.name] = biome
|
||||
biome_names[rarity][#biome_names[rarity]+1] = biome.name
|
||||
end
|
||||
end
|
||||
biomes["control"] = {}
|
||||
end
|
||||
|
||||
if false then
|
||||
local cave_stones = {
|
||||
"fun_caves:stone_with_moss",
|
||||
"fun_caves:stone_with_lichen",
|
||||
"fun_caves:stone_with_algae",
|
||||
"fun_caves:stone_with_salt",
|
||||
fun_caves_mod.cave_biomes = {
|
||||
algae = {
|
||||
biome_val_low = 0,
|
||||
biome_val_high = 0.2,
|
||||
ceiling_node = 'fun_caves:stone_with_algae',
|
||||
dirt = 'default:dirt',
|
||||
dirt_chance = 10,
|
||||
floor_node = 'fun_caves:stone_with_algae',
|
||||
fungi = true,
|
||||
stalactite = 'fun_caves:stalactite_slimy',
|
||||
stalactite_chance = 12,
|
||||
stalagmite = 'fun_caves:stalagmite_slimy',
|
||||
stalagmite_chance = 12,
|
||||
stone_depth = 1,
|
||||
underwater = true,
|
||||
},
|
||||
coal = {
|
||||
biome_val_low = 0.5,
|
||||
biome_val_high = 0.6,
|
||||
ceiling_node = 'fun_caves:black_sand',
|
||||
deco = 'default:coalblock',
|
||||
deco_chance = 100,
|
||||
floor_node = 'fun_caves:black_sand',
|
||||
stalagmite = 'fun_caves:constant_flame',
|
||||
stalagmite_chance = 50,
|
||||
stone_depth = 2,
|
||||
underwater = false,
|
||||
},
|
||||
hot = {
|
||||
biome_val_low = 0.6,
|
||||
biome_val_high = 99,
|
||||
ceiling_node = 'fun_caves:hot_cobble',
|
||||
floor_node = 'fun_caves:hot_cobble',
|
||||
fluid = 'default:lava_source',
|
||||
fluid_chance = 300,
|
||||
stalagmite = fun_caves_mod.hot_spikes,
|
||||
stalagmite_chance = 50,
|
||||
stone_depth = 1,
|
||||
underwater = false,
|
||||
},
|
||||
ice = {
|
||||
biome_val_low = -99,
|
||||
biome_val_high = -0.6,
|
||||
ceiling_node = 'default:ice',
|
||||
floor_node = 'default:ice',
|
||||
stalactite = 'fun_caves:icicle_down',
|
||||
stalactite_chance = 12,
|
||||
stalagmite = 'fun_caves:icicle_up',
|
||||
stalagmite_chance = 12,
|
||||
stone_depth = 2,
|
||||
underwater = true,
|
||||
},
|
||||
ice_thin = {
|
||||
biome_val_low = -0.6,
|
||||
biome_val_high = -0.5,
|
||||
ceiling_node = 'fun_caves:thin_ice',
|
||||
floor_node = 'fun_caves:thin_ice',
|
||||
stone_depth = 2,
|
||||
underwater = true,
|
||||
},
|
||||
lichen = {
|
||||
biome_val_low = -0.3,
|
||||
biome_val_high = 0,
|
||||
ceiling_node = 'fun_caves:stone_with_lichen',
|
||||
dirt = 'default:dirt',
|
||||
dirt_chance = 10,
|
||||
floor_node = 'fun_caves:stone_with_lichen',
|
||||
fungi = true,
|
||||
stalactite = 'fun_caves:stalactite',
|
||||
stalactite_chance = 12,
|
||||
stalagmite = 'fun_caves:stalagmite',
|
||||
stalagmite_chance = 12,
|
||||
stone_depth = 1,
|
||||
underwater = true,
|
||||
},
|
||||
lichen_dead = {
|
||||
biome_val_low = -0.6,
|
||||
biome_val_high = -0.5,
|
||||
ceiling_node = 'fun_caves:stone_with_lichen',
|
||||
floor_node = 'fun_caves:stone_with_lichen',
|
||||
stalactite = 'fun_caves:stalactite',
|
||||
stalactite_chance = 12,
|
||||
stalagmite = 'fun_caves:stalagmite',
|
||||
stalagmite_chance = 12,
|
||||
stone_depth = 1,
|
||||
underwater = true,
|
||||
},
|
||||
moss = {
|
||||
biome_val_low = -0.5,
|
||||
biome_val_high = -0.3,
|
||||
ceiling_node = 'fun_caves:stone_with_moss',
|
||||
deco = 'fun_caves:glowing_fungal_stone',
|
||||
deco_chance = 50,
|
||||
floor_node = 'fun_caves:stone_with_moss',
|
||||
fluid = 'default:water_source',
|
||||
fluid_chance = 300,
|
||||
stalactite = 'fun_caves:stalactite_mossy',
|
||||
stalactite_chance = 12,
|
||||
stalagmite = 'fun_caves:stalagmite_mossy',
|
||||
stalagmite_chance = 12,
|
||||
stone_depth = 1,
|
||||
underwater = true,
|
||||
},
|
||||
salt = {
|
||||
biome_val_low = 0.2,
|
||||
biome_val_high = 0.35,
|
||||
ceiling_node = 'fun_caves:stone_with_salt',
|
||||
deco = 'fun_caves:radioactive_ore',
|
||||
deco_chance = 500,
|
||||
floor_node = 'fun_caves:stone_with_salt',
|
||||
stone_depth = 2,
|
||||
underwater = false,
|
||||
},
|
||||
sand = {
|
||||
biome_val_low = 0.35,
|
||||
biome_val_high = 0.5,
|
||||
ceiling_node = 'default:sand',
|
||||
floor_node = 'default:sand',
|
||||
stone_depth = 2,
|
||||
underwater = true,
|
||||
},
|
||||
}
|
||||
local mushroom_stones = {}
|
||||
mushroom_stones[node("default:stone")] = true
|
||||
mushroom_stones[node("fun_caves:stone_with_algae")] = true
|
||||
mushroom_stones[node("fun_caves:stone_with_lichen")] = true
|
||||
end
|
||||
|
||||
local function place_schematic(pos, schem, center)
|
||||
local rot = math.random(4) - 1
|
||||
local yslice = {}
|
||||
if schem.yslice_prob then
|
||||
for _, ys in pairs(schem.yslice_prob) do
|
||||
yslice[ys.ypos] = ys.prob
|
||||
end
|
||||
end
|
||||
|
||||
if center then
|
||||
pos.x = pos.x - math.floor(schem.size.x / 2)
|
||||
pos.z = pos.z - math.floor(schem.size.z / 2)
|
||||
end
|
||||
|
||||
for z1 = 0, schem.size.z - 1 do
|
||||
for x1 = 0, schem.size.x - 1 do
|
||||
local x, z
|
||||
if rot == 0 then
|
||||
x, z = x1, z1
|
||||
elseif rot == 1 then
|
||||
x, z = schem.size.z - z1 - 1, x1
|
||||
elseif rot == 2 then
|
||||
x, z = schem.size.x - x1 - 1, schem.size.z - z1 - 1
|
||||
elseif rot == 3 then
|
||||
x, z = z1, schem.size.x - x1 - 1
|
||||
end
|
||||
local dz = pos.z - minp.z + z
|
||||
local dx = pos.x - minp.x + x
|
||||
if pos.x + x > minp.x and pos.x + x < maxp.x and pos.z + z > minp.z and pos.z + z < maxp.z then
|
||||
local ivm = a:index(pos.x + x, pos.y, pos.z + z)
|
||||
local isch = z1 * schem.size.y * schem.size.x + x1 + 1
|
||||
for y = 0, schem.size.y - 1 do
|
||||
local dy = pos.y - minp.y + y
|
||||
if math.min(dx, csize.x - dx) + math.min(dy, csize.y - dy) + math.min(dz, csize.z - dz) > bevel then
|
||||
if yslice[y] or 255 >= math.random(255) then
|
||||
local prob = schem.data[isch].prob or schem.data[isch].param1 or 255
|
||||
if prob >= math.random(255) and schem.data[isch].name ~= "air" then
|
||||
data[ivm] = node(schem.data[isch].name)
|
||||
end
|
||||
local param2 = schem.data[isch].param2 or 0
|
||||
p2data[ivm] = param2
|
||||
end
|
||||
end
|
||||
|
||||
ivm = ivm + a.ystride
|
||||
isch = isch + schem.size.x
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_decoration(biome)
|
||||
for i, deco in pairs(fun_caves.decorations) do
|
||||
if not deco.biomes or deco.biomes[biome] then
|
||||
local range = 1000
|
||||
if deco.deco_type == "simple" then
|
||||
if deco.fill_ratio and math.random(range) - 1 < deco.fill_ratio * 1000 then
|
||||
return deco.decoration
|
||||
end
|
||||
else
|
||||
-- nop
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local np_cave = {offset = 6, scale = 6, seed = 34329, spread = {x = 250, y = 250, z = 250}, octaves = 3, persist = 0.5, lacunarity = 2}
|
||||
|
||||
local function rangelim(x, y, z)
|
||||
return math.max(math.min(x, z), y)
|
||||
local function generate(p_minp, p_maxp, seed)
|
||||
if not (p_minp and p_maxp and seed) then
|
||||
return
|
||||
end
|
||||
|
||||
local function carveRoute(this, vec, f, randomize_xz, tunnel_above_ground)
|
||||
local startp = vector.new(this.orp)
|
||||
startp = vector.add(startp, this.of)
|
||||
|
||||
local fp = vector.add(this.orp, vector.multiply(vec, f))
|
||||
fp.x = fp.x + 0.1 * math.random(-10, 10)
|
||||
fp.z = fp.z + 0.1 * math.random(-10, 10)
|
||||
local cp = vector.new(fp)
|
||||
|
||||
local d0 = -this.rs/2
|
||||
local d1 = d0 + this.rs
|
||||
if (randomize_xz) then
|
||||
d0 = d0 + math.random(-1, 1)
|
||||
d1 = d1 + math.random(-1, 1)
|
||||
local minp, maxp = p_minp, p_maxp
|
||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
if not (vm and emin and emax) then
|
||||
return
|
||||
end
|
||||
|
||||
for z0 = d0, d1 do
|
||||
local si = this.rs / 2 - math.max(0, math.abs(z0) - this.rs / 7 - 1)
|
||||
for x0 = -si - math.random(0,1), si - 1 + math.random(0,1) do
|
||||
if (tunnel_above_ground) then
|
||||
--continue
|
||||
else
|
||||
local maxabsxz = math.max(math.abs(x0), math.abs(z0))
|
||||
local si2 = this.rs / 2 - math.max(0, maxabsxz - this.rs / 7 - 1)
|
||||
for y0 = -si2, si2 do
|
||||
if (this.large_cave_is_flat) then
|
||||
-- Make large caves not so tall
|
||||
if (this.rs > 7 and math.abs(y0) >= this.rs / 3) then
|
||||
--continue
|
||||
else
|
||||
local p = vector.new(cp.x + x0, cp.y + y0, cp.z + z0)
|
||||
p = vector.add(p, this.of)
|
||||
|
||||
if not a:containsp(p) then
|
||||
--continue
|
||||
else
|
||||
local i = a:indexp(vector.round(p))
|
||||
local c = data[i]
|
||||
--if (not ndef.get(c).is_ground_content) then
|
||||
-- ** check for ground content? **
|
||||
local donotdig = false
|
||||
if c == node("default:desert_sand") then
|
||||
donotdig = true
|
||||
end
|
||||
|
||||
if donotdig then
|
||||
--continue
|
||||
else
|
||||
if (this.large_cave) then
|
||||
local full_ymin = minp.y - 16
|
||||
local full_ymax = maxp.y + 16
|
||||
|
||||
if this.flooded and not this.lava_cave then
|
||||
data[i] = (p.y <= this.water_level) and node("default:water_source") or node("air")
|
||||
elseif this.flooded then
|
||||
data[i] = (p.y < startp.y - 2) and node("default:lava_source") or node("air")
|
||||
else
|
||||
data[i] = node("air")
|
||||
end
|
||||
else
|
||||
if (c == node("ignore") or c == node("air")) then
|
||||
--continue
|
||||
else
|
||||
data[i] = node("air")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function makeTunnel(this, dirswitch)
|
||||
if dirswitch and not this.large_cave then
|
||||
this.main_direction = vector.new(
|
||||
((math.random() * 20) - 10) / 10,
|
||||
((math.random() * 20) - 10) / 30,
|
||||
((math.random() * 20) - 10) / 10
|
||||
)
|
||||
this.main_direction = vector.multiply(this.main_direction, math.random(0, 10) / 10)
|
||||
end
|
||||
|
||||
-- Randomize size
|
||||
local min_d = this.min_tunnel_diameter
|
||||
local max_d = this.max_tunnel_diameter
|
||||
this.rs = math.random(min_d, max_d)
|
||||
local rs_part_max_length_rs = this.rs * this.part_max_length_rs
|
||||
|
||||
local maxlen
|
||||
if this.large_cave then
|
||||
maxlen = vector.new(
|
||||
rs_part_max_length_rs,
|
||||
rs_part_max_length_rs / 2,
|
||||
rs_part_max_length_rs
|
||||
)
|
||||
else
|
||||
maxlen = vector.new(
|
||||
rs_part_max_length_rs,
|
||||
math.random(1, rs_part_max_length_rs),
|
||||
rs_part_max_length_rs
|
||||
)
|
||||
end
|
||||
|
||||
local vec = vector.new(
|
||||
(math.random() * maxlen.x) - maxlen.x / 2,
|
||||
(math.random() * maxlen.y) - maxlen.y / 2,
|
||||
(math.random() * maxlen.z) - maxlen.z / 2
|
||||
)
|
||||
|
||||
-- Jump downward sometimes
|
||||
if not this.large_cave and math.random(0, 12) == 0 then
|
||||
vec = vector.new(
|
||||
(math.random() * maxlen.x) - maxlen.x / 2,
|
||||
(math.random() * (maxlen.y * 2)) - maxlen.y,
|
||||
(math.random() * maxlen.z) - maxlen.z / 2
|
||||
)
|
||||
end
|
||||
|
||||
-- Do not make caves that are entirely above ground, to fix
|
||||
-- shadow bugs caused by overgenerated large caves.
|
||||
-- It is only necessary to check the startpoint and endpoint.
|
||||
local orpi = vector.new(this.orp.x, this.orp.y, this.orp.z)
|
||||
local veci = vector.new(vec.x, vec.y, vec.z)
|
||||
local h1
|
||||
local h2
|
||||
|
||||
local p1 = vector.add(orpi, veci, this.of, this.rs / 2)
|
||||
if (p1.z >= minp.z and p1.z <= maxp.z and
|
||||
p1.x >= minp.x and p1.x <= maxp.x) then
|
||||
local index1 = math.floor(p1.z - minp.z + 0.5) * csize.x + math.floor(p1.x - minp.x + 0.5) + 1
|
||||
h1 = heightmap[index1]
|
||||
else
|
||||
h1 = this.water_level -- If not in heightmap
|
||||
end
|
||||
|
||||
local p2 = vector.add(orpi, this.of, this.rs / 2)
|
||||
if (p2.z >= minp.z and p2.z <= maxp.z and
|
||||
p2.x >= minp.x and p2.x <= maxp.x) then
|
||||
local index2 = math.floor(p2.z - minp.z + 0.5) * csize.x + math.floor(p2.x - minp.x + 0.5) + 1
|
||||
h2 = heightmap[index2]
|
||||
else
|
||||
h2 = this.water_level
|
||||
end
|
||||
|
||||
-- If startpoint and endpoint are above ground,
|
||||
-- disable placing of nodes in carveRoute while
|
||||
-- still running all pseudorandom calls to ensure
|
||||
-- caves consistent with existing worlds.
|
||||
local tunnel_above_ground = p1.y > h1 and p2.y > h2
|
||||
|
||||
vec = vector.add(vec, this.main_direction)
|
||||
|
||||
local rp = vector.add(this.orp, vec)
|
||||
if (rp.x < 0) then
|
||||
rp.x = 0
|
||||
elseif (rp.x >= this.ar.x) then
|
||||
rp.x = this.ar.x - 1
|
||||
end
|
||||
|
||||
if (rp.y < this.route_y_min) then
|
||||
rp.y = this.route_y_min
|
||||
elseif (rp.y >= this.route_y_max) then
|
||||
rp.y = this.route_y_max - 1
|
||||
end
|
||||
|
||||
if (rp.z < 0) then
|
||||
rp.z = 0
|
||||
elseif (rp.z >= this.ar.z) then
|
||||
rp.z = this.ar.z - 1
|
||||
end
|
||||
|
||||
vec = vector.subtract(rp, this.orp)
|
||||
|
||||
local veclen = vector.length(vec)
|
||||
-- As odd as it sounds, veclen is *exactly* 0.0 sometimes, causing a FPE
|
||||
if (veclen < 0.05) then
|
||||
veclen = 1.0
|
||||
end
|
||||
|
||||
-- Every second section is rough
|
||||
local randomize_xz = (math.random(1, 2) == 1)
|
||||
|
||||
-- Carve routes
|
||||
for f = 0, 1, 1.0 / veclen do
|
||||
--print(dump(vec))
|
||||
carveRoute(this, vec, f, randomize_xz, tunnel_above_ground)
|
||||
end
|
||||
|
||||
this.orp = rp
|
||||
end
|
||||
|
||||
local function makeCave(this, max_stone_height)
|
||||
this.max_stone_y = max_stone_height
|
||||
this.main_direction = vector.new(0, 0, 0)
|
||||
--print(dump(this))
|
||||
|
||||
-- Allowed route area size in nodes
|
||||
this.ar = vector.add(vector.subtract(maxp, minp), 1)
|
||||
-- Area starting point in nodes
|
||||
this.of = minp
|
||||
|
||||
-- Allow a bit more
|
||||
--(this should be more than the maximum radius of the tunnel)
|
||||
local max_spread_amount = 16
|
||||
local insure = 10
|
||||
local more = math.max(max_spread_amount - this.max_tunnel_diameter / 2 - insure, 1)
|
||||
this.ar = vector.add(this.ar, vector.multiply(vector.new(1,0,1), (more * 2)))
|
||||
this.of = vector.subtract(this.of, vector.multiply(vector.new(1,0,1), more))
|
||||
|
||||
this.route_y_min = 0
|
||||
-- Allow half a diameter + 7 over stone surface
|
||||
this.route_y_max = -this.of.y + this.max_stone_y + this.max_tunnel_diameter / 2 + 7
|
||||
|
||||
-- Limit maximum to area
|
||||
this.route_y_max = rangelim(this.route_y_max, 0, this.ar.y - 1)
|
||||
|
||||
if this.large_cave then
|
||||
local min = 0
|
||||
if minp.y < this.water_level and maxp.y > this.water_level then
|
||||
min = this.water_level - this.max_tunnel_diameter/3 - this.of.y
|
||||
this.route_y_max = this.water_level + this.max_tunnel_diameter/3 - this.of.y
|
||||
end
|
||||
this.route_y_min = math.random(min, min + this.max_tunnel_diameter)
|
||||
this.route_y_min = rangelim(this.route_y_min, 0, this.route_y_max)
|
||||
end
|
||||
|
||||
local route_start_y_min = this.route_y_min
|
||||
local route_start_y_max = this.route_y_max
|
||||
|
||||
route_start_y_min = rangelim(route_start_y_min, 0, this.ar.y-1)
|
||||
route_start_y_max = rangelim(route_start_y_max, route_start_y_min, this.ar.y-1)
|
||||
|
||||
-- Randomize starting position
|
||||
this.orp = vector.new(
|
||||
(math.random() * this.ar.x) + 0.5,
|
||||
(math.random(route_start_y_min, route_start_y_max)) + 0.5,
|
||||
(math.random() * this.ar.z) + 0.5
|
||||
)
|
||||
|
||||
-- Generate some tunnel starting from orp
|
||||
for j = 0, this.tunnel_routepoints do
|
||||
--print(dump(this.orp))
|
||||
makeTunnel(this, j % this.dswitchint == 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function CaveV6(is_large_cave)
|
||||
local this = {}
|
||||
this.water_level = 1
|
||||
this.large_cave = is_large_cave
|
||||
|
||||
this.min_tunnel_diameter = 2
|
||||
this.max_tunnel_diameter = math.random(2, 6)
|
||||
this.dswitchint = math.random(1, 14)
|
||||
this.flooded = true
|
||||
this.lava_cave = false
|
||||
|
||||
if maxp.y < this.water_level and minp.y / 31000 - math.random() < -0.5 then
|
||||
this.lava_cave = true
|
||||
end
|
||||
|
||||
if this.large_cave then
|
||||
this.part_max_length_rs = math.random(2,4)
|
||||
this.tunnel_routepoints = math.random(5, math.random(15,30))
|
||||
this.min_tunnel_diameter = 5
|
||||
this.max_tunnel_diameter = math.random(7, math.random(8,24))
|
||||
else
|
||||
this.part_max_length_rs = math.random(2,9)
|
||||
this.tunnel_routepoints = math.random(10, math.random(15,30))
|
||||
end
|
||||
|
||||
this.large_cave_is_flat = (math.random(0,1) == 0)
|
||||
return this
|
||||
end
|
||||
|
||||
local function getBiome(x, z)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function generateCaves(max_stone_y)
|
||||
local cave_amount = minetest.get_perlin(np_cave):get2d({x=minp.x, y=minp.y})
|
||||
local volume_nodes = (maxp.x - minp.x + 1) * (maxp.y - minp.y + 1) * 16
|
||||
cave_amount = math.max(0.0, cave_amount)
|
||||
local caves_count = cave_amount * volume_nodes / 50000
|
||||
local bruises_count = 1
|
||||
|
||||
if (math.random(1, 6) == 1) then
|
||||
bruises_count = math.random(0, math.random(0, 2))
|
||||
end
|
||||
|
||||
if (getBiome(minp.x, minp.z) == "desert") then
|
||||
caves_count = caves_count / 3
|
||||
bruises_count = caves_count / 3
|
||||
end
|
||||
|
||||
for i = 0, caves_count + bruises_count do
|
||||
local large_cave = (i >= caves_count)
|
||||
local cave = CaveV6(large_cave)
|
||||
|
||||
--print(dump(cave))
|
||||
makeCave(cave, max_stone_y)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function fun_caves.generate(p_minp, p_maxp, seed)
|
||||
minp, maxp = p_minp, p_maxp
|
||||
vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
vm:get_data(data)
|
||||
--p2data = vm:get_param2_data()
|
||||
a = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
||||
csize = vector.add(vector.subtract(maxp, minp), 1)
|
||||
heightmap = minetest.get_mapgen_object("heightmap")
|
||||
local heightmap
|
||||
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
||||
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
||||
local write
|
||||
|
||||
local max_stone_height = -40000
|
||||
|
||||
if minetest.get_modpath('ramoid') and ramoid_mod and ramoid_mod.ramoid_depth then
|
||||
local avg = (minp.y + maxp.y) / 2
|
||||
if avg > (ramoid_mod.ramoid_depth - 1) * 80 - 32 and avg < ramoid_mod.ramoid_depth * 80 - 32 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.get_modpath('underworlds') and underworlds_mod and underworlds_mod.underzones then
|
||||
local avg = (minp.y + maxp.y) / 2
|
||||
for _, uz in pairs(underworlds_mod.underzones) do
|
||||
if avg <= uz.upper_bound and avg >= uz.lower_bound then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if fun_caves_mod.use_bi_hi then
|
||||
heightmap = minetest.get_mapgen_object("heightmap")
|
||||
end
|
||||
|
||||
|
||||
-- Correct heightmap.
|
||||
if maxp.y < -300 or minp.y > 300 then
|
||||
for i = 1, #heightmap do
|
||||
heightmap[i] = (maxp.y < 0) and max_depth or - max_depth
|
||||
end
|
||||
else
|
||||
local index = 0
|
||||
for z = minp.z, maxp.z do
|
||||
for x = minp.x, maxp.x do
|
||||
index = index + 1
|
||||
if max_stone_height < heightmap[index] then
|
||||
max_stone_height = heightmap[index]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Deal with memory issues. This, of course, is supposed to be automatic.
|
||||
local mem = math.floor(collectgarbage("count")/1024)
|
||||
if mem > 400 then
|
||||
print("Fun Caves: Manually collecting garbage...")
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
-- use the same seed (based on perlin noise).
|
||||
math.randomseed(minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z}))
|
||||
|
||||
-- Keep this first after seeding!
|
||||
local px = math.floor((minp.x + 32) / csize.x)
|
||||
local pz = math.floor((minp.z + 32) / csize.z)
|
||||
|
||||
generateCaves(max_stone_height)
|
||||
|
||||
--local index = 0
|
||||
--local index3d = 0
|
||||
--for z = minp.z, maxp.z do
|
||||
-- local dz = z - minp.z
|
||||
-- for x = minp.x, maxp.x do
|
||||
-- index = index + 1
|
||||
-- local dx = x - minp.x
|
||||
-- index3d = dz * csize.y * csize.x + dx + 1
|
||||
-- local ivm = a:index(x, minp.y, z)
|
||||
|
||||
-- for y = minp.y, maxp.y do
|
||||
-- local dy = y - minp.y
|
||||
|
||||
-- ivm = ivm + a.ystride
|
||||
-- index3d = index3d + csize.x
|
||||
-- end
|
||||
-- end
|
||||
--end
|
||||
|
||||
|
||||
vm:set_data(data)
|
||||
--minetest.generate_ores(vm, minp, maxp)
|
||||
--minetest.generate_decorations(vm, minp, maxp)
|
||||
--vm:set_param2_data(p2data)
|
||||
if DEBUG then
|
||||
vm:set_lighting({day = 15, night = 15})
|
||||
local height = heightmap[index]
|
||||
if height and height < maxp.y - 1 and height > minp.y then
|
||||
--nop
|
||||
else
|
||||
vm:set_lighting({day = 0, night = 0})
|
||||
height = - max_depth
|
||||
local ivm2 = area:index(x, maxp.y + 8, z)
|
||||
for y = maxp.y + 8, minp.y - 8, -1 do
|
||||
if ground_nodes[data[ivm2]] then
|
||||
height = (y < maxp.y + 8) and y or max_depth
|
||||
break
|
||||
end
|
||||
ivm2 = ivm2 - area.ystride
|
||||
end
|
||||
heightmap[index] = height
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for fake_loop = 1, 1 do
|
||||
if fun_caves_mod.cavegen and fun_caves_mod.decogen then
|
||||
local h2, write_cave
|
||||
write_cave = fun_caves_mod.cavegen(minp, maxp, data, area, node, heightmap)
|
||||
write = write or write_cave
|
||||
|
||||
local write_deco
|
||||
write_deco = fun_caves_mod.decogen(minp, maxp, data, area, node, heightmap)
|
||||
write = write or write_deco
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if write then
|
||||
vm:set_data(data)
|
||||
|
||||
if DEBUG then
|
||||
vm:set_lighting({day = 8, night = 8})
|
||||
else
|
||||
vm:set_lighting({day = 0, night = 0}, minp, maxp)
|
||||
vm:calc_lighting()
|
||||
end
|
||||
vm:update_liquids()
|
||||
vm:write_to_map()
|
||||
|
||||
vm, a, lightmap, heightmap, biomemap, terrain, cave = nil, nil, nil, nil, nil, nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if fun_caves_mod.path then
|
||||
dofile(fun_caves_mod.path .. "/cavegen.lua")
|
||||
dofile(fun_caves_mod.path .. "/deco.lua")
|
||||
end
|
||||
|
||||
|
||||
local function pgenerate(...)
|
||||
local status, err = pcall(generate, ...)
|
||||
--local status, err = true
|
||||
--generate(...)
|
||||
if not status then
|
||||
print('Fun Caves: Could not generate terrain:')
|
||||
print(dump(err))
|
||||
collectgarbage("collect")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Inserting helps to ensure that fun_caves_mod operates first.
|
||||
--table.insert(minetest.registered_on_generateds, 1, pgenerate)
|
||||
minetest.register_on_generated(pgenerate)
|
||||
|
|
451
nodes.lua
Normal file
|
@ -0,0 +1,451 @@
|
|||
-- Fun_Caves nodes.lua
|
||||
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||
|
||||
|
||||
local light_max = fun_caves_mod.light_max or 10
|
||||
|
||||
if minetest.registered_items['underworlds:black_sand'] then
|
||||
minetest.register_alias("fun_caves:black_sand", 'underworlds:black_sand')
|
||||
else
|
||||
-- black (oily) sand
|
||||
local newnode = fun_caves_mod.clone_node("default:sand")
|
||||
newnode.description = "Black Sand"
|
||||
newnode.tiles = {"fun_caves_black_sand.png"}
|
||||
newnode.groups['falling_node'] = 0
|
||||
minetest.register_node("fun_caves:black_sand", newnode)
|
||||
end
|
||||
|
||||
if minetest.registered_items['underworlds:hot_cobble'] then
|
||||
minetest.register_alias("fun_caves:hot_cobble", 'underworlds:hot_cobble')
|
||||
else
|
||||
-- cobble, hot - cobble with lava instead of mortar XD
|
||||
minetest.register_node("fun_caves:hot_cobble", {
|
||||
description = "Hot Cobble",
|
||||
tiles = {"caverealms_hot_cobble.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=2, surface_hot=3},
|
||||
--light_source = 2,
|
||||
damage_per_second = 1,
|
||||
sounds = default.node_sound_stone_defaults({
|
||||
footstep = {name="default_stone_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
if minetest.registered_items['underworlds:glowing_fungal_stone'] then
|
||||
minetest.register_alias("fun_caves:glowing_fungal_stone", 'underworlds:glowing_fungal_stone')
|
||||
minetest.register_alias("fun_caves:glowing_fungus", 'underworlds:glowing_fungus')
|
||||
else
|
||||
-- Glowing fungal stone provides an eerie light.
|
||||
minetest.register_node("fun_caves:glowing_fungal_stone", {
|
||||
description = "Glowing Fungal Stone",
|
||||
tiles = {"default_stone.png^vmg_glowing_fungal.png",},
|
||||
is_ground_content = true,
|
||||
light_source = light_max - 4,
|
||||
groups = {cracky=3, stone=1},
|
||||
drop = {items={ {items={"default:cobble"},}, {items={"fun_caves:glowing_fungus",},},},},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
-- Glowing fungus grows underground.
|
||||
minetest.register_craftitem("fun_caves:glowing_fungus", {
|
||||
description = "Glowing Fungus",
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
tiles = {"vmg_glowing_fungus.png"},
|
||||
inventory_image = "vmg_glowing_fungus.png",
|
||||
groups = {dig_immediate = 3},
|
||||
})
|
||||
end
|
||||
|
||||
-- moon glass (glows)
|
||||
if not minetest.registered_items['elixirs:moon_glass'] then
|
||||
newnode = fun_caves_mod.clone_node("default:glass")
|
||||
newnode.description = "Glowing Glass"
|
||||
newnode.light_source = default.LIGHT_MAX
|
||||
minetest.register_node("fun_caves:moon_glass", newnode)
|
||||
end
|
||||
|
||||
-- Moon juice is extracted from glowing fungus, to make glowing materials.
|
||||
minetest.register_craftitem("fun_caves:moon_juice", {
|
||||
description = "Moon Juice",
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
tiles = {"vmg_moon_juice.png"},
|
||||
inventory_image = "vmg_moon_juice.png",
|
||||
--groups = {dig_immediate = 3, attached_node = 1},
|
||||
groups = {dig_immediate = 3, vessel = 1},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
-- mushroom cap, giant
|
||||
local cap = {
|
||||
description = "Giant Mushroom Cap",
|
||||
tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"},
|
||||
is_ground_content = false,
|
||||
paramtype = "light",
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed",
|
||||
fixed = {
|
||||
{-0.3, -0.25, -0.3, 0.3, 0.5, 0.3},
|
||||
{-0.3, -0.25, -0.4, 0.3, 0.4, -0.3},
|
||||
{-0.3, -0.25, 0.3, 0.3, 0.4, 0.4},
|
||||
{-0.4, -0.25, -0.3, -0.3, 0.4, 0.3},
|
||||
{0.3, -0.25, -0.3, 0.4, 0.4, 0.3},
|
||||
{-0.4, -0.5, -0.4, 0.4, -0.25, 0.4},
|
||||
{-0.5, -0.5, -0.4, -0.4, -0.25, 0.4},
|
||||
{0.4, -0.5, -0.4, 0.5, -0.25, 0.4},
|
||||
{-0.4, -0.5, -0.5, 0.4, -0.25, -0.4},
|
||||
{-0.4, -0.5, 0.4, 0.4, -0.25, 0.5},
|
||||
} },
|
||||
light_source = light_max,
|
||||
groups = {fleshy=1, falling_node = 1, dig_immediate=3, flammable=2, plant=1},
|
||||
}
|
||||
minetest.register_node("fun_caves:giant_mushroom_cap", cap)
|
||||
|
||||
-- mushroom cap, huge
|
||||
minetest.register_node("fun_caves:huge_mushroom_cap", {
|
||||
description = "Huge Mushroom Cap",
|
||||
tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"},
|
||||
is_ground_content = false,
|
||||
paramtype = "light",
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.33, 0.5, -0.33, 0.33},
|
||||
{-0.33, -0.5, 0.33, 0.33, -0.33, 0.5},
|
||||
{-0.33, -0.5, -0.33, 0.33, -0.33, -0.5},
|
||||
{-0.33, -0.33, -0.33, 0.33, -0.17, 0.33},
|
||||
} },
|
||||
light_source = light_max,
|
||||
groups = {fleshy=1, falling_node = 1, dig_immediate=3, flammable=2, plant=1},
|
||||
})
|
||||
|
||||
-- mushroom stem, giant or huge
|
||||
minetest.register_node("fun_caves:giant_mushroom_stem", {
|
||||
description = "Giant Mushroom Stem",
|
||||
tiles = {"vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png"},
|
||||
is_ground_content = false,
|
||||
groups = {choppy=2, flammable=2, plant=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed", fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, }},
|
||||
})
|
||||
|
||||
-- obsidian, glowing
|
||||
minetest.register_node("fun_caves:glow_obsidian", {
|
||||
description = "Glowing Obsidian",
|
||||
tiles = {"caverealms_glow_obsidian.png"},
|
||||
is_ground_content = true,
|
||||
groups = {stone=2, crumbly=1},
|
||||
--light_source = 7,
|
||||
sounds = default.node_sound_stone_defaults({
|
||||
footstep = {name="default_stone_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
-- obsidian, glowing, 2 - has traces of lava
|
||||
minetest.register_node("fun_caves:glow_obsidian_2", {
|
||||
description = "Hot Glow Obsidian",
|
||||
tiles = {"caverealms_glow_obsidian2.png"},
|
||||
is_ground_content = true,
|
||||
groups = {stone=2, crumbly=1, surface_hot=3, igniter=1},
|
||||
damage_per_second = 1,
|
||||
--light_source = 9,
|
||||
sounds = default.node_sound_stone_defaults({
|
||||
footstep = {name="default_stone_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
-- salt
|
||||
minetest.register_node("fun_caves:stone_with_salt", {
|
||||
description = "Cave Stone with Salt",
|
||||
tiles = {"caverealms_salty2.png"},
|
||||
paramtype = "light",
|
||||
use_texture_alpha = true,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = false,
|
||||
is_ground_content = true,
|
||||
groups = {stone=1, crumbly=3, cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
-- salt, radioactive ore
|
||||
newnode = fun_caves_mod.clone_node("fun_caves:stone_with_salt")
|
||||
newnode.description = "Salt With Radioactive Ore"
|
||||
newnode.tiles = {"fun_caves_radioactive_ore.png"}
|
||||
newnode.light_source = 4
|
||||
minetest.register_node("fun_caves:radioactive_ore", newnode)
|
||||
|
||||
if minetest.registered_items['underworlds:thin_ice'] then
|
||||
minetest.register_alias("fun_caves:thin_ice", 'underworlds:thin_ice')
|
||||
else
|
||||
-- ice, thin -- transparent
|
||||
minetest.register_node("fun_caves:thin_ice", {
|
||||
description = "Thin Ice",
|
||||
tiles = {"caverealms_thin_ice.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
use_texture_alpha = true,
|
||||
light_source = 1,
|
||||
drawtype = "glasslike",
|
||||
sunlight_propagates = true,
|
||||
freezemelt = "default:water_source",
|
||||
paramtype = "light",
|
||||
})
|
||||
end
|
||||
|
||||
-- What's a cave without speleothems?
|
||||
local spel = {
|
||||
{type1="stalactite", type2="stalagmite", tile="default_stone.png"},
|
||||
{type1="stalactite_slimy", type2="stalagmite_slimy", tile="default_stone.png^fun_caves_algae.png"},
|
||||
{type1="stalactite_mossy", type2="stalagmite_mossy", tile="default_stone.png^fun_caves_moss.png"},
|
||||
{type1="icicle_down", type2="icicle_up", desc="Icicle", tile="caverealms_thin_ice.png", drop="default:ice"},
|
||||
}
|
||||
|
||||
if minetest.registered_items['underworlds:stalactite'] then
|
||||
for _, desc in pairs(spel) do
|
||||
minetest.register_alias("fun_caves:"..desc.type1, 'underworlds:'..desc.type1)
|
||||
minetest.register_alias("fun_caves:"..desc.type2, 'underworlds:'..desc.type2)
|
||||
end
|
||||
else
|
||||
for _, desc in pairs(spel) do
|
||||
minetest.register_node("fun_caves:"..desc.type1, {
|
||||
description = (desc.desc or "Stalactite"),
|
||||
tiles = {desc.tile},
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
paramtype = "light",
|
||||
drop = (desc.drop or "fun_caves:stalactite"),
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed",
|
||||
fixed = {
|
||||
{-0.07, 0.0, -0.07, 0.07, 0.5, 0.07},
|
||||
{-0.04, -0.25, -0.04, 0.04, 0.0, 0.04},
|
||||
{-0.02, -0.5, -0.02, 0.02, 0.25, 0.02},
|
||||
} },
|
||||
groups = {rock=1, cracky=3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("fun_caves:"..desc.type2, {
|
||||
description = (desc.desc or "Stalagmite"),
|
||||
tiles = {desc.tile},
|
||||
is_ground_content = true,
|
||||
walkable = false,
|
||||
paramtype = "light",
|
||||
drop = "fun_caves:stalagmite",
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed",
|
||||
fixed = {
|
||||
{-0.07, -0.5, -0.07, 0.07, 0.0, 0.07},
|
||||
{-0.04, 0.0, -0.04, 0.04, 0.25, 0.04},
|
||||
{-0.02, 0.25, -0.02, 0.02, 0.5, 0.02},
|
||||
} },
|
||||
groups = {rock=1, cracky=3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- spikes, hot -- silicon-based life
|
||||
local spike_size = { 1.0, 1.2, 1.4, 1.6, 1.7 }
|
||||
fun_caves_mod.hot_spikes = {}
|
||||
|
||||
for i in ipairs(spike_size) do
|
||||
if i == 1 then
|
||||
nodename = "fun_caves:hot_spike"
|
||||
else
|
||||
nodename = "fun_caves:hot_spike_"..i
|
||||
end
|
||||
|
||||
fun_caves_mod.hot_spikes[#fun_caves_mod.hot_spikes+1] = nodename
|
||||
|
||||
vs = spike_size[i]
|
||||
|
||||
minetest.register_node(nodename, {
|
||||
description = "Stone Spike",
|
||||
tiles = {"fun_caves_hot_spike.png"},
|
||||
inventory_image = "fun_caves_hot_spike.png",
|
||||
wield_image = "fun_caves_hot_spike.png",
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3, oddly_breakable_by_hand=1, surface_hot=3},
|
||||
damage_per_second = 1,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
paramtype = "light",
|
||||
drawtype = "plantlike",
|
||||
walkable = false,
|
||||
light_source = i * 2,
|
||||
buildable_to = true,
|
||||
visual_scale = vs,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5*vs, -0.5*vs, -0.5*vs, 0.5*vs, -5/16*vs, 0.5*vs},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
fun_caves_mod.hot_spike = {}
|
||||
for i = 1, #fun_caves_mod.hot_spikes do
|
||||
fun_caves_mod.hot_spike[fun_caves_mod.hot_spikes[i]] = i
|
||||
end
|
||||
|
||||
-- stone with algae
|
||||
newnode = fun_caves_mod.clone_node("default:stone")
|
||||
newnode.description = "Cave Stone With Algae"
|
||||
newnode.tiles = {"default_stone.png^fun_caves_algae.png"}
|
||||
newnode.groups = {stone=1, cracky=3, crumbly=3}
|
||||
newnode.sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
})
|
||||
minetest.register_node("fun_caves:stone_with_algae", newnode)
|
||||
|
||||
if minetest.registered_items['underworlds:hot_stone'] then
|
||||
minetest.register_alias("fun_caves:hot_stone", 'underworlds:hot_stone')
|
||||
else
|
||||
-- stone, hot
|
||||
minetest.register_node("fun_caves:hot_stone", {
|
||||
description = "Hot Stone",
|
||||
tiles = {"default_desert_stone.png^[colorize:#FF0000:150"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=2, surface_hot=3},
|
||||
light_source = light_max - 5,
|
||||
damage_per_second = 1,
|
||||
sounds = default.node_sound_stone_defaults({
|
||||
footstep = {name="default_stone_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
end
|
||||
|
||||
-- stone with lichen
|
||||
newnode = fun_caves_mod.clone_node("default:stone")
|
||||
newnode.description = "Cave Stone With Lichen"
|
||||
newnode.tiles = {"default_stone.png^fun_caves_lichen.png"}
|
||||
newnode.groups = {stone=1, cracky=3, crumbly=3}
|
||||
newnode.sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
})
|
||||
minetest.register_node("fun_caves:stone_with_lichen", newnode)
|
||||
|
||||
-- stone with moss
|
||||
newnode = fun_caves_mod.clone_node("default:stone")
|
||||
newnode.description = "Cave Stone With Moss"
|
||||
newnode.tiles = {"default_stone.png^fun_caves_moss.png"}
|
||||
newnode.groups = {stone=1, cracky=3, crumbly=3}
|
||||
newnode.sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
})
|
||||
minetest.register_node("fun_caves:stone_with_moss", newnode)
|
||||
|
||||
|
||||
------------------------------------
|
||||
-- recipes
|
||||
------------------------------------
|
||||
|
||||
-- Mushroom stems can be used as wood and leather,
|
||||
-- ala Journey to the Center of the Earth.
|
||||
minetest.register_craft({
|
||||
output = "default:wood",
|
||||
recipe = {
|
||||
{"fun_caves:giant_mushroom_stem"}
|
||||
}
|
||||
})
|
||||
|
||||
if minetest.registered_items['mobs:leather'] then
|
||||
minetest.register_craft({
|
||||
output = "mobs:leather",
|
||||
recipe = {
|
||||
{"fun_caves:giant_mushroom_cap"}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = "dye:red",
|
||||
recipe = {
|
||||
{"flowers:mushroom_red"}
|
||||
}
|
||||
})
|
||||
|
||||
--minetest.register_craft({
|
||||
-- output = "dye:yellow",
|
||||
-- recipe = {
|
||||
-- {"flowers:mushroom_brown"}
|
||||
-- }
|
||||
--})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'default:paper 6',
|
||||
recipe = {
|
||||
{'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem'},
|
||||
}
|
||||
})
|
||||
|
||||
-- Caps can be cooked and eaten.
|
||||
minetest.register_node("fun_caves:mushroom_steak", {
|
||||
description = "Mushroom Steak",
|
||||
drawtype = "plantlike",
|
||||
paramtype = "light",
|
||||
tiles = {"vmg_mushroom_steak.png"},
|
||||
inventory_image = "vmg_mushroom_steak.png",
|
||||
on_use = minetest.item_eat(4),
|
||||
--groups = {dig_immediate = 3, attached_node = 1},
|
||||
groups = {dig_immediate = 3},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "fun_caves:mushroom_steak",
|
||||
recipe = "fun_caves:huge_mushroom_cap",
|
||||
cooktime = 2,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "fun_caves:mushroom_steak 2",
|
||||
recipe = "fun_caves:giant_mushroom_cap",
|
||||
cooktime = 2,
|
||||
})
|
||||
|
||||
-- moon juice from fungus
|
||||
minetest.register_craft({
|
||||
output = "fun_caves:moon_juice",
|
||||
recipe = {
|
||||
{"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"},
|
||||
{"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"},
|
||||
{"fun_caves:glowing_fungus", "vessels:glass_bottle", "fun_caves:glowing_fungus"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "fun_caves:moon_glass",
|
||||
type = "shapeless",
|
||||
recipe = {
|
||||
"fun_caves:moon_juice",
|
||||
"fun_caves:moon_juice",
|
||||
"default:glass",
|
||||
},
|
||||
})
|
||||
|
||||
-- Speleothems can be made into cobblestone, to get them out of inventory.
|
||||
minetest.register_craft({
|
||||
output = "default:cobble",
|
||||
recipe = {
|
||||
{"", "", ""},
|
||||
{"fun_caves:stalactite", "fun_caves:stalactite", ""},
|
||||
{"fun_caves:stalactite", "fun_caves:stalactite", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "default:cobble",
|
||||
recipe = {
|
||||
{"", "", ""},
|
||||
{"fun_caves:stalagmite", "fun_caves:stalagmite", ""},
|
||||
{"fun_caves:stalagmite", "fun_caves:stalagmite", ""},
|
||||
},
|
||||
})
|
BIN
textures/caverealms_glow_obsidian.png
Normal file
After Width: | Height: | Size: 162 B |
BIN
textures/caverealms_glow_obsidian2.png
Normal file
After Width: | Height: | Size: 661 B |
BIN
textures/caverealms_hot_cobble.png
Normal file
After Width: | Height: | Size: 431 B |
BIN
textures/caverealms_salty2.png
Normal file
After Width: | Height: | Size: 330 B |
BIN
textures/caverealms_thin_ice.png
Normal file
After Width: | Height: | Size: 679 B |
BIN
textures/fun_caves_algae.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
textures/fun_caves_black_sand.png
Normal file
After Width: | Height: | Size: 321 B |
BIN
textures/fun_caves_disgusting_gruel.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
textures/fun_caves_disgusting_gruel_raw.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
textures/fun_caves_fungal_tree_fruit.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
textures/fun_caves_fungal_tree_leaves.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
textures/fun_caves_hot_spike.png
Normal file
After Width: | Height: | Size: 724 B |
BIN
textures/fun_caves_lichen.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
textures/fun_caves_moss.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
textures/fun_caves_radioactive_ore.png
Normal file
After Width: | Height: | Size: 424 B |
BIN
textures/fun_caves_wooden_bowl.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
1
textures/image_credits.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Modified radioactive ore: everamzah
|
Before Width: | Height: | Size: 258 KiB |
BIN
textures/screenshot3.jpg
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
textures/vmg_glowing_fungal.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
textures/vmg_glowing_fungus.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
textures/vmg_moon_juice.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
textures/vmg_mushroom_giant_cap.png
Normal file
After Width: | Height: | Size: 788 B |
BIN
textures/vmg_mushroom_giant_stem.png
Normal file
After Width: | Height: | Size: 714 B |
BIN
textures/vmg_mushroom_giant_under.png
Normal file
After Width: | Height: | Size: 765 B |
BIN
textures/vmg_mushroom_steak.png
Normal file
After Width: | Height: | Size: 2.9 KiB |