Remove everything except the caves.

This commit is contained in:
Duane Robertson 2017-01-24 19:54:46 -06:00
parent e5e7475476
commit 6cb7f1da1d
205 changed files with 1251 additions and 15326 deletions

505
LICENSE
View file

@ -1,23 +1,504 @@
All of the goblin code and art are taken from FreeLikeGNU's Goblins mod,
distributed under the CC-by-SA license.
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
https://forum.minetest.net/viewtopic.php?f=9&t=13004&hilit=goblins
http://creativecommons.org/licenses/by-sa/3.0/
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.)
Some of the code, art and ideas were taken from HeroOfTheWinds' Caverealms
mod, distributed under the WTFPL license.
Preamble
https://forum.minetest.net/viewtopic.php?f=9&t=9522
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
Translocator node design, including models and textures came from Auke Kok's warps mod, distributed under LGPL 2.1 and cc-by-sa 3.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
https://github.com/minetest-mods/warps/blob/master/LICENSE
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
The rest of this mod is distributed under the LGPL 2.1 license for
historic reasons.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
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.
http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
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
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
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
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
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
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
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.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
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
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
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
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
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
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
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
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
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
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
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.
{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
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
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
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
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.
{signature of Ty Coon}, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View file

@ -1,15 +1,14 @@
# fun_caves
# hard_wood
Fun Caves started as an attempt to convert the mapgen V6 caves into a lua mod, so they could be used with any mapgen. Then I turned it into an all cave environment, with no surface at all. Now it's just a more extensive underworld, with biomes owing much to caverealms. Once you go underground, you should find everything you need to survive without ever returning to the surface.
A pathetically simple mod that makes wood unbreakable by hand and gives new players basic equipment when they start.
The surface has some neat extras such as coral, water plants, extra desert resources (deserts are hard). You'll also find big dungeon mazes underground, which will (soon) be replete with monsters and traps (though just finding your way through them is exhausting enough). There will be a little treasure, but the main goal is to retrieve a full set of trophy items for bragging rights.
![screenshot](https://raw.githubusercontent.com/duane-r/hard_wood/master/screenshot.png)
![screenshot](https://github.com/duane-r/fun_caves/raw/master/textures/screenshot3.jpg)
The source is available on github.
Code: LGPL2, textures: CC-BY-SA and CC0
Code: LGPL2
Mod dependencies: default, flowers, wool, mobs_redo, mobs_monster
Mod dependencies: default
Download: https://github.com/duane-r/fun_caves/archive/master.zip
Download: https://github.com/duane-r/hard_wood/archive/master.zip

588
abms.lua
View file

@ -1,22 +1,20 @@
-- 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 and hunger
-- player surface damage
local dps_delay = 3
local last_dps_check = 0
local cold_delay = 5
local monster_delay = 3
local hunger_delay = 60
local dps_count = hunger_delay
local dungeon_monster_density = 5
local players_in_orbit = {}
local dps_count = cold_delay
local mushrooms = {"flowers:mushroom_brown", "flowers:mushroom_red"}
local time_factor = (fun_caves.time_factor or 10)
local light_max = (fun_caves.light_max or 10)
local time_factor = (fun_caves_mod.time_factor or 10)
local light_max = (fun_caves_mod.light_max or 10)
-- fungal tree nodes
@ -37,7 +35,7 @@ end
fungal_nodes[#fungal_nodes+1] = {name = 'fun_caves:fungal_tree_fruit'}
local fungi_to_explode = {} -- see below
local exploding_fungi = fun_caves.exploding_fungi
local exploding_fungi = fun_caves_mod.exploding_fungi
if not exploding_fungi then
exploding_fungi = {}
end
@ -58,70 +56,26 @@ spike_soil['fun_caves:black_sand'] = true
-- all the fun_caves globalstep functions
------------------------------------------------------------
local hot_stuff = {"group:surface_hot"}
local traps = {"group:trap"}
local cold_stuff = {"group:surface_cold"}
local poison_stuff = {"group:poison"}
local gravity_off = {gravity = 0.1}
local gravity_on = {gravity = 1}
local dungeon_group = {'group:dungeon'}
local firework_active = false
local function firework()
local t = minetest.get_timeofday()
if not (t and type(t) == 'number') then
return
end
if not firework_active and (t < 0.25 or t > 0.75) then
firework_active = true
local ps = {}
local players = minetest.get_connected_players()
if not (players and type(players) == 'table') then
return
end
for i = 1, #players do
local pp = players[i]:getpos()
if pp and pp.y > 0 then
local sky = {}
sky.bgcolor, sky.type, sky.textures = players[i]:get_sky()
ps[#ps+1] = { p = players[i], sky = sky }
--players[i]:set_sky(0xffffff, "plain", {})
players[i]:set_sky('#000000', 'skybox', {'fun_caves_firework_'..math.random(3)..'.png', 'fun_caves_blank.png', 'fun_caves_blank.png', 'fun_caves_blank.png', 'fun_caves_blank.png', 'fun_caves_blank.png'})
end
minetest.sound_play("fireworks", {gain = 1, pos = pp, max_hear_distance = 2})
end
minetest.after(4, function()
for i = 1, #ps do
ps[i].p:set_sky(ps[i].sky.bgcolor, ps[i].sky.type, ps[i].sky.textures)
end
firework_active = false
end)
end
end
local sparking = {}
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
if not (fun_caves.db.status and fun_caves.registered_status) then
return
end
local time = minetest.get_gametime()
if not (time and type(time) == 'number') then
return
end
-- Trap check
if last_dps_check and time - last_dps_check < 1 then
-- Execute only after an interval.
if not last_dps_check or time - last_dps_check < dps_delay then
return
end
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
local players = minetest.get_connected_players()
if not (players and type(players) == 'table') then
return
@ -133,66 +87,8 @@ minetest.register_globalstep(function(dtime)
pos = vector.round(pos)
local player_name = player:get_player_name()
local minp = vector.subtract(pos, 2)
local maxp = vector.add(pos, 2)
local counts = minetest_find_nodes_in_area(minp, maxp, traps)
if counts and type(counts) == 'table' and #counts > 0 then
for _, tpos in ipairs(counts) do
local node = minetest.get_node_or_nil(tpos)
if not node then
return
end
if node.name == 'fun_caves:stone_with_coal_trap' then
minetest.set_node(tpos, {name="fire:basic_flame"})
local hp = player:get_hp()
if hp > 0 then
player:set_hp(hp - 1)
end
elseif node.name == 'fun_caves:stone_with_diamond_trap' then
fun_caves.diamond_trap(tpos, player)
elseif node.name == 'fun_caves:stone_with_gold_trap' then
fun_caves.gold_trap(tpos, player)
elseif node.name == 'fun_caves:mossycobble_trap' then
player:set_physics_override({speed = 0.1})
minetest.after(1, function() -- this effect is temporary
player:set_physics_override({speed = 1}) -- we'll just set it to 1 and be done.
end)
elseif node.name == 'fun_caves:ice_trap' then
fun_caves.ice_trap(tpos, player)
elseif node.name == 'fun_caves:stone_with_copper_trap' or node.name == 'fun_caves:stone_with_iron_trap' then
if not sparking[player_name] then
sparking[player_name] = true
fun_caves.copper_trap(tpos, player)
minetest.after(1, function()
sparking[player_name] = nil
end)
end
else
minetest.remove_node(tpos)
end
end
end
-- Execute only after an interval.
if last_dps_check and time - last_dps_check > dps_delay then
if pos.y >= 11168 and pos.y <= 15168 then
if not players_in_orbit[player_name] then
player:set_physics_override(gravity_off)
player:set_sky("#000000", "plain")
players_in_orbit[player_name] = true
end
elseif players_in_orbit[player_name] then
player:set_sky("#000000", "regular")
minetest.after(20, function()
player:set_physics_override(gravity_on)
end)
players_in_orbit[player_name] = false
end
-- environmental damage
if fun_caves.DEBUG and player:get_hp() < 20 then
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)
@ -201,37 +97,6 @@ minetest.register_globalstep(function(dtime)
local minp = vector.subtract(pos, 0.5)
local maxp = vector.add(pos, 0.5)
-- Remove status effects.
local status = fun_caves.db.status[player_name]
for status_name, status_param in pairs(status) do
local def = fun_caves.registered_status[status_name]
if not def then
print('Fun Caves: Error - unregistered status ' .. status_name)
break
end
local remove
if type(status_param.remove) == 'number' then
if status_param.remove < time then
remove = true
end
elseif def.remove then
remove = def.remove(player)
else
print('Fun Caves: Error in status remove for ' .. status_name)
end
if remove then
fun_caves.remove_status(player_name, status_name)
elseif def.during then
def.during(player)
end
end
if fun_caves.db.status[player_name]['breathe'] then
player:set_breath(11)
end
-- ... 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
@ -263,52 +128,12 @@ minetest.register_globalstep(function(dtime)
player:set_hp(player:get_hp() - 1)
end
end
-- ... from hunger (even less often).
if dps_count % hunger_delay == 0 and fun_caves.hunger_change then
fun_caves.hunger_change(player, -1)
end
end
end
end
-- Execute only after an interval.
if last_dps_check and time - last_dps_check < dps_delay then
return
end
local out = io.open(fun_caves.world..'/fun_caves_data.txt','w')
if out then
out:write(minetest.serialize(fun_caves.db))
out:close()
end
if fun_caves.date and fun_caves.date[2] == 7 and fun_caves.date[3] == 4 and math.random(30) == 1 then
firework()
end
-- Promote mobs based on spawn position
for _, mob in pairs(minetest.luaentities) do
if not mob.initial_promotion then
local pos = mob.object:getpos()
if mob.hp_max and mob.object and mob.health and mob.damage then
local factor = 1 + (math.max(math.abs(pos.x), math.abs(pos.y), math.abs(pos.z)) / 6200)
mob.hp_max = math.floor(mob.hp_max * factor)
mob.damage = math.floor(mob.damage * factor)
mob.health = math.floor(mob.health * factor)
mob.object:set_hp(mob.health)
mob.initial_promotion = true
check_for_death(mob)
--local name = mob.object:get_entity_name() or ''
--print('Promoting '..name..': '..mob.health..' health, '..mob.damage..' damage')
end
end
end
-- Set this outside of the player loop, to affect everyone.
if dps_count % hunger_delay == 0 then
dps_count = hunger_delay
if dps_count % cold_delay < 1 then
dps_count = cold_delay
end
last_dps_check = minetest.get_gametime()
@ -323,19 +148,6 @@ end)
-- destruction
------------------------------------------------------------
minetest.register_abm({
nodenames = {"fun_caves:flare",},
interval = 5,
chance = 10,
action = function(pos, node)
if not (pos and node) then
return
end
minetest.remove_node(pos)
end,
})
minetest.register_abm({
nodenames = {"fun_caves:hot_cobble",},
neighbors = {"group:water"},
@ -364,7 +176,7 @@ minetest.register_abm({
return
end
fun_caves.soft_boom(pos)
fun_caves_mod.soft_boom(pos)
end
})
@ -385,285 +197,20 @@ minetest.register_abm({
end
})
minetest.register_abm({
nodenames = {"fire:basic_flame"},
interval = 2 * time_factor,
chance = 50,
action = function(p0, node, _, _)
minetest.remove_node(p0)
end,
})
--minetest.register_abm({
-- nodenames = {"fire:basic_flame"},
-- interval = 2 * time_factor,
-- chance = 50,
-- action = function(p0, node, _, _)
-- minetest.remove_node(p0)
-- end,
--})
minetest.register_abm({
nodenames = {"fun_caves:coffer"},
interval = 5,
chance = 20,
catch_up = false,
action = function(p0, node, _, _)
minetest.remove_node(p0)
end,
})
------------------------------------------------------------
-- creation
------------------------------------------------------------
if fun_caves.dungeon_spawns and #fun_caves.dungeon_spawns > 0 then
minetest.register_abm({
nodenames = {"fun_caves:dungeon_floor_1"},
neighbors = {'air'},
interval = 7 * time_factor,
chance = 350,
catch_up = false,
action = function(pos, node, aoc, active_object_count_wider)
if not (pos and node) or active_object_count_wider > dungeon_monster_density then
return
end
for i = 1, 2 do
pos.y = pos.y + 1
local node = minetest.get_node_or_nil(pos)
if not node or node.name ~= "air" then
return
end
end
local target_level = math.max(2, math.ceil((pos.y - 3 ^ math.random(9)) / -200))
local desc
for i = 1, 100 do
desc = fun_caves.dungeon_spawns[math.random(#fun_caves.dungeon_spawns)]
if desc.level <= target_level then
break
else
desc = nil
end
end
if not desc then
return
end
local obj = minetest.add_entity(pos, desc.name)
if not obj then
return
end
local mob = obj:get_luaentity()
if not mob then
return
end
if mob.hp_max and mob.object and mob.health and mob.damage then
local factor = 1 + (math.max(math.abs(pos.x), math.abs(pos.y), math.abs(pos.z)) / 6200)
mob.started_in_dungeon = true
factor = factor * 1.5
mob.hp_max = math.floor(mob.hp_max * factor)
mob.damage = math.floor(mob.damage * factor)
mob.health = math.floor(mob.health * factor)
mob.object:set_hp(mob.health)
mob.initial_promotion = true
check_for_death(mob)
--print('Dungeon quality '..desc.name..': '..mob.health..' health, '..mob.damage..' damage')
end
end
})
end
minetest.register_abm({
nodenames = {"fun_caves:dungeon_floor_1"},
neighbors = {'air'},
interval = 20 * time_factor,
chance = 1000,
catch_up = false,
action = function(pos, node)
if not (pos and node) then
return
end
pos.y = pos.y + 1
local node = minetest.get_node_or_nil(pos)
if not node or node.name ~= "air" then
return
end
minetest.set_node(pos, {name = 'fun_caves:coffer'})
end
})
minetest.register_abm({
nodenames = {"fun_caves:dungeon_wall_1"},
neighbors = {'air'},
interval = 25 * time_factor,
chance = 2000,
catch_up = false,
action = function(pos, node)
if not (pos and node) then
return
end
pos = vector.round(pos)
local dir = math.random(4)
local p2 = 3
if dir == 1 then
pos.x = pos.x + 1
elseif dir == 2 then
pos.x = pos.x - 1
p2 = 2
elseif dir == 3 then
pos.z = pos.z + 1
p2 = 5
elseif dir == 4 then
pos.z = pos.z - 1
p2 = 4
end
local node = minetest.get_node_or_nil(pos)
if not node or node.name ~= "air" then
return
end
if (minetest.get_node_light(pos, nil) or 99) > 0 then
return
end
minetest.set_node(pos, {name = 'default:torch', param2 = p2})
end
})
-- This puts the burdon on fires, which shouldn't be happening much.
minetest.register_abm({
nodenames = {'fire:basic_flame'},
neighbors = {"fun_caves:tree"},
interval = time_factor,
chance = 50,
action = function(pos, node)
if not (pos and node) then
return
end
minetest.set_node(pos, {name = 'fun_caves:sap'})
end
})
minetest.register_abm({
nodenames = {"default:leaves"},
neighbors = {'air'},
interval = 10 * time_factor,
chance = 500,
catch_up = false,
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 node_below and node_below.name == 'air' then
minetest.set_node(pos, {name = 'default:apple'})
end
end
})
minetest.register_abm({
nodenames = {"default:apple"},
interval = 2 * time_factor,
chance = 50,
catch_up = false,
action = function(pos, node)
if not (pos and node) then
return
end
minetest.remove_node(pos)
end
})
-- Freezing vapor hardens into ice.
local ice_node = {name = 'default:ice'}
minetest.register_abm({
nodenames = {"fun_caves:freezing_vapor"},
interval = time_factor,
chance = 10,
action = function(pos, node)
if not (pos and node) then
return
end
minetest.set_node(pos, ice_node)
end
})
local no_tree_grow = {'fun_caves:bark', 'fun_caves:leaves'}
local wood_nodes = {{name = 'fun_caves:diamondwood'}, {name = 'fun_caves:ironwood'}, {name = 'fun_caves:sap'}, {name = 'fun_caves:tree'}}
minetest.register_abm({
neighbors = {'air'},
interval = 10 * time_factor,
chance = 450,
catch_up = false,
action = function(pos, node)
if not (pos and node) then
return
end
local new_pos = minetest.find_node_near(pos, 1, no_tree_grow)
if new_pos then
return
end
new_pos = minetest.find_node_near(pos, 1, "air")
if not new_pos then
return
end
if math.random(50) == 1 then
minetest.set_node(new_pos, wood_nodes[1])
elseif math.random(25) == 1 then
minetest.set_node(new_pos, wood_nodes[2])
elseif math.random(25) == 1 then
minetest.set_node(new_pos, wood_nodes[3])
else
minetest.set_node(new_pos, wood_nodes[4])
end
end
})
-- vacuum sucks
local vacuum = {name = 'fun_caves:vacuum'}
local air_list = {'air'}
minetest.register_abm({
nodenames = {"fun_caves:vacuum"},
neighbors = {"air"},
interval = time_factor,
chance = 10,
action = function(pos, node)
if not (pos and node) then
return
end
if pos.y <= 11168 or pos.y >= 15168 then
return
end
local p1 = vector.subtract(pos, 1)
local p2 = vector.add(pos, 1)
local positions = minetest.find_nodes_in_area(p1, p2, air_list)
if not (positions and type(positions) == 'table') then
return
end
local minetest_get_node_or_nil = minetest.get_node_or_nil
local minetest_set_node = minetest.set_node
for _, p3 in pairs(positions) do
local node2 = minetest_get_node_or_nil(p3)
if node2 and node2.name == 'air' then
minetest_set_node(p3, vacuum)
end
end
end
})
-- fungal spread
minetest.register_abm({
nodenames = fungal_tree_leaves,
@ -828,7 +375,7 @@ minetest.register_abm({
-- Spike spread and death
minetest.register_abm({
nodenames = fun_caves.hot_spikes,
nodenames = fun_caves_mod.hot_spikes,
interval = 40 * time_factor,
chance = 2000,
action = function(pos, node)
@ -836,17 +383,17 @@ minetest.register_abm({
return
end
if not (fun_caves.hot_spike and fun_caves.hot_spikes) then
if not (fun_caves_mod.hot_spike and fun_caves_mod.hot_spikes) then
return
end
local spike_num = fun_caves.hot_spike[node.name]
local spike_num = fun_caves_mod.hot_spike[node.name]
if not spike_num then
return
end
if spike_num < #fun_caves.hot_spikes then
minetest.set_node(pos, {name=fun_caves.hot_spikes[spike_num+1]})
if spike_num < #fun_caves_mod.hot_spikes then
minetest.set_node(pos, {name=fun_caves_mod.hot_spikes[spike_num+1]})
return
end
@ -868,71 +415,6 @@ minetest.register_abm({
})
------------------------------------------------------------
-- meteors
------------------------------------------------------------
local last_meteor_strike = 0
-- meteor strikes
minetest.register_abm({
nodenames = {"default:dirt_with_grass", "default:dirt_with_dry_grass", 'default:dirt_with_snow'},
neighbors = {"air", 'default:snow'},
interval = 150 * time_factor,
catch_up = false,
chance = 5500,
action = function(pos, node)
if not (pos and node and pos.y > 0) then
return
end
minetest.set_node(pos, {name="fun_caves:meteorite_crater"})
local time = minetest.get_gametime()
if time - last_meteor_strike < 10 then
return
end
last_meteor_strike = time
local ps = {}
local players = minetest.get_connected_players()
if not (players and type(players) == 'table') then
return
end
for i = 1, #players do
local pp = players[i]:getpos()
local pd = vector.subtract(pp, pos)
if pp and pp.y > 0 and math.abs(pd.x) < 1000 and math.abs(pd.z) < 1000 then
local sky = {}
sky.bgcolor, sky.type, sky.textures = players[i]:get_sky()
ps[#ps+1] = { p = players[i], sky = sky }
players[i]:set_sky(0xffffff, "plain")
end
end
minetest.after(1, function()
for i = 1, #ps do
ps[i].p:set_sky(ps[i].sky.bgcolor, ps[i].sky.type, ps[i].sky.textures)
end
end)
end
})
-- Remove old craters.
minetest.register_abm({
nodenames = {"fun_caves:meteorite_crater"},
interval = 5 * time_factor,
chance = 200,
action = function(pos, node)
if not (pos and node) then
return
end
minetest.set_node(pos, {name="default:dirt"})
end
})
------------------------------------------------------------
-- explosive functions
------------------------------------------------------------
@ -1010,6 +492,7 @@ local function destroy(pos, cid)
end
end
local math_random = math.random
local function explode(pos, radius)
if not (pos and radius and type(radius) == 'number') then
return
@ -1027,7 +510,6 @@ local function explode(pos, radius)
local c_air = minetest.get_content_id("air")
local math_random = math.random
for z = -radius, radius do
for y = -radius, 4*radius do
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
@ -1096,7 +578,7 @@ local function entity_physics(pos, radius)
end
end
fun_caves.soft_boom = function(pos)
fun_caves_mod.soft_boom = function(pos)
if not pos then
return
end
@ -1118,10 +600,6 @@ fun_caves.soft_boom = function(pos)
end
end
--local function burn(pos)
-- minetest.get_node_timer(pos):start(1)
--end
-----------------------------------------------
-- testing only -- remove before distribution

View file

@ -1,111 +0,0 @@
local max_depth = 31000
newnode = fun_caves.clone_node("default:water_source")
newnode.description = "Water"
newnode.liquid_range = 0
newnode.liquid_viscosity = 1
newnode.liquid_renewable = false
newnode.liquid_renewable = false
newnode.liquid_alternative_flowing = "fun_caves:asteroid_water"
newnode.liquid_alternative_source = "fun_caves:asteroid_water"
newnode.drowning = 0
newnode.light_source = 2
newnode.sunlight_propagates = true
newnode.post_effect_color = {a = 50, r = 30, g = 60, b = 90},
minetest.register_node("fun_caves:asteroid_water", newnode)
--bucket.liquids['fun_caves:asteroid_water'] = {
-- source = 'fun_caves:asteroid_water',
-- flowing = 'fun_caves:asteroid_water',
-- itemname = 'bucket:bucket_water',
--}
minetest.register_node("fun_caves:vacuum", {
description = "Vacuum",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
drawtype = "glasslike",
sunlight_propagates = true,
drowning = 1,
post_effect_color = {a = 20, r = 220, g = 200, b = 200},
tiles = {'fun_caves_blank.png'},
alpha = 0.1,
paramtype = "light",
})
local asteroid_noise_1 = {offset = 0, scale = 1, seed = -7620, spread = {x = 40, y = 40, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = -2525, octaves = 3, persist = 0.7, lacunarity = 2.0}
local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = -1471, octaves = 3, persist = 0.5, lacunarity = 2.0}
fun_caves.asteroids = function(minp, maxp, data, p2data, area, node)
if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then
return
end
if minp.y < 11168 or minp.y > 15168 then
return
end
-- What's this for?
--math.randomseed(minetest.get_us_time())
local density = 4 + math.abs(minp.y - 13168) / 500
local empty = false
if math.random(math.floor(density)) ~= 1 then
empty = true
--return
end
local csize = vector.add(vector.subtract(maxp, minp), 1)
local map_max = {x = csize.x, y = csize.y, z = csize.z}
local map_min = {x = minp.x, y = minp.y, z = minp.z}
local asteroid_1 = minetest.get_perlin_map(asteroid_noise_1, map_max):get3dMap_flat(map_min)
if not asteroid_1 then
return
end
local write = false
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
local dx = x - minp.x
index = index + 1
index3d = (z - minp.z) * (csize.y) * csize.x + (x - minp.x) + 1
local ivm = area:index(x, minp.y, z)
for y = minp.y, maxp.y do
local dy = y - minp.y
if empty then
data[ivm] = node['fun_caves:vacuum']
write = true
else
local dist2 = (40 - dy) ^ 2 + (40 - dx) ^ 2 + (40 - dz) ^ 2
if dist2 < (40 - math.abs(asteroid_1[index3d]) * 30) ^ 2 then
data[ivm] = node['default:stone']
write = true
elseif dist2 < 35 ^ 2 then
data[ivm] = node['fun_caves:asteroid_water']
write = true
else
data[ivm] = node['fun_caves:vacuum']
write = true
end
end
ivm = ivm + area.ystride
index3d = index3d + csize.x
end
end
end
return write
end

View file

@ -1,106 +0,0 @@
local csize
fun_caves.ice_castle = function(minp, maxp, data, p2data, area, node, heightmap, biomemap, biome_ids, underzone)
csize = vector.add(vector.subtract(maxp, minp), 1)
local write = false
local write_p2 = false
local max_height = -33000
local min_height = 33000
local avg_height = 0
local avg_count = 0
local height_grid = {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}
for z = minp.z, maxp.z do
local dz = math.ceil((z - minp.z + 1) / 8)
for x = minp.x, maxp.x do
local dx = math.ceil((x - minp.x + 1) / 8)
local ivm = area:index(x, maxp.y, z)
for y = maxp.y, minp.y, -1 do
if data[ivm] ~= node['air'] then
if y > minp.y + 50 then
return
end
if y > max_height then
max_height = y
end
if y < min_height then
min_height = y
end
print(dx, dz)
if not height_grid[dx][dz] then
height_grid[dx][dz] = -33000
end
if y > height_grid[dx][dz] then
height_grid[dx][dz] = y
end
if x == minp.x + 8 or x == maxp.x - 8 or z == minp.z + 8 or z == maxp.z - 8 then
avg_height = avg_height + y
avg_count = avg_count + 1
end
break
end
ivm = ivm - area.ystride
end
end
end
avg_height = avg_height / avg_count
max_height = max_height
for z = 1, 10 do
for x = 1, 10 do
height_grid[x][z] = height_grid[x][z] + math.random(20) + 5
end
end
local index = 0
local index3d = 0
local pos = {x=0, y=0, z=0}
local math_floor = math.floor
local math_max = math.max
local math_min = math.min
local math_log = math.log
for z = minp.z + 8, maxp.z - 8 do
local dz = math.ceil((z - minp.z + 1) / 8)
local r1z = (z - minp.z) % 8
local r2z = r1z < 4 and r1z or 7 - r1z
for x = minp.x + 8, maxp.x - 8 do
local dx = math.ceil((x - minp.x + 1) / 8)
local r1x = (x - minp.x) % 8
local r2x = r1x < 4 and r1x or 7 - r1x
index = index + 1
index3d = (z - minp.z) * (csize.y + 2) * csize.x + (x - minp.x) + 1
local ivm = area:index(x, minp.y, z)
for y = minp.y, maxp.y do
if y > height_grid[dx][dz] + 2 * math.min(r2x, r2z) then
data[ivm] = node['air']
elseif r1x == 0 and (dx < 3 or height_grid[dx - 1][dz] < y) then
data[ivm] = node['default:ice']
elseif r1x == 7 and (dx > 8 or height_grid[dx + 1][dz] < y) then
data[ivm] = node['default:ice']
elseif r1z == 0 and (dz < 3 or height_grid[dx][dz - 1] < y) then
data[ivm] = node['default:ice']
elseif r1z == 7 and (dz > 8 or height_grid[dx][dz + 1] < y) then
data[ivm] = node['default:ice']
elseif y > height_grid[dx][dz] + 2 * math.min(r2x, r2z) - 2 then
data[ivm] = node['default:ice']
elseif y > min_height - 5 and (not ((dx < 5 or dx > 6) or (dz < 5 or dz > 6)) or ((y - minp.y) % 8 ~= 0 and y < height_grid[dx][dz] - 5)) then
data[ivm] = node['air']
elseif y > min_height - 5 and (y - minp.y) % 8 == 0 then
data[ivm] = node['default:ice']
elseif y > min_height - 10 then
data[ivm] = node['default:ice']
end
ivm = ivm + area.ystride
index3d = index3d + csize.x
end
end
end
return write, write_p2
end

View file

@ -1,120 +1,48 @@
fun_caves.cave_width = 0.05 -- figurative width
-- 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 = 31000
fun_caves.cave_noise_1 = {offset = 0, scale = 1, seed = 3901, spread = {x = 40, y = 10, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
fun_caves.cave_noise_2 = {offset = 0, scale = 1, seed = -8402, spread = {x = 40, y = 20, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
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.cavegen = function(minp, maxp, data, area, node, heightmap, underzone, ground_nodes)
if not (minp and maxp and data and area and node and type(data) == 'table' and fun_caves.underzones) then
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 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 return_heightmap = false
local cave_1 = minetest.get_perlin_map(fun_caves.cave_noise_1, map_max):get3dMap_flat(map_min)
local cave_2 = minetest.get_perlin_map(fun_caves.cave_noise_2, map_max):get3dMap_flat(map_min)
local cave_3 = minetest.get_perlin_map(cave_noise_3, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=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 write = false
local index = 0
local crater
if not underzone and math.random(10) == 1 then
crater = {
x = minp.x + math.random(math.floor(csize.x / 2)) + math.floor(csize.x / 4),
y = 15,
z = minp.z + math.random(math.floor(csize.z / 2)) + math.floor(csize.z / 4),
}
end
local crater_min = 33000
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
local height = heightmap[index]
if crater then
local dist = crater.y - math.sqrt((x - crater.x) ^ 2 + (z - crater.z) ^ 2)
if dist > 0 and (height > maxp.y - 20 or height < minp.y + crater.y) then
crater = nil
end
if crater and dist > 0 and dist <= 1 and crater_min > height then
crater_min = height
end
end
end
end
index = 0
local index3d = 0
local cave_width = fun_caves.cave_width
local styx_sea_level = fun_caves.underzones['Styx'].sealevel
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-1, z)
local ivm = area:index(x, minp.y, z)
local height = heightmap[index]
local column = 0
if underzone then
if cave_3[index] < 30 then
column = 1
elseif cave_3[index] < 35 then
column = 2
end
end
local dist
if crater then
dist = crater.y - math.sqrt((x - crater.x) ^ 2 + (z - crater.z) ^ 2)
end
for y = minp.y-1, maxp.y+1 do
if crater and dist and dist > 0 then
if y > crater_min - 1.5 * dist and y < maxp.y - 1.5 * dist then
data[ivm] = data[ivm + (math.floor((height - crater_min) * dist / crater.y) + math.ceil(dist / 2)) * area.ystride]
end
if y > crater_min - dist and ground_nodes[data[ivm]] and math.random(300) == 1 then
data[ivm] = node['fun_caves:stone_with_meteoritic_iron']
end
end
if underzone and underzone.regular_columns and (x - minp.x) < 8 and (z - minp.z) < 8 then
data[ivm] = node[underzone.column_node]
write = true
elseif underzone and underzone.column_node and not underzone.regular_columns and column == 2 then
if underzone.column_node_rare and math.random(70) == 1 then
data[ivm] = node[underzone.column_node_rare]
else
data[ivm] = node[underzone.column_node]
end
write = true
elseif underzone and (y < underzone.ceiling - (underzone.vary and cave_3[index] or 0) and y > underzone.floor + (underzone.vary and cave_3[index] or 0)) then
if underzone.sealevel and y <= underzone.sealevel then
data[ivm] = node["default:water_source"]
else
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"]
end
write = true
elseif underzone and (y < underzone.ceiling + 10 - (underzone.vary and cave_3[index] or 0) and y > underzone.floor - 10 + (underzone.vary and cave_3[index] or 0)) then
-- nop
elseif ((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
if y <= styx_sea_level then
data[ivm] = node["default:water_source"]
else
data[ivm] = node["air"]
end
write = true
if y > 0 and cave_3[index] < 1 and y == height then
-- Clear the air above a cave mouth.
@ -134,6 +62,5 @@ fun_caves.cavegen = function(minp, maxp, data, area, node, heightmap, underzone,
end
end
end
return write
end

279
chat.lua
View file

@ -1,279 +0,0 @@
minetest.register_chatcommand("armor", {
params = "",
description = "Display your armor values",
privs = {},
func = function(player_name, param)
if not (player_name and type(player_name) == 'string' and player_name ~= '' and fun_caves.db.status) then
return
end
local player = minetest.get_player_by_name(player_name)
if not player then
return
end
local armor = player:get_armor_groups()
if armor then
minetest.chat_send_player(player_name, "Armor:")
for group, value in pairs(armor) do
minetest.chat_send_player(player_name, " "..group.." "..value)
end
if fun_caves.db.status[player_name].armor_elixir then
local armor_time = fun_caves.db.status[player_name].armor_elixir.remove
local game_time = minetest.get_gametime()
if not (armor_time and type(armor_time) == 'number' and game_time and type(game_time) == 'number') then
return
end
local min = math.floor(math.max(0, armor_time - game_time) / 60)
minetest.chat_send_player(player_name, "Your armor elixir will expire in "..min..' minutes.')
end
end
end,
})
minetest.register_chatcommand("setspawn", {
params = "",
description = "change your spawn position",
privs = {},
func = function(player_name, param)
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
local player = minetest.get_player_by_name(player_name)
if not player then
return
end
local pos = player:getpos()
beds.spawn[player_name] = pos
minetest.chat_send_player(player_name, 'Your spawn position has been changed.')
end,
})
minetest.register_chatcommand("fixlight", {
params = "<radius>",
description = "attempt to fix light bugs",
privs = {},
func = function(player_name, param)
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
local privs = minetest.check_player_privs(player_name, {server=true})
if not privs then
return
end
print('Fun Caves: '..player_name..' used the fixlight command')
local player = minetest.get_player_by_name(player_name)
if not player then
return
end
local pos = player:getpos()
if not pos then
return
end
pos = vector.round(pos)
local radius = tonumber(param) or 50
radius = math.floor(radius)
local minp = vector.subtract(pos, radius)
local maxp = vector.add(pos, radius)
local vm = minetest.get_voxel_manip(minp, maxp)
if not vm then
return
end
--vm:set_lighting({day = 0, night = 0}, minp, maxp)
vm:calc_lighting(minp, maxp)
vm:update_liquids()
vm:write_to_map()
vm:update_map()
end,
})
minetest.register_chatcommand("flatten", {
params = "<radius>",
description = "flatten terrain",
privs = {},
func = function(player_name, param)
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
local privs = minetest.check_player_privs(player_name, {server=true})
if not privs then
return
end
print('Fun Caves: '..player_name..' used the flatten command')
local player = minetest.get_player_by_name(player_name)
if not player then
return
end
local pos = player:getpos()
if not pos then
return
end
pos = vector.round(pos)
local radius = tonumber(param) or 50
radius = math.floor(radius)
local minp = vector.subtract(pos, radius)
minp.y = minp.y - math.ceil(radius / 2)
local maxp = vector.add(pos, radius)
maxp.y = maxp.y + math.ceil(radius / 2)
local air = minetest.get_content_id('air')
local stone = minetest.get_content_id('default:stone')
local water = minetest.get_content_id('default:water_source')
local waters = {}
waters[minetest.get_content_id('default:water_source')] = true
waters[minetest.get_content_id('default:river_water_source')] = true
local stone_types = {'default:stone', 'default:desert_stone', 'default:sandstone', 'default:dirt', 'fun_caves:dirt', 'default:dirt_with_snow', 'default:dirt_with_grass', 'default:dirt_with_dry_grass', 'default:sand', 'default:desert_sand'}
local stones = {}
for i = 1, #stone_types do
stones[minetest.get_content_id(stone_types[i])] = true
end
local vm = minetest.get_voxel_manip(minp, maxp)
if not vm then
return
end
local emin, emax = vm:read_from_map(minp, maxp)
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
local heightmap = {}
local height_avg = 0
local count = 0
local index = 1
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
local ivm = area:index(x, maxp.y, z)
for y = maxp.y, minp.y, -1 do
if stones[data[ivm]] then
if y >= maxp.y then
minetest.chat_send_player(player_name, 'Terrain altitude exceeds the given radius.')
return
end
heightmap[index] = y
height_avg = height_avg + heightmap[index]
count = count + 1
break
end
ivm = ivm - area.ystride
end
if not heightmap[index] then
minetest.chat_send_player(player_name, 'Terrain altitude exceeds the given radius.')
return
end
index = index + 1
end
end
height_avg = math.floor(height_avg / count + 0.5)
index = 1
for z = minp.z, maxp.z do
local dz = z - minp.z
for x = minp.x, maxp.x do
local dx = x - minp.x
local r = math.max(math.abs(radius - dx), math.abs(radius - dz)) / radius
local new_y = heightmap[index]
if r < 1 then
new_y = math.floor(heightmap[index] * r ^ 2 + height_avg * (1 - r ^ 2) + 0.5)
end
local delta = new_y - heightmap[index]
if delta > 0 then
local ivm = area:index(x, maxp.y, z)
for y = maxp.y - delta, new_y, -1 do
data[ivm] = data[ivm - area.ystride * delta]
ivm = ivm - area.ystride
end
elseif delta < 0 then
local ivm = area:index(x, new_y - 2, z)
for y = new_y - 2, maxp.y + delta do
data[ivm] = data[ivm - area.ystride * delta]
ivm = ivm + area.ystride
end
for y = maxp.y + delta + 1, maxp.y do
data[ivm] = air
ivm = ivm + area.ystride
end
end
local ivm = area:index(x, minp.y, z)
for y = minp.y, maxp.y do
if y <= 1 and data[ivm] == air then
data[ivm] = water
elseif y > 1 and waters[data[ivm]] then
data[ivm] = air
end
ivm = ivm + area.ystride
end
index = index + 1
end
end
vm:set_data(data)
vm:calc_lighting(minp, maxp)
vm:update_liquids()
vm:write_to_map()
vm:update_map()
end,
})
minetest.register_chatcommand("sleep", {
params = "",
description = "Sleep on the ground",
privs = {},
func = function(player_name, param)
local player = minetest.get_player_by_name(player_name)
if not (player and beds) then
return
end
if (beds.player and beds.player[player_name]) then
minetest.chat_send_player(player_name, 'You can\'t sleep.')
return
end
local pos = player:getpos()
if not pos then
return
end
pos = vector.round(pos)
local status, err = pcall(beds.on_rightclick, pos, player)
if status then
minetest.after(5, function()
local time = minetest.get_timeofday()
if not time or time < 0.23 or time > 0.3 then
return
end
local hp = player:get_hp()
if hp and type(hp) == 'number' then
player:set_hp(hp - 1)
end
minetest.chat_send_player(player_name, 'You\'d sleep better in a bed.')
end)
end
end,
})

View file

@ -1,235 +0,0 @@
local newnode = fun_caves.clone_node("default:dirt")
newnode.description = "Cloud"
newnode.tiles = {'fun_caves_cloud.png'}
newnode.sunlight_propagates = true
minetest.register_node("fun_caves:cloud", newnode)
newnode = fun_caves.clone_node("default:dirt")
newnode.description = "Storm Cloud"
newnode.tiles = {'fun_caves_storm_cloud.png'}
--newnode.sunlight_propagates = true
minetest.register_node("fun_caves:storm_cloud", newnode)
minetest.register_node("fun_caves:wispy_cloud", {
description = "Wispy Cloud",
tiles = {'fun_caves_wisp.png'},
sunlight_propagates = true,
use_texture_alpha = true,
drawtype = "glasslike",
paramtype = 'light',
walkable = false,
buildable_to = true,
pointable = false,
})
minetest.register_node("fun_caves:moon_weed", {
description = "Moon Weed",
drawtype = "plantlike",
tiles = {"fun_caves_moon_weed.png"},
inventory_image = "fun_caves_moon_weed.png",
waving = false,
sunlight_propagates = true,
paramtype = "light",
light_source = 8,
walkable = false,
groups = {snappy=3,flammable=2,flora=1,attached_node=1},
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
})
minetest.register_node("fun_caves:leaves_lumin", {
description = "Leaves",
drawtype = "allfaces_optional",
waving = 1,
visual_scale = 1.3,
tiles = {"default_leaves.png^[colorize:#FFDF00:150"},
special_tiles = {"default_leaves_simple.png^[colorize:#FFDF00:150"},
paramtype = "light",
is_ground_content = false,
light_source = 8,
groups = {snappy = 3, leafdecay = 4, flammable = 2, leaves = 1},
drop = {
max_items = 1,
items = {
--{
-- -- player will get sapling with 1/20 chance
-- items = {'default:sapling'},
-- rarity = 20,
--},
{
-- player will get leaves only if he get no saplings,
-- this is because max_items is 1
items = {'fun_caves:leaves_lumin'},
}
}
},
sounds = default.node_sound_leaves_defaults(),
after_place_node = default.after_place_leaves,
})
minetest.register_node("fun_caves:lumin_tree", {
description = "Lumin Tree",
tiles = {
"default_tree_top.png", "default_tree_top.png", "fun_caves_lumin_tree.png"
},
paramtype = "light",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, }
},
paramtype2 = "facedir",
is_ground_content = false,
groups = {tree = 1, choppy = 2, flammable = 2},
sounds = default.node_sound_wood_defaults(),
on_place = minetest.rotate_node
})
newnode = fun_caves.clone_node("default:stone_with_iron")
newnode.description = "Silver Lining"
newnode.tiles = {'fun_caves_cloud.png^default_mineral_coal.png^[colorize:#FFFFFF:175'}
newnode.drop = "fun_caves:silver_lump"
minetest.register_node("fun_caves:silver_lining", newnode)
minetest.register_craftitem("fun_caves:silver_lump", {
description = "Lump of Silver",
inventory_image = 'default_coal_lump.png^[colorize:#FFFFFF:175',
})
minetest.register_craftitem("fun_caves:silver_ingot", {
description = "Silver Ingot",
inventory_image = 'default_steel_ingot.png^[colorize:#FFFFFF:175',
})
minetest.register_craft({
type = "cooking",
output = "fun_caves:silver_ingot",
recipe = "fun_caves:silver_lump",
})
local max_depth = 31000
local cloud_noise_1 = {offset = 10, scale = 10, seed = 4877, spread = {x = 120, y = 120, z = 120}, octaves = 3, persist = 1, lacunarity = 2}
local cloud_noise_2 = {offset = 0, scale = 1, seed = 5748, spread = {x = 40, y = 10, z = 40}, octaves = 3, persist = 1, lacunarity = 2}
local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = -2525, octaves = 3, persist = 0.7, lacunarity = 2.0}
local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = -1471, octaves = 3, persist = 0.5, lacunarity = 2.0}
fun_caves.cloudgen = function(minp, maxp, data, p2data, area, node)
if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table' and fun_caves.place_schematic and fun_caves.schematics and fun_caves.surround) then
return
end
if minp.y ~= 4368 then
return
end
local csize = vector.add(vector.subtract(maxp, minp), 1)
local map_max = {x = csize.x, y = csize.y, z = csize.z}
local map_min = {x = minp.x, y = minp.y, z = minp.z}
local cloud_1 = minetest.get_perlin_map(cloud_noise_1, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
local cloud_2 = minetest.get_perlin_map(cloud_noise_2, map_max):get3dMap_flat(map_min)
local plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
local biome_n = minetest.get_perlin_map(biome_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
if not (cloud_1 and cloud_2 and plant_n and biome_n) then
return
end
local write = false
local index = 0
local index3d = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
index3d = (z - minp.z) * (csize.y) * csize.x + (x - minp.x) + 1
local ivm = area:index(x, minp.y, z)
local cloud
if biome_n[index] < 0 then
cloud = 'storm_cloud'
else
cloud = 'cloud'
end
cloud_1[index] = math.floor(cloud_1[index] + 0.5)
for y = minp.y, maxp.y do
local dy = y - minp.y
if dy > 32 and cloud_1[index] > 15 and dy < 47 then
if dy < 48 - (cloud_1[index] - 15) then
if cloud == 'cloud' and math.random(10000) == 1 then
data[ivm] = node['fun_caves:silver_lining']
else
data[ivm] = node['fun_caves:'..cloud]
end
else
data[ivm] = node['default:water_source']
write = true
end
elseif cloud_1[index] > 0 and (dy <= 32 or cloud_1[index] <= 15) and dy >= 32 - cloud_1[index] and dy <= 32 + cloud_1[index] then
if cloud == 'cloud' and math.random(10000) == 1 then
data[ivm] = node['fun_caves:silver_lining']
else
data[ivm] = node['fun_caves:'..cloud]
end
write = true
elseif data[ivm - area.ystride] == node['fun_caves:'..cloud] and data[ivm] == node['air'] then
if math.random(30) == 1 and plant_n[index] > 0.5 then
data[ivm] = node['fun_caves:moon_weed']
write = true
elseif math.random(60) == 1 and plant_n[index] > 0.5 then
fun_caves.place_schematic(minp, maxp, data, p2data, area, node, {x=x,y=y,z=z}, fun_caves.schematics['lumin_tree'], true)
write = true
elseif math.random(10) == 1 then
data[ivm] = node['default:grass_'..math.random(4)]
write = true
end
elseif data[ivm] == node['air'] and (dy < 29 - cloud_1[index] or dy > 35 + cloud_1[index]) and cloud_2[index3d] > math.abs((dy - 40) / 20) then
data[ivm] = node['fun_caves:wispy_cloud']
write = true
end
ivm = ivm + area.ystride
index3d = index3d + csize.x
end
end
end
local index = 0
local index3d = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
local ivm = area:index(x, minp.y, z)
local cloud
if biome_n[index] < 0 then
cloud = 'storm_cloud'
else
cloud = 'cloud'
end
cloud_1[index] = math.floor(cloud_1[index] + 0.5)
if cloud_1[index] > 0 then
for y = minp.y, maxp.y do
local dy = y - minp.y
if data[ivm] == node['fun_caves:'..cloud] and data[ivm + area.ystride] == node['default:water_source'] and math.random(30) == 1 and fun_caves.surround(node, data, area, ivm) then
data[ivm] = node['fun_caves:water_plant_1_water_'..cloud]
end
ivm = ivm + area.ystride
end
end
end
end
return write
end

404
deco.lua
View file

@ -1,259 +1,221 @@
-- I like having different stone scattered about. Sandstone forms
-- in layers. Desert stone... doesn't exist, but let's assume it's
-- another sedementary rock and place it similarly.
minetest.register_ore({ore_type="sheet", ore="default:sandstone", wherein="default:stone", clust_num_ores=250, clust_scarcity=60, clust_size=10, y_min=-1000, y_max=31000, noise_threshold=0.1, noise_params={offset=0, scale=1, spread={x=256, y=256, z=256}, seed=4130293965, octaves=5, persist=0.60}, random_factor=1.0})
minetest.register_ore({ore_type="sheet", ore="default:desert_stone", wherein="default:stone", clust_num_ores=250, clust_scarcity=60, clust_size=10, y_min=-1000, y_max=31000, noise_threshold=0.1, noise_params={offset=0, scale=1, spread={x=256, y=256, z=256}, seed=163281090, octaves=5, persist=0.60}, random_factor=1.0})
-- 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)
if not fun_caves.breakable_wood then
print('* Fun Caves: Wood is NOT breakable by hand.')
for _, item in pairs(minetest.registered_items) do
if item.groups.tree or item.groups.wood then
local groups = table.copy(item.groups)
groups.oddly_breakable_by_hand = nil
minetest.override_item(item.name, {groups=groups})
end
end
end
dofile(fun_caves_mod.path .. "/nodes.lua")
dofile(fun_caves_mod.path .. "/fungal_tree.lua")
minetest.register_node("fun_caves:sand_with_rocks", {
description = "Sand and rocks",
tiles = {"fun_caves_sand_with_rocks.png"},
groups = {crumbly = 3, falling_node = 1, sand = 1},
sounds = default.node_sound_sand_defaults(),
drop = {max_items=2, items={{items={"fun_caves:small_rocks"}, rarity=1}, {items={"default:sand"}, rarity=1}}},
})
minetest.register_craft({
output = "default:stick 2",
recipe = {
{"group:sapling"}
}
})
minetest.register_craft({
output = "default:stick 2",
recipe = {
{"default:cactus"}
}
})
--minetest.add_group("default:cactus", {oddly_breakable_by_hand=1})
local deco_depth = -30 -- place cave stuff this far beneath the surface
local water_level = 1
local fluid_compression = -200 -- the depth to start planting lava/water
local max_depth = 31000
if fun_caves.use_bi_hi then
local biome_mod = {
coniferous_forest_dunes = { heat_point = 35, humidity_point = 60, },
coniferous_forest = { heat_point = 35, humidity_point = 60, },
coniferous_forest_ocean = { heat_point = 35, humidity_point = 60, },
deciduous_forest = { heat_point = 60, humidity_point = 60, },
deciduous_forest_ocean = { heat_point = 60, humidity_point = 60, },
deciduous_forest_swamp = { heat_point = 60, humidity_point = 60, },
desert = { heat_point = 80, humidity_point = 10, },
desert_ocean = { heat_point = 80, humidity_point = 10, },
glacier = {},
glacier_ocean = {},
rainforest = { heat_point = 85, humidity_point = 70, },
rainforest_ocean = { heat_point = 85, humidity_point = 70, },
rainforest_swamp = { heat_point = 85, humidity_point = 70, },
sandstone_grassland_dunes = { heat_point = 55, humidity_point = 40, },
sandstone_grassland = { heat_point = 55, humidity_point = 40, },
sandstone_grassland_ocean = { heat_point = 55, humidity_point = 40, },
savanna = { heat_point = 80, humidity_point = 25, },
savanna_ocean = { heat_point = 80, humidity_point = 25, },
savanna_swamp = { heat_point = 80, humidity_point = 25, },
stone_grassland_dunes = { heat_point = 35, humidity_point = 40, },
stone_grassland = { heat_point = 35, humidity_point = 40, },
stone_grassland_ocean = { heat_point = 35, humidity_point = 40, },
taiga = {},
taiga_ocean = {},
tundra = { node_river_water = "fun_caves:thin_ice", },
tundra_beach = { node_river_water = "fun_caves:thin_ice", },
tundra_ocean = {},
}
local rereg = {}
for n, bi in pairs(biome_mod) do
for i, rbi in pairs(minetest.registered_biomes) do
if rbi.name == n then
rereg[#rereg+1] = table.copy(rbi)
for j, prop in pairs(bi) do
rereg[#rereg][j] = prop
end
end
end
end
minetest.clear_registered_biomes()
for _, bi in pairs(rereg) do
minetest.register_biome(bi)
end
rereg = {}
for _, dec in pairs(minetest.registered_decorations) do
rereg[#rereg+1] = dec
end
minetest.clear_registered_decorations()
for _, dec in pairs(rereg) do
minetest.register_decoration(dec)
end
rereg = nil
local csize
local node_match_cache = {}
minetest.register_biome({
name = "desertstone_grassland",
--node_dust = "",
node_top = "default:dirt_with_grass",
depth_top = 1,
node_filler = "default:dirt",
depth_filler = 1,
node_stone = "default:desert_stone",
node_riverbed = "default:sand",
depth_riverbed = 2,
--node_water_top = "",
--depth_water_top = ,
--node_water = "",
--node_river_water = "",
y_min = 6,
y_max = 31000,
heat_point = 80,
humidity_point = 55,
})
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}
minetest.register_decoration({
deco_type = "simple",
place_on = {"default:dirt_with_grass"},
sidelen = 80,
fill_ratio = 0.1,
biomes = {"desertstone_grassland", },
y_min = 1,
y_max = 31000,
decoration = "default:junglegrass",
})
end
-- Create and initialize a table for a schematic.
function fun_caves.schematic_array(width, height, depth)
if not (width and height and depth and type(width) == 'number' and type(height) == 'number' and type(depth) == 'number') then
-- 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
-- Dimensions of data array.
local s = {size={x=width, y=height, z=depth}}
s.data = {}
csize = vector.add(vector.subtract(maxp, minp), 1)
for z = 0,depth-1 do
for y = 0,height-1 do
for x = 0,width-1 do
local i = z*width*height + y*width + x + 1
s.data[i] = {}
s.data[i].name = "air"
s.data[i].param1 = 000
end
end
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
s.yslice_prob = {}
local biome
local biome_val = biome_n[index3d]
return s
end
fun_caves.schematics = {}
do
local w, h, d = 5, 8, 5
local s = fun_caves.schematic_array(w, h, d)
for y = 0, math.floor(h/2)-1 do
s.data[2*d*h + y*d + 2 + 1].name = 'default:tree'
s.data[2*d*h + y*d + 2 + 1].param1 = 255
-- 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 z = 0, d-1 do
for y = math.floor(h/2), h-1 do
for x = 0, w-1 do
if y < h - 1 or (x ~= 0 and x ~= w-1 and z ~= 0 and z ~= d-1) then
if math.random(2) == 1 then
s.data[z*d*h + y*d + x + 1].name = 'fun_caves:leaves_black'
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
s.data[z*d*h + y*d + x + 1].name = 'fun_caves:sticks_default'
data[ivm] = node[biome.floor_node]
write = true
break
end
end
if y == h-1 or x == 0 or x == w-1 or z == 0 or z == d-1 then
s.data[z*d*h + y*d + x + 1].param1 = 150
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
s.data[z*d*h + y*d + x + 1].param1 = 225
end
end
data[ivm] = node[biome.ceiling_node]
write = true
break
end
end
end
for z = math.floor(d/2)-1, math.floor(d/2)+1, 2 do
for x = math.floor(w/2)-1, math.floor(w/2)+1, 2 do
s.data[z*d*h + math.floor(h/2)*d + x + 1].name = 'default:tree'
s.data[z*d*h + math.floor(h/2)*d + x + 1].param1 = 150
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
for y = 0, h-1 do
if y / 3 == math.floor(y / 3) then
s.yslice_prob[#s.yslice_prob+1] = {ypos=y,prob=170}
end
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
fun_caves.schematics['decaying_tree'] = s
end
do
local w, h, d = 5, 8, 5
local s = fun_caves.schematic_array(w, h, d)
for y = 0, math.floor(h/2)-1 do
s.data[2*d*h + y*d + 2 + 1].name = 'fun_caves:lumin_tree'
s.data[2*d*h + y*d + 2 + 1].param1 = 255
end
for z = 0, d-1 do
for y = math.floor(h/2), h-1 do
for x = 0, w-1 do
if y < h - 1 or (x ~= 0 and x ~= w-1 and z ~= 0 and z ~= d-1) then
s.data[z*d*h + y*d + x + 1].name = 'fun_caves:leaves_lumin'
if y == h-1 or x == 0 or x == w-1 or z == 0 or z == d-1 then
s.data[z*d*h + y*d + x + 1].param1 = 150
-- 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
s.data[z*d*h + y*d + x + 1].param1 = 225
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
for z = math.floor(d/2)-1, math.floor(d/2)+1, 2 do
for x = math.floor(w/2)-1, math.floor(w/2)+1, 2 do
s.data[z*d*h + math.floor(h/2)*d + x + 1].name = 'fun_caves:lumin_tree'
s.data[z*d*h + math.floor(h/2)*d + x + 1].param1 = 150
end
end
for y = 0, h-1 do
if y / 3 == math.floor(y / 3) then
s.yslice_prob[#s.yslice_prob+1] = {ypos=y,prob=170}
end
end
fun_caves.schematics['lumin_tree'] = s
end
if fun_caves.path then
dofile(fun_caves.path .. "/deco_caves.lua")
--dofile(fun_caves.path.."/deco_dirt.lua")
dofile(fun_caves.path.."/deco_plants.lua")
dofile(fun_caves.path.."/deco_rocks.lua")
--dofile(fun_caves.path.."/deco_ferns.lua")
--dofile(fun_caves.path.."/deco_ferns_tree.lua")
return write
end

View file

@ -1,480 +0,0 @@
local light_max = fun_caves.light_max or 10
-- black (oily) sand
local newnode = fun_caves.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)
-- 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},
}),
})
-- dirt, glowing
newnode = fun_caves.clone_node("default:dirt")
newnode.description = "Glowing Dirt"
newnode.light_source = default.LIGHT_MAX
newnode.soil = {
base = "fun_caves:glowing_dirt",
dry = "fun_caves:glowing_soil",
wet = "fun_caves:glowing_soil_wet"
}
minetest.register_node("fun_caves:glowing_dirt", newnode)
-- Dirt can become soil.
newnode = fun_caves.clone_node("farming:soil")
newnode.description = "Glowing Soil"
newnode.light_source = default.LIGHT_MAX
newnode.soil = {
base = "fun_caves:glowing_dirt",
dry = "fun_caves:glowing_soil",
wet = "fun_caves:glowing_soil_wet"
}
minetest.register_node("fun_caves:glowing_dirt", newnode)
-- Dirt to soil to wet soil...
newnode = fun_caves.clone_node("farming:soil_wet")
newnode.description = "Wet Glowing Soil"
newnode.light_source = default.LIGHT_MAX
newnode.soil = {
base = "fun_caves:glowing_dirt",
dry = "fun_caves:glowing_soil",
wet = "fun_caves:glowing_soil_wet"
}
minetest.register_node("fun_caves:glowing_dirt", newnode)
-- flame, constant -- does not expire
minetest.register_node("fun_caves:constant_flame", {
description = "Fire",
drawtype = "plantlike",
tiles = {{
name="fire_basic_flame_animated.png",
animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=1},
}},
inventory_image = "fire_basic_flame.png",
light_source = 14,
groups = {igniter=2,dig_immediate=3,hot=3, not_in_creative_inventory=1},
drop = '',
walkable = false,
buildable_to = true,
damage_per_second = 4,
})
-- 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},
})
-- Iron, hot
newnode = fun_caves.clone_node("default:steelblock")
newnode.description = "Hot Iron Block"
newnode.tiles = {"default_steel_block.png^[colorize:#FF3000:150"}
newnode.groups.surface_hot=3
newnode.light_source = 3
minetest.register_node("fun_caves:hot_iron", newnode)
-- Brass, hot
newnode = fun_caves.clone_node("default:steelblock")
newnode.description = "Hot Brass Block"
newnode.tiles = {"default_steel_block.png^[colorize:#FFBF00:150"}
newnode.groups.surface_hot=3
newnode.light_source = 2
minetest.register_node("fun_caves:hot_brass", newnode)
-- moon glass (glows)
newnode = fun_caves.clone_node("default:glass")
newnode.description = "Glowing Glass"
newnode.light_source = default.LIGHT_MAX
minetest.register_node("fun_caves:moon_glass", newnode)
-- 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 = {
-- Originally, this extended beyond the node boundaries.
-- {-0.4, -0.5, -0.4, 0.4, 0.0, 0.4},
-- {-0.75, -0.5, -0.4, -0.4, -0.25, 0.4},
-- {0.4, -0.5, -0.4, 0.75, -0.25, 0.4},
-- {-0.4, -0.5, -0.75, 0.4, -0.25, -0.4},
-- {-0.4, -0.5, 0.4, 0.4, -0.25, 0.75},
{-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.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)
-- 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"},
}
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
-- spikes, hot -- silicon-based life
local spike_size = { 1.0, 1.2, 1.4, 1.6, 1.7 }
fun_caves.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.hot_spikes[#fun_caves.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.hot_spike = {}
for i = 1, #fun_caves.hot_spikes do
fun_caves.hot_spike[fun_caves.hot_spikes[i]] = i
end
-- stone with algae
newnode = fun_caves.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)
-- 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},
}),
})
-- stone with lichen
newnode = fun_caves.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.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"}
}
})
minetest.register_craft({
output = "mobs:leather",
recipe = {
{"fun_caves:giant_mushroom_cap"}
}
})
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",
},
})
minetest.register_craft({
output = "fun_caves:glowing_dirt",
type = "shapeless",
recipe = {
"fun_caves:moon_juice",
"default:dirt",
},
})
-- 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", ""},
},
})

View file

@ -1,255 +0,0 @@
fun_caves.water_plants = {}
local function register_water_plant(desc)
if not (desc and type(desc) == 'table') then
return
end
fun_caves.water_plants[#fun_caves.water_plants+1] = desc
end
minetest.register_node("fun_caves:pillar_coral", {
description = "Pillar Coral",
tiles = {"fun_caves_pillar_coral.png"},
paramtype = "light",
light_source = 2,
groups = {cracky = 3, stone=1},
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("fun_caves:brain_coral", {
description = "Brain Coral",
tiles = {"fun_caves_brain_coral.png"},
light_source = 4,
groups = {cracky = 3, stone=1,},
sounds = default.node_sound_stone_defaults(),
})
minetest.register_node("fun_caves:dragon_eye", {
description = "Dragon Eye",
tiles = {"fun_caves_dragon_eye.png"},
light_source = 4,
groups = {cracky = 3, stone=1,},
sounds = default.node_sound_stone_defaults(),
})
plantlist = {
{name="staghorn_coral",
desc="Staghorn Coral",
water=true,
light_source=1,
coral=true,
sounds = default.node_sound_stone_defaults(),
},
{name="precious_coral",
desc="Precious Coral",
water=true,
light_source=2,
coral=true,
sounds = default.node_sound_stone_defaults(),
},
{name="water_plant_1",
desc="Water Plant",
water=true,
},
{name="bird_of_paradise",
desc="Bird of Paradise",
light=true,
groups={flower=1},
},
{name="gerbera",
desc="Gerbera",
light=true,
groups={flower=1, color_pink=1},
},
{name="hibiscus",
desc="Hibiscus",
wave=true,
groups={flower=1, color_white=1},
},
{name="orchid",
desc="Orchid",
wave=true,
light=true,
groups={flower=1, color_white=1},
},
}
for _, plant in ipairs(plantlist) do
if plant.coral then
groups = {cracky=3, stone=1, attached_node=1}
else
groups = {snappy=3,flammable=2,flora=1,attached_node=1}
end
if plant.groups then
for k,v in pairs(plant.groups) do
groups[k] = v
end
end
minetest.register_node("fun_caves:"..plant.name, {
description = plant.desc,
drawtype = "plantlike",
tiles = {"fun_caves_"..plant.name..".png"},
waving = plant.wave,
sunlight_propagates = plant.light,
paramtype = "light",
walkable = false,
groups = groups,
sounds = default.node_sound_leaves_defaults(),
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
})
if plant.water then
local def = {
description = plant.desc,
drawtype = "nodebox",
node_box = {type='fixed', fixed={{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, {-0.5, 0.5, -0.001, 0.5, 1.5, 0.001}, {-0.001, 0.5, -0.5, 0.001, 1.5, 0.5}}},
drop = "fun_caves:"..plant.name,
tiles = { "default_sand.png", "fun_caves_"..plant.name..".png",},
--tiles = { "default_dirt.png", "fun_caves_"..plant.name..".png",},
sunlight_propagates = plant.light,
--light_source = 14,
paramtype = "light",
light_source = plant.light_source,
walkable = true,
groups = groups,
selection_box = {
type = "fixed",
fixed = {-0.5, 0.5, -0.5, 0.5, 11/16, 0.5},
},
sounds = plant.sounds or default.node_sound_leaves_defaults(),
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if not (pos and oldnode) then
return
end
local replacement = oldnode.name:gsub('.*_water_(.*)', 'default:%1')
if replacement:find('cloud$') then
replacement = replacement:gsub('^default', 'fun_caves')
end
minetest.set_node(pos, {name = replacement})
end,
}
minetest.register_node("fun_caves:"..plant.name.."_water_sand", def)
def2 = table.copy(def)
def2.tiles = { "default_dirt.png", "fun_caves_"..plant.name..".png",}
minetest.register_node("fun_caves:"..plant.name.."_water_dirt", def2)
def2 = table.copy(def)
def2.tiles = { "fun_caves_cloud.png", "fun_caves_"..plant.name..".png",}
minetest.register_node("fun_caves:"..plant.name.."_water_cloud", def2)
def2 = table.copy(def)
def2.tiles = { "fun_caves_storm_cloud.png", "fun_caves_"..plant.name..".png",}
minetest.register_node("fun_caves:"..plant.name.."_water_storm_cloud", def2)
end
end
local function register_flower(name, seed, biomes)
if not (name and seed and biomes and type(name) == 'string' and type(seed) == 'number' and type(biomes) == 'table') then
return
end
local param = {
deco_type = "simple",
place_on = {"default:dirt_with_grass"},
sidelen = 16,
noise_params = {
offset = -0.02,
scale = 0.03,
spread = {x = 200, y = 200, z = 200},
seed = seed,
octaves = 3,
persist = 0.6
},
biomes = biomes,
y_min = 6,
y_max = 31000,
decoration = "fun_caves:"..name,
}
if not fun_caves.use_bi_hi then
param.biomes = nil
end
-- Let rainforest plants show up more often.
local key1 = table.contains(biomes, "rainforest")
local key2 = table.contains(biomes, "desertstone_grassland")
if fun_caves.use_bi_hi and (key1 or key2) then
if key1 then
table.remove(param.biomes, key1)
else
table.remove(param.biomes, key2)
end
if #param.biomes > 0 then
minetest.register_decoration(param)
end
local param2 = table.copy(param)
param2.biomes = {"rainforest", "desertstone_grassland", }
param2.noise_params.seed = param2.noise_params.seed + 20
param2.noise_params.offset = param2.noise_params.offset + 0.01
minetest.register_decoration(param2)
else
minetest.register_decoration(param)
end
end
register_flower("bird_of_paradise", 8402, {"rainforest", "desertstone_grassland", })
register_flower("orchid", 3944, {"sandstone_grassland", "tundra", "taiga", "stone_grassland", "coniferous_forest", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp", "desertstone_grassland", })
register_flower("hibiscus", 7831, {"sandstone_grassland", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp", "desertstone_grassland", })
--register_flower("calla_lily", 7985, {"sandstone_grassland", "stone_grassland", "deciduous_forest", "rainforest", "desertstone_grassland", })
register_flower("gerbera", 1976, {"savanna", "rainforest", "desertstone_grassland", })
do
-- Water Plant
local water_plant_1_def_sand = {
fill_ratio = 0.05,
place_on = {"group:sand"},
decoration = {"fun_caves:water_plant_1_water_sand"},
--biomes = {"sandstone_grassland", "stone_grassland", "coniferous_forest", "deciduous_forest", "desert", "savanna", "rainforest", "rainforest_swamp", },
biomes = {"sandstone_grassland", "stone_grassland", "coniferous_forest", "deciduous_forest", "savanna", "rainforest", "rainforest_swamp","sandstone_grassland_ocean", "stone_grassland_ocean", "coniferous_forest_ocean", "deciduous_forest_ocean", "desert_ocean", "savanna_ocean", "desertstone_grassland", },
y_max = 60,
}
if not fun_caves.use_bi_hi then
water_plant_1_def_sand.biomes = nil
end
local water_plant_1_def_dirt = table.copy(water_plant_1_def_sand)
water_plant_1_def_dirt.place_on = {"group:soil"}
water_plant_1_def_dirt.decoration = {"fun_caves:water_plant_1_water_dirt",}
local water_plant_1_def_cloud = table.copy(water_plant_1_def_sand)
water_plant_1_def_cloud.place_on = {"group:cloud"}
water_plant_1_def_cloud.decoration = {"fun_caves:water_plant_1_water_cloud",}
local water_plant_1_def_storm_cloud = table.copy(water_plant_1_def_sand)
water_plant_1_def_storm_cloud.place_on = {"group:cloud"}
water_plant_1_def_storm_cloud.decoration = {"fun_caves:water_plant_1_water_storm_cloud",}
register_water_plant(water_plant_1_def_sand)
register_water_plant(water_plant_1_def_dirt)
register_water_plant(water_plant_1_def_cloud)
register_water_plant(water_plant_1_def_storm_cloud)
end
-- Get the content ids for all registered water plants.
for _, desc in pairs(fun_caves.water_plants) do
if type(desc.decoration) == 'string' then
desc.content_id = minetest.get_content_id(desc.decoration)
elseif type(desc.decoration) == 'table' then
desc.content_id = minetest.get_content_id(desc.decoration[1])
end
end

View file

@ -1,155 +0,0 @@
-- Place a small nodebox.
local function small_cube(grid, pos, diameters)
if not (grid and pos and diameters and type(grid) == 'table' and type(diameters) == 'table') then
return
end
local rock = {}
rock[1] = pos.x
rock[2] = pos.y
rock[3] = pos.z
rock[4] = pos.x + diameters.x
rock[5] = pos.y + diameters.y
rock[6] = pos.z + diameters.z
grid[#grid+1] = rock
end
-- Create some tiles of small rocks that can be picked up.
local default_grid
local tiles = {"default_stone.png", "default_desert_stone.png", "default_sandstone.png"}
for grid_count = 1,6 do
local grid = {}
for rock_count = 2, math.random(1,4) + 1 do
local diameter = math.random(5,15)/100
local x = math.random(1,80)/100 - 0.5
local z = math.random(1,80)/100 - 0.5
--step_sphere(grid, {x=x,y=-0.5,z=z}, {x=diameter, y=diameter, z=diameter})
small_cube(grid, {x=x,y=-0.5,z=z}, {x=diameter, y=diameter, z=diameter})
end
--local stone = tiles[math.random(1,#tiles)]
local stone = tiles[(grid_count % #tiles) + 1]
minetest.register_node("fun_caves:small_rocks"..grid_count, {
description = "Small Rocks",
tiles = {stone},
is_ground_content = true,
walkable = false,
paramtype = "light",
sunlight_propagates = true,
drawtype = "nodebox",
buildable_to = true,
node_box = { type = "fixed",
fixed = grid },
selection_box = { type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
groups = {stone=1, oddly_breakable_by_hand=3, dig_immediate = 3},
drop = "fun_caves:small_rocks",
sounds = default.node_sound_stone_defaults(),
})
local param = {
deco_type = "simple",
decoration = "fun_caves:small_rocks"..grid_count,
sidelen = 80,
place_on = {"group:soil", "group:sand"},
fill_ratio = 0.001,
biomes = {"sandstone_grassland", "tundra", "taiga", "stone_grassland", "coniferous_forest", "deciduous_forest", "desert", "savanna", "rainforest", "desertstone_grassland", },
flags = "place_center_x, place_center_z",
rotation = "random",
}
if not fun_caves.use_bi_hi then
param.biomes = nil
end
minetest.register_decoration(param)
default_grid = grid
end
-- This is the inventory item, so we don't have six different stacks.
minetest.register_node("fun_caves:small_rocks", {
description = "Small Rocks",
tiles = {"default_stone.png"},
inventory_image = "fun_caves_small_rocks.png",
is_ground_content = true,
walkable = false,
paramtype = "light",
sunlight_propagates = true,
drawtype = "nodebox",
node_box = { type = "fixed",
fixed = default_grid },
selection_box = { type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
},
groups = {stone=1, oddly_breakable_by_hand=3, dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
after_place_node = function(pos, placer, itemstack, pointed_thing)
if not pos then
return
end
minetest.set_node(pos, {name = "fun_caves:small_rocks"..math.random(6)})
end,
})
-- Small rocks can be used to create cobblestone, if you like.
minetest.register_craft({
output = "default:cobble",
recipe = {
{"", "", ""},
{"fun_caves:small_rocks", "fun_caves:small_rocks", ""},
{"fun_caves:small_rocks", "fun_caves:small_rocks", ""},
},
})
minetest.register_craft({
output = "default:stick",
type = 'shapeless',
recipe = {
"default:dry_shrub", "default:dry_shrub",
"default:dry_shrub", "default:dry_shrub",
},
})
minetest.register_craft({
output = "default:stick",
type = 'shapeless',
recipe = {
"fun_caves:roots",
},
})
minetest.register_node("fun_caves:roots", {
description = "Exposed Roots",
tiles = {"fun_caves_dry_twigs.png"},
inventory_image = "fun_caves_dry_twigs.png",
is_ground_content = true,
walkable = false,
paramtype = "light",
sunlight_propagates = true,
drawtype = "raillike",
selection_box = { type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -7/16, 0.5},
},
groups = {stone=1, oddly_breakable_by_hand=3, dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
})
local param = {
deco_type = "simple",
decoration = "fun_caves:roots",
sidelen = 80,
place_on = {"group:soil", "group:sand"},
fill_ratio = 0.0005,
biomes = {"sandstone_grassland", "stone_grassland", "desertstone_grassland", },
flags = "place_center_x, place_center_z",
rotation = "random",
}
if not fun_caves.use_bi_hi then
param.biomes = nil
end
minetest.register_decoration(param)

View file

@ -1,409 +0,0 @@
dofile(fun_caves.path .. "/castles.lua")
local deco_depth = -30 -- place cave stuff this far beneath the surface
local light_depth = -13 -- depth above which to place corals/sea plants
local water_level = 1
local fluid_compression = -200 -- the depth to start planting lava/water
local water_lily_ratio = 15 -- place this many water for every lily
local max_depth = 31000
local water_lily_biomes = {}
for _, i in pairs({"rainforest_swamp", "rainforest", "savanna_swamp", "savanna", "deciduous_forest_swamp", "deciduous_forest", "desertstone_grassland", }) do
water_lily_biomes[i] = true
end
local coral_biomes = {}
for _, i in pairs({"desert_ocean", "savanna_ocean", "rainforest_ocean", }) do
coral_biomes[i] = true
end
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}
local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = 33, octaves = 3, persist = 0.7, lacunarity = 2.0}
-- Air needs to be placed prior to decorations.
fun_caves.decogen = function(minp, maxp, data, p2data, area, node, heightmap, biomemap, biome_ids, underzone)
if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table' and fun_caves.underzones and fun_caves.cave_biomes and fun_caves.place_schematic and fun_caves.schematics and fun_caves.make_fungal_tree and fun_caves.surround and fun_caves.water_plants) 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 plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
if not (biome_n and plant_n) then
return
end
local math_random = math.random
local dis_map = {}
if underzone and underzone.name == 'Dis' then
for i = 0, 10, 2 do
dis_map[i] = {}
for j = 0, 10, 2 do
dis_map[i][j] = math_random(6)
if dis_map[i][j] == 6 then
dis_map[i][j] = 5 + math_random(10)
end
end
end
end
if false and underzone and underzone.name == 'Caina' and math.abs(minp.y - underzone.floor) < math.abs(minp.y - underzone.ceiling) then
local write, writep2 = fun_caves.ice_castle(minp, maxp, data, p2data, area, node, heightmap, biomemap, biome_ids, underzone)
if write then
return write, writep2
end
end
local undersea = fun_caves.underzones['Styx'].sealevel
local write = false
local write_p2 = false
local index = 0
local index3d = 0
local pos = {x=0, y=0, z=0}
local math_floor = math.floor
local math_max = math.max
local math_min = math.min
local math_log = math.log
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
----------------------------------------------------------
-- cave decoration non-loop -- only there to enable breaks
-- Remove this loop to eliminate cave decorations.
----------------------------------------------------------
for deco_non_loop = 1, 1 do
if not (data[ivm] == node["air"] or data[ivm] == node["default:stone"]) then
break
end
local biome
--if underzone and y < (underzone.ceiling + underzone.floor) / 2 then
if underzone then
biome = underzone
else
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.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.cave_biomes['salt']
if not biome then
print(("* Error in biome selection: %s"):format(biome_val))
end
if not biome or (y < undersea and not biome.underwater) then
biome = fun_caves.cave_biomes['algae']
end
end
local node_below
if y > minp.y then
node_below = data[ivm - area.ystride]
end
local node_above = data[ivm + area.ystride]
if underzone and underzone.lake and y < underzone.floor + underzone.lake_level and data[ivm] == node['air'] then
data[ivm] = node[underzone.lake]
write = true
break
end
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"] or (y < undersea and data[ivm + area.ystride * i] == node["default:water_source"]) 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
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
-- smallest city generator ever
if underzone and underzone.name == 'Dis' and data[ivm] == node['air'] and math_floor((x - minp.x) / 8) % 2 == 0 and math_floor((z - minp.z) / 8) % 2 == 0 and y - underzone.floor < dis_map[math_floor((x - minp.x) / 8)][math_floor((z - minp.z) / 8)] * 4 + 1 and y - underzone.floor >= 0 then
local dx = (x - minp.x) % 16
local dy = y - underzone.floor + 1
local dz = (z - minp.z) % 16
if dx == 1 and dz == 1 then
data[ivm] = node["default:ladder_steel"]
p2data[ivm] = 3
write_p2 = true
elseif ((dx == 0 or dx == 7) and (dz % 3 ~= 2 or dy % 4 == 0)) or ((dz == 0 or dz == 7) and (dx % 3 ~= 2 or dy % 4 == 0)) then
data[ivm] = node["fun_caves:hot_iron"]
elseif dy % 4 == 0 then
data[ivm] = node["fun_caves:hot_brass"]
end
write = true
break
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["fun_caves:polluted_dirt"] then
if math_random(10) == 1 then
data[ivm] = node["default:dry_shrub"]
write = true
break
elseif math_random(50) == 1 then
local air_count = 0
local j
for i = 1, 9 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 > 6 then
pos.x = x
pos.y = y
pos.z = z
fun_caves.place_schematic(minp, maxp, data, p2data, area, node, pos, fun_caves.schematics['decaying_tree'], true)
end
end
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.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
-----------------------------------------------------
-- end of cave decoration non-loop
-----------------------------------------------------
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
else
local pn = plant_n[index]
local biome
if biomemap then
biome = biome_ids[biomemap[index]]
end
-----------------------------------------------------------
-- water decoration non-loop -- only there to enable breaks
-- Remove this loop to eliminate water decorations.
-----------------------------------------------------------
for deco_non_loop = 1, 1 do
if y < light_depth then
break
end
local node_below = data[ivm - area.ystride]
local node_above = data[ivm + area.ystride]
if y < water_level and data[ivm] == node["default:sand"] and node_above == node["default:water_source"] and data[ivm + area.ystride * 2] == node["default:water_source"] and (not biomemap or coral_biomes[biome]) and pn < -0.1 and math_random(5) == 1 and fun_caves.surround(node, data, area, ivm) then
if math_random(100) == 1 then
data[ivm] = node["fun_caves:precious_coral_water_sand"]
else
data[ivm] = node["fun_caves:staghorn_coral_water_sand"]
end
write = true
break
elseif y < water_level and node_below == node["default:sand"] and node_above == node["default:water_source"] and data[ivm] == node["default:water_source"] and (not biomemap or coral_biomes[biome]) and pn < -0.1 and math_random(5) < 3 then
if math_random(15) == 1 then
data[ivm] = node["fun_caves:brain_coral"]
write = true
break
elseif math_random(15) == 1 then
data[ivm] = node["fun_caves:dragon_eye"]
write = true
break
else
data[ivm] = node["fun_caves:pillar_coral"]
write = true
break
end
elseif x < maxp.x and y < maxp.y and z < maxp.z and x > minp.x and y > minp.y and z > minp.z and (node_above == node["default:water_source"] or node_above == node["default:river_water_source"]) and (data[ivm] == node["default:sand"] or data[ivm] == node["default:dirt"]) then
-- Check the biomes and plant water plants, if called for.
if not fun_caves.surround(node, data, area, ivm) then
break
end
for i = 1, #fun_caves.water_plants do
local desc = fun_caves.water_plants[i]
if desc.content_id then
if not node_match_cache[desc.content_id] then
node_match_cache[desc.content_id] = {}
end
if not node_match_cache[desc.content_id][data[ivm]] then
-- This is a great way to match all node type strings
-- against a given node (or nodes). However, it's slow.
-- To speed it up, we cache the results for each plant
-- on each node, and avoid calling find_nodes every time.
pos.x = x
pos.y = y
pos.z = z
local posm = minetest.find_nodes_in_area(pos, pos, desc.place_on)
if not (posm and type(posm) == 'table') then
return
end
if #posm > 0 then
node_match_cache[desc.content_id][data[ivm]] = "good"
else
node_match_cache[desc.content_id][data[ivm]] = "bad"
end
end
if node_match_cache[desc.content_id][data[ivm]] == "good" and desc.fill_ratio and (not desc.biomes or (not biomemap) or (biome and desc.biomes and table.contains(desc.biomes, biome))) and math_random() <= desc.fill_ratio then
data[ivm] = desc.content_id
write = true
break
end
end
end
elseif y > minp.y and node_below == node["default:river_water_source"] and data[ivm] == node["air"] and (not biomemap or water_lily_biomes[biome]) and pn > 0.5 and math_random(water_lily_ratio) == 1 then
-- on top of the water
-- I haven't figured out what the decoration manager is
-- doing with the noise functions, but this works ok.
data[ivm] = node["flowers:waterlily"]
write = true
break
end
end
-----------------------------------------------------
-- end of water decoration non-loop
-----------------------------------------------------
end
ivm = ivm + area.ystride
index3d = index3d + csize.x
end
end
end
return write, write_p2
end

234
demon.lua
View file

@ -1,234 +0,0 @@
-- Ice Demon -- creates and moves ice nodes
minetest.register_node("fun_caves:freezing_vapor", {
description = "Freezing Vapor",
tiles = {'fun_caves_wisp.png'},
sunlight_propagates = true,
use_texture_alpha = true,
drawtype = "glasslike",
paramtype = 'light',
walkable = false,
buildable_to = true,
pointable = false,
})
local function snow_effect(pos, radius)
if not (pos and radius and type(radius) == 'number') then
return
end
minetest.add_particlespawner({
amount = 30,
time = 1,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x=-10, y=-10, z=-10},
maxvel = {x=10, y=10, z=10},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 1,
maxexptime = 3,
minsize = 16,
maxsize = 32,
texture = "fun_caves_snowflakes.png",
})
end
mobs:register_mob("fun_caves:ice_demon", {
description = "Ice Demon",
type = "monster",
passive = false,
damage = 3,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 10,
hp_max = 20,
armor = 50,
collisionbox = {-0.30,-1.0,-0.30, 0.30,0.8,0.30},
visual = "mesh",
mesh = "character.b3d",
drawtype = "front",
textures = {
{"default_ice.png"},
},
makes_footstep_sound = true,
--sounds = {
-- random = "goblins_goblin_ambient",
-- warcry = "goblins_goblin_attack",
-- attack = "goblins_goblin_attack",
-- damage = "goblins_goblin_damage",
-- death = "goblins_goblin_death",
-- distance = 15,
--},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:ice", chance = 3, min = 1, max = 3},
{name = "fun_caves:eternal_ice_crystal", chance = 10, min = 1, max = 1},
},
water_damage = 0,
lava_damage = 4,
light_damage = 2,
view_range = 15,
animation = {
stand_start = 0,
stand_end = 79,
sit_start = 81,
sit_end = 160,
sleep_start = 162,
sleep_end = 166,
walk_start = 168,
walk_end = 187,
mine_start = 189,
mine_end = 198,
walkmine_start = 200,
walkmine_end = 219,
},
animation_speed = 30,
fly_in = 'fun_caves:freezing_vapor',
do_custom = function(self)
if not (self and fun_caves.surface_damage and fun_caves.search_replace and fun_caves.custom_ready) then
return
end
-- This has to happen fast.
if self.attack then
self.fly = true
local pos = self.attack:getpos()
pos.y = pos.y - 0
fun_caves.search_replace(pos, 1, {'default:ice', 'air'}, 'fun_caves:freezing_vapor')
end
if not fun_caves.custom_ready(self) then
return
end
if not self.attack then
self.fly = false
end
fun_caves.surface_damage(self, true)
end,
})
if fun_caves.underzones then
mobs:spawn_specific("fun_caves:ice_demon", {"default:ice"}, nil, -1, 10, 300, 3000, 2, fun_caves.underzones['Caina'].lower_bound, fun_caves.underzones['Caina'].upper_bound)
mobs:spawn_specific("fun_caves:ice_demon", {"default:ice"}, {'default:torch'}, -1, 20, 100, 300, 2, fun_caves.underzones['Caina'].lower_bound, fun_caves.underzones['Caina'].upper_bound)
end
-- Blizzard Demon -- storm that slows players
local snow_demon = {
description = "Ice Demon",
type = "monster",
passive = false,
damage = 3,
-- change to dogshoot?
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 10,
hp_max = 20,
armor = 50,
collisionbox = {-0.30,-1.0,-0.30, 0.30,0.8,0.30},
visual = "mesh",
mesh = "character.b3d",
drawtype = "front",
textures = {
{"default_snow.png"},
},
makes_footstep_sound = true,
sounds = {
random = "wind_howl_2",
warcry = "wind_howl_2",
distance = 25,
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = {
{name = "default:snow", chance = 3, min = 1, max = 3},
{name = "fun_caves:eternal_ice_crystal", chance = 10, min = 1, max = 1},
},
water_damage = 0,
lava_damage = 4,
light_damage = 2,
view_range = 15,
animation = {
stand_start = 0,
stand_end = 79,
sit_start = 81,
sit_end = 160,
sleep_start = 162,
sleep_end = 166,
walk_start = 168,
walk_end = 187,
mine_start = 189,
mine_end = 198,
walkmine_start = 200,
walkmine_end = 219,
},
animation_speed = 30,
do_custom = function(self)
if not (self and fun_caves.set_status and fun_caves.custom_ready and fun_caves.surface_damage) then
return
end
if not self.attack then
self.fly = false
end
local pos = self.object:getpos()
snow_effect(pos, 20)
if self.attack then
fun_caves.set_status(self.attack:get_player_name(), 'slow_cold', 20)
end
if not fun_caves.custom_ready(self) then
return
end
fun_caves.surface_damage(self, true)
end,
}
if fun_caves.register_status then
fun_caves.register_status({
name = 'slow_cold',
start = function(player)
if not player then
return
end
player:set_physics_override({speed=0.3})
end,
terminate = function(player)
if not player then
return
end
player:set_physics_override({speed=1})
end,
})
end
if minetest.registered_entities["mobs_yeti:yeti"] then
snow_demon.arrow = "mobs_yeti:snowball"
snow_demon.attack_type = 'dogshoot'
snow_demon.shoot_interval = .7
snow_demon.shoot_offset = 2
end
mobs:register_mob("fun_caves:snow_demon", snow_demon)
if fun_caves.underzones then
mobs:spawn_specific("fun_caves:snow_demon", {"default:ice"}, nil, -1, 10, 300, 3000, 2, fun_caves.underzones['Caina'].lower_bound, fun_caves.underzones['Caina'].upper_bound)
end
-- Magma Demon -- creates lava under player (!)

View file

@ -1,17 +1,5 @@
default
dye
flowers
wool
bucket
beds
stairs
farming?
hunger?
vessels
mobs?
mobs_monster?
mobs_slimes?
mobs_creeper?
kpgmobs?
mobs_fish?
dmobs?
3d_armor?
fun_caves_mobs?

View file

@ -1,606 +0,0 @@
local max_depth = 31000
local cells = 10
local border = 10
local cell_size = math.floor((80 - border * 2) / cells)
local cells_y = math.floor(80 / cell_size)
local dead_space = 80 - cells_y * cell_size
local dungeon_depth = -1 -- close to y / 80
local dungeon_noise = {offset = 0, scale = 1, seed = -4082, spread = {x = 7, y = 7, z = 7}, octaves = 4, persist = 1, lacunarity = 2}
if fun_caves.path then
dofile(fun_caves.path .. "/trophies.lua")
dofile(fun_caves.path .. "/tesseract.lua")
end
-- dungeon floor, rooms
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.legacy_mineral = false
newnode.groups.dungeon = 1
minetest.register_node("fun_caves:dungeon_floor_1", newnode)
-- dungeon floor, halls
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.legacy_mineral = false
newnode.groups.dungeon = 1
newnode.drop = 'default:cobble'
minetest.register_node("fun_caves:dungeon_floor_2", newnode)
-- dungeon walls, basic
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.groups.dungeon = 1
newnode.drop = 'default:cobble'
minetest.register_node("fun_caves:dungeon_wall_1", newnode)
-- dungeon walls, type 2
newnode = fun_caves.clone_node("default:cobble")
newnode.description = "Dungeon Stone"
newnode.groups.dungeon = 1
newnode.drop = 'default:cobble'
minetest.register_node("fun_caves:dungeon_wall_2", newnode)
local treasures = {
{ level = 1, rarity = 10, name = 'default:apple 10', },
{ level = 1, rarity = 20, name = 'fun_caves:onion 10', },
{ level = 1, rarity = 120, name = 'default:bronze_ingot 5', },
{ level = 1, rarity = 30, name = 'default:coal_lump 10', },
{ level = 1, rarity = 85, name = 'default:copper_ingot 5', },
{ level = 1, rarity = 155, name = 'default:diamond 5', },
{ level = 1, rarity = 155, name = 'default:gold_ingot 5', },
{ level = 1, rarity = 200, name = 'default:mese_crystal', },
{ level = 1, rarity = 240, name = 'default:obsidian', },
{ level = 1, rarity = 85, name = 'default:obsidian_shard', },
{ level = 1, rarity = 450, name = 'default:pick_diamond', },
{ level = 1, rarity = 600, name = 'default:pick_mese', },
{ level = 1, rarity = 50, name = 'default:steel_ingot 5', },
{ level = 1, rarity = 450, name = 'default:sword_diamond', },
{ level = 1, rarity = 400, name = 'default:sword_mese', },
{ level = 1, rarity = 10, name = 'default:wood 10', },
{ level = 1, rarity = 400, name = 'fun_caves:aquamarine', },
{ level = 1, rarity = 400, name = 'fun_caves:constant_flame', },
{ level = 1, rarity = 400, name = 'fun_caves:coral_gem', },
{ level = 1, rarity = 400, name = 'fun_caves:garnet', },
{ level = 2, rarity = 960, name = 'fun_caves:metallic_ice', },
{ level = 2, rarity = 120, name = 'fun_caves:eternal_ice_crystal', },
{ level = 1, rarity = 480, name = 'fun_caves:moon_glass 5', },
{ level = 1, rarity = 240, name = 'fun_caves:moon_juice 5', },
{ level = 1, rarity = 400, name = 'fun_caves:moonstone', },
{ level = 1, rarity = 5000, name = 'fun_caves:philosophers_stone', },
{ level = 1, rarity = 160, name = 'fun_caves:pure_copper', },
{ level = 2, rarity = 175, name = 'fun_caves:silver_ingot 5', },
{ level = 1, rarity = 960, name = 'fun_caves:sky_iron', },
{ level = 1, rarity = 120, name = 'fun_caves:meteorite', },
{ level = 1, rarity = 5000, name = 'fun_caves:unobtainium', },
}
for name, desc in pairs(minetest.registered_items) do
if name:find('^wool:') then
treasures[#treasures+1] = { level = 1, rarity = 80, name = name..' 2' }
elseif name == 'farming:cotton' then
treasures[#treasures+1] = { level = 1, rarity = 80, name = name..' 10' }
elseif name == 'farming:flour' then
treasures[#treasures+1] = { level = 1, rarity = 80, name = name..' 10' }
end
end
if minetest.registered_entities['mobs_monster:stone_monster'] then
treasures[#treasures+1] = { level = 1, rarity = 400, name = 'mobs_monster:stone_monster', }
end
if minetest.registered_entities['mobs_monster:dungeon_master'] then
treasures[#treasures+1] = { level = 1, rarity = 400, name = 'mobs_monster:dungeon_master', }
end
local chest_formspec =
"size[8,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[current_name;main;0,0.3;8,4;]" ..
"list[current_player;main;0,4.85;8,1;]" ..
"list[current_player;main;0,6.08;8,3;8]" ..
"listring[current_name;main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
local function disintigrate(minp, maxp)
if not (minp and maxp) then
return
end
minp = vector.round(minp)
maxp = vector.round(maxp)
local air = minetest.get_content_id('air')
local vm = minetest.get_voxel_manip()
if not vm then
return
end
local emin, emax = vm:read_from_map(minp, maxp)
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
local p = {}
for z = minp.z, maxp.z do
for y = minp.y, maxp.y do
local ivm = area:index(minp.x, y, z)
for x = minp.x, maxp.x do
data[ivm] = air
ivm = ivm + 1
end
end
end
vm:set_data(data)
vm:write_to_map()
vm:update_map()
end
if fun_caves.register_status then
fun_caves.register_status({
name = 'poisoned',
during = function(player)
if not player then
return
end
local player_name = player:get_player_name()
if not player_name or player_name == '' then
return
end
local damage = 1
if fun_caves.db.status and fun_caves.db.status[player_name] and fun_caves.db.status[player_name]['poisoned'] and fun_caves.db.status[player_name]['poisoned']['damage'] then
damage = tonumber(fun_caves.db.status[player_name]['poisoned']['damage'])
end
local hp = player:get_hp()
if hp and type(hp) == 'number' then
hp = hp - damage
player:set_hp(hp)
end
end,
terminate = function(player)
if not player then
return
end
local player_name = player:get_player_name()
minetest.chat_send_player(player_name, 'Your sickness ebbs away.')
end,
})
end
local newnode = fun_caves.clone_node("default:chest")
newnode.description = "Treasure Chest"
newnode.on_construct = nil
newnode.drop = 'default:chest'
newnode.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if not (pos and clicker) then
return
end
local meta = minetest.get_meta(pos)
if not meta then
return
end
local depth = math.min(20, math.max(1, math.ceil(pos.y / -200)))
local level = math.max(1, math.floor(pos.y / -4900))
local ready = meta:get_string('formspec')
if treasures and ready == '' then
meta:set_string("formspec", '0')
if math.random(10) == 1 and fun_caves.dungeon_spawns and #fun_caves.dungeon_spawns > 0 then
meta:set_string("formspec", '')
minetest.remove_node(pos)
local desc = fun_caves.dungeon_spawns[math.random(#fun_caves.dungeon_spawns)]
if not desc then
return
end
local mpos = table.copy(pos)
mpos.y = mpos.y + 1
local obj = minetest.add_entity(mpos, desc.name)
if not obj then
return
end
local mob = obj:get_luaentity()
if not mob then
return
end
if mob.hp_max and mob.object and mob.health and mob.damage then
local factor = 1 + (math.max(math.abs(pos.x), math.abs(pos.y), math.abs(pos.z)) / 6200)
mob.started_in_dungeon = true
factor = factor * 1.5
mob.hp_max = math.floor(mob.hp_max * factor)
mob.damage = math.floor(mob.damage * factor)
mob.health = math.floor(mob.health * factor)
mob.object:set_hp(mob.health)
mob.initial_promotion = true
check_for_death(mob)
--print('Dungeon quality '..desc.name..': '..mob.health..' health, '..mob.damage..' damage')
end
elseif math.random(20) == 1 then
local player_name = clicker:get_player_name()
if not player_name or player_name == '' or not fun_caves.set_status then
return
end
minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'You\'ve been poisoned!'))
fun_caves.set_status(player_name, 'poisoned', 2 ^ math.random(8), {damage = 1})
meta:set_string("formspec", '')
return
elseif minetest.get_modpath('tnt') and math.random(20) == 1 then
meta:set_string("formspec", '')
minetest.set_node(pos, {name = 'tnt:tnt_burning'})
local timer = minetest.get_node_timer(pos)
if timer then
timer:start(3)
end
minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10})
return
elseif math.random(20) == 1 then
minetest.remove_node(pos)
pos = clicker:getpos()
if not pos then
return
end
disintigrate({x = pos.x - 1, y = pos.y - 12, z = pos.z - 1}, {x = pos.x + 1, y = pos.y - 1, z = pos.z + 1})
return
end
meta:set_string("formspec", chest_formspec)
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
local something
for i = 1, 100 do
for j = 1, 5 * depth do
for _, tre in pairs(treasures) do
if tre.name and tre.level and tre.rarity and tre.level <= level and math.random(tre.rarity) == 1 and inv:room_for_item('main', tre.name) then
inv:add_item('main', tre.name)
something = true
end
end
end
if something then
break
end
end
end
end
minetest.register_node("fun_caves:coffer", newnode)
fun_caves.dungeon = function(minp_in, maxp_in, data, p2data, area, node, heightmap)
if not (minp_in and maxp_in and data and area and node and heightmap and type(data) == 'table' and type(heightmap) == 'table') then
return
end
local n = minetest.get_perlin(dungeon_noise):get2d({x=minp_in.x, y=minp_in.z})
if not (n and type(n) == 'number') then
return
end
if math.floor((n * 10000) % 13) ~= 1 then
return
end
local center_off = cell_size * 4 + border
if minp_in.y > -100 then
local minp, maxp = minp_in, maxp_in
local stair, avg, count = nil, 0, 0
local index = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
if not heightmap[index] or type(heightmap[index]) ~= 'number' then
return
end
if x > minp.x + center_off and x < maxp.x - center_off and z > minp.z + center_off and z < maxp.z - center_off and heightmap[index] >= minp.y and heightmap[index] < maxp.y - 2 then
stair = true
avg = avg + heightmap[index]
count = count + 1
end
end
end
avg = math.ceil(avg / count)
if stair then
for z = -1, (cell_size * 2) do
for x = -1, (cell_size * 2) do
local ivm = area:index(x + minp.x + center_off, minp.y - 8, z + minp.z + center_off)
for y = minp.y - 8, avg do
if y > minp.y - 4 and (x == -1 or x == (cell_size * 2) or z == -1 or z == (cell_size * 2)) then
data[ivm] = node['default:cobble']
elseif ((x == 2 or x == 9) and z > 1 and z < 10) or ((z == 2 or z == 9) and x > 1 and x < 10) then
data[ivm] = node['default:cobble']
else
local t
if z < 2 then
t = x
elseif x > 9 then
t = z + 11
elseif z > 9 then
t = 33 - x
else
t = 44 - z
end
t = math.floor(t / 44 * 10 * 2 + 0.5) / 2
if x < 2 or x > 9 or z < 2 or z > 9 then
if math.floor((y - minp.y) % 10 * 2 + 0.5) / 2 == t then
data[ivm] = node['stairs:slab_cobble']
elseif math.floor((y - minp.y) % 10 * 2 + 0.5) / 2 == t - 0.5 then
data[ivm] = node['default:cobble']
else
data[ivm] = node['air']
end
end
end
ivm = ivm + area.ystride
end
end
end
end
return true, true
end
if minp_in.y > 0 then
return
end
local minp = table.copy(minp_in)
minp.x = minp.x + border
minp.z = minp.z + border
local maxp = table.copy(maxp_in)
maxp.x = maxp.x - border
maxp.z = maxp.z - border
center_off = center_off - border
local level = math.min(6, math.ceil(maxp.y / math.floor(max_depth / -6)))
local inner_floor = node['fun_caves:dungeon_floor_1']
local outer_wall = node['fun_caves:dungeon_wall_2']
local inner_wall = node['fun_caves:dungeon_wall_1']
local treasure_count = 0
local leave_alone = {}
leave_alone[node['default:cobble']] = true
leave_alone[node['stairs:stair_cobble']] = true
leave_alone[node['stairs:slab_cobble']] = true
leave_alone['stairway'] = true
for z = minp.z - 1, maxp.z + 1 do
for y = minp.y, maxp.y + 1 do
local ivm = area:index(minp.x - 1, y, z)
for x = minp.x - 1, maxp.x + 1 do
local centered_out = (z >= minp.z + center_off - 1 and z <= maxp.z - center_off + 1 and x >= minp.x + center_off - 1 and x <= maxp.x - center_off + 1)
local centered_in = (z >= minp.z + center_off and z <= maxp.z - center_off and x >= minp.x + center_off and x <= maxp.x - center_off)
if y > maxp.y - dead_space then
if centered_out and (x == minp.x + center_off - 1 or x == maxp.x - center_off + 1 or z == minp.z + center_off - 1 or z == maxp.z - center_off + 1) then
data[ivm] = node['fun_caves:dungeon_wall_1']
elseif not centered_out and y <= maxp.y then
data[ivm] = node['default:stone']
elseif y <= maxp.y and not leave_alone[data[ivm]] then
data[ivm] = node['air']
end
elseif x == minp.x - 1 or x == maxp.x + 1 or z == minp.z - 1 or z == maxp.z + 1 then
data[ivm] = node['fun_caves:dungeon_wall_1']
elseif (y == minp.y or y == maxp.y - dead_space) and not centered_in then
data[ivm] = node['fun_caves:dungeon_floor_1']
end
ivm = ivm + 1
end
end
end
local content = {}
for cx = 0, (cells - 1) do
content[cx] = {}
for cy = 0, (cells_y - 1) do
content[cx][cy] = {}
for cz = 0, (cells - 1) do
if cy == (cells_y - 1) and (cz == 4 or cz == 5) and (cx == 4 or cx == 5) then
content[cx][cy][cz] = 'room'
elseif cy == 0 and (cz == 4 or cz == 5) and (cx == 4 or cx == 5) then
content[cx][cy][cz] = 'room'
else
content[cx][cy][cz] = '4way'
end
end
end
end
for cy = 0, (cells_y - 2) do
local x, z = math.random(1,8), math.random(0,(cells - 1))
while cy == (cells_y - 1) and (z == 4 or z == 5) and (x == 4 or x == 5) do
x, z = math.random(1,8), math.random(0,(cells - 1))
end
content[x][cy][z] = 'stair1'
content[x - 1][cy][z] = 'room'
if cy < (cells_y - 1) then
content[x][cy + 1][z] = 'room'
content[x + 1][cy + 1][z] = 'room'
end
x, z = math.random(0,(cells - 1)), math.random(1,8)
while cy == (cells_y - 1) and (z == 4 or z == 5) and (x == 4 or x == 5) do
x, z = math.random(0,(cells - 1)), math.random(1,8)
end
content[x][cy][z] = 'stair0'
content[x][cy][z - 1] = 'room'
if cy < (cells_y - 1) then
content[x][cy + 1][z] = 'room'
content[x][cy + 1][z + 1] = 'room'
end
end
for cx = 0, (cells - 1) do
for cy = 0, (cells_y - 1) do
for cz = 0, (cells - 1) do
if content[cx][cy][cz] == '4way' and math.random(2) == 1 then
content[cx][cy][cz] = 'room'
end
end
end
end
for cz = 0, (cells - 1) do
local oz = minp.z + cz * cell_size
for cy = 0, (cells_y - 1) do
local oy = minp.y + cy * cell_size
for cx = 0, (cells - 1) do
local ox = minp.x + cx * cell_size
local centered_in = ((cx == 4 or cx == 5) and (cz == 4 or cz == 5))
if content[cx][cy][cz] == 'stair0' then
for rz = 0, cell_size do
for ry = 0, 9 do
local ivm = area:index(ox, oy + ry, oz + rz)
for rx = 0, (cell_size - 1) do
if ry == rz + 1 and (rx == 2 or rx == 3) and (cy == (cells_y - 1) or rz < cell_size) then
data[ivm] = node['stairs:stair_cobble']
p2data[ivm] = 0
elseif (ry >= rz + 1 and ry <= rz + 5) and (rx == 2 or rx == 3) then
data[ivm] = 'stairway'
elseif ry == rz and (rx == 2 or rx == 3) then
data[ivm] = node['fun_caves:dungeon_floor_1']
elseif rz < cell_size and ry == 0 then
data[ivm] = node['fun_caves:dungeon_floor_1']
elseif ry < cell_size and rz < cell_size then
data[ivm] = node['fun_caves:dungeon_wall_1']
end
ivm = ivm + 1
end
end
end
elseif content[cx][cy][cz] == 'stair1' then
for rz = 0, (cell_size - 1) do
for ry = 0, 9 do
local ivm = area:index(ox, oy + ry, oz + rz)
for rx = 0, cell_size do
if ry == rx + 1 and (rz == 2 or rz == 3) and (cy == (cells_y - 1) or rx < cell_size) then
data[ivm] = node['stairs:stair_cobble']
p2data[ivm] = 1
elseif (ry >= rx + 1 and ry <= rx + 5) and (rz == 2 or rz == 3) then
data[ivm] = 'stairway'
elseif ry == rx and (rz == 2 or rz == 3) then
data[ivm] = node['fun_caves:dungeon_floor_1']
elseif rx < cell_size and ry == 0 then
data[ivm] = node['fun_caves:dungeon_floor_1']
elseif ry < cell_size and rx < cell_size then
data[ivm] = node['fun_caves:dungeon_wall_1']
end
ivm = ivm + 1
end
end
end
else
for rz = 0, (cell_size - 1) do
for ry = 0, (cell_size - 1) do
local ivm = area:index(ox, oy + ry, oz + rz)
for rx = 0, (cell_size - 1) do
if not leave_alone[data[ivm]] then
if ry == 0 and (cy > 0 or not centered_in) then
if content[cx][cy][cz] == 'room' then
local r = math.random(1000)
if r == 1 then
data[ivm] = node['fun_caves:stone_with_gold_trap']
elseif r == 2 then
data[ivm] = node['fun_caves:stone_with_coal_trap']
elseif r == 3 then
data[ivm] = node['fun_caves:stone_with_iron_trap']
elseif r == 4 then
data[ivm] = node['fun_caves:stone_with_diamond_trap']
else
data[ivm] = node['fun_caves:dungeon_floor_1']
end
else
data[ivm] = node['fun_caves:dungeon_floor_2']
end
elseif ry == (cell_size - 1) and (cy < (cells_y - 1) or not centered_in) then
data[ivm] = node['fun_caves:dungeon_floor_2']
elseif content[cx][cy][cz] == 'room' then
if ry == 1 and math.random(250) == 1 and data[ivm - area.ystride] == node['fun_caves:dungeon_floor_1'] then
data[ivm] = node['fun_caves:coffer']
else
data[ivm] = node['air']
end
elseif content[cx][cy][cz] == '4way' and ry <= 2 and (rz == 2 or rz == 3 or rx == 2 or rx == 3) and (ox + rx >= minp.x + 2 and ox + rx <= maxp.x - 2 and oz + rz >= minp.z + 2 and oz + rz <= maxp.z - 2) then
data[ivm] = node['air']
elseif ry > 0 and content[cx][cy][cz] == '4way' then
data[ivm] = node['fun_caves:dungeon_wall_1']
end
end
ivm = ivm + 1
end
end
end
end
end
end
end
for z = minp.z + 1, maxp.z - 1 do
for y = minp.y + 1, maxp.y - 1 do
local ivm = area:index(minp.x + 1, y, z)
for x = minp.x + 1, maxp.x - 1 do
local height = (y - minp.y) % cell_size
if data[ivm] == node['fun_caves:dungeon_wall_1'] and (x - minp.x) % 2 == 0 and (z - minp.z) % 2 == 0 and (height == 4 or (height == 2 and math.random(5) == 1)) then
local dir = math.random(4)
local ivm2 = ivm
local p2 = 3
if dir == 1 then
ivm2 = ivm2 + 1
elseif dir == 2 then
ivm2 = ivm2 - 1
p2 = 2
elseif dir == 3 then
ivm2 = ivm2 + area.zstride
p2 = 5
elseif dir == 4 then
ivm2 = ivm2 - area.zstride
p2 = 4
end
if data[ivm2] == node['air'] then
data[ivm2] = node['default:torch']
p2data[ivm2] = p2
end
end
ivm = ivm + 1
end
end
end
for i = 0, #data do
if data[i] == 'stairway' then
data[i] = node['air']
end
end
return true, true, true
end

View file

@ -1,480 +0,0 @@
local elixir_duration = 3600
local armor_mod = minetest.get_modpath("3d_armor") and armor and armor.set_player_armor
local elixir_ingredients = {
'default:acacia_leaves',
'default:acacia_sapling',
'default:acacia_tree',
'default:acacia_wood',
'default:apple',
'default:aspen_leaves',
'default:aspen_sapling',
'default:aspen_tree',
'default:aspen_wood',
'default:cactus',
'default:clay_lump',
'default:cloud',
'default:coal_lump',
'default:copper_lump',
'default:desert_sand',
'default:desert_stone',
'default:diamond',
'default:dirt',
'default:dry_shrub',
'default:gold_lump',
'default:gravel',
'default:ice',
'default:iron_lump',
'default:junglegrass',
'default:jungleleaves',
'default:junglesapling',
'default:jungletree',
'default:junglewood',
'default:leaves',
'default:pine_needles',
'default:pine_sapling',
'default:pine_tree',
'default:pine_wood',
'default:sand',
'default:sandstone',
'default:sapling',
'default:snow',
'default:stone',
'default:tree',
'default:wood',
'farming:seed_cotton',
'farming:seed_wheat',
'flowers:dandelion_white',
'flowers:dandelion_yellow',
'flowers:geranium',
'flowers:mushroom_brown',
'flowers:mushroom_red',
'flowers:rose',
'flowers:tulip',
'flowers:viola',
'flowers:waterlily',
'fun_caves:amber',
'fun_caves:bark',
'fun_caves:bird_of_paradise',
'fun_caves:black_sand',
'fun_caves:brain_coral',
'fun_caves:diamondwood',
'fun_caves:dragon_eye',
'fun_caves:dry_fiber',
'fun_caves:gerbera',
'fun_caves:giant_mushroom_cap',
'fun_caves:giant_mushroom_stem',
'fun_caves:hibiscus',
'fun_caves:huge_mushroom_cap',
'fun_caves:icicle_down',
'fun_caves:icicle_up',
'fun_caves:ironwood',
'fun_caves:leaves',
'fun_caves:onion',
'fun_caves:orchid',
'fun_caves:petrified_wood',
'fun_caves:pillar_coral',
'fun_caves:silver_lump',
'fun_caves:small_rocks',
'fun_caves:staghorn_coral',
'fun_caves:stalactite',
'fun_caves:stalactite_mossy',
'fun_caves:stalactite_slimy',
'fun_caves:stalagmite',
'fun_caves:stalagmite_mossy',
'fun_caves:stalagmite_slimy',
'fun_caves:thin_ice',
'fun_caves:tree',
'wool:white',
'wool:black',
}
local count = 0
for _, name in pairs(elixir_ingredients) do
local item = minetest.registered_items[name]
if not item then
item = minetest.registered_nodes[name]
end
if item then
if item.groups then
groups = table.copy(item.groups)
else
groups = {}
end
groups.elixir_ingredient = 1
minetest.override_item(name, {groups = groups})
count = count + 1
else
--print(name)
end
end
if count > 15 then
--for _, list in pairs({'registered_items', 'registered_nodes', 'registered_craftitems'}) do
-- for _, item in pairs(minetest[list]) do
-- if item and item.groups.elixir_ingredient then
-- print(item.name)
-- end
-- end
--end
local elixirs = {}
minetest.register_craftitem("fun_caves:elixir", {
description = "unknown elixir",
inventory_image = "fun_caves_elixir.png",
on_use = minetest.item_eat(-2),
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:elixir',
recipe = {
'mobs_slimes:green_slimeball',
'group:elixir_ingredient',
'group:elixir_ingredient',
"vessels:glass_bottle",
},
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:elixir',
recipe = {
'fun_caves:syrup',
'group:elixir_ingredient',
'group:elixir_ingredient',
},
})
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not (player and itemstack and old_craft_grid and itemstack:get_name() == "fun_caves:elixir") then
return
end
local ingredients = {}
local inv = player:get_inventory()
if not inv then
return
end
for i = 1, inv:get_size("craft") do
local name = old_craft_grid[i]:get_name()
if name ~= '' and name ~= 'fun_caves:syrup' and type(name) == 'string' and not name:find('green_slimeball$') then
ingredients[#ingredients+1] = name
end
end
end)
end
if fun_caves.register_status and fun_caves.set_status then
fun_caves.register_status({
name = 'breathe',
terminate = function(player)
if not player then
return
end
local player_name = player:get_player_name()
minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'Your breathing becomes more difficult...'))
end,
})
minetest.register_craftitem("fun_caves:elixir_breathe", {
description = 'Dr Robertson\'s Patented Easy Breathing Elixir',
inventory_image = "fun_caves_elixir_breathe.png",
on_use = function(itemstack, user, pointed_thing)
if not (itemstack and user) then
return
end
local player_name = user:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
fun_caves.set_status(player_name, 'breathe', elixir_duration)
minetest.chat_send_player(player_name, 'Your breathing becomes easier...')
itemstack:take_item()
return itemstack
end,
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:elixir_breathe',
recipe = {
'mobs_slimes:green_slimeball',
'fun_caves:coral_gem',
"vessels:glass_bottle",
},
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:elixir_breathe',
recipe = {
'fun_caves:syrup',
'fun_caves:coral_gem',
},
})
fun_caves.register_status({
name = 'damage_elixir',
terminate = function(player)
if not (player and fun_caves.db.status) then
return
end
local player_name = player:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'You feel weaker...'))
end,
})
local function increase_damage(user, bonus)
if not (user and fun_caves.set_status) then
return
end
local player_name = user:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
minetest.chat_send_player(player_name, 'You feel strong...')
fun_caves.set_status(player_name, 'damage_elixir', elixir_duration, {bonus = bonus})
end
local descs = {
{'boar', 2, 'fun_caves:meteorite'},
{'lion', 4, 'fun_caves:eternal_ice_crystal'},
{'grizzly', 6},
{'bull', 8},
{'rhino', 10},
{'elephant', 12},
}
for _, desc in pairs(descs) do
local name = desc[1]
local uname = name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end)
local bonus = desc[2]
minetest.register_craftitem("fun_caves:elixir_strength_"..name, {
description = 'Dr Robertson\'s Patented '..uname..' Strength Elixir',
drawtype = "plantlike",
paramtype = "light",
tiles = {'fun_caves_elixir_strength_'..name..'.png'},
inventory_image = 'fun_caves_elixir_strength_'..name..'.png',
groups = {dig_immediate = 3, vessel = 1},
sounds = default.node_sound_glass_defaults(),
on_use = function(itemstack, user, pointed_thing)
if not (itemstack and user) then
return
end
increase_damage(user, bonus)
itemstack:take_item()
return itemstack
end,
})
if desc[3] then
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:elixir_strength_'..name,
recipe = {
'mobs_slimes:green_slimeball',
desc[3],
"vessels:glass_bottle",
},
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:elixir_strength_'..name,
recipe = {
'fun_caves:syrup',
desc[3],
},
})
end
end
fun_caves.reconcile_armor = function(elixir_armor, worn_armor)
if elixir_armor < worn_armor then
return elixir_armor
end
return worn_armor
end
-- set_armor assumes any armor mods have already set the normal armor values.
local function set_armor(player, value, delay)
if not (player and fun_caves.reconcile_armor) then
return
end
local armor = player:get_armor_groups()
if not (armor and armor.fleshy and armor.fleshy >= value) then
return
end
if armor_mod then
armor.fleshy = fun_caves.reconcile_armor(value, armor.fleshy)
else
armor.fleshy = value
end
player:set_armor_groups(armor)
if fun_caves.display_armor then
if delay then
-- Delay display, in case of lag.
minetest.after(delay, function()
fun_caves.display_armor(player)
end)
else
fun_caves.display_armor(player)
end
end
return true
end
-- called only by armor elixirs
local function ingest_armor_elixir(player, value)
if not (player and fun_caves.set_status) then
return
end
-- support for 3d_armor
-- This may or may not work with all versions.
if armor_mod then
armor:set_player_armor(player)
end
if not set_armor(player, value) then
return
end
local player_name = player:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
minetest.chat_send_player(player_name, 'Your skin feels harder...')
fun_caves.set_status(player_name, 'armor_elixir', elixir_duration, {value = value})
end
-- called on joinplayer and every time an armor mod updates
fun_caves.load_armor_elixir = function(player)
if not (player and fun_caves.db.status) then
return
end
local player_name = player:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
if fun_caves.db.status[player_name] and fun_caves.db.status[player_name].armor_elixir then
local value = fun_caves.db.status[player_name].armor_elixir.value
set_armor(player, value, 3)
end
end
fun_caves.register_status({
name = 'armor_elixir',
terminate = function(player)
if not player then
return
end
player:set_armor_groups({fleshy = 100})
if fun_caves.display_armor then
fun_caves.display_armor(player)
end
-- support for 3d_armor
-- This may or may not work with all versions.
if armor_mod then
minetest.after(1, function()
armor:set_player_armor(player)
end)
end
local player_name = player:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'Your skin feels softer...'))
end,
})
local descs = {
{'wood', 95, 'group:wood'},
{'stone', 90, 'group:stone'},
{'steel', 80, 'default:steel_ingot'},
{'copper', 85, 'default:copper_ingot'},
{'bronze', 70, 'default:bronze_ingot'},
{'gold', 60, 'default:gold_ingot'},
{'diamond', 50, 'default:diamond'},
{'silver', 40, 'fun_caves:silver_ingot'},
{'mese', 30, 'default:mese_crystal'},
--{'', 20, ''},
--{'adamant', 10, 'fun_caves:adamant'},
}
if fun_caves.elixir_armor then
for _, desc in pairs(descs) do
local name = desc[1]
local value = desc[2]
local cap = name:gsub('^%l', string.upper)
minetest.register_craftitem("fun_caves:liquid_"..name, {
description = 'Dr Robertson\'s Patented Liquid '..cap..' Elixir',
drawtype = "plantlike",
paramtype = "light",
tiles = {'fun_caves_liquid_'..name..'.png'},
inventory_image = 'fun_caves_liquid_'..name..'.png',
groups = {dig_immediate = 3, vessel = 1},
sounds = default.node_sound_glass_defaults(),
on_use = function(itemstack, user, pointed_thing)
if not (itemstack and user) then
return
end
ingest_armor_elixir(user, value)
itemstack:take_item()
return itemstack
end,
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:liquid_'..name,
recipe = {
'mobs_slimes:green_slimeball',
desc[3],
"vessels:glass_bottle",
},
})
minetest.register_craft({
type = "shapeless",
output = 'fun_caves:liquid_'..name,
recipe = {
'fun_caves:syrup',
desc[3],
},
})
end
end
end

View file

@ -1,6 +1,7 @@
-------------------
-- Fungal Tree --
-------------------
-- 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"
@ -9,7 +10,7 @@ colors["^[colorize:#FF4500:80"] = "dye:green"
colors[""] = "dye:white"
local fungal_tree_leaves = {}
local newnode = fun_caves.clone_node("farming:straw")
local newnode = fun_caves_mod.clone_node("farming:straw")
newnode.description = "Dry Fiber"
minetest.register_node("fun_caves:dry_fiber", newnode)
@ -32,13 +33,13 @@ minetest.register_node("fun_caves:fungal_tree_fruit", {
groups = {fleshy = 3, dig_immediate = 3, flammable = 2},
--on_use = minetest.item_eat(2),
sounds = default.node_sound_leaves_defaults(),
on_timer = fun_caves.soft_boom,
on_punch = fun_caves.soft_boom,
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.make_fungal_tree(data, area, ivm, height)
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

View file

@ -1,664 +0,0 @@
---------------------------------------------------------------
-- GOBLINS
---------------------------------------------------------------
local spawn_frequency = 350 -- 350
local dig_freq = 5 -- 5
local trap_freq = 25 -- 25
local torch_freq = 2 -- 2
local diggable = {
'default:dirt',
'default:dirt_with_grass',
'default:dirt_with_dry_grass',
'default:sand',
'default:stone',
'default:sandstone',
'default:desert_stone',
'default:stone_with_coal',
'default:stone_with_copper',
'default:stone_with_diamond',
'default:stone_with_gold',
'default:stone_with_iron',
'default:stone_with_mese',
'fun_caves:stone_with_coal_trap',
'fun_caves:stone_with_copper_trap',
'fun_caves:stone_with_diamond_trap',
'fun_caves:stone_with_gold_trap',
'fun_caves:stone_with_iron_trap',
'fun_caves:stone_with_salt',
'fun_caves:stone_with_algae',
'fun_caves:stone_with_lichen',
'fun_caves:stone_with_moss',
'fun_caves:dirt_with_snow',
'fun_caves:giant_mushroom_cap',
'fun_caves:huge_mushroom_cap',
'fun_caves:giant_mushroom_stem',
'fun_caves:stalactite',
'fun_caves:stalagmite',
'fun_caves:stalactite_slimy',
'fun_caves:stalagmite_slimy',
'fun_caves:stalactite_mossy',
'fun_caves:stalagmite_mossy',
'flowers:mushroom_red',
'flowers:mushroom_brown'
}
local burnable = {}
for i = 1, 4 do
burnable[#burnable+1] = "fun_caves:fungal_tree_leaves_"..i
end
local traps = {
'fun_caves:mossycobble_trap',
'fun_caves:stone_with_coal_trap',
'fun_caves:stone_with_copper_trap',
'fun_caves:stone_with_diamond_trap',
'fun_caves:stone_with_gold_trap',
'fun_caves:stone_with_iron_trap',
}
local function goblin_do(self)
if not (self and fun_caves.custom_ready and fun_caves.search_replace and fun_caves.surface_damage and fun_caves.custom_ready(self)) then
return
end
local cold_natured = false
local pos = self.object:getpos()
pos.y = pos.y + 0.5
-- dig
if self.name == 'fun_caves:goblin_digger' then
fun_caves.search_replace(pos, 1, diggable, 'air')
else
fun_caves.search_replace(pos, dig_freq, diggable, 'air')
end
fun_caves.search_replace(pos, dig_freq * 3, burnable, 'fire:basic_flame')
-- steal torches
fun_caves.search_replace(self.object:getpos(), torch_freq, {"default:torch"}, "air")
pos.y = pos.y - 0.5
-- place a mossycobble
local cobbling = trap_freq
if self.name == 'fun_caves:goblin_cobbler' then
cobbling = torch_freq
end
fun_caves.search_replace(pos, cobbling, {"group:stone", "default:sandstone"}, "default:mossycobble")
-- place a trap
local trap = 'fun_caves:mossycobble_trap'
if self.name == 'fun_caves:goblin_ice' then
cold_natured = true
trap = 'fun_caves:ice_trap'
fun_caves.search_replace(pos, trap_freq, {"default:ice"}, trap)
else
if self.name == 'fun_caves:goblin_coal' then
trap = 'fun_caves:stone_with_coal_trap'
elseif self.name == 'fun_caves:goblin_copper' then
trap = 'fun_caves:stone_with_copper_trap'
elseif self.name == 'fun_caves:goblin_diamond' then
trap = 'fun_caves:stone_with_diamond_trap'
elseif self.name == 'fun_caves:goblin_gold' then
trap = 'fun_caves:stone_with_gold_trap'
elseif self.name == 'fun_caves:goblin_iron' then
trap = 'fun_caves:stone_with_iron_trap'
elseif self.name == 'fun_caves:goblin_king' then
trap = traps[math.random(#traps)]
end
fun_caves.search_replace(pos, trap_freq, {"group:stone", "default:sandstone"}, trap)
end
fun_caves.surface_damage(self, cold_natured)
end
--local function goblin_right_click(self, clicker)
-- local item = clicker:get_wielded_item()
-- local name = clicker:get_player_name()
--
-- -- feed to heal goblin
-- if item:get_name() == "default:apple"
-- or item:get_name() == "farming:bread" then
--
-- local hp = self.object:get_hp()
-- -- return if full health
-- if hp >= self.hp_max then
-- minetest.chat_send_player(name, "goblin at full health.")
-- return
-- end
-- hp = hp + 4
-- if hp > self.hp_max then hp = self.hp_max end
-- self.object:set_hp(hp)
-- -- take item
-- if not minetest.setting_getbool("creative_mode") then
-- item:take_item()
-- clicker:set_wielded_item(item)
-- end
--
-- -- right clicking with gold lump drops random item from fun_caves.goblin_drops
-- elseif item:get_name() == "default:gold_lump" then
-- if not minetest.setting_getbool("creative_mode") then
-- item:take_item()
-- clicker:set_wielded_item(item)
-- end
-- local pos = self.object:getpos()
-- pos.y = pos.y + 0.5
-- minetest.add_item(pos, {name = fun_caves.goblin_drops[math.random(1, #fun_caves.goblin_drops)]})
--
-- else
-- -- if owner switch between follow and stand
-- if self.owner and self.owner == clicker:get_player_name() then
-- if self.order == "follow" then
-- self.order = "stand"
-- else
-- self.order = "follow"
-- end
-- -- else
-- -- self.owner = clicker:get_player_name()
-- end
-- end
--
-- mobs:capture_mob(self, clicker, 0, 5, 80, false, nil)
--end
local drops = {
digger = {
{name = "default:mossycobble", chance = 1, min = 1, max = 3},
},
cobbler = {
{name = "fun_caves:glowing_fungus", chance = 1, min = 2, max = 5},
},
coal = {
{name = "default:coal_lump", chance = 1, min = 1, max = 3},
},
copper = {
{name = "default:copper_lump", chance = 1, min = 1, max = 3},
},
diamond = {
{name = "default:diamond", chance = 5, min = 1, max = 3},
},
gold = {
{name = "default:gold_lump", chance = 1, min = 1, max = 3},
},
ice = {
{name = "default:coal_lump", chance = 1, min = 1, max = 3},
},
iron = {
{name = "default:iron_lump", chance = 1, min = 1, max = 3},
},
king = {
{name = "default:mese_crystal", chance = 1, min = 1, max = 3},
},
}
for name, drop in pairs(drops) do
if name == 'digger' or name == 'cobbler' or name == 'coal' or name == 'ice' then
drop[#drop+1] = {name = "default:pick_stone", chance = 3, min = 1, max = 3}
drop[#drop+1] = {name = "default:sword_stone", chance = 5, min = 1, max = 1}
elseif name == 'copper' or name == 'iron' then
drop[#drop+1] = {name = "default:pick_steel", chance = 3, min = 1, max = 3}
drop[#drop+1] = {name = "default:sword_steel", chance = 5, min = 1, max = 1}
elseif name == 'diamond' or name == 'gold' then
drop[#drop+1] = {name = "default:pick_diamond", chance = 3, min = 1, max = 3}
drop[#drop+1] = {name = "default:sword_diamond", chance = 5, min = 1, max = 1}
elseif name == 'king' then
drop[#drop+1] = {name = "default:pick_mese", chance = 3, min = 1, max = 3}
drop[#drop+1] = {name = "default:sword_mese", chance = 5, min = 1, max = 1}
end
drop[#drop+1] = {name = "fun_caves:mushroom_steak", chance = 2, min = 1, max = 2}
drop[#drop+1] = {name = "default:torch", chance = 3, min = 1, max = 10}
end
mobs:register_mob("fun_caves:goblin_digger", {
description = "Digger Goblin",
type = "monster",
passive = false,
damage = 1,
attack_type = "dogfight",
attacks_monsters = true,
hp_min = 5,
hp_max = 10,
armor = 100,
fear_height = 4,
collisionbox = {-0.35,-1,-0.35, 0.35,-.1,0.35},
visual = "mesh",
mesh = "goblins_goblin.b3d",
drawtype = "front",
textures = {
{"goblins_goblin_digger.png"},
},
makes_footstep_sound = true,
sounds = {
random = "goblins_goblin_ambient",
warcry = "goblins_goblin_attack",
attack = "goblins_goblin_attack",
damage = "goblins_goblin_damage",
death = "goblins_goblin_death",
distance = 15,
},
walk_velocity = 2,
run_velocity = 3,
jump = true,
drops = drops['digger'],
water_damage = 1,
lava_damage = 2,
light_damage = 0,
--lifetimer = 360,
follow = {"default:diamond"},
view_range = 10,
owner = "",
order = "follow",
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = nil,
do_custom = goblin_do,
})
mobs:register_egg("fun_caves:goblin_digger", "Goblin Egg (digger)", "default_mossycobble.png", 1)
mobs:register_spawn("fun_caves:goblin_digger", {'fun_caves:stone_with_algae', 'fun_caves:stone_with_lichen'}, 100, 0, 30 * spawn_frequency, 3, 2000)
mobs:register_spawn("fun_caves:goblin_digger", {"default:mossycobble"}, 100, 0, 3 * spawn_frequency, 3, 2000)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_cobbler'
m.textures = { {"goblins_goblin_cobble1.png"}, {"goblins_goblin_cobble2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['cobbler']
minetest.registered_entities["fun_caves:goblin_cobbler"] = m
mobs.spawning_mobs["fun_caves:goblin_cobbler"] = true
mobs:register_spawn("fun_caves:goblin_cobbler", {'fun_caves:stone_with_algae', 'fun_caves:stone_with_lichen'}, 100, 0, 30 * spawn_frequency, 3, 2000)
mobs:register_spawn("fun_caves:goblin_cobbler", {"default:mossycobble"}, 100, 0, 3 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_cobbler", "Goblin Egg (cobbler)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_coal'
m.hp_min = 7
m.hp_max = 15
m.armor = 90
m.textures = { {"goblins_goblin_coal1.png"}, {"goblins_goblin_coal2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['coal']
minetest.registered_entities["fun_caves:goblin_coal"] = m
mobs.spawning_mobs["fun_caves:goblin_coal"] = true
mobs:register_spawn("fun_caves:goblin_coal", {"default:mossycobble"}, 100, 0, 4 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_coal", "Goblin Egg (coal)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_copper'
m.damage = 2
m.hp_min = 7
m.hp_max = 15
m.armor = 70
m.textures = { {"goblins_goblin_copper1.png"}, {"goblins_goblin_copper2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['copper']
minetest.registered_entities["fun_caves:goblin_copper"] = m
mobs.spawning_mobs["fun_caves:goblin_copper"] = true
mobs:register_spawn("fun_caves:goblin_copper", {"default:mossycobble"}, 100, 0, 6 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_copper", "Goblin Egg (copper)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_diamond'
m.damage = 3
m.hp_min = 7
m.hp_max = 15
m.armor = 50
m.textures = { {"goblins_goblin_diamond1.png"}, {"goblins_goblin_diamond2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['diamond']
minetest.registered_entities["fun_caves:goblin_diamond"] = m
mobs.spawning_mobs["fun_caves:goblin_diamond"] = true
mobs:register_spawn("fun_caves:goblin_diamond", {"default:mossycobble"}, 100, 0, 8 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_diamond", "Goblin Egg (diamond)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_gold'
m.damage = 3
m.hp_min = 7
m.hp_max = 15
m.armor = 60
m.textures = { {"goblins_goblin_gold1.png"}, {"goblins_goblin_gold2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['gold']
minetest.registered_entities["fun_caves:goblin_gold"] = m
mobs.spawning_mobs["fun_caves:goblin_gold"] = true
mobs:register_spawn("fun_caves:goblin_gold", {"default:mossycobble"}, 100, 0, 7 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_gold", "Goblin Egg (gold)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_ice'
m.textures = { {"fun_caves_goblin_ice2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['ice']
minetest.registered_entities["fun_caves:goblin_ice"] = m
mobs.spawning_mobs["fun_caves:goblin_ice"] = true
mobs:register_spawn("fun_caves:goblin_ice", {"default:ice"}, 100, 0, 20 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_ice", "Goblin Egg (ice)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_iron'
m.damage = 2
m.hp_min = 7
m.hp_max = 15
m.armor = 80
m.textures = { {"goblins_goblin_iron1.png"}, {"goblins_goblin_iron2.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['iron']
minetest.registered_entities["fun_caves:goblin_iron"] = m
mobs.spawning_mobs["fun_caves:goblin_iron"] = true
mobs:register_spawn("fun_caves:goblin_iron", {"default:mossycobble"}, 100, 0, 5 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_iron", "Goblin Egg (iron)", "default_mossycobble.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:goblin_digger"])
m.name = 'fun_caves:goblin_king'
m.damage = 3
m.hp_min = 10
m.hp_max = 20
m.armor = 40
m.textures = { {"goblins_goblin_king.png"}, }
m.base_texture = m.textures[1]
m.drops = drops['king']
minetest.registered_entities["fun_caves:goblin_king"] = m
mobs.spawning_mobs["fun_caves:goblin_king"] = true
mobs:register_spawn("fun_caves:goblin_king", {"default:mossycobble"}, 100, 0, 9 * spawn_frequency, 3, 2000)
mobs:register_egg("fun_caves:goblin_king", "Goblin Egg (king)", "default_mossycobble.png", 1)
---------------------------------------------------------------
-- Traps
---------------------------------------------------------------
minetest.register_node("fun_caves:mossycobble_trap", {
description = "Messy Gobblestone",
tiles = {"default_mossycobble.png"},
is_ground_content = false,
groups = {cracky = 2, stone = 1, trap = 1},
sounds = default.node_sound_stone_defaults(),
paramtype = "light",
light_source = 4,
})
minetest.register_craft({
type = "cooking",
output = "default:stone",
recipe = "fun_caves:mossycobble_trap",
})
minetest.register_node("fun_caves:stone_with_coal_trap", {
description = "Coal Trap",
tiles = {"default_cobble.png^default_mineral_coal.png"},
groups = {cracky = 3, trap = 1},
drop = 'default:coal_lump',
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
})
if minetest.registered_nodes['tnt:tnt_burning'] then
-- 5... 4... 3... 2... 1...
fun_caves.diamond_trap = function(pos, player)
if not (pos and player) then
return
end
minetest.set_node(pos, {name="tnt:tnt_burning"})
local timer = minetest.get_node_timer(pos)
if timer then
timer:start(5)
end
minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10})
end
else
-- wimpier trap for non-tnt settings
fun_caves.diamond_trap = function(pos, player)
if not (pos and player) then
return
end
minetest.set_node(pos, {name="default:lava_source"})
local hp = player:get_hp()
if hp > 0 then
player:set_hp(hp - 2)
minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10})
end
end
end
minetest.register_node("fun_caves:stone_with_diamond_trap", {
description = "Diamond Trap",
tiles = {"default_cobble.png^(default_mineral_diamond.png^[colorize:#000000:160)"},
groups = {cracky = 3, trap = 1},
drop = 'default:diamond',
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_dig = function(pos, node, digger)
if not (pos and digger) then
return
end
if math.random(3) == 1 then
fun_caves.diamond_trap(pos, digger)
else
minetest.node_dig(pos, node, digger)
end
end
})
newnode = fun_caves.clone_node("default:lava_source")
newnode.description = "Molten Gold Source"
newnode.wield_image = "goblins_molten_gold.png"
newnode.tiles[1].name = "goblins_molten_gold_source_animated.png"
newnode.special_tiles[1].name = "goblins_molten_gold_source_animated.png"
newnode.liquid_alternative_flowing = "fun_caves:molten_gold_flowing"
newnode.liquid_alternative_source = "fun_caves:molten_gold_source"
newnode.liquid_renewable = false
newnode.post_effect_color = {a=192, r=255, g=64, b=0}
minetest.register_node("fun_caves:molten_gold_source", newnode)
newnode = fun_caves.clone_node("default:lava_flowing")
newnode.description = "Flowing Molten Gold"
newnode.wield_image = "goblins_molten_gold.png"
newnode.tiles = {"goblins_molten_gold.png"}
newnode.special_tiles[1].name = "goblins_molten_gold_flowing_animated.png"
newnode.liquid_alternative_flowing = "fun_caves:molten_gold_flowing"
newnode.liquid_alternative_source = "fun_caves:molten_gold_source"
newnode.liquid_renewable = false
newnode.post_effect_color = {a=192, r=255, g=64, b=0}
minetest.register_node("fun_caves:molten_gold_flowing", newnode)
bucket.register_liquid(
"fun_caves:molten_gold_source",
"fun_caves:molten_gold_flowing",
"fun_caves:bucket_molten_gold",
"fun_caves_bucket_molten_gold.png",
"Bucket of Molten Gold",
{}
)
fun_caves.gold_trap = function(pos, player)
if not (pos and player) then
return
end
minetest.set_node(pos, {name="fun_caves:molten_gold_source"})
minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10})
local hp = player:get_hp()
if hp > 0 then
player:set_hp(hp - 2)
end
end
minetest.register_node("fun_caves:stone_with_gold_trap", {
description = "Gold Trap",
tiles = {"default_cobble.png^(default_mineral_gold.png^[colorize:#000000:160)"},
groups = {cracky = 3, trap = 1},
drop = 'default:gold_lump',
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_dig = function(pos, node, digger)
if not (pos and digger) then
return
end
if math.random(3) == 1 then
fun_caves.gold_trap(pos, digger)
else
minetest.node_dig(pos, node, digger)
end
end
})
fun_caves.ice_trap = function(pos, player)
if not (pos and player) then
return
end
local ppos = player:getpos()
if ppos then
ppos.y = ppos.y + 1
local p1 = vector.subtract(ppos, 2)
local p2 = vector.add(ppos, 2)
local nodes = minetest.find_nodes_in_area(p1, p2, 'air')
if not (nodes and type(nodes) == 'table') then
return
end
for _, npos in pairs(nodes) do
minetest.set_node(npos, {name="default:ice"})
end
minetest.set_node(pos, {name="default:ice"})
end
end
minetest.register_node("fun_caves:ice_trap", {
description = "Ice Trap",
tiles = {"default_ice.png^fun_caves_mineral_moonstone.png"},
groups = {cracky = 3, trap = 1},
drop = 'default:ice',
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_dig = function(pos, node, digger)
if not (pos and digger) then
return
end
if math.random(3) == 1 then
fun_caves.ice_trap(pos, digger)
else
minetest.node_dig(pos, node, digger)
end
end
})
local function lightning_effects(pos, radius)
if not (pos and radius) then
return
end
minetest.add_particlespawner({
amount = 30,
time = 1,
minpos = vector.subtract(pos, radius / 2),
maxpos = vector.add(pos, radius / 2),
minvel = {x=-10, y=-10, z=-10},
maxvel = {x=10, y=10, z=10},
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 1,
maxexptime = 3,
minsize = 16,
maxsize = 32,
texture = "goblins_lightning.png",
})
end
fun_caves.copper_trap = function(pos, player)
if not (pos and player) then
return
end
local hp = player:get_hp()
if hp > 0 then
player:set_hp(hp - 1)
lightning_effects(pos, 3)
minetest.sound_play("default_dig_crumbly", {pos = pos, gain = 0.5, max_hear_distance = 10})
end
end
minetest.register_node("fun_caves:stone_with_copper_trap", {
description = "Copper Trap",
tiles = {"default_cobble.png^(default_mineral_copper.png^[colorize:#000000:160)"},
groups = {cracky = 3, trap = 1},
drop = 'default:copper_lump',
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_dig = function(pos, node, digger)
if not (pos and digger) then
return
end
if math.random(3) == 1 then
fun_caves.copper_trap(pos, digger)
else
minetest.node_dig(pos, node, digger)
end
end
})
-- summon a metallic goblin?
-- pit of iron razors?
minetest.register_node("fun_caves:stone_with_iron_trap", {
description = "Iron Trap",
tiles = {"default_cobble.png^(default_mineral_iron.png^[colorize:#000000:160)"},
groups = {cracky = 3, trap = 1},
drop = 'default:iron_lump',
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_dig = function(pos, node, digger)
if not (pos and digger) then
return
end
if math.random(3) == 1 then
fun_caves.copper_trap(pos, digger)
else
minetest.node_dig(pos, node, digger)
end
end
})

View file

@ -1,66 +0,0 @@
-- This code and all associated textures and models were
-- originated by DOOMED <heiselong@gmx.com>, and published in
-- the horror mod, under the GPL 2.1 license and CC-by-SA 3.
-- https://forum.minetest.net/viewtopic.php?f=9&t=12961&hilit=doomed
mobs:register_mob("fun_caves:manticore", {
type = "monster",
passive = false,
attacks_monsters = true,
damage = 5,
reach = 4,
attack_type = "dogfight",
hp_min = 15,
hp_max = 28,
armor = 70,
collisionbox = {-0.7, -0.5, -0.7, 0.7, 1.5, 0.7},
visual = "mesh",
mesh = "manticore.b3d",
textures = {
{"manticore.png"},
},
blood_texture = "mobs_blood.png",
visual_size = {x=2.5, y=2.5},
makes_footstep_sound = true,
walk_velocity = 3,
run_velocity = 5,
jump = true,
drops = {
{name = "mobs:meat_raw", chance = 1, min = 1, max = 9},
},
water_damage = 2,
lava_damage = 1,
light_damage = 0,
view_range = 20,
animation = {
speed_normal = 10,
speed_run = 20,
walk_start = 1,
walk_end = 11,
stand_start = 1,
stand_end = 11,
run_start = 1,
run_end = 11,
punch_start = 11,
punch_end = 26,
},
do_custom = function(self)
if not (self and fun_caves.custom_ready and fun_caves.set_status and fun_caves.surface_damage and fun_caves.custom_ready(self)) then
return
end
if self.attack and math.random(3) == 1 and self.attack:is_player(self.attack) and minetest.line_of_sight(self.attack:getpos(), self.object:getpos(), stepsize) then
local player_name = self.attack:get_player_name()
if player_name and player_name ~= '' then
minetest.chat_send_player(player_name, minetest.colorize('#FF0000', 'You\'ve been poisoned!'))
fun_caves.set_status(player_name, 'poisoned', 2 ^ math.random(8), {damage = 1})
end
end
fun_caves.surface_damage(self)
end,
})
--mobs:spawn_specific("horror:manticore", {"default:dirt_with_grass"}, {"default:stone"}, 20, 0, 300, 15000, 2, -100, 11000)
mobs:register_egg("fun_caves:manticore", "Manticore", "default_dirt.png", 1)

470
init.lua
View file

@ -1,144 +1,17 @@
fun_caves = {}
fun_caves.version = "1.0"
fun_caves.time_factor = 10 -- affects growth abms
fun_caves.light_max = 8 -- light intensity for mushroom growth
fun_caves.path = minetest.get_modpath(minetest.get_current_modname())
fun_caves.world = minetest.get_worldpath()
local armor_mod = minetest.get_modpath("3d_armor") and armor and armor.set_player_armor
fun_caves.elixir_armor = minetest.setting_getbool('fun_caves_use_armor_elixirs')
if fun_caves.elixir_armor == nil then
fun_caves.elixir_armor = true
end
fun_caves.expire_elixir_on_death = minetest.setting_getbool('fun_caves_expire_elixir_on_death')
if fun_caves.expire_elixir_on_death == nil then
fun_caves.expire_elixir_on_death = true
end
fun_caves.exploding_fungi = minetest.setting_getbool('fun_caves_exploding_fungi')
if fun_caves.exploding_fungi == nil then
fun_caves.exploding_fungi = true
end
fun_caves.breakable_wood = minetest.setting_getbool('fun_caves_breakable_wood')
if fun_caves.breakable_wood == nil then
fun_caves.breakable_wood = false
end
fun_caves.use_villages = minetest.setting_getbool('fun_caves_use_villages')
if fun_caves.use_villages == nil then
fun_caves.use_villages = true
end
fun_caves.starting_equipment = minetest.setting_getbool('fun_caves_starting_equipment')
if fun_caves.starting_equipment == nil then
fun_caves.starting_equipment = false
end
fun_caves.pyramids_everywhere = minetest.setting_getbool('fun_caves_pyramids_everywhere')
if fun_caves.pyramids_everywhere == nil then
fun_caves.pyramids_everywhere = false
end
fun_caves.quick_leaf_decay = minetest.setting_getbool('fun_caves_quick_leaf_decay')
if fun_caves.quick_leaf_decay == nil then
fun_caves.quick_leaf_decay = false
end
fun_caves.DEBUG = false -- for maintenance only
-- 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)
local f_date = io.open(fun_caves.world .. '/date.txt', 'r')
if f_date then
local s = f_date:read('*a')
f_date:close()
for y, m, d in s:gmatch('(%d%d%d%d)(%d%d)(%d%d)') do
local yn, mn, dn = tonumber(y), tonumber(m), tonumber(d)
if yn and mn and dn then
fun_caves.date = {yn, mn, dn}
end
break
end
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()
local inp = io.open(fun_caves.world..'/fun_caves_data.txt','r')
if inp then
local d = inp:read('*a')
fun_caves.db = minetest.deserialize(d)
inp:close()
end
if not fun_caves.db then
fun_caves.db = {}
end
for _, i in pairs({'teleport_data', 'hunger', 'status', 'translocators', 'elixir_formulae'}) do
if not fun_caves.db[i] then
fun_caves.db[i] = {}
end
end
-- whether to use biomes and heightmap
fun_caves.use_bi_hi = false
local mgname
if minetest.get_mapgen_setting then
mgname = minetest.get_mapgen_setting('mg_name')
else
local mg_params = minetest.get_mapgen_params()
if mg_params then
mgname = mg_params.mgname
end
end
if mgname ~= "v6" and mgname ~= "v5" then
fun_caves.use_bi_hi = true
end
minetest.register_on_mapgen_init(function(mgparams)
if minetest.set_mapgen_setting then
minetest.set_mapgen_setting('mg_flags', "nocaves, nodungeons", true)
else
minetest.set_mapgen_params({flags="nocaves,nodungeons"})
end
end)
-- Check if the table contains an element.
function table.contains(table, element)
for key, value in pairs(table) do
if value == element then
if key then
return key
else
return true
end
end
end
return false
end
-- Modify a node to add a group
function minetest.add_group(node, groups)
local def = minetest.registered_items[node]
if not (node and def and groups and type(groups) == 'table') 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
end
function fun_caves.clone_node(name)
function fun_caves_mod.clone_node(name)
if not (name and type(name) == 'string') then
return
end
@ -149,324 +22,11 @@ function fun_caves.clone_node(name)
end
fun_caves.registered_status = {}
function fun_caves.register_status(def)
if not (def and fun_caves.registered_status and type(def) == 'table') then
return
end
fun_caves.registered_status[def.name] = {
remove = def.remove,
start = def.start,
during = def.during,
terminate = def.terminate,
}
end
function fun_caves.set_status(player_name, status, time, param)
if not (player_name and type(player_name) == 'string' and status and type(status) == 'string') and fun_caves.db and fun_caves.db.status and fun_caves.db.status[player_name] then
return
end
local player = minetest.get_player_by_name(player_name)
local def = fun_caves.registered_status[status]
if not (def and player) then
return
end
if not param then
param = {}
end
if time then
param.remove = (minetest.get_gametime() or 0) + time
end
fun_caves.db.status[player_name][status] = param
if def.start then
def.start(player)
end
end
function fun_caves.remove_status(player_name, status)
if not (player_name and type(player_name) == 'string' and status and type(status) == 'string') and fun_caves.db and fun_caves.db.status and fun_caves.db.status[player_name] then
return
end
local player = minetest.get_player_by_name(player_name)
local def = fun_caves.registered_status[status]
if player and def then
if def.terminate then
fun_caves.db.status[player_name][status] = def.terminate(player)
else
fun_caves.db.status[player_name][status] = nil
end
end
end
--dofile(fun_caves.path .. "/recipe_list.lua")
dofile(fun_caves.path .. "/nodes.lua")
dofile(fun_caves.path .. "/deco.lua")
dofile(fun_caves.path .. "/fungal_tree.lua")
dofile(fun_caves.path .. "/wallhammer.lua")
dofile(fun_caves.path .. "/mapgen.lua")
dofile(fun_caves.path .. "/wooden_buckets.lua")
dofile(fun_caves.path .. "/tools.lua")
dofile(fun_caves.path .. "/elixir.lua") -- must go after all items are registered
dofile(fun_caves.path .. "/chat.lua")
if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" then
dofile(fun_caves.path .. "/mobs.lua")
end
dofile(fun_caves.path .. "/abms.lua")
--fun_caves.print_recipes()
-- Attempt to save data at shutdown (as well as periodically).
minetest.register_on_shutdown(function()
local out = io.open(fun_caves.world..'/fun_caves_data.txt','w')
if out then
print('Fun Caves: Saving database at shutdown')
out:write(minetest.serialize(fun_caves.db))
out:close()
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)
local hunger_mod = minetest.get_modpath("hunger")
fun_caves.hunger_id = {}
function fun_caves.hunger_change(player, change)
if not (player and change and type(change) == 'number') then
return
end
local player_name = player:get_player_name()
if hunger_mod then
if change < 0 and hunger and hunger.update_hunger and hunger.players then
hunger.update_hunger(player, hunger.players[player_name].lvl + change * 4)
end
return
end
if not (fun_caves.db.hunger and fun_caves.hunger_id) then
return
end
local hp = player:get_hp()
if not (hp and type(hp) == 'number') then
return
end
if change < 0 or hp >= 16 then
fun_caves.db.hunger[player_name] = math.min(20, math.max(0, fun_caves.db.hunger[player_name] + change))
player:hud_change(fun_caves.hunger_id[player_name], 'number', fun_caves.db.hunger[player_name])
if fun_caves.db.hunger[player_name] == 0 then
player:set_hp(hp - 1)
end
end
end
local hunger_hud
if not hunger_mod then
hunger_hud = function(player)
if not (player and fun_caves.db.hunger and fun_caves.hunger_id) then
return
end
local player_name = player:get_player_name()
if not fun_caves.db.hunger[player_name] then
fun_caves.db.hunger[player_name] = 20
end
local hunger_bar = {
hud_elem_type = 'statbar',
position = {x=0.52, y=1},
offset = {x = 0, y = -90},
name = "hunger",
text = "farming_bread.png",
number = fun_caves.db.hunger[player_name],
direction = 0,
size = { x=24, y=24 },
}
fun_caves.hunger_id[player_name] = player:hud_add(hunger_bar)
end
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
if not (hp_change and type(hp_change) == 'number') then
return
end
if hp_change > 0 then
fun_caves.hunger_change(user, hp_change)
end
end)
end
minetest.register_on_dieplayer(function(player)
if fun_caves.db.status and not player then
return
end
local player_name = player:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
if fun_caves.db.status[player_name] then
for status in pairs(fun_caves.db.status[player_name]) do
local def = fun_caves.registered_status[status]
if not def.remain_after_death then
fun_caves.remove_status(player_name, status)
end
end
end
if fun_caves.db.hunger and fun_caves.hunger_id and not hunger_mod then
fun_caves.db.hunger[player_name] = 20
player:hud_change(fun_caves.hunger_id[player_name], 'number', 20)
end
local pos = vector.round(player:getpos())
if pos then
minetest.chat_send_player(player_name, 'Your bones will lie at ('..pos.x..','..pos.y..','..pos.z..'), in ignominy, unless you collect them.')
end
end)
fun_caves.armor_id = {}
local armor_hud
if not armor_mod then
armor_hud = function(player)
if not (player and fun_caves.armor_id) then
return
end
local player_name = player:get_player_name()
if not player_name then
return
end
local armor_icon = {
hud_elem_type = 'image',
name = "armor_icon",
text = 'fun_caves_shield.png',
scale = {x=1,y=1},
position = {x=0.8, y=1},
offset = {x = -30, y = -80},
}
local armor_text = {
hud_elem_type = 'text',
name = "armor_text",
text = '0%',
number = 0xFFFFFF,
position = {x=0.8, y=1},
offset = {x = 0, y = -80},
}
fun_caves.armor_id[player_name] = {}
fun_caves.armor_id[player_name].icon = player:hud_add(armor_icon)
fun_caves.armor_id[player_name].text = player:hud_add(armor_text)
end
fun_caves.display_armor = function(player)
if not (player and fun_caves.armor_id) then
return
end
local player_name = player:get_player_name()
local armor = player:get_armor_groups()
if not (player_name and armor and armor.fleshy) then
return
end
player:hud_change(fun_caves.armor_id[player_name].text, 'text', (100 - armor.fleshy)..'%')
end
end
if fun_caves.starting_equipment then
minetest.register_on_newplayer(function(player)
local inv = player:get_inventory()
inv:add_item("main", 'default:sword_wood')
inv:add_item("main", 'default:axe_wood')
inv:add_item("main", 'default:pick_wood')
inv:add_item("main", 'default:apple 10')
inv:add_item("main", 'default:torch 10')
if minetest.registered_items['unified_inventory:bag_small'] then
inv:add_item("main", 'unified_inventory:bag_small')
end
end)
end
minetest.register_on_joinplayer(function(player)
if not (player and fun_caves.db.status) then
return
end
local player_name = player:get_player_name()
if not (player_name and type(player_name) == 'string' and player_name ~= '') then
return
end
if not fun_caves.db.status[player_name] then
fun_caves.db.status[player_name] = {}
end
if armor_hud then
armor_hud(player)
end
if hunger_hud then
hunger_hud(player)
end
-- If there's an armor mod, we wait for it to load armor.
if fun_caves.load_armor_elixir and not armor_mod then
fun_caves.load_armor_elixir(player)
end
end)
-- support for 3d_armor
-- This may or may not work with all versions.
if armor_mod then
local old_set_player_armor = armor.set_player_armor
armor.set_player_armor = function(self, player)
old_set_player_armor(self, player)
if fun_caves.load_armor_elixir then
fun_caves.load_armor_elixir(player)
end
end
end
----------------------------------------------------------------------
-- Change old factor to current value.
if fun_caves.db.status then
for player_name, status in pairs(fun_caves.db.status) do
if status.armor_elixir and status.armor_elixir.factor then
status.armor_elixir.value = status.armor_elixir.factor * 100
status.armor_elixir.factor = nil
end
end
end
----------------------------------------------------------------------
if fun_caves.quick_leaf_decay then
for name, node in pairs(minetest.registered_nodes) do
if node.groups.leafdecay then
node.groups.leafdecay = 0
node.groups.qfc_leafdecay = 0
end
end
end
dofile(fun_caves_mod.path .. "/mapgen.lua")
dofile(fun_caves_mod.path .. "/abms.lua")

View file

@ -1,5 +1,23 @@
-- 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 max_depth = 31000
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.
@ -15,195 +33,9 @@ local node = setmetatable({}, {
})
local data = {}
local p2data = {} -- vm rotation data buffer
local biome_ids = {}
if fun_caves.use_bi_hi then
-- Create a table of biome ids, so I can use the biomemap.
local get_biome_id = minetest.get_biome_id
for name, desc in pairs(minetest.registered_biomes) do
biome_ids[get_biome_id(desc.name)] = desc.name
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
fun_caves.place_schematic = function(minp, maxp, data, p2data, area, node, pos, schem, center)
if not (minp and maxp and data and p2data and area and node and pos and schem and type(data) == 'table' and type(p2data) == 'table' and type(schem) == 'table') then
return
end
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 = area:index(pos.x + x, pos.y, pos.z + z)
local isch = z1 * schem.size.y * schem.size.x + x1 + 1
local math_random = math.random
for y = 0, schem.size.y - 1 do
local dy = pos.y - minp.y + y
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
ivm = ivm + area.ystride
isch = isch + schem.size.x
end
end
end
end
end
fun_caves.surround = function(node, data, area, ivm)
if not (node and data and area and ivm and type(data) == 'table' and type(ivm) == 'number') then
return
end
-- Check to make sure that a plant root is fully surrounded.
-- This is due to the kludgy way you have to make water plants
-- in minetest, to avoid bubbles.
for x1 = -1,1,2 do
local n = data[ivm+x1]
if n == node["default:river_water_source"] or n == node["default:water_source"] or n == node["air"] then
return false
end
end
for z1 = -area.zstride,area.zstride,2*area.zstride do
local n = data[ivm+z1]
if n == node["default:river_water_source"] or n == node["default:water_source"] or n == node["air"] then
return false
end
end
return true
end
fun_caves.underzones = {
Caina = {
name = 'Caina',
ceiling = -4852,
ceiling_node = 'default:ice',
column_node = 'default:ice',
column_node_rare = 'fun_caves:thin_ice',
floor = -4972,
floor_node = 'default:ice',
lower_bound = -4992,
regular_columns = false,
stalactite = 'fun_caves:icicle_down',
stalactite_chance = 12,
stone_depth = 2,
upper_bound = -4832,
vary = true,
},
Phlegethos = {
name = 'Phlegethos',
ceiling = -9892,
ceiling_node = 'fun_caves:black_sand',
column_node = 'default:stone',
column_node_rare = 'fun_caves:hot_stone',
floor = -10012,
floor_node = 'fun_caves:hot_cobble',
fluid = 'default:lava_source',
fluid_chance = 1200,
lake = 'default:lava_source',
lake_level = 5,
lower_bound = -10032,
regular_columns = false,
stone_depth = 1,
upper_bound = -9872,
vary = true,
},
Dis = {
name = 'Dis',
ceiling = -14914,
ceiling_node = 'fun_caves:hot_brass',
column_node = 'default:steelblock',
floor = -14982,
floor_node = 'fun_caves:hot_brass',
lower_bound = -14992,
regular_columns = true,
stone_depth = 1,
upper_bound = -14912,
vary = false,
},
Minauros = {
name = 'Minauros',
ceiling = -19812,
ceiling_node = 'fun_caves:black_sand',
column_node = 'fun_caves:polluted_dirt',
column_node_rare = 'fun_caves:glowing_fungal_stone',
floor = -19932,
floor_node = 'fun_caves:polluted_dirt',
fluid = 'fun_caves:water_poison_source',
fluid_chance = 2000,
lake = 'fun_caves:water_poison_source',
lake_level = 10,
lower_bound = -19952,
regular_columns = false,
stone_depth = 2,
upper_bound = -19792,
vary = true,
},
Styx = {
name = 'Styx',
ceiling = -29812,
ceiling_node = 'default:dirt',
floor = -30012,
floor_node = 'default:dirt',
lower_bound = -30032,
regular_columns = false,
stone_depth = 2,
sealevel = -29842,
upper_bound = -29792,
vary = true,
},
}
fun_caves.cave_biomes = {
fun_caves_mod.cave_biomes = {
algae = {
biome_val_low = 0,
biome_val_high = 0.2,
@ -236,9 +68,9 @@ fun_caves.cave_biomes = {
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.hot_spikes,
--fluid = 'default:lava_source',
--fluid_chance = 300,
stalagmite = fun_caves_mod.hot_spikes,
stalagmite_chance = 50,
stone_depth = 1,
underwater = false,
@ -297,8 +129,8 @@ fun_caves.cave_biomes = {
deco = 'fun_caves:glowing_fungal_stone',
deco_chance = 50,
floor_node = 'fun_caves:stone_with_moss',
fluid = 'default:water_source',
fluid_chance = 300,
--fluid = 'default:water_source',
--fluid_chance = 300,
stalactite = 'fun_caves:stalactite_mossy',
stalactite_chance = 12,
stalagmite = 'fun_caves:stalagmite_mossy',
@ -327,17 +159,6 @@ fun_caves.cave_biomes = {
}
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
local function generate(p_minp, p_maxp, seed)
if not (p_minp and p_maxp and seed) then
return
@ -350,40 +171,32 @@ local function generate(p_minp, p_maxp, seed)
end
vm:get_data(data)
p2data = vm:get_param2_data()
local heightmap
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local csize = vector.add(vector.subtract(maxp, minp), 1)
local write
if fun_caves.use_bi_hi then
if fun_caves_mod.use_bi_hi then
heightmap = minetest.get_mapgen_object("heightmap")
end
-- use the same seed (based on perlin noise).
do
local seed = minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})
if not (seed and type(seed) == 'number') then
return
end
--do
-- local seed = minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})
-- if not (seed and type(seed) == 'number') then
-- return
-- end
math.randomseed(seed)
end
local write = false
local write_p2, write_p4 = false, false
local underzone
if not fun_caves.underzones then
return
end
for _, uz in pairs(fun_caves.underzones) do
local avg = (minp.y + maxp.y) / 2
if avg <= uz.upper_bound and avg >= uz.lower_bound then
underzone = uz
end
end
-- math.randomseed(seed)
--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
@ -406,97 +219,29 @@ local function generate(p_minp, p_maxp, seed)
end
end
end
end
local aster = false
for fake_loop = 1, 1 do
if minp.y > 17200 then
break
end
if minp.y > 11000 and fun_caves.asteroids then
write = fun_caves.asteroids(minp, maxp, data, p2data, area, node)
aster = true
break
end
if minp.y > 8400 and fun_caves.skysea then
write = fun_caves.skysea(minp, maxp, data, p2data, area, node)
break
end
if minp.y > 4000 and fun_caves.cloudgen then
write = fun_caves.cloudgen(minp, maxp, data, p2data, area, node)
break
end
if not underzone and fun_caves.dungeon and not (fun_caves.is_tree and fun_caves.is_tree(minp)) then
local write_dungeon, write_p4
write_dungeon, write_p4 = fun_caves.dungeon(minp, maxp, data, p2data, area, node, heightmap)
if write_dungeon then
write = true
write_p2 = write_p2 or write_p4
break
end
end
local biomemap
if fun_caves.cavegen and fun_caves.decogen then
if fun_caves_mod.cavegen and fun_caves_mod.decogen then
local h2, write_cave
write_cave = fun_caves.cavegen(minp, maxp, data, area, node, heightmap, underzone, ground_nodes)
write_cave = fun_caves_mod.cavegen(minp, maxp, data, area, node, heightmap)
write = write or write_cave
if fun_caves.use_bi_hi then
biomemap = minetest.get_mapgen_object("biomemap")
end
local write_deco
write_deco, write_p2 = fun_caves.decogen(minp, maxp, data, p2data, area, node, heightmap, biomemap, biome_ids, underzone)
write_deco = fun_caves_mod.decogen(minp, maxp, data, area, node, heightmap)
write = write or write_deco
end
if fun_caves.treegen then
local write_tree = fun_caves.treegen(minp, maxp, data, p2data, area, node)
if write_tree then
write = true
break
end
end
if fun_caves.pyramid then
local write_pyr, write_p4 = fun_caves.pyramid(minp, maxp, data, p2data, area, biomemap, biome_ids, node, heightmap)
if write_pyr then
write = true
write_p2 = write_p2 or write_p4
break
end
end
if fun_caves.use_villages and biomemap and fun_caves.village then
local biome = biome_ids[biomemap[40*80+40]]
local write_vill = fun_caves.village(minp, maxp, data, p2data, area, node, biome, heightmap)
if write_vill then
write = true
break
end
end
end
if write then
vm:set_data(data)
if write_p2 or write_p4 then
vm:set_param2_data(p2data)
end
if fun_caves.DEBUG then
vm:set_lighting({day = 15, night = 15})
if DEBUG then
vm:set_lighting({day = 8, night = 8})
else
-- set_lighting causes lighting artifacts,
-- but corrects the light inside trees.
vm:set_lighting({day = 0, night = 0}, minp, maxp)
vm:calc_lighting(minp, maxp, not aster)
-- Does not work:
--vm:calc_lighting({x=minp.x,y=emin.y,z=minp.z}, maxp)
vm:calc_lighting()
end
vm:update_liquids()
vm:write_to_map()
@ -504,23 +249,16 @@ local function generate(p_minp, p_maxp, seed)
end
if fun_caves.path then
dofile(fun_caves.path .. "/asteroids.lua")
dofile(fun_caves.path .. "/cavegen.lua")
dofile(fun_caves.path .. "/cloudgen.lua")
dofile(fun_caves.path .. "/decogen.lua")
dofile(fun_caves.path .. "/dungeon.lua")
dofile(fun_caves.path .. "/pyramid.lua")
dofile(fun_caves.path .. "/treegen.lua")
dofile(fun_caves.path .. "/village.lua")
dofile(fun_caves.path .. "/skyseagen.lua")
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(...)
--local status, err = pcall(generate, ...)
local status, err = true
generate(...)
if not status then
print('Fun Caves: Could not generate terrain:')
print(dump(err))
@ -529,5 +267,5 @@ local function pgenerate(...)
end
-- Inserting helps to ensure that fun_caves operates first.
-- Inserting helps to ensure that fun_caves_mod operates first.
table.insert(minetest.registered_on_generateds, 1, pgenerate)

880
mobs.lua
View file

@ -1,880 +0,0 @@
-- search/replace -- lets mobs change the terrain
-- used for goblin traps and torch thieving
fun_caves.search_replace = function(pos, search_rate, replace_what, replace_with)
if not (pos and search_rate and replace_what and replace_with and type(search_rate) == 'number' and type(replace_what) == 'string' and type(replace_with) == 'string') then
return
end
if math.random(search_rate) == 1 then
local p1 = vector.subtract(pos, 1)
local p2 = vector.add(pos, 1)
--look for nodes
local nodelist = minetest.find_nodes_in_area(p1, p2, replace_what)
if not (nodelist and type(nodelist) == 'table') then
return
end
if #nodelist > 0 then
for _, new_pos in pairs(nodelist) do
minetest.set_node(new_pos, {name = replace_with})
return true -- only one at a time
end
end
end
end
function fun_caves.climb(self)
if not self then
return
end
if self.state == "stand" and math.random() < 0.2 then
if self.fall_speed == 2 then
self.fall_speed = -2
else
self.fall_speed = 2
end
elseif self.state == "attack" and self.fall_speed ~= -2 then
self.fall_speed = -2
end
end
-- causes mobs to take damage from hot/cold surfaces
fun_caves.surface_damage = function(self, cold_natured)
if not self then
return
end
local pos = self.object:getpos()
if not pos then
return
end
local minp = vector.subtract(pos, 1.5)
local maxp = vector.add(pos, 1.5)
local counts = 0
if self.lava_damage > 1 then
counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_hot"})
if not (counts and type(counts) == 'table') then
return
end
if #counts > 0 then
self.health = self.health - math.floor(self.lava_damage / 2)
effect(pos, 5, "fire_basic_flame.png")
end
end
if not cold_natured then
counts = minetest.find_nodes_in_area(minp, maxp, {"group:surface_cold"})
if not (counts and type(counts) == 'table') then
return
end
if #counts > 0 then
self.health = self.health - 1
end
end
check_for_death(self)
end
-- executed in a mob's do_custom() to regulate their actions
-- if false, do nothing
local custom_delay = 2000000
fun_caves.custom_ready = function(self, delay)
if not self then
return
end
local time = minetest.get_us_time()
if not (time and type(time) == 'number') then
return
end
if not delay then
delay = custom_delay
end
if not self.custom_time or time - self.custom_time > delay then
self.custom_time = time
return true
else
return false
end
end
local fun_caves_stones = {'fun_caves:stone_with_moss', 'fun_caves:stone_with_lichen', 'fun_caves:stone_with_algae'}
-- Try to standardize creature stats based on (log of) mass.
local mob_stats = {
{name = 'dmobs:badger', hp = 12, damage = 1, armor = 100, reach = 1, meat = true},
{name = 'dmobs:dragon', hp = 40, damage = 6, armor = 50, reach = 3, meat = true},
{name = 'dmobs:elephant', hp = 38, damage = 5, armor = 75, reach = 3, meat = true},
{name = 'dmobs:fox', hp = 8, damage = 1, armor = 100, reach = 1, meat = true},
{name = 'dmobs:hedgehog', hp = 2, damage = 1, armor = 100, reach = 1, meat = true},
{name = 'dmobs:ogre', hp = 26, damage = 3, armor = 75, reach = 3, meat = true},
{name = 'dmobs:orc', hp = 22, damage = 2, armor = 100, reach = 2, meat = true},
{name = 'dmobs:owl', hp = 6, damage = 1, armor = 100, reach = 1, meat = true},
{name = 'dmobs:panda', hp = 22, damage = 2, armor = 100, reach = 2, meat = true},
{name = 'kpgmobs:deer', hp = 20, damage = 2, armor = 100, reach = 2},
{name = 'kpgmobs:horse2', hp = 30, damage = 3, armor = 100, reach = 2},
{name = 'kpgmobs:horse3', hp = 30, damage = 3, armor = 100, reach = 2},
{name = 'kpgmobs:horse', hp = 30, damage = 3, armor = 100, reach = 2},
{name = 'kpgmobs:jeraf', hp = 32, damage = 3, armor = 100, reach = 2},
{name = 'kpgmobs:medved', hp = 26, damage = 3, armor = 100, reach = 2},
{name = 'kpgmobs:wolf', hp = 18, damage = 3, armor = 100, reach = 1},
{name = 'mobs_animal:bee', hp = 1, damage = 1, armor = 200, reach = 1},
{name = 'mobs_animal:bunny', hp = 2, damage = 1, armor = 100, reach = 1},
{name = 'mobs_animal:chicken', hp = 8, damage = 1, armor = 150, reach = 1},
{name = 'mobs_animal:cow', hp = 30, damage = 3, armor = 150, reach = 1},
{name = 'mobs_animal:kitten', hp = 8, damage = 1, armor = 100, reach = 1},
{name = 'mobs_animal:pumba', hp = 20, damage = 2, armor = 100, reach = 1},
{name = 'mobs_animal:rat', hp = 2, damage = 1, armor = 100, reach = 1},
{name = 'mobs_animal:sheep', hp = 18, damage = 1, armor = 150, reach = 1},
{name = 'mobs_bat:bat', hp = 2, damage = 1, armor = 150, reach = 1},
{name = 'mobs_birds:bird_lg', hp = 4, damage = 1, armor = 150, reach = 1},
{name = 'mobs_birds:bird_sm', hp = 2, damage = 1, armor = 150, reach = 1},
{name = 'mobs_birds:gull', hp = 4, damage = 1, armor = 150, reach = 1},
{name = 'mobs_butterfly:butterfly', hp = 1, damage = 0, armor = 200, reach = 1},
{name = 'mobs_creeper:creeper', hp = 14, damage = 2, armor = 150, reach = 1},
{name = 'mobs_crocs:crocodile_float', hp = 26, damage = 3, armor = 75, reach = 2},
{name = 'mobs_crocs:crocodile', hp = 26, damage = 3, armor = 75, reach = 2},
{name = 'mobs_crocs:crocodile_swim', hp = 26, damage = 3, armor = 75, reach = 2},
{name = 'mobs_fish:clownfish', hp = 2, damage = 0, armor = 100, reach = 1},
{name = 'mobs_fish:tropical', hp = 2, damage = 0, armor = 100, reach = 1},
{name = 'mobs_jellyfish:jellyfish', hp = 2, damage = 2, armor = 200, reach = 1},
{name = 'mobs_monster:dirt_monster', hp = 20, damage = 2, armor = 100, reach = 2},
{name = 'mobs_monster:dungeon_master', hp = 30, damage = 5, armor = 50, reach = 2},
{name = 'mobs_monster:lava_flan', hp = 16, damage = 3, armor = 50, reach = 2},
{name = 'mobs_monster:mese_monster', hp = 10, damage = 2, armor = 40, reach = 2},
{name = 'mobs_monster:oerkki', hp = 16, damage = 2, armor = 100, reach = 2},
{name = 'mobs_monster:sand_monster', hp = 20, damage = 2, armor = 200, reach = 2},
{name = 'mobs_monster:spider', hp = 22, damage = 2, armor = 100, reach = 2},
{name = 'mobs_monster:stone_monster', hp = 20, damage = 2, armor = 50, reach = 2},
{name = 'mobs_monster:tree_monster', hp = 18, damage = 2, armor = 75, reach = 2},
{name = 'mobs_sandworm:sandworm', hp = 42, damage = 7, armor = 100, reach = 3},
{name = 'mobs_sharks:shark_lg', hp = 34, damage = 5, armor = 80, reach = 3},
{name = 'mobs_sharks:shark_md', hp = 25, damage = 3, armor = 80, reach = 2},
{name = 'mobs_sharks:shark_sm', hp = 16, damage = 2, armor = 80, reach = 1},
--{name = 'mobs_slimes:green_big', hp = 16, damage = 3, armor = 100},
--{name = 'mobs_slimes:green_medium', hp = 16, damage = 3, armor = 100},
--{name = 'mobs_slimes:green_small', hp = 16, damage = 3, armor = 100},
--{name = 'mobs_slimes:lava_big', hp = 16, damage = 3, armor = 100},
--{name = 'mobs_slimes:lava_medium', hp = 16, damage = 3, armor = 100},
--{name = 'mobs_slimes:lava_small', hp = 16, damage = 3, armor = 100},
{name = 'mobs_turtles:seaturtle', hp = 18, damage = 2, armor = 75, reach = 1},
{name = 'mobs_turtles:turtle', hp = 10, damage = 1, armor = 50, reach = 1},
{name = 'mobs_yeti:yeti', hp = 22, damage = 2, armor = 100, reach = 2},
}
local colors = { 'black', 'blue', 'brown', 'cyan', 'dark_green', 'dark_grey', 'green', 'grey', 'magenta', 'orange', 'pink', 'red', 'violet', 'white', 'yellow',}
for _, color in pairs(colors) do
mob_stats[#mob_stats+1] = {name = 'mobs_animal:sheep_'..color, hp = 18, damage = 1, armor = 150}
end
for _, mob in pairs(mob_stats) do
if string.find(mob.name, 'mobs_monster') or string.find(mob.name, 'mobs_animal') then
local i, j = string.find(mob.name, ':')
local suff = string.sub(mob.name, i)
mob_stats[#mob_stats+1] = {name = 'mobs'..suff, hp = mob.hp, damage = mob.damage, armor = mob.armor}
end
end
local function fun_caves_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
if not self then
return
end
if puncher and puncher.get_player_name then
local player_name = puncher:get_player_name()
if player_name and type(player_name) == 'string' and player_name ~= '' and fun_caves.db.status[player_name] and fun_caves.db.status[player_name].damage_elixir and tool_capabilities and tool_capabilities.damage_groups and tool_capabilities.damage_groups.fleshy then
tool_capabilities.damage_groups.fleshy = tool_capabilities.damage_groups.fleshy + fun_caves.db.status[player_name].damage_elixir.bonus
end
end
self.on_punch_orig(self, puncher, time_from_last_punch, tool_capabilities, dir)
end
for _, mob in pairs(mob_stats) do
if minetest.registered_entities[mob.name] then
minetest.registered_entities[mob.name].on_punch_orig = minetest.registered_entities[mob.name].on_punch
minetest.registered_entities[mob.name].on_punch = function(...)
local status, err = pcall(fun_caves_punch, ...)
if not status then
print(dump(err))
end
end
minetest.registered_entities[mob.name].damage = mob.damage
minetest.registered_entities[mob.name].hp_min = math.ceil(mob.hp * 0.5)
minetest.registered_entities[mob.name].hp_max = math.ceil(mob.hp * 1.5)
minetest.registered_entities[mob.name].armor = mob.armor
if mob.reach then
minetest.registered_entities[mob.name].reach = mob.reach
end
if mob.meat then
minetest.registered_entities[mob.name].drops[#minetest.registered_entities[mob.name].drops+1] = {name = "mobs:meat_raw", chance = 1, min = 1, max = mob.damage ^ 2}
end
end
end
if minetest.registered_entities["dmobs:dragon"] and minetest.registered_entities["mobs_yeti:yeti"] then
local m = table.copy(minetest.registered_entities["dmobs:dragon"])
m.name = 'fun_caves:snow_dragon'
m.lava_damage = 4
m.textures = { {"fun_caves_snow_dragon.png"}, }
m.base_texture = m.textures[1]
m.arrow = "fun_caves:snow_blast"
m.attack_type = 'dogshoot'
m.shoot_interval = .7
m.shoot_offset = 2
m.drops = {
{name = "default:ice", chance = 1, min = 1, max = 3},
{name = "fun_caves:eternal_ice_crystal", chance = 2, min = 1, max = 1},
}
minetest.registered_entities["fun_caves:snow_dragon"] = m
mobs.spawning_mobs["fun_caves:snow_dragon"] = true
local m = table.copy(minetest.registered_entities["mobs_yeti:snowball"])
m.hit_player = function(self, player)
if not (self and player) then
return
end
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 8},
}, nil)
end
m.hit_mob = function(self, player)
if not (self and player) then
return
end
player:punch(self.object, 1.0, {
full_punch_interval = 1.0,
damage_groups = {fleshy = 8},
}, nil)
end
minetest.registered_entities["fun_caves:snow_blast"] = m
mobs:spawn_specific("fun_caves:snow_dragon", {"air"}, {"fun_caves:cloud", "fun_caves:storm_cloud"}, -1, 20, 300, 15000, 2, 4000, 31000)
end
if minetest.registered_entities["dmobs:fox"] then
-- fire_walk overwrites bones, under some circumstances.
-- Keep it disabled until it's definitely working.
local function fire_walk(self)
if not (self and fun_caves.custom_ready(self, 1000000)) then
return
end
local pos = self.object:getpos()
local p1 = vector.subtract(pos, 1)
local p2 = vector.add(pos, 1)
--look for nodes
local nodelist = minetest.find_nodes_in_area(p1, p2, "air")
if not (nodelist and type(nodelist) == 'table') then
return
end
for n in pairs(nodelist) do
--minetest.set_node(pos, {name='fire:basic_flame'})
end
end
minetest.registered_entities["dmobs:fox"].type = 'animal'
local m = table.copy(minetest.registered_entities["dmobs:fox"])
m.name = 'fun_caves:fire_fox'
m.type = 'monster'
m.damage = 3
m.hp_min = 8
m.hp_max = 24
m.lava_damage = 0
m.textures = { {"fun_caves_fire_fox_2.png"}, }
m.base_texture = m.textures[1]
--m.do_custom = fire_walk
minetest.registered_entities["fun_caves:fire_fox"] = m
mobs.spawning_mobs["fun_caves:fire_fox"] = true
mobs:register_spawn("fun_caves:fire_fox", {'fun_caves:hot_cobble'}, 20, -1, 5000, 1, 31000)
end
mobs:register_mob("fun_caves:star", {
description = "Star",
type = "monster",
passive = false,
attack_type = "dogfight",
attacks_monsters = true,
fly = true,
fly_in = 'fun_caves:vacuum',
reach = 2,
damage = 2,
hp_min = 10,
hp_max = 20,
armor = 100,
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
visual = "mesh",
visual_size = {x = 5, y = 5},
mesh = "star.x",
drawtype = "front",
textures = {
{"fun_caves_albino.png"},
},
makes_footstep_sound = false,
sounds = {
random = "mobs_bee",
},
walk_velocity = 1,
run_velocity = 3,
jump = true,
view_range = 15,
floats = 0,
--drops = {
-- {name = "mobs:honey", chance = 2, min = 1, max = 2},
--},
water_damage = 0,
lava_damage = 0,
light_damage = 0,
fall_damage = 0,
lifetimer = 360,
do_custom = function(self)
if not (self and fun_caves.custom_ready(self)) then
return
end
local pos = self.object:getpos()
local node = minetest.get_node_or_nil(pos)
if node and node.name then
self.fly_in = node.name
end
end
})
mobs:spawn_specific("fun_caves:star", {'default:stone', 'fun_caves:asteroid_water'}, {'fun_caves:vacuum'}, -1, 20, nil, 300, 2, 11168, 15168, nil)
if minetest.registered_entities["mobs:bee"] then
mobs:register_spawn("mobs_animal:bee", {"group:flower"}, 20, 10, 300, 1, 31000, true)
local function bee_summon(self)
if not (self and self.state == 'attack') then
return
end
-- To keep bees from summoning infinitely, they lose health each round.
self.health = self.health - 1
check_for_death(self)
local prob = 10
if self.name == 'fun_caves:killer_bee_queen' then
prob = 4
end
if math.random(prob) == 1 then
local pos = self.object:getpos()
local p1 = vector.subtract(pos, 1)
local p2 = vector.add(pos, 1)
--look for nodes
local nodelist = minetest.find_nodes_in_area(p1, p2, "air")
if not (nodelist and type(nodelist) == 'table') then
return
end
if #nodelist > 0 then
for key,value in pairs(nodelist) do
minetest.add_entity(value, "fun_caves:killer_bee_drone")
print("Fun Caves: A bee summons reinforcement.")
return -- only one at a time
end
end
end
end
local function bee_do(self)
if not (self and fun_caves.custom_ready(self)) then
return
end
local pos = self.object:getpos()
pos.y = pos.y + 1
local odds = 25
if self.name == 'fun_caves:killer_bee' then
odds = 5
end
fun_caves.search_replace(pos, odds, {'fun_caves:tree', 'fun_caves:ironwood', 'fun_caves:diamondwood', 'fun_caves:glowing_fungal_wood',}, 'air')
fun_caves.search_replace(pos, 10, {"fun_caves:tree"}, "fun_caves:glowing_fungal_wood")
fun_caves.search_replace(pos, 60, {"fun_caves:glowing_fungal_wood", 'fun_caves:sap'}, "air")
bee_summon(self)
fun_caves.surface_damage(self)
end
mobs:register_mob("fun_caves:killer_bee", {
description = "Killer Bee",
type = "monster",
passive = false,
attack_type = "dogfight",
attacks_monsters = true,
reach = 1,
damage = 1,
hp_min = 2,
hp_max = 6,
armor = 100,
collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.2, 0.2},
visual = "mesh",
mesh = "mobs_bee.x",
drawtype = "front",
textures = {
{"mobs_bee.png"},
},
--textures = { {"fun_caves_killer_bee.png"}, }
--visual_size = {x = 1.5, y = 1.5},
makes_footstep_sound = false,
sounds = {
random = "mobs_bee",
},
walk_velocity = 1,
run_velocity = 2,
fall_speed = -3,
jump = true,
view_range = 10,
floats = 0,
drops = {
{name = "mobs:honey", chance = 2, min = 1, max = 2},
},
water_damage = 0,
lava_damage = 5,
light_damage = 0,
fall_damage = 0,
--lifetimer = 360,
follow = nil,
animation = {
speed_normal = 15,
stand_start = 0,
stand_end = 30,
walk_start = 35,
walk_end = 65,
},
do_custom = bee_do
})
mobs:register_spawn("fun_caves:killer_bee", {"fun_caves:tree", "fun_caves:ironwood", "fun_caves:diamondwood"}, 20, -1, 2000, 5, 31000)
mobs:register_spawn("fun_caves:killer_bee", {"fun_caves:glowing_fungal_wood"}, 20, -1, 150, 5, 31000)
mobs:register_egg("fun_caves:killer_bee", "Killer Bee", "mobs_bee_inv.png", 1)
local m = table.copy(minetest.registered_entities["fun_caves:killer_bee"])
m.name = 'fun_caves:killer_bee_drone'
m.damage = 3
m.hp_min = 3
m.hp_max = 9
m.collisionbox = {-0.25, 0, -0.25, 0.25, 0.25, 0.25}
m.visual_size = {x = 1.25, y = 1.25}
minetest.registered_entities["fun_caves:killer_bee_drone"] = m
mobs.spawning_mobs["fun_caves:killer_bee_drone"] = true
mobs:register_spawn("fun_caves:killer_bee_drone", {"fun_caves:glowing_fungal_wood"}, 20, -1, 300, 3, 31000)
m = table.copy(minetest.registered_entities["fun_caves:killer_bee"])
m.name = 'fun_caves:killer_bee_queen'
m.damage = 2
m.hp_min = 4
m.hp_max = 12
m.collisionbox = {-0.3, 0, -0.3, 0.3, 0.3, 0.3}
m.visual_size = {x = 1.5, y = 1.25}
minetest.registered_entities["fun_caves:killer_bee_queen"] = m
mobs.spawning_mobs["fun_caves:killer_bee_queen"] = true
mobs:register_spawn("fun_caves:killer_bee_queen", {"fun_caves:glowing_fungal_wood"}, 20, -1, 600, 1, 31000)
end
if minetest.registered_entities["kpgmobs:wolf"] then
local m = table.copy(minetest.registered_entities["kpgmobs:wolf"])
m.name = 'fun_caves:white_wolf'
m.textures = { {"fun_caves_white_wolf.png"}, }
m.base_texture = m.textures[1]
minetest.registered_entities["fun_caves:white_wolf"] = m
mobs.spawning_mobs["fun_caves:white_wolf"] = true
mobs:register_spawn("fun_caves:white_wolf", {"default:dirt_with_snow", "fun_caves:cloud", "fun_caves:storm_cloud"}, 20, -1, 11000, 3, 31000)
mobs:register_egg("fun_caves:white_wolf", "White Wolf", "wool_white.png", 1)
end
if minetest.registered_entities["kpgmobs:horse2"] then
mobs:register_spawn("kpgmobs:horse2", {"fun_caves:cloud", "fun_caves:storm_cloud"}, 20, 8, 11000, 1, 31000)
end
if minetest.registered_entities["dmobs:dragon"] then
mobs:spawn_specific("dmobs:dragon", {"air"}, {"fun_caves:cloud", "fun_caves:storm_cloud"}, -1, 20, 300, 15000, 2, 4000, 31000)
end
if minetest.registered_entities["kpgmobs:medved"] then
local m = table.copy(minetest.registered_entities["kpgmobs:medved"])
m.name = 'fun_caves:moon_bear'
m.textures = { {"fun_caves_moon_bear.png"}, }
m.type = 'monster'
m.base_texture = m.textures[1]
minetest.registered_entities["fun_caves:moon_bear"] = m
mobs.spawning_mobs["fun_caves:moon_bear"] = true
mobs:register_spawn("fun_caves:moon_bear", {"default:dirt_with_snow", "fun_caves:cloud", "fun_caves:storm_cloud"}, 20, -1, 11000, 3, 31000, false)
mobs:register_egg("fun_caves:moon_bear", "Moon Bear", "wool_white.png", 1)
end
if minetest.registered_entities["mobs_fish:clownfish"] then
--local l_spawn_near = {"default:sand","default:dirt","group:seaplants","group:seacoral"}
mobs:spawn_specific("mobs_fish:clownfish", {"default:water_source", "default:water_flowing"}, {'fun_caves:water_plant_1_water_cloud', 'fun_caves:water_plant_1_water_storm_cloud'}, 5, 20, 30, 10000, 1, 4000, 5000)
mobs:spawn_specific("mobs_fish:tropical", {"default:water_source", "default:water_flowing"}, {'fun_caves:water_plant_1_water_cloud', 'fun_caves:water_plant_1_water_storm_cloud'}, 5, 20, 30, 10000, 1, 4000, 5000)
mobs:spawn_specific("mobs_fish:tropical", {"default:water_source", "default:water_flowing"}, nil, 5, 20, 30, 10000, 1, 8769, 8798)
end
if minetest.registered_entities["mobs_monster:spider"] then
-- Deep spider
local m = table.copy(minetest.registered_entities["mobs_monster:spider"])
m.name = 'fun_caves:spider'
m.docile_by_day = false
m.drops = {
{name = "mobs:meat_raw", chance = 1, min = 1, max = 3},
{name = "wool:black", chance = 1, min = 1, max = 3},
}
m.water_damage = 0
m.do_custom = function(self)
if not (self and fun_caves.custom_ready(self)) then
return
end
fun_caves.surface_damage(self)
end
minetest.registered_entities["fun_caves:spider"] = m
mobs.spawning_mobs["fun_caves:spider"] = true
mobs:register_spawn("fun_caves:spider", fun_caves_stones, 14, 0, 2000, 2, -51)
mobs:register_egg("fun_caves:spider", "Deep Spider", "mobs_cobweb.png", 1)
-- ice spider
m = table.copy(minetest.registered_entities["mobs_monster:spider"])
m.name = 'fun_caves:spider_ice'
m.docile_by_day = false
m.textures = { {"fun_caves_spider_ice.png"}, }
m.base_texture = m.textures[1]
m.drops = {
{name = "mobs:meat_raw", chance = 1, min = 1, max = 3},
{name = "wool:white", chance = 1, min = 1, max = 3},
}
m.water_damage = 0
m.do_custom = function(self)
if not (self and fun_caves.custom_ready(self)) then
return
end
fun_caves.surface_damage(self, true)
end
minetest.registered_entities["fun_caves:spider_ice"] = m
mobs.spawning_mobs["fun_caves:spider_ice"] = true
mobs:register_spawn("fun_caves:spider_ice", {"default:ice"}, 14, 0, 1000, 2, 31000)
mobs:register_egg("fun_caves:spider_ice", "Ice Spider", "mobs_cobweb.png", 1)
-- dangling spiders
m = table.copy(minetest.registered_entities["mobs_monster:spider"])
m.name = 'fun_caves:dangler'
m.docile_by_day = false
m.attacks_monsters = true
m.damage = 2
m.hp_min = 9
m.hp_max = 27
m.armor = 100
m.water_damage = 0
m.fall_damage = 0
m.collisionbox = {-0.32, -0.0, -0.25, 0.25, 0.25, 0.25}
m.visual_size = {x = 1.5, y = 1.5}
m.drops = {
{name = "mobs:meat_raw", chance = 2, min = 1, max = 4},
{name = "farming:cotton", chance = 2, min = 1, max = 4},
}
m.do_custom = function(self)
if not (self and fun_caves.custom_ready(self)) then
return
end
fun_caves.climb(self)
fun_caves.search_replace(self.object:getpos(), 30, {"air"}, "mobs:cobweb")
fun_caves.surface_damage(self)
end
minetest.registered_entities["fun_caves:dangler"] = m
mobs.spawning_mobs["fun_caves:dangler"] = true
mobs:register_spawn("fun_caves:dangler", fun_caves_stones, 14, 0, 1000, 3, -51)
mobs:register_egg("fun_caves:dangler", "Dangling Spider", "mobs_cobweb.png", 1)
-- tarantula
m = table.copy(minetest.registered_entities["mobs_monster:spider"])
m.name = 'fun_caves:tarantula'
m.type = "animal"
m.reach = 1
m.damage = 1
m.hp_min = 1
m.hp_max = 2
m.collisionbox = {-0.15, -0.01, -0.15, 0.15, 0.1, 0.15}
m.textures = { {"fun_caves_tarantula.png"}, }
m.base_texture = m.textures[1]
m.visual_size = {x = 1, y = 1}
m.sounds = {}
m.run_velocity = 2
m.jump = false
m.drops = { {name = "mobs:meat_raw", chance = 1, min = 1, max = 1}, }
m.do_custom = function(self)
if not self then
return
end
if not self.fun_caves_damage_timer then
self.fun_caves_damage_timer = 0
end
fun_caves.surface_damage(self)
end
minetest.registered_entities["fun_caves:tarantula"] = m
mobs.spawning_mobs["fun_caves:tarantula"] = true
mobs:register_spawn("fun_caves:tarantula", {"default:desert_sand", "default:dirt_with_dry_grass"}, 99, 0, 4000, 2, 31000)
mobs:register_egg("fun_caves:tarantula", "Tarantula", "mobs_cobweb.png", 1)
end
if minetest.registered_entities["mobs_monster:sand_monster"] then
local m = table.copy(minetest.registered_entities["mobs_monster:sand_monster"])
m.name = 'fun_caves:tar_monster'
m.damage = 2
m.hp_min = 10
m.hp_max = 30
m.armor = 200
m.textures = { {"fun_caves_tar_monster.png"}, }
m.base_texture = m.textures[1]
m.drops = { {name = "default:coal_lump", chance = 1, min = 3, max = 5}, }
m.water_damage = 1
m.lava_damage = 2
m.light_damage = 1
minetest.registered_entities["fun_caves:tar_monster"] = m
mobs.spawning_mobs["fun_caves:tar_monster"] = true
mobs:register_spawn("fun_caves:tar_monster", {"fun_caves:black_sand"}, 20, 0, 4000, 1, 31000)
mobs:register_egg("fun_caves:tar_monster", "Tar Monster", "fun_caves_black_sand.png", 1)
m = table.copy(minetest.registered_entities["mobs_monster:sand_monster"])
m.name = 'fun_caves:sand_monster'
m.textures = { {"fun_caves_sand_monster.png"}, }
m.base_texture = m.textures[1]
m.drops = { {name = "default:sand", chance = 1, min = 3, max = 5}, }
minetest.registered_entities["fun_caves:sand_monster"] = m
mobs.spawning_mobs["fun_caves:sand_monster"] = true
mobs:register_spawn("fun_caves:sand_monster", {"default:sand"}, 20, 0, 4000, 3, -50)
mobs:register_egg("fun_caves:sand_monster", "Deep Sand Monster", "default_sand.png", 1)
mobs:register_spawn("fun_caves:sand_monster", {"fun_caves:pyramid_1"}, 20, 0, 150, 5, 31000)
end
if minetest.registered_entities["mobs_monster:stone_monster"] then
mobs:register_spawn("mobs_monster:stone_monster", {"fun_caves:pyramid_1"}, 20, 0, 300, 5, 31000)
local stones = table.copy(fun_caves_stones)
stones[#stones+1] = 'fun_caves:hot_cobble'
stones[#stones+1] = 'fun_caves:salt'
mobs:register_spawn("mobs_monster:stone_monster", stones, 7, 0, 7000, 1, 0)
m = table.copy(minetest.registered_entities["mobs_monster:stone_monster"])
m.name = 'fun_caves:radiated_stone_monster'
m.damage = 4
m.hp_min = 20
m.hp_max = 45
m.armor = 70
m.textures = { {"fun_caves_radiated_stone_monster.png"}, }
m.base_texture = m.textures[1]
m.drops = { {name = "fun_caves:radioactive_ore", chance = 1, min = 3, max = 5}, }
minetest.registered_entities["fun_caves:radiated_stone_monster"] = m
mobs.spawning_mobs["fun_caves:radiated_stone_monster"] = true
mobs:register_spawn("fun_caves:radiated_stone_monster", {"default:salt"}, 20, 0, 7000, 3, -50)
mobs:register_egg("fun_caves:radiated_stone_monster", "Radiated Stone Monster", "fun_caves_radioactive_ore.png", 1)
end
if minetest.registered_entities["mobs_monster:dungeon_master"] then
mobs:register_spawn("mobs_monster:dungeon_master", {"fun_caves:pyramid_1"}, 20, 0, 3500, 5, 31000)
local stones = table.copy(fun_caves_stones)
stones[#stones+1] = 'fun_caves:hot_cobble'
mobs:register_spawn("mobs_monster:dungeon_master", stones, 7, 0, 7000, 1, -70)
end
if minetest.registered_entities["mobs_monster:oerkki"] then
mobs:register_spawn("mobs_monster:oerkki", fun_caves_stones, 7, 0, 7000, 1, -10)
end
if minetest.registered_entities["mobs_monster:mese_monster"] then
local stones = table.copy(fun_caves_stones)
stones[#stones+1] = 'fun_caves:hot_cobble'
mobs:register_spawn("mobs_monster:mese_monster", stones, 7, 0, 5000, 1, -20)
end
-- Change the original, rather than making a copy.
if minetest.registered_entities["dmobs:elephant"] then
local m = minetest.registered_entities["dmobs:elephant"]
m.type = "monster"
m.water_damage = 0
end
if minetest.registered_entities["mobs_bat:bat"] then
mobs:spawn_specific("mobs_bat:bat", {"air"}, fun_caves_stones, 0, 6, 30, 20000, 2, -31000, 11000)
end
if minetest.registered_entities["dmobs:orc"] then
mobs:register_spawn("dmobs:orc", fun_caves_stones, 20, -1, 7000, 2, 4000)
end
if minetest.registered_entities["mobs_monster:dirt_monster"] then
-- check this
mobs:register_spawn("mobs_monster:dirt_monster", {"default:dirt", 'fun_caves:dirt'}, 7, 0, 4000, 1, -50)
mobs:register_spawn("mobs_monster:dirt_monster", {"default:dirt_with_dry_grass"}, 7, 0, 7000, 1, 31000, false)
end
if minetest.registered_entities["mobs_slimes:green_big"] then
local slime_surfaces = {"fun_caves:stone_with_moss", "fun_caves:stone_with_algae", 'fun_caves:polluted_dirt'}
mobs:spawn_specific("mobs_slimes:green_big", slime_surfaces, {"air"}, -1, 20, 30, 30000, 1, -31000, 31000
)
mobs:spawn_specific("mobs_slimes:green_medium", slime_surfaces, {"air"}, -1, 20, 30, 30000, 2, -31000, 31000
)
mobs:spawn_specific("mobs_slimes:green_small", slime_surfaces, {"air"}, -1, 20, 30, 30000, 3, -31000, 31000
)
end
if minetest.registered_entities["mobs_creeper:creeper"] then
mobs:spawn_specific("mobs_creeper:creeper",
{"fun_caves:stone_with_moss"},
{"air"},
-1, 20, 30, 20000, 1, -31000, 31000
)
end
if minetest.registered_entities["mobs_sharks:shark_lg"] then
mobs:spawn_specific("mobs_sharks:shark_sm", {"default:water_source"}, nil, -1, 20, 30, 60000, 1, 8769, 8798)
mobs:spawn_specific("mobs_sharks:shark_md", {"default:water_source"}, nil, -1, 20, 30, 60000, 1, 8769, 8798)
mobs:spawn_specific("mobs_sharks:shark_lg", {"default:water_source"}, nil, -1, 20, 30, 60000, 1, 8769, 8798)
local m = table.copy(minetest.registered_entities["mobs_sharks:shark_lg"])
local l_spawn_in = {"default:water_flowing","default:water_source"}
local l_spawn_near = {"default:water_flowing","default:water_source","seawrecks:woodship","seawrecks:uboot"}
m.name = 'fun_caves:shark_giant'
m.damage = 7
m.hp_min = 20
m.hp_max = 60
m.visual_size = {x=3, y=3}
m.collisionbox = {-2, -1.5, -2, 2, 1.5, 2}
m.textures = {"fun_caves_albino.png"}
m.base_texture = m.textures[1]
minetest.registered_entities["fun_caves:shark_giant"] = m
mobs.spawning_mobs["fun_caves:shark_giant"] = true
mobs:spawn_specific("fun_caves:shark_giant", l_spawn_in, l_spawn_near, -1, 20, 30, 60000, 1, -31000, -29620)
mobs:register_egg("fun_caves:shark_md", "Shark (giant)", "mob_shark_shark_item.png", 0)
end
if fun_caves.path then
dofile(fun_caves.path.."/zombie.lua")
dofile(fun_caves.path.."/goblin.lua")
dofile(fun_caves.path.."/demon.lua")
dofile(fun_caves.path.."/horror.lua")
end
fun_caves.dungeon_spawns = {}
local t_mobs = {
"mobs_monster:dungeon_master",
"mobs_monster:lava_flan",
"mobs_monster:mese_monster",
"mobs_monster:oerkki",
"mobs_monster:stone_monster",
"fun_caves:spider",
"mobs_slimes:green_big",
"mobs_slimes:green_medium",
"mobs_slimes:green_small",
'fun_caves:fire_fox',
"fun_caves:goblin_cobble",
"fun_caves:goblin_copper",
"fun_caves:goblin_coal",
"fun_caves:goblin_ice",
"fun_caves:goblin_iron",
"fun_caves:goblin_gold",
"fun_caves:goblin_diamond",
"fun_caves:goblin_king",
"fun_caves:zombie",
"fun_caves:zombie",
'fun_caves:manticore',
"dmobs:orc",
"dmobs:orc",
"dmobs:orc",
"dmobs:ogre",
"dmobs:ogre",
}
for _, mob in pairs(t_mobs) do
if minetest.registered_entities[mob] then
local obj = minetest.registered_entities[mob]
if obj.hp_max and obj.hp_min and obj.damage then
local hp = (obj.hp_min + obj.hp_max) / 2
local level = math.floor(hp / 10 + obj.damage + 0.5)
fun_caves.dungeon_spawns[#fun_caves.dungeon_spawns+1] = {
name = mob,
level = level,
}
--print(mob, level)
end
end
end
table.sort(fun_caves.dungeon_spawns, function(a, b)
if a.level < b.level then
return true
elseif a.level > b.level then
return false
elseif a.name < b.name then
return true
else
return false
end
end)

File diff suppressed because it is too large Load diff

View file

@ -1,70 +0,0 @@
# Blender v2.60 (sub 0) OBJ File: ''
# www.blender.org
mtllib warps_warpstone.mtl
o Plane
v 0.000345 -0.332211 0.238072
v -0.238873 -0.332211 -0.000181
v -0.187467 0.347788 0.000753
v 0.003339 0.347788 0.186987
v -0.000061 0.473738 -0.000013
v -0.000061 -0.400212 -0.000013
v 0.238345 -0.332211 0.000071
v 0.187345 0.347788 -0.000779
v -0.000467 -0.332211 -0.238097
v -0.003461 0.347788 -0.187013
vt 0.247005 0.000534
vt 0.000000 0.000534
vt 0.000000 0.499516
vt 0.247005 0.499516
vt 0.744000 0.749758
vt 0.744000 0.501019
vt 0.248498 0.501019
vt 0.248498 0.749758
vt 0.495503 0.000534
vt 0.248498 0.000534
vt 0.248498 0.499516
vt 0.495503 0.499516
vt 0.744000 1.000000
vt 0.744000 0.751261
vt 0.248498 0.751261
vt 0.248498 1.000000
vt 0.247005 1.000000
vt 0.247005 0.752012
vt 0.000746 1.000000
vt 0.497742 0.249273
vt 0.744000 0.001285
vt 0.744000 0.249273
vt 0.744000 0.251528
vt 0.497742 0.499516
vt 0.744000 0.499516
vt 0.247005 0.749758
vt 0.000746 0.749758
vt 0.247005 0.501770
vt 0.000000 0.751261
vt 0.000000 0.999249
vt 0.246259 0.751261
vt 0.743254 0.000534
vt 0.496995 0.248522
vt 0.496995 0.000534
vt 0.496995 0.250776
vt 0.496995 0.498764
vt 0.743254 0.250776
vt 0.000000 0.501019
vt 0.246259 0.501019
vt 0.000000 0.749006
g Plane_Plane_Material.001
usemtl Material.001
s off
f 2/1 1/2 4/3 3/4
f 1/5 7/6 8/7 4/8
f 7/9 9/10 10/11 8/12
f 9/13 2/14 3/15 10/16
s 1
f 5/17 3/18 4/19
f 1/20 2/21 6/22
f 7/23 1/24 6/25
f 5/26 4/27 8/28
f 5/29 8/30 10/31
f 9/32 7/33 6/34
f 6/35 2/36 9/37
f 5/38 10/39 3/40

Binary file not shown.

Binary file not shown.

View file

@ -1,132 +0,0 @@
xof 0303txt 0032
Frame Root {
FrameTransformMatrix {
1.000000, 0.000000, 0.000000, 0.000000,
0.000000,-0.000000, 1.000000, 0.000000,
0.000000, 1.000000, 0.000000, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000;;
}
Frame Cube {
FrameTransformMatrix {
1.000000, 0.000000, 0.000000, 0.000000,
0.000000, 1.000000, 0.000000, 0.000000,
0.000000, 0.000000, 1.000000, 0.000000,
0.000000, 0.000000, 0.000000, 1.000000;;
}
Mesh { // Cube mesh
34;
-0.100000;-0.100000;-0.100000;,
-0.100000; 0.100000;-0.100000;,
0.100000; 0.100000;-0.100000;,
0.100000;-0.100000;-0.100000;,
-0.100000;-0.100000; 0.100000;,
-0.100000; 0.100000; 0.100000;,
0.100000; 0.100000; 0.100000;,
0.100000;-0.100000; 0.100000;,
-0.100000;-0.100000;-0.100000;,
-0.100000; 0.100000;-0.100000;,
0.100000; 0.100000;-0.100000;,
0.100000;-0.100000;-0.100000;,
-0.100000;-0.100000; 0.100000;,
-0.100000; 0.100000; 0.100000;,
0.100000; 0.100000; 0.100000;,
0.100000;-0.100000; 0.100000;,
-0.100000;-0.100000; 0.001563;,
-0.100000; 0.100000; 0.001563;,
0.100000; 0.100000; 0.001563;,
0.100000;-0.100000; 0.001563;,
-0.100000; 0.000000; 0.100000;,
-0.100000; 0.000000;-0.100000;,
0.100000; 0.000000; 0.100000;,
0.100000; 0.000000;-0.100000;,
-0.998266; 0.000422;-0.004041;,
0.985912; 0.004690; 0.008512;,
0.000000; 0.100000; 0.100000;,
0.000000; 0.100000;-0.100000;,
0.000000;-0.100000; 0.100000;,
0.000000;-0.100000;-0.100000;,
0.002391; 0.999240; 0.000504;,
0.000000;-1.003160;-0.001113;,
-0.005045; 0.000661;-1.005413;,
-0.003414;-0.001039; 0.994975;;
24;
4;21,1,17,24;,
4;27,2,18,30;,
4;23,3,19,25;,
4;29,0,16,31;,
4;23,2,27,32;,
4;20,5,26,33;,
4;24,17,5,20;,
4;30,18,6,26;,
4;25,19,7,22;,
4;31,16,4,28;,
4;0,21,24,16;,
4;2,23,25,18;,
4;3,23,32,29;,
4;4,20,33,28;,
4;16,24,20,4;,
4;18,25,22,6;,
4;1,27,30,17;,
4;3,29,31,19;,
4;32,27,1,21;,
4;33,26,6,22;,
4;17,30,26,5;,
4;19,31,28,7;,
4;29,32,21,0;,
4;28,33,22,7;;
MeshNormals { // Cube normals
24;
-0.152150; 0.704271;-0.693436;,
0.704077; 0.153905;-0.693245;,
0.167733;-0.702472;-0.691664;,
-0.704082;-0.153861;-0.693250;,
0.698267; 0.698267;-0.157624;,
-0.698642; 0.698642; 0.154272;,
-0.158289; 0.692673; 0.703668;,
0.693239; 0.153169; 0.704243;,
0.154613;-0.693082; 0.704083;,
-0.692979;-0.155542; 0.703979;,
-0.152796;-0.704200;-0.693366;,
0.160490; 0.703330;-0.692510;,
0.698155;-0.698155;-0.158618;,
-0.698816;-0.698816; 0.152688;,
-0.158924;-0.692602; 0.703595;,
0.147438; 0.693851; 0.704864;,
-0.703667; 0.157558;-0.692841;,
0.704082;-0.153861;-0.693250;,
-0.699104; 0.699104;-0.150022;,
0.698058; 0.698058; 0.159468;,
-0.692843; 0.156766; 0.703841;,
0.692979;-0.155542; 0.703979;,
-0.698997;-0.698997;-0.151019;,
0.698238;-0.698238; 0.157888;;
24;
4;0,0,0,0;,
4;1,1,1,1;,
4;2,2,2,2;,
4;3,3,3,3;,
4;4,4,4,4;,
4;5,5,5,5;,
4;6,6,6,6;,
4;7,7,7,7;,
4;8,8,8,8;,
4;9,9,9,9;,
4;10,10,10,10;,
4;11,11,11,11;,
4;12,12,12,12;,
4;13,13,13,13;,
4;14,14,14,14;,
4;15,15,15,15;,
4;16,16,16,16;,
4;17,17,17,17;,
4;18,18,18,18;,
4;19,19,19,19;,
4;20,20,20,20;,
4;21,21,21,21;,
4;22,22,22,22;,
4;23,23,23,23;;
} // End of Cube normals
} // End of Cube mesh
} // End of Cube
} // End of Root

832
nodes.lua
View file

@ -1,496 +1,408 @@
local get_node_or_nil = minetest.get_node_or_nil
local get_item_group = minetest.get_item_group
local max_depth = 31000
-- 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 old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
if not (pos and name and type(name) == 'string') then
return
end
local node = get_node_or_nil(pos)
if node and node.name == 'fun_caves:translocator' and (name == '' or not minetest.get_player_by_name(name)) then
return true
end
return old_is_protected(pos, name)
local light_max = fun_caves_mod.light_max or 10
-- 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)
-- 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},
}),
})
-- 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},
})
-- 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
-- dirt, cave
local newnode = fun_caves.clone_node("default:dirt")
newnode.drop = "default:dirt"
newnode.groups.soil = 0
minetest.register_node("fun_caves:dirt", newnode)
newnode = fun_caves.clone_node("default:dirt")
newnode.description = "Polluted Dirt"
newnode.tiles = {"default_dirt.png^[colorize:#100020:100"}
newnode.groups.soil = 0
minetest.register_node("fun_caves:polluted_dirt", newnode)
-- ice -- add cold damage
minetest.add_group("default:ice", {surface_cold = 3})
-- 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",
-- 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(),
})
minetest.register_node('fun_caves:sticks_default', {
description = 'Sticks',
drawtype = 'allfaces_optional',
waving = 1,
visual_scale = 1.3,
tiles = {'fun_caves_dry_twigs.png'},
paramtype = 'light',
-- 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,
drop = 'default:stick 2',
groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1},
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},
})
newnode = fun_caves.clone_node("default:leaves")
newnode.description = "Blackened Leaves"
newnode.tiles = {"default_leaves.png^[colorize:#100020:200"}
newnode.special_tiles = {"default_leaves_simple.png^[colorize:#100020:200"}
newnode.groups = {snappy = 3, flammable = 2}
minetest.register_node("fun_caves:leaves_black", newnode)
-- 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}, }},
})
newnode = fun_caves.clone_node("default:water_source")
newnode.description = "Poisonous Water"
newnode.groups.poison = 3
newnode.light_source = 6
newnode.liquid_alternative_flowing = "fun_caves:water_poison_flowing"
newnode.liquid_alternative_source = "fun_caves:water_poison_source"
newnode.post_effect_color = {a = 103, r = 108, g = 128, b = 64}
newnode.special_tiles[1].name = "fun_caves_water_poison_source_animated.png"
newnode.tiles[1].name = "fun_caves_water_poison_source_animated.png"
minetest.register_node("fun_caves:water_poison_source", newnode)
-- 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},
}),
})
newnode = fun_caves.clone_node("default:water_flowing")
newnode.description = "Poisonous Water"
newnode.groups.poison = 3
newnode.light_source = 6
newnode.liquid_alternative_flowing = "fun_caves:water_poison_flowing"
newnode.liquid_alternative_source = "fun_caves:water_poison_source"
newnode.post_effect_color = {a = 103, r = 108, g = 128, b = 64}
newnode.special_tiles[1].name = "fun_caves_water_poison_flowing_animated.png"
newnode.tiles[1] = "fun_caves_water_poison.png"
minetest.register_node("fun_caves:water_poison_flowing", newnode)
-- 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},
}),
})
--minetest.register_node("fun_caves:bright_air", {
-- drawtype = "glasslike",
-- tiles = {"technic_light.png"},
-- paramtype = "light",
-- groups = {not_in_creative_inventory=1},
-- drop = "",
-- walkable = false,
-- buildable_to = true,
-- sunlight_propagates = true,
-- light_source = LIGHT_MAX,
-- pointable = false,
-- 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)
-- 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"},
}
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
-- 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)
-- 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},
}),
})
-- 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"}
-- }
--})
local newnode = fun_caves.clone_node("default:dirt")
newnode.description = "Meteor Crater"
newnode.tiles = {"fun_caves_crater.png", "default_dirt.png", "default_dirt.png", "default_dirt.png", "default_dirt.png", "default_dirt.png"}
newnode.drop = "fun_caves:meteorite"
newnode.groups.soil = 0
minetest.register_node("fun_caves:meteorite_crater", newnode)
local newnode = fun_caves.clone_node("default:stone_with_iron")
newnode.description = "Stone With Meteoritic Iron"
newnode.drop = "fun_caves:meteorite"
minetest.register_node("fun_caves:stone_with_meteoritic_iron", newnode)
newnode = fun_caves.clone_node("default:stone")
newnode.tiles = {'dna.png'}
minetest.register_node("fun_caves:dna", newnode)
newnode = fun_caves.clone_node("farming:straw")
newnode.description = 'Bundle of Grass'
newnode.tiles = {'farming_straw.png^[colorize:#00FF00:50'}
minetest.register_node("fun_caves:bundle_of_grass", newnode)
minetest.register_craft({
output = 'fun_caves:bundle_of_grass',
type = 'shapeless',
output = 'default:paper 6',
recipe = {
'default:junglegrass', 'default:junglegrass',
'default:junglegrass', 'default:junglegrass',
{'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem', 'fun_caves:giant_mushroom_stem'},
}
})
minetest.register_craft({
type = "cooking",
output = "fun_caves:dry_fiber",
recipe = 'fun_caves:bundle_of_grass',
cooktime = 3,
})
local function rope_remove(pos)
if not pos then
return
end
for i = 1, 100 do
local newpos = table.copy(pos)
newpos.y = newpos.y - i
local node = minetest.get_node_or_nil(newpos)
if node and node.name and node.name == 'fun_caves:rope_ladder_piece' then
minetest.set_node(newpos, {name='air'})
else
break
end
end
end
local good_params = {nil, true, true, true, true}
for length = 10, 50, 10 do
minetest.register_node("fun_caves:rope_ladder_"..length, {
description = "Rope Ladder ("..length.." meter)",
drawtype = "signlike",
tiles = {"fun_caves_rope_ladder.png"},
inventory_image = "fun_caves_rope_ladder.png",
wield_image = "fun_caves_rope_ladder.png",
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = false,
climbable = true,
is_ground_content = false,
selection_box = {
type = "wallmounted",
},
groups = {snappy = 2, oddly_breakable_by_hand = 3, flammable = 2},
legacy_wallmounted = true,
sounds = default.node_sound_leaves_defaults(),
after_place_node = function(pos, placer, itemstack, pointed_thing)
if not (pointed_thing and pointed_thing.above) then
return
end
local pos_old = pointed_thing.above
local orig = minetest.get_node_or_nil(pos_old)
if orig and orig.name and orig.param2 and good_params[orig.param2] then
for i = 1, length do
local newpos = table.copy(pos_old)
newpos.y = newpos.y - i
local node = minetest.get_node_or_nil(newpos)
if node and node.name and node.name == 'air' then
minetest.set_node(newpos, {name='fun_caves:rope_ladder_piece', param2=orig.param2})
else
break
end
end
end
end,
on_destruct = rope_remove,
})
if length > 10 then
rec = {}
for i = 10, length, 10 do
rec[#rec+1] = 'fun_caves:rope_ladder_10'
end
minetest.register_craft({
output = 'fun_caves:rope_ladder_'..length,
type = 'shapeless',
recipe = rec,
})
end
end
minetest.register_node("fun_caves:rope_ladder_piece", {
description = "Rope Ladder",
drawtype = "signlike",
tiles = {"fun_caves_rope_ladder.png"},
inventory_image = "fun_caves_rope_ladder.png",
wield_image = "fun_caves_rope_ladder.png",
drop = {},
paramtype = "light",
paramtype2 = "wallmounted",
buildable_to = true,
sunlight_propagates = true,
walkable = false,
climbable = true,
is_ground_content = false,
selection_box = {
type = "wallmounted",
},
groups = {snappy = 2, oddly_breakable_by_hand = 3, flammable = 2},
legacy_wallmounted = true,
sounds = default.node_sound_leaves_defaults(),
on_destruct = rope_remove,
})
minetest.register_craft({
output = 'fun_caves:rope_ladder_10',
recipe = {
{'fun_caves:dry_fiber', '', 'fun_caves:dry_fiber'},
{'fun_caves:dry_fiber', 'fun_caves:dry_fiber', 'fun_caves:dry_fiber'},
{'fun_caves:dry_fiber', '', 'fun_caves:dry_fiber'},
}
})
minetest.register_craftitem("fun_caves:apple_pie_slice", {
description = "Apple Pie Slice",
inventory_image = "fun_caves_apple_pie_slice.png",
on_use = minetest.item_eat(5),
})
minetest.register_craft({
output = 'fun_caves:apple_pie_slice 6',
type = 'shapeless',
recipe = {
'fun_caves:apple_pie',
}
})
minetest.register_node("fun_caves:apple_pie", {
description = "Apple Pie",
drawtype = "raillike",
tiles = {"fun_caves_apple_pie.png"},
inventory_image = "fun_caves_apple_pie.png",
paramtype = "light",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-0.4, -0.5, -0.4, 0.5, -0.4, 0.4}
},
groups = {dig_immediate = 3, attached_node = 1},
sounds = default.node_sound_dirt_defaults(),
})
minetest.register_craftitem("fun_caves:apple_pie_uncooked", {
description = "Uncooked Apple Pie",
inventory_image = "fun_caves_apple_pie_uncooked.png",
})
minetest.register_craft({
output = 'fun_caves:apple_pie_uncooked',
type = 'shapeless',
recipe = {
'default:apple',
'default:apple',
'farming:flour',
'fun_caves:syrup',
'fun_caves:syrup',
'fun_caves:syrup',
},
replacements = {
{'fun_caves:syrup', 'vessels:glass_bottle'},
{'fun_caves:syrup', 'vessels:glass_bottle'},
{'fun_caves:syrup', 'vessels:glass_bottle'},
},
})
if minetest.registered_items['mobs:bucket_milk'] then
minetest.register_craft({
output = 'fun_caves:apple_pie_uncooked',
type = 'shapeless',
recipe = {
'default:apple',
'default:apple',
'farming:flour',
'mobs:bucket_milk',
},
replacements = {
{'mobs:bucket_milk', 'fun_caves:bucket_empty'},
},
})
end
if minetest.registered_items['mobs:honey'] then
minetest.register_craft({
output = 'fun_caves:apple_pie_uncooked',
type = 'shapeless',
recipe = {
'default:apple',
'default:apple',
'farming:flour',
'mobs:honey',
},
})
end
if minetest.registered_items['mobs:meat_raw'] then
minetest.register_craftitem("fun_caves:meat_pie_uncooked", {
description = "Uncooked Meat Pie",
inventory_image = "fun_caves_meat_pie_uncooked.png",
})
minetest.register_craft({
output = 'fun_caves:meat_pie_uncooked',
type = 'shapeless',
recipe = {
'mobs:meat_raw',
'mobs:meat_raw',
'fun_caves:onion',
'farming:flour',
},
})
minetest.register_node("fun_caves:meat_pie", {
description = "Meat Pie",
drawtype = "raillike",
tiles = {"fun_caves_meat_pie.png"},
inventory_image = "fun_caves_meat_pie.png",
paramtype = "light",
walkable = false,
selection_box = {
type = "fixed",
fixed = {-0.4, -0.5, -0.4, 0.5, -0.4, 0.4}
},
groups = {dig_immediate = 3, attached_node = 1},
sounds = default.node_sound_dirt_defaults(),
})
minetest.register_craft({
type = "cooking",
cooktime = 15,
output = "fun_caves:meat_pie",
recipe = "fun_caves:meat_pie_uncooked"
})
minetest.register_craftitem("fun_caves:meat_pie_slice", {
description = "Meat Pie Slice",
inventory_image = "fun_caves_meat_pie_slice.png",
on_use = minetest.item_eat(9),
})
minetest.register_craft({
output = 'fun_caves:meat_pie_slice 5',
type = 'shapeless',
recipe = {
'fun_caves:meat_pie',
}
})
end
farming.register_plant("fun_caves:onion", {
description = "Onion",
inventory_image = "fun_caves_onion.png",
steps = 3,
minlight = 13,
maxlight = default.LIGHT_MAX,
fertility = {"grassland"}
})
minetest.registered_items['fun_caves:seed_onion'] = nil
minetest.registered_nodes['fun_caves:seed_onion'] = nil
minetest.registered_craftitems['fun_caves:seed_onion'] = nil
minetest.register_alias('fun_caves:seed_onion', 'fun_caves:onion')
for i = 1, 3 do
local onion = minetest.registered_items['fun_caves:onion_'..i]
if onion then
onion.drop = {
max_items = i,
items = {
{ items = {'fun_caves:onion'}, rarity = 4 - i, },
{ items = {'fun_caves:onion'}, rarity = (4 - i) * 2, },
{ items = {'fun_caves:onion'}, rarity = (4 - i) * 4, },
},
}
end
end
minetest.register_node("fun_caves:onion", {
description = "Onion",
drawtype = "plantlike",
visual_scale = 0.75,
tiles = {"fun_caves_onion.png"},
inventory_image = "fun_caves_onion.png",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
is_ground_content = false,
selection_box = {
type = "fixed",
fixed = {-0.2, -0.5, -0.2, 0.2, 0, 0.2}
},
fertility = {'grassland'},
groups = {seed = 1, fleshy = 3, dig_immediate = 3, flammable = 2},
on_use = minetest.item_eat(2),
sounds = default.node_sound_leaves_defaults(),
next_plant = 'fun_caves:onion_1',
on_timer = farming.grow_plant,
minlight = 10,
maxlight = 15,
on_place = function(itemstack, placer, pointed_thing)
local stack = farming.place_seed(itemstack, placer, pointed_thing, 'fun_caves:onion')
if stack then
return stack
end
return minetest.item_place(itemstack, placer, pointed_thing)
end,
})
minetest.register_craft({
type = "cooking",
cooktime = 15,
output = "fun_caves:apple_pie",
recipe = "fun_caves:apple_pie_uncooked"
})
for i = 3, 5 do
minetest.override_item("default:grass_" .. i, {
drop = {
max_items = 2,
items = {
{ items = { "default:grass_1"}, },
{ items = {'farming:seed_wheat'},rarity = 5 },
{ items = {"fun_caves:onion",}, rarity = 5 },
},
},
})
end
minetest.register_craftitem("fun_caves:wooden_bowl", {
description = "Wooden Bowl",
-- Caps can be cooked and eaten.
minetest.register_node("fun_caves:mushroom_steak", {
description = "Mushroom Steak",
drawtype = "plantlike",
paramtype = "light",
tiles = {"fun_caves_wooden_bowl.png"},
inventory_image = "fun_caves_wooden_bowl.png",
groups = {bowl = 1, dig_immediate = 3},
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({
output = 'fun_caves:wooden_bowl 20',
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 = {
{'group:wood', '', 'group:wood'},
{'group:wood', '', 'group:wood'},
{'', 'group:wood', ''},
{"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 = 'default:diamondblock',
output = "fun_caves:moon_glass",
type = "shapeless",
recipe = {
{'default:coalblock', 'default:coalblock', 'default:coalblock'},
{'default:coalblock', 'default:mese_crystal_fragment', 'default:coalblock'},
{'default:coalblock', 'default:coalblock', 'default:coalblock'},
}
"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:mese_crystal 2',
output = "default:cobble",
recipe = {
{'default:diamond', 'default:diamond', 'default:diamond'},
{'default:diamond', 'default:mese_crystal', 'default:diamond'},
{'default:diamond', 'default:diamond', 'default:diamond'},
}
{"", "", ""},
{"fun_caves:stalagmite", "fun_caves:stalagmite", ""},
{"fun_caves:stalagmite", "fun_caves:stalagmite", ""},
},
})

View file

@ -1,160 +0,0 @@
local max_depth = 31000
-- pyramid stone
newnode = fun_caves.clone_node("default:sandstone")
newnode.description = "Pyramid Stone"
newnode.tiles = {'fun_caves_pyramid_stone.png'}
newnode.groups.pyramid = 1
newnode.drop = 'default:sandstone'
minetest.register_node("fun_caves:pyramid_1", newnode)
local chest_formspec =
"size[8,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[current_name;main;0,0.3;8,4;]" ..
"list[current_player;main;0,4.85;8,1;]" ..
"list[current_player;main;0,6.08;8,3;8]" ..
"listring[current_name;main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
local filler = {'default:apple 10', 'default:coal_lump 99', 'default:obsidian_shard', 'farming:seed_cotton 99', 'farming:seed_wheat 99', 'default:junglewood 99', 'default:acacia_wood 99', 'default:glass 99', 'default:obsidian_glass 10', 'default:meselamp 5', 'fun_caves:moon_juice 10', 'default:sword_diamond', 'default:axe_diamond', 'default:paper 25', 'default:book 10', 'default:mese_crystal_fragment'}
if minetest.registered_entities['mobs_monster:sand_monster'] then
filler[#filler+1] = 'mobs_monster:sand_monster'
end
local gems = {'fun_caves:moonstone', 'fun_caves:coral_gem', 'fun_caves:garnet', 'fun_caves:aquamarine', 'fun_caves:sky_iron'}
local newnode = fun_caves.clone_node("default:chest")
newnode.description = "Treasure Casket"
newnode.light_source = 1
newnode.on_construct = nil
newnode.drop = 'default:chest'
newnode.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if not (pos and clicker) then
return
end
local meta = minetest.get_meta(pos)
if not meta then
return
end
local ready = meta:get_string('formspec')
if ready == '' then
if math.random(10) == 1 then
meta:set_string("formspec", chest_formspec)
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
for i = 1, math.random(12) do
inv:add_item('main', filler[math.random(#filler)])
end
inv:add_item('main', gems[math.random(#gems)])
else
meta:set_string("formspec", 'del')
clicker:set_hp(clicker:get_hp() - 2)
minetest.remove_node(pos)
end
end
end
minetest.register_node("fun_caves:casket", newnode)
local pyramid_biomes = {}
for _, i in pairs({"rainforest", "desert", "desertstone_grassland", }) do
pyramid_biomes[i] = true
end
local pyramid_noise_1 = {offset = 0, scale = 1, seed = -6012, spread = {x = 20, y = 10, z = 20}, octaves = 6, persist = 1, lacunarity = 2}
fun_caves.pyramid = function(minp, maxp, data, p2data, area, biomemap, biome_ids, node, heightmap)
if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then
return
end
if math.random(20) ~= 1 then
return
end
if biomemap then
local biome = biome_ids[biomemap[3240]]
if not (fun_caves.pyramids_everywhere or pyramid_biomes[biome]) then
return
end
elseif math.random(5) ~= 1 then
return
end
local min_y = 80
local index = 0
for z = minp.z, maxp.z do
local dz = z - minp.z
for x = minp.x, maxp.x do
local dx = x - minp.x
index = index + 1
if dz > 8 and dz < 72 and dx > 8 and dx < 72 and heightmap[index] - minp.y < 0 then
return
elseif heightmap[index] - minp.y < min_y then
min_y = heightmap[index] - minp.y
end
end
end
if min_y >= 72 or heightmap[3240] >= 72 then
return
end
local base_height = math.min(min_y, 35)
local csize = vector.add(vector.subtract(maxp, minp), 1)
local map_max = {x = csize.x, y = csize.y, z = csize.z}
local map_min = {x = minp.x, y = minp.y, z = minp.z}
local pyramid_1 = minetest.get_perlin_map(pyramid_noise_1, map_max):get3dMap_flat(map_min)
if not pyramid_1 then
return
end
local write = true
local p2write = false
index = 0
local index3d = 0
for z = minp.z, maxp.z do
local dz = z - minp.z
for x = minp.x, maxp.x do
local dx = x - minp.x
index = index + 1
index3d = math.floor((z - minp.z) / 5) * (csize.y) * csize.x + math.floor((x - minp.x) / 5) + 1
local ivm = area:index(x, minp.y, z)
for y = minp.y, maxp.y do
local dy = y - minp.y
if dy >= base_height + 3 and dy <= base_height + 37 - math.max(math.abs(dx - 40), math.abs(dz - 40)) and pyramid_1[index3d] > 0 then
if data[ivm - area.ystride] == node['fun_caves:pyramid_1'] and math.random(50) == 1 then
data[ivm] = node['fun_caves:casket']
else
data[ivm] = node['air']
end
elseif dy >= base_height + 3 and dy <= base_height + 37 - math.max(math.abs(dx - 40), math.abs(dz - 40)) then
data[ivm] = node['fun_caves:pyramid_1']
elseif dy >= base_height and dy <= base_height + 40 - math.max(math.abs(dx - 40), math.abs(dz - 40)) then
data[ivm] = node['default:sandstone_block']
end
ivm = ivm + area.ystride
if dy % 5 == 0 then
index3d = index3d + csize.x
end
end
end
end
return write, p2write
end

View file

@ -1,56 +0,0 @@
local original_register_craft = minetest.register_craft
local craft_list = {}
minetest.register_craft = function(recipe)
craft_list[#craft_list+1] = recipe
original_register_craft(recipe)
end
local function get_name(inp)
inp = string.gsub(inp, ' [0-9]$', '')
local item = minetest.registered_items[inp]
if item and item.description then
return item.description
end
return inp
end
fun_caves.print_recipes = function()
--print(dump(recipe))
table.sort(craft_list, function(a, b)
if a.output and b.output and a.output < b.output then
return true
end
end)
for _, recipe in pairs(craft_list) do
if recipe.type == 'cooking' then
local input = get_name(recipe.recipe)
local output = get_name(recipe.output)
print('Cook '..input..' to produce '..output..'.')
elseif recipe.type == 'shapeless' then
local inputs = {}
for _, input in pairs(recipe.recipe) do
inputs[#inputs+1] = get_name(input)
end
local output = get_name(recipe.output)
print('Combine '..table.concat(inputs, ', ')..' to produce '..output..'.')
elseif recipe.type == 'fuel' then
-- nop
else
local output = get_name(recipe.output)
print('Combine the following to produce '..output..':')
for _, line in pairs(recipe.recipe) do
local out = {}
for _, input in pairs(line) do
input = get_name(input)
if input == '' then
input = '[empty]'
end
out[#out+1] = input
end
print(' '..table.concat(out, ', '))
end
end
print()
end
end

View file

@ -1,23 +0,0 @@
# Set to false if you're using an armor mod.
fun_caves_use_armor_elixirs (Use Armor Elixirs) bool true
# If set, you will lose the effects of elixirs when you die.
fun_caves_expire_elixir_on_death (Elixirs Expire On Death) bool true
# Unset this to remove exploding fungi from the underworld.
fun_caves_exploding_fungi (Exploding Fungi) bool true
# Unset this to make wook breakable by hand.
fun_caves_breakable_wood (Breakable Wood) bool false
# Unset this to remove primitive villages.
fun_caves_use_villages (Villages) bool true
# Set to give wooden tools to starting players.
fun_caves_starting_equipment (Starting Equipment) bool false
# Set to create pyramids in any biome.
fun_caves_pyramids_everywhere (Pyramids Everywhere) bool false
# Set to use experimental leaf decay.
fun_caves_quick_leaf_decay (Experimental Decay) bool false

View file

@ -1,100 +0,0 @@
local max_depth = 31000
local newnode = fun_caves.clone_node("default:dirt")
newnode.description = "Air"
newnode.tiles = {'fun_caves_blank.png'}
newnode.sunlight_propagates = true
newnode.use_texture_alpha = true
newnode.light_source = 14
newnode.walkable = false
newnode.buildable_to = false
newnode.pointable = false
minetest.register_node("fun_caves:airy", newnode)
local terrain_noise_1 = {offset = 10, scale = 10, seed = 4877, spread = {x = 120, y = 120, z = 120}, octaves = 3, persist = 1, lacunarity = 2}
local plant_noise = {offset = 0.0, scale = 1.0, spread = {x = 200, y = 200, z = 200}, seed = -2525, octaves = 3, persist = 0.7, lacunarity = 2.0}
local biome_noise = {offset = 0.0, scale = 1.0, spread = {x = 400, y = 400, z = 400}, seed = -1471, octaves = 3, persist = 0.5, lacunarity = 2.0}
fun_caves.skysea = function(minp, maxp, data, p2data, area, node)
if not (minp and maxp and data and p2data and area and node and type(data) == 'table' and type(p2data) == 'table') then
return
end
if minp.y ~= 8768 then
return
end
local csize = vector.add(vector.subtract(maxp, minp), 1)
local terrain_1 = minetest.get_perlin_map(terrain_noise_1, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
local plant_n = minetest.get_perlin_map(plant_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
local biome_n = minetest.get_perlin_map(biome_noise, {x=csize.x, y=csize.z}):get2dMap_flat({x=minp.x, y=minp.z})
if not (terrain_1 and plant_n and biome_n) then
return
end
local write = false
local index = 0
local index3d = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
index3d = (z - minp.z) * (csize.y) * csize.x + (x - minp.x) + 1
local ivm = area:index(x, minp.y, z)
terrain_1[index] = math.floor(terrain_1[index] + 0.5)
for y = minp.y, maxp.y do
local dy = y - minp.y
if dy == 0 then
data[ivm] = node['fun_caves:airy']
write = true
elseif dy == 32 and terrain_1[index] > 9 then
data[ivm] = node['default:wood']
write = true
elseif dy < 33 then
data[ivm] = node['default:water_source']
write = true
elseif dy == 33 and terrain_1[index] > 10 then
data[ivm] = node['default:wood']
write = true
elseif dy > 33 and dy == terrain_1[index] + 22 then
data[ivm] = node['default:dirt_with_grass']
write = true
elseif dy > 33 and dy < terrain_1[index] + 22 then
data[ivm] = node['default:dirt']
write = true
end
ivm = ivm + area.ystride
index3d = index3d + csize.x
end
end
end
local index = 0
local index3d = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
index = index + 1
local ivm = area:index(x, minp.y, z)
local cloud
--if biome_n[index] < 0 then
terrain_1[index] = math.floor(terrain_1[index] + 0.5)
if terrain_1[index] > 0 then
for y = minp.y, maxp.y do
local dy = y - minp.y
if data[ivm] == node['air'] and data[ivm - area.ystride] == node['default:dirt_with_grass'] then
end
ivm = ivm + area.ystride
end
end
end
end
return write
end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,546 +0,0 @@
local max_depth = 31000
local function teleporter(user, area, power)
if not (user and area and power and type(power) == 'number' and fun_caves.world and fun_caves.db and fun_caves.db.teleport_data and fun_caves.underzones and fun_caves.cave_noise_1 and fun_caves.cave_noise_2 and fun_caves.cave_width) then
return
end
local name = user:get_player_name()
local pos = user:getpos()
if not (name and pos and name ~= '' and type(name) == 'string') then
return
end
if not fun_caves.db.teleport_data[name] then
fun_caves.db.teleport_data[name] = {}
end
local out = io.open(fun_caves.world..'/fun_caves_data.txt','w')
if not (out and name) then
return
end
if fun_caves.db.teleport_data[name].teleported_from then
user:setpos(fun_caves.db.teleport_data[name].teleported_from)
fun_caves.db.teleport_data[name].teleported_from = nil
else
local newpos
if area == 'overworld' then
newpos = {
x = (math.random(2)*2-3)*(math.random(math.floor(max_depth/6))+power*math.floor(max_depth/6)),
y = 120,
z = (math.random(2)*2-3)*(math.random(math.floor(max_depth/6))+power*math.floor(max_depth/6))
}
elseif area == 'hell' then
newpos = {
x = pos.x + (math.random(5) - math.random(5)) * 80,
y = fun_caves.underzones[({'Caina','Phlegethos','Dis','Minauros', 'Phlegethos','Styx'})[power+1]].ceiling-30,
z = pos.z + (math.random(5) - math.random(5)) * 80,
}
elseif area == 'sky' then
newpos = {
x = pos.x + (math.random(5) - math.random(5)) * 80,
y = ({4368, 8768, 13168, 4368, 4368, 4368})[power+1]+76,
z = pos.z + (math.random(5) - math.random(5)) * 80,
}
elseif area == 'underworld' then
local good = false
local base_pos = table.copy(pos)
base_pos.y = -100
if power > 0 then
base_pos.y = fun_caves.underzones[({'Caina','Phlegethos','Dis','Minauros', 'Phlegethos','Styx'})[power]].lower_bound
end
local c1, c2
for i = 1, 1000 do
newpos = {
x = base_pos.x + (math.random(5) - math.random(5)) * 80,
y = base_pos.y - math.random(50) * 80,
z = base_pos.z + (math.random(5) - math.random(5)) * 80,
}
c1 = minetest.get_perlin(fun_caves.cave_noise_1):get3d(newpos)
c2 = minetest.get_perlin(fun_caves.cave_noise_2):get3d(newpos)
if not (c1 and c2 and type(c1) == 'number' and type(c2) == 'number') then
return
end
if c1 * c2 > fun_caves.cave_width then
newpos.y = newpos.y - 1
c1 = minetest.get_perlin(fun_caves.cave_noise_1):get3d(newpos)
c2 = minetest.get_perlin(fun_caves.cave_noise_2):get3d(newpos)
if not (c1 and c2 and type(c1) == 'number' and type(c2) == 'number') then
return
end
if c1 * c2 > fun_caves.cave_width then
good = true
break
end
end
end
if not good then
return
end
else
return
end
user:setpos(newpos)
print('Fun Caves: '..name..' teleported to ('..pos.x..','..pos.y..','..pos.z..')')
fun_caves.db.teleport_data[name].teleported_from = pos
user:set_physics_override({gravity=0.1})
minetest.after(20, function()
user:set_physics_override({gravity=1})
end)
end
end
local gems = {
{gem = 'Moonstone', teleport = 'sky', ore = true},
{gem = 'Garnet', teleport = 'underworld', ore = true},
{gem = 'Coral Gem', teleport = 'hell'},
{gem = 'Aquamarine', teleport = 'overworld', ore = true},
}
for _, gem in pairs(gems) do
if not gem.lower then
gem.lower = gem.gem:lower()
gem.lower = gem.lower:gsub(' ', '_')
end
minetest.register_craftitem("fun_caves:"..gem.lower, {
description = gem.gem,
drawtype = "plantlike",
paramtype = "light",
tiles = {'fun_caves_'..gem.lower..'.png'},
inventory_image = 'fun_caves_'..gem.lower..'.png',
groups = {dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
})
if gem.ore then
minetest.register_node('fun_caves:stone_with_'..gem.lower..'s', {
description = gem.gem..' Ore',
tiles = {'default_stone.png^fun_caves_mineral_'..gem.lower..'.png'},
groups = {cracky = 1},
drop = 'fun_caves:'..gem.lower..'',
sounds = default.node_sound_stone_defaults(),
})
minetest.register_ore({
ore_type = "scatter",
ore = 'fun_caves:stone_with_'..gem.lower..'s',
wherein = "default:stone",
clust_scarcity = 21 * 21 * 21,
clust_num_ores = 1,
clust_size = 1,
y_min = -31000,
y_max = 31000,
})
end
end
local metals = {
{
base = 'copper',
crucible = 'copper_crucible',
crucible_desc = 'Crucible of Copper',
level = 0,
metal = 'Copper',
node = 'Very Pure Copper',
node_lower = 'pure_copper',
tile = 'default_copper_ingot.png',
},
{
base = 'meteorite',
base_desc = 'Iron Meteorite',
crucible = 'meteoritic_iron_crucible',
crucible_desc = 'Crucible of Meteoritic Iron',
level = 0,
metal = 'Iron',
node = 'Sky Iron',
tile = 'default_steel_ingot.png',
},
{
base = 'eternal_ice_crystal',
base_desc = 'Eternal Ice Crystal',
crucible = 'metallic_ice_crucible',
crucible_desc = 'Crucible of Metallic Ice',
level = 1,
metal = 'Metallic Ice',
node = 'metallic_ice',
tile = 'default_steel_ingot.png^[colorize:#385B72:150',
},
}
for _, metal in pairs(metals) do
if not metal.lower then
metal.lower = metal.metal:lower()
metal.lower = metal.lower:gsub(' ', '_')
end
if not metal.node_lower then
metal.node_lower = metal.node:lower()
metal.node_lower = metal.node_lower:gsub(' ', '_')
end
local full_base
if minetest.registered_items['default:'..metal.base..'_ingot'] then
full_base = 'default:'..metal.base..'_ingot'
else
full_base = 'fun_caves:'..metal.base
minetest.register_craftitem(full_base, {
description = metal.base_desc,
drawtype = "plantlike",
paramtype = "light",
tiles = {'fun_caves_'..metal.base..'.png'},
inventory_image = 'fun_caves_'..metal.base..'.png',
groups = {dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
})
end
minetest.register_craftitem("fun_caves:"..metal.node_lower, {
description = metal.node,
drawtype = "plantlike",
paramtype = "light",
tiles = {metal.tile},
inventory_image = metal.tile,
groups = {dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
})
minetest.register_craftitem("fun_caves:"..metal.crucible, {
description = metal.crucible_desc,
drawtype = "plantlike",
paramtype = "light",
tiles = {"fun_caves_crucible.png"},
inventory_image = "fun_caves_crucible.png",
groups = {dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
})
minetest.register_craft({
output = 'fun_caves:'..metal.crucible,
recipe = {
{full_base, full_base, full_base},
{full_base, full_base, full_base},
{full_base, 'fun_caves:crucible', full_base},
}
})
minetest.register_craft({
type = "cooking",
output = "fun_caves:"..metal.node_lower,
recipe = "fun_caves:"..metal.crucible,
cooktime = 30,
})
if metal.base ~= 'copper' then
for _, gem in pairs(gems) do
minetest.register_craftitem('fun_caves:tesseract_'..metal.lower..'_'..gem.lower, {
description = metal.metal..' and '..gem.gem..' Tesseract',
drawtype = "plantlike",
paramtype = "light",
tiles = {'fun_caves_tesseract_'..metal.lower..'_'..gem.lower..'.png'},
inventory_image = 'fun_caves_tesseract_'..metal.lower..'_'..gem.lower..'.png',
groups = {dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
on_use = function(itemstack, user, pointed_thing)
teleporter(user, gem.teleport, metal.level)
end,
})
minetest.register_alias('fun_caves:teleporter_'..metal.lower..'_'..gem.lower, 'fun_caves:tesseract_'..metal.lower..'_'..gem.lower)
minetest.register_craft({
output = 'fun_caves:tesseract_'..metal.lower..'_'..gem.lower,
recipe = {
{'fun_caves:'..metal.node_lower, 'fun_caves:pure_copper', 'fun_caves:'..metal.node_lower},
{'fun_caves:'..gem.lower, 'fun_caves:'..gem.lower, 'fun_caves:'..gem.lower},
{'fun_caves:'..metal.node_lower, 'default:obsidian_shard', 'fun_caves:'..metal.node_lower},
}
})
end
end
end
minetest.register_craft({
type = "cooking",
output = "fun_caves:coral_gem",
recipe = "fun_caves:precious_coral",
cooktime = 5,
})
minetest.register_craftitem("fun_caves:crucible", {
description = "Crucible",
drawtype = "plantlike",
paramtype = "light",
tiles = {"fun_caves_crucible.png"},
inventory_image = "fun_caves_crucible.png",
groups = {dig_immediate = 3},
sounds = default.node_sound_stone_defaults(),
})
minetest.register_craft({
output = 'fun_caves:crucible',
recipe = {
{'default:clay', '', 'default:clay'},
{'default:clay', '', 'default:clay'},
{'', 'default:clay', ''},
}
})
local function translocate(pos, node, clicker, itemstack, pointed_thing)
if not (pos and clicker and fun_caves.db.translocators) then
return
end
local meta = minetest.get_meta(pos)
if not meta then
return
end
local id = meta:get_string('id')
local owner = meta:get_string('owner')
if not (id and tonumber(id)) then
return
end
local pair = fun_caves.db.translocators[tonumber(id)]
if not pair or #pair < 2 then
return
end
local pos2
if minetest.serialize(pair[2]) == minetest.serialize(pos) then
pos2 = pair[1]
else
pos2 = pair[2]
end
if pos2 then
clicker:setpos(pos2)
-- If the mated translocator doesn't exist, recreate it.
minetest.after(1, function()
if not owner then
return
end
-- If we can't get the node, we can't set it.
local node = minetest.get_node_or_nil(pos2)
if not node or node.name == 'fun_caves:translocator' then
return
end
minetest.set_node(pos2, {name = 'fun_caves:translocator'})
local meta = minetest.get_meta(pos2)
if not meta then
return
end
meta:set_string('id', id)
meta:set_string('owner', owner)
print('Fun Caves: recreated a missing translocator')
end)
end
end
local function trans_use(itemstack, user, pointed_thing)
if not (itemstack and user) then
return
end
local data = minetest.deserialize(itemstack:get_metadata())
if not (data and data.id) then
return
end
local player_name = user:get_player_name()
minetest.chat_send_player(player_name, "You see a serial number: "..data.id)
end
local function trans_place(itemstack, placer, pointed_thing)
if not (itemstack and placer and pointed_thing and fun_caves.db.translocators) then
return
end
local data = minetest.deserialize(itemstack:get_metadata())
if not (data and data.id and tonumber(data.id)) then
return
end
local player_name = placer:get_player_name()
if not data.owner or data.owner == '' then
print('Fun Caves: Unowned translocator has been assigned to placer.')
data.owner = player_name
end
local pos = pointed_thing.above
local pair = fun_caves.db.translocators[tonumber(data.id)]
if not pair or #pair > 1 then
print('* Fun Caves: high error in translocator storage')
return
end
local ret, place_good = minetest.item_place_node(itemstack, placer, pointed_thing)
if place_good then
pair[#pair+1] = pos
local meta = minetest.get_meta(pos)
if not meta then
return
end
meta:set_string('id', data.id)
meta:set_string('owner', data.owner)
end
return ret, place_good
end
local function trans_dig(pos, node, digger)
if not (pos and node and digger and fun_caves.db.translocators) then
return
end
local player_name = digger:get_player_name()
if minetest.is_protected(pos, player_name) then
return
end
local meta = minetest.get_meta(pos)
if not meta then
return
end
local id = meta:get_string('id')
local owner = meta:get_string('owner')
if owner == '' then
owner = player_name
print('Fun Caves: Unowned translocator has been assigned to taker.')
end
local data = { id = id, owner = owner }
if not (data and data.id and data.owner == player_name) then
local privs = minetest.check_player_privs(player_name, {server=true})
if privs then
print('Fun Caves: Admin has destroyed ['..data.owner..']\'s translocator')
minetest.remove_node(pos)
end
return
end
local pair = fun_caves.db.translocators[tonumber(data.id)]
if not pair or #pair < 1 then
print('* Fun Caves: low error in translocator storage')
minetest.remove_node(pos)
return
end
local inv = digger:get_inventory()
local item = ItemStack(node.name)
local data_str = minetest.serialize(data)
item:set_metadata(data_str)
if not inv:room_for_item('main', item) or not inv:add_item('main', item) then
return
end
minetest.remove_node(pos)
if #pair > 1 and minetest.serialize(pair[2]) == minetest.serialize(pos) then
table.remove(pair, 2)
else
table.remove(pair, 1)
end
end
local function trans_dest(pos)
if not (pos and fun_caves.db.translocators) then
return
end
local meta = minetest.get_meta(pos)
if not meta then
return
end
local id = meta:get_string('id')
local owner = meta:get_string('owner')
if not (id and owner) then
return
end
if not fun_caves.db.translocators[tonumber(id)] then
return
end
local pair = table.copy(fun_caves.db.translocators[tonumber(id)])
minetest.after(1, function()
if not fun_caves.db.translocators[tonumber(id)] or #fun_caves.db.translocators[tonumber(id)] < #pair then
return
end
minetest.set_node(pos, {name = 'fun_caves:translocator'})
local meta = minetest.get_meta(pos)
if not meta then
return
end
meta:set_string('id', id)
meta:set_string('owner', owner)
print('Fun Caves: recreated a destroyed translocator')
end)
end
minetest.register_node("fun_caves:translocator", {
visual = 'mesh',
mesh = "fun_caves_translocator.obj",
description = 'Translocator',
tiles = {'fun_caves_translocator.png'},
drawtype = 'mesh',
sunlight_propagates = true,
walkable = false,
paramtype = 'light',
paramtype2 = 'facedir',
use_texture_alpha = true,
groups = {cracky = 3, oddly_breakable_by_hand = 3},
light_source = 13,
sounds = default.node_sound_glass_defaults(),
stack_max = 1,
selection_box = {
type = "fixed",
fixed = {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}
},
on_rightclick = translocate,
on_use = trans_use,
on_place = trans_place,
on_dig = trans_dig,
on_destruct = trans_dest,
})
for _, gem in pairs(gems) do
minetest.register_craft({
output = 'fun_caves:translocator 2',
type = 'shapeless',
recipe = {
'fun_caves:'..gem.lower,
'default:mese_crystal',
}
})
end
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
if not (itemstack and player and fun_caves.db.translocators and itemstack:get_name() == "fun_caves:translocator") then
return
end
local data = {}
data.id = string.format('%d', #fun_caves.db.translocators+1)
data.owner = player:get_player_name()
fun_caves.db.translocators[#fun_caves.db.translocators+1] = {}
local data_str = minetest.serialize(data)
itemstack:set_metadata(data_str)
end)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 818 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 949 B

Some files were not shown because too many files have changed in this diff Show more