Remove everything except the caves.
505
LICENSE
|
@ -1,23 +1,504 @@
|
||||||
All of the goblin code and art are taken from FreeLikeGNU's Goblins mod,
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
distributed under the CC-by-SA license.
|
Version 2.1, February 1999
|
||||||
|
|
||||||
https://forum.minetest.net/viewtopic.php?f=9&t=13004&hilit=goblins
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
http://creativecommons.org/licenses/by-sa/3.0/
|
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
|
Preamble
|
||||||
mod, distributed under the WTFPL license.
|
|
||||||
|
|
||||||
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
|
To protect each distributor, we want to make it very clear that
|
||||||
historic reasons.
|
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!
|
||||||
|
|
13
README.md
|
@ -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.
|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The source is available on github.
|
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
|
||||||
|
|
662
abms.lua
|
@ -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
|
-- Abms
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
-- player surface damage and hunger
|
-- player surface damage
|
||||||
local dps_delay = 3
|
local dps_delay = 3
|
||||||
|
|
||||||
local last_dps_check = 0
|
local last_dps_check = 0
|
||||||
local cold_delay = 5
|
local cold_delay = 5
|
||||||
local monster_delay = 3
|
local dps_count = cold_delay
|
||||||
local hunger_delay = 60
|
|
||||||
local dps_count = hunger_delay
|
|
||||||
local dungeon_monster_density = 5
|
|
||||||
local players_in_orbit = {}
|
|
||||||
|
|
||||||
local mushrooms = {"flowers:mushroom_brown", "flowers:mushroom_red"}
|
local mushrooms = {"flowers:mushroom_brown", "flowers:mushroom_red"}
|
||||||
|
local time_factor = (fun_caves_mod.time_factor or 10)
|
||||||
local time_factor = (fun_caves.time_factor or 10)
|
local light_max = (fun_caves_mod.light_max or 10)
|
||||||
local light_max = (fun_caves.light_max or 10)
|
|
||||||
|
|
||||||
|
|
||||||
-- fungal tree nodes
|
-- fungal tree nodes
|
||||||
|
@ -37,7 +35,7 @@ end
|
||||||
fungal_nodes[#fungal_nodes+1] = {name = 'fun_caves:fungal_tree_fruit'}
|
fungal_nodes[#fungal_nodes+1] = {name = 'fun_caves:fungal_tree_fruit'}
|
||||||
|
|
||||||
local fungi_to_explode = {} -- see below
|
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
|
if not exploding_fungi then
|
||||||
exploding_fungi = {}
|
exploding_fungi = {}
|
||||||
end
|
end
|
||||||
|
@ -58,70 +56,26 @@ spike_soil['fun_caves:black_sand'] = true
|
||||||
-- all the fun_caves globalstep functions
|
-- all the fun_caves globalstep functions
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
local hot_stuff = {"group:surface_hot"}
|
local hot_stuff = {"group:surface_hot"}
|
||||||
local traps = {"group:trap"}
|
|
||||||
local cold_stuff = {"group:surface_cold"}
|
local cold_stuff = {"group:surface_cold"}
|
||||||
local poison_stuff = {"group:poison"}
|
local poison_stuff = {"group:poison"}
|
||||||
local gravity_off = {gravity = 0.1}
|
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
|
||||||
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 = {}
|
|
||||||
|
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
if not (dtime and type(dtime) == 'number') then
|
if not (dtime and type(dtime) == 'number') then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not (fun_caves.db.status and fun_caves.registered_status) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local time = minetest.get_gametime()
|
local time = minetest.get_gametime()
|
||||||
if not (time and type(time) == 'number') then
|
if not (time and type(time) == 'number') then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Trap check
|
-- Execute only after an interval.
|
||||||
if last_dps_check and time - last_dps_check < 1 then
|
if not last_dps_check or time - last_dps_check < dps_delay then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
|
|
||||||
local players = minetest.get_connected_players()
|
local players = minetest.get_connected_players()
|
||||||
if not (players and type(players) == 'table') then
|
if not (players and type(players) == 'table') then
|
||||||
return
|
return
|
||||||
|
@ -133,182 +87,53 @@ minetest.register_globalstep(function(dtime)
|
||||||
pos = vector.round(pos)
|
pos = vector.round(pos)
|
||||||
local player_name = player:get_player_name()
|
local player_name = player:get_player_name()
|
||||||
|
|
||||||
local minp = vector.subtract(pos, 2)
|
-- environmental damage
|
||||||
local maxp = vector.add(pos, 2)
|
if fun_caves_mod.DEBUG and player:get_hp() < 20 then
|
||||||
local counts = minetest_find_nodes_in_area(minp, maxp, traps)
|
-- Regenerate the player while testing.
|
||||||
if counts and type(counts) == 'table' and #counts > 0 then
|
print("HP: "..player:get_hp())
|
||||||
for _, tpos in ipairs(counts) do
|
player:set_hp(20)
|
||||||
local node = minetest.get_node_or_nil(tpos)
|
return
|
||||||
if not node then
|
else
|
||||||
return
|
local minp = vector.subtract(pos, 0.5)
|
||||||
end
|
local maxp = vector.add(pos, 0.5)
|
||||||
if node.name == 'fun_caves:stone_with_coal_trap' then
|
|
||||||
minetest.set_node(tpos, {name="fire:basic_flame"})
|
|
||||||
|
|
||||||
local hp = player:get_hp()
|
-- ... from standing on or near hot objects.
|
||||||
if hp > 0 then
|
local counts = minetest_find_nodes_in_area(minp, maxp, hot_stuff)
|
||||||
player:set_hp(hp - 1)
|
if not (counts and type(counts) == 'table') then
|
||||||
end
|
return
|
||||||
elseif node.name == 'fun_caves:stone_with_diamond_trap' then
|
end
|
||||||
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()
|
if #counts > 1 then
|
||||||
sparking[player_name] = nil
|
player:set_hp(player:get_hp() - 1)
|
||||||
end)
|
end
|
||||||
end
|
|
||||||
else
|
|
||||||
minetest.remove_node(tpos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Execute only after an interval.
|
-- ... from standing on or near poison.
|
||||||
if last_dps_check and time - last_dps_check > dps_delay then
|
local counts = minetest_find_nodes_in_area(minp, maxp, poison_stuff)
|
||||||
if pos.y >= 11168 and pos.y <= 15168 then
|
if not (counts and type(counts) == 'table') then
|
||||||
if not players_in_orbit[player_name] then
|
return
|
||||||
player:set_physics_override(gravity_off)
|
end
|
||||||
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 #counts > 1 then
|
||||||
if fun_caves.DEBUG and player:get_hp() < 20 then
|
player:set_hp(player:get_hp() - 1)
|
||||||
-- Regenerate the player while testing.
|
end
|
||||||
print("HP: "..player:get_hp())
|
|
||||||
player:set_hp(20)
|
|
||||||
return
|
|
||||||
else
|
|
||||||
local minp = vector.subtract(pos, 0.5)
|
|
||||||
local maxp = vector.add(pos, 0.5)
|
|
||||||
|
|
||||||
-- Remove status effects.
|
-- ... from standing on or near cold objects (less often).
|
||||||
local status = fun_caves.db.status[player_name]
|
if dps_count % cold_delay == 0 then
|
||||||
for status_name, status_param in pairs(status) do
|
counts = minetest_find_nodes_in_area(minp, maxp, cold_stuff)
|
||||||
local def = fun_caves.registered_status[status_name]
|
if not (counts and type(counts) == 'table') then
|
||||||
if not def then
|
return
|
||||||
print('Fun Caves: Error - unregistered status ' .. status_name)
|
end
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
local remove
|
if #counts > 1 then
|
||||||
if type(status_param.remove) == 'number' then
|
player:set_hp(player:get_hp() - 1)
|
||||||
if status_param.remove < time then
|
end
|
||||||
remove = true
|
end
|
||||||
end
|
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
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #counts > 1 then
|
|
||||||
player:set_hp(player:get_hp() - 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ... from standing on or near poison.
|
|
||||||
local counts = minetest_find_nodes_in_area(minp, maxp, poison_stuff)
|
|
||||||
if not (counts and type(counts) == 'table') then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #counts > 1 then
|
|
||||||
player:set_hp(player:get_hp() - 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ... from standing on or near cold objects (less often).
|
|
||||||
if dps_count % cold_delay == 0 then
|
|
||||||
counts = minetest_find_nodes_in_area(minp, maxp, cold_stuff)
|
|
||||||
if not (counts and type(counts) == 'table') then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if #counts > 1 then
|
|
||||||
player:set_hp(player:get_hp() - 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ... 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
|
end
|
||||||
|
|
||||||
-- Set this outside of the player loop, to affect everyone.
|
-- Set this outside of the player loop, to affect everyone.
|
||||||
if dps_count % hunger_delay == 0 then
|
if dps_count % cold_delay < 1 then
|
||||||
dps_count = hunger_delay
|
dps_count = cold_delay
|
||||||
end
|
end
|
||||||
|
|
||||||
last_dps_check = minetest.get_gametime()
|
last_dps_check = minetest.get_gametime()
|
||||||
|
@ -323,19 +148,6 @@ end)
|
||||||
-- destruction
|
-- 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({
|
minetest.register_abm({
|
||||||
nodenames = {"fun_caves:hot_cobble",},
|
nodenames = {"fun_caves:hot_cobble",},
|
||||||
neighbors = {"group:water"},
|
neighbors = {"group:water"},
|
||||||
|
@ -364,7 +176,7 @@ minetest.register_abm({
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
fun_caves.soft_boom(pos)
|
fun_caves_mod.soft_boom(pos)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -385,285 +197,20 @@ minetest.register_abm({
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_abm({
|
--minetest.register_abm({
|
||||||
nodenames = {"fire:basic_flame"},
|
-- nodenames = {"fire:basic_flame"},
|
||||||
interval = 2 * time_factor,
|
-- interval = 2 * time_factor,
|
||||||
chance = 50,
|
-- chance = 50,
|
||||||
action = function(p0, node, _, _)
|
-- action = function(p0, node, _, _)
|
||||||
minetest.remove_node(p0)
|
-- minetest.remove_node(p0)
|
||||||
end,
|
-- 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
|
-- 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
|
-- fungal spread
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
nodenames = fungal_tree_leaves,
|
nodenames = fungal_tree_leaves,
|
||||||
|
@ -828,7 +375,7 @@ minetest.register_abm({
|
||||||
|
|
||||||
-- Spike spread and death
|
-- Spike spread and death
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
nodenames = fun_caves.hot_spikes,
|
nodenames = fun_caves_mod.hot_spikes,
|
||||||
interval = 40 * time_factor,
|
interval = 40 * time_factor,
|
||||||
chance = 2000,
|
chance = 2000,
|
||||||
action = function(pos, node)
|
action = function(pos, node)
|
||||||
|
@ -836,17 +383,17 @@ minetest.register_abm({
|
||||||
return
|
return
|
||||||
end
|
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
|
return
|
||||||
end
|
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
|
if not spike_num then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if spike_num < #fun_caves.hot_spikes then
|
if spike_num < #fun_caves_mod.hot_spikes then
|
||||||
minetest.set_node(pos, {name=fun_caves.hot_spikes[spike_num+1]})
|
minetest.set_node(pos, {name=fun_caves_mod.hot_spikes[spike_num+1]})
|
||||||
return
|
return
|
||||||
end
|
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
|
-- explosive functions
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
@ -1010,6 +492,7 @@ local function destroy(pos, cid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local math_random = math.random
|
||||||
local function explode(pos, radius)
|
local function explode(pos, radius)
|
||||||
if not (pos and radius and type(radius) == 'number') then
|
if not (pos and radius and type(radius) == 'number') then
|
||||||
return
|
return
|
||||||
|
@ -1027,7 +510,6 @@ local function explode(pos, radius)
|
||||||
|
|
||||||
local c_air = minetest.get_content_id("air")
|
local c_air = minetest.get_content_id("air")
|
||||||
|
|
||||||
local math_random = math.random
|
|
||||||
for z = -radius, radius do
|
for z = -radius, radius do
|
||||||
for y = -radius, 4*radius do
|
for y = -radius, 4*radius do
|
||||||
local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
fun_caves.soft_boom = function(pos)
|
fun_caves_mod.soft_boom = function(pos)
|
||||||
if not pos then
|
if not pos then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -1118,10 +600,6 @@ fun_caves.soft_boom = function(pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--local function burn(pos)
|
|
||||||
-- minetest.get_node_timer(pos):start(1)
|
|
||||||
--end
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
-- testing only -- remove before distribution
|
-- testing only -- remove before distribution
|
||||||
|
|
111
asteroids.lua
|
@ -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
|
|
106
castles.lua
|
@ -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
|
|
117
cavegen.lua
|
@ -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
|
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_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.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_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}
|
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)
|
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' and fun_caves.underzones) then
|
if not (minp and maxp and data and area and node and type(data) == 'table') then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
||||||
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
|
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 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_1, cave_2, cave_3
|
||||||
local cave_2 = minetest.get_perlin_map(fun_caves.cave_noise_2, map_max):get3dMap_flat(map_min)
|
cave_1 = minetest.get_perlin_map(fun_caves_mod.cave_noise_1, 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})
|
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
|
if not (cave_1 and cave_2 and cave_3) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local write = false
|
|
||||||
|
|
||||||
local index = 0
|
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 index3d = 0
|
||||||
local cave_width = fun_caves.cave_width
|
local cave_width = fun_caves_mod.cave_width
|
||||||
local styx_sea_level = fun_caves.underzones['Styx'].sealevel
|
local write
|
||||||
for z = minp.z, maxp.z do
|
for z = minp.z, maxp.z do
|
||||||
for x = minp.x, maxp.x do
|
for x = minp.x, maxp.x do
|
||||||
index = index + 1
|
index = index + 1
|
||||||
index3d = (z - minp.z) * (csize.y + 2) * csize.x + (x - minp.x) + 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 height = heightmap[index]
|
||||||
|
for y = minp.y, maxp.y do
|
||||||
local column = 0
|
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
|
||||||
if underzone then
|
data[ivm] = node["air"]
|
||||||
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
|
|
||||||
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
|
write = true
|
||||||
if y > 0 and cave_3[index] < 1 and y == height then
|
if y > 0 and cave_3[index] < 1 and y == height then
|
||||||
-- Clear the air above a cave mouth.
|
-- 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
|
end
|
||||||
end
|
end
|
||||||
|
return write
|
||||||
return write
|
|
||||||
end
|
end
|
||||||
|
|
279
chat.lua
|
@ -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,
|
|
||||||
})
|
|
235
cloudgen.lua
|
@ -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
|
|
428
deco.lua
|
@ -1,259 +1,221 @@
|
||||||
-- I like having different stone scattered about. Sandstone forms
|
-- Fun_Caves deco.lua
|
||||||
-- in layers. Desert stone... doesn't exist, but let's assume it's
|
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||||
-- another sedementary rock and place it similarly.
|
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||||
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})
|
|
||||||
|
|
||||||
|
|
||||||
if not fun_caves.breakable_wood then
|
dofile(fun_caves_mod.path .. "/nodes.lua")
|
||||||
print('* Fun Caves: Wood is NOT breakable by hand.')
|
dofile(fun_caves_mod.path .. "/fungal_tree.lua")
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
minetest.register_node("fun_caves:sand_with_rocks", {
|
local deco_depth = -30 -- place cave stuff this far beneath the surface
|
||||||
description = "Sand and rocks",
|
local water_level = 1
|
||||||
tiles = {"fun_caves_sand_with_rocks.png"},
|
local fluid_compression = -200 -- the depth to start planting lava/water
|
||||||
groups = {crumbly = 3, falling_node = 1, sand = 1},
|
local max_depth = 31000
|
||||||
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})
|
|
||||||
|
|
||||||
|
|
||||||
if fun_caves.use_bi_hi then
|
local csize
|
||||||
local biome_mod = {
|
local node_match_cache = {}
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
minetest.register_biome({
|
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}
|
||||||
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,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
minetest.register_decoration({
|
-- Air needs to be placed prior to decorations.
|
||||||
deco_type = "simple",
|
fun_caves_mod.decogen = function(minp, maxp, data, area, node, heightmap)
|
||||||
place_on = {"default:dirt_with_grass"},
|
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
|
||||||
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
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Dimensions of data array.
|
csize = vector.add(vector.subtract(maxp, minp), 1)
|
||||||
local s = {size={x=width, y=height, z=depth}}
|
|
||||||
s.data = {}
|
|
||||||
|
|
||||||
for z = 0,depth-1 do
|
local map_max = {x = csize.x, y = csize.y + 2, z = csize.z}
|
||||||
for y = 0,height-1 do
|
local map_min = {x = minp.x, y = minp.y - 1, z = minp.z}
|
||||||
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
|
|
||||||
end
|
|
||||||
|
|
||||||
s.yslice_prob = {}
|
local biome_n = minetest.get_perlin_map(biome_noise, map_max):get3dMap_flat(map_min)
|
||||||
|
|
||||||
return s
|
local write
|
||||||
end
|
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
|
||||||
|
|
||||||
fun_caves.schematics = {}
|
for z = minp.z, maxp.z do
|
||||||
do
|
for x = minp.x, maxp.x do
|
||||||
local w, h, d = 5, 8, 5
|
index = index + 1
|
||||||
local s = fun_caves.schematic_array(w, h, d)
|
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 = 0, math.floor(h/2)-1 do
|
for y = minp.y-1, maxp.y+1 do
|
||||||
s.data[2*d*h + y*d + 2 + 1].name = 'default:tree'
|
if y <= height + deco_depth and (height < max_depth or y < 0) then
|
||||||
s.data[2*d*h + y*d + 2 + 1].param1 = 255
|
for deco_non_loop = 1, 1 do
|
||||||
end
|
if not (data[ivm] == node["air"] or data[ivm] == node["default:stone"]) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
for z = 0, d-1 do
|
local biome
|
||||||
for y = math.floor(h/2), h-1 do
|
local biome_val = biome_n[index3d]
|
||||||
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
|
-- Compress biomes at the surface to avoid fluids.
|
||||||
if math.random(2) == 1 then
|
if y > fluid_compression then
|
||||||
s.data[z*d*h + y*d + x + 1].name = 'fun_caves:leaves_black'
|
biome_val = biome_val / math_max(1, math_log(y - fluid_compression))
|
||||||
else
|
end
|
||||||
s.data[z*d*h + y*d + x + 1].name = 'fun_caves:sticks_default'
|
|
||||||
end
|
for _, bi in pairs(fun_caves_mod.cave_biomes) do
|
||||||
|
if biome_val >= bi.biome_val_low and biome_val < bi.biome_val_high then
|
||||||
if y == h-1 or x == 0 or x == w-1 or z == 0 or z == d-1 then
|
biome = bi
|
||||||
s.data[z*d*h + y*d + x + 1].param1 = 150
|
end
|
||||||
else
|
end
|
||||||
s.data[z*d*h + y*d + x + 1].param1 = 225
|
--biome = fun_caves_mod.cave_biomes['salt']
|
||||||
|
|
||||||
|
if not biome then
|
||||||
|
print(("* Fun Caves: Error in biome selection: %s"):format(biome_val))
|
||||||
|
biome = fun_caves_mod.cave_biomes['algae']
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local node_below
|
||||||
|
if y > minp.y then
|
||||||
|
node_below = data[ivm - area.ystride]
|
||||||
|
end
|
||||||
|
local node_above = data[ivm + area.ystride]
|
||||||
|
|
||||||
|
if data[ivm] == node["default:stone"] then
|
||||||
|
if node_above == node["air"] and biome and biome.dirt and math_random(biome.dirt_chance) == 1 then
|
||||||
|
data[ivm] = node[biome.dirt]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
local air_above = false
|
||||||
|
for i = 1, biome.stone_depth do
|
||||||
|
if data[ivm + area.ystride * i] == node["air"] then
|
||||||
|
air_above = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if air_above then
|
||||||
|
if biome and biome.deco and math_random(biome.deco_chance) == 1 then
|
||||||
|
data[ivm] = node[biome.deco]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
else
|
||||||
|
data[ivm] = node[biome.floor_node]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local air_below = false
|
||||||
|
for i = 1, biome.stone_depth do
|
||||||
|
if data[ivm - area.ystride * i] == node["air"] then
|
||||||
|
air_below = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prevent server-crashing sandslides.
|
||||||
|
if not air_above and biome.floor_node == "default:sand" then
|
||||||
|
data[ivm] = node["default:sandstone"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
if air_below then
|
||||||
|
if biome and biome.deco and math_random(biome.deco_chance) == 1 then
|
||||||
|
data[ivm] = node[biome.deco]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
else
|
||||||
|
data[ivm] = node[biome.ceiling_node]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if data[ivm] == node["air"] and y < maxp.y then
|
||||||
|
-- hanging down
|
||||||
|
-- stone hasn't yet been changed
|
||||||
|
if biome and biome.stalactite and node_above == node["default:stone"] and math_random(biome.stalactite_chance) == 1 then
|
||||||
|
data[ivm] = node[biome.stalactite]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fluids
|
||||||
|
if y > minp.y and biome and biome.fluid and node_below == node[biome.floor_node] and math_random(biome.fluid_chance) == 1 then
|
||||||
|
data[ivm] = node[biome.fluid]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
|
||||||
|
-- standing up
|
||||||
|
elseif node_below == node[biome.floor_node] and biome and biome.stalagmite and math_random(biome.stalagmite_chance) == 1 then
|
||||||
|
if type(biome.stalagmite) == 'table' then
|
||||||
|
data[ivm] = node[biome.stalagmite[math_random(#biome.stalagmite)]]
|
||||||
|
else
|
||||||
|
data[ivm] = node[biome.stalagmite]
|
||||||
|
end
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
|
||||||
|
-- vegetation
|
||||||
|
elseif node_below == node["default:dirt"] and biome and biome.fungi then
|
||||||
|
if math_random(10) == 1 then
|
||||||
|
data[ivm] = node["flowers:mushroom_red"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
elseif math_random(10) == 1 then
|
||||||
|
data[ivm] = node["flowers:mushroom_brown"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
elseif node_above == node["air"] and math_random(10) == 1 then
|
||||||
|
data[ivm] = node["fun_caves:giant_mushroom_stem"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
elseif math_random(30) == 1 then
|
||||||
|
local air_count = 0
|
||||||
|
local j
|
||||||
|
for i = 1, 12 do
|
||||||
|
j = ivm + area.ystride * i
|
||||||
|
if j <= #data and data[j] == node["air"] then
|
||||||
|
air_count = air_count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if air_count > 5 then
|
||||||
|
fun_caves_mod.make_fungal_tree(data, area, ivm, math_random(2, math_min(air_count, 12)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif node_below == node["fun_caves:giant_mushroom_stem"] and data[ivm - area.ystride * 2] == node["fun_caves:giant_mushroom_stem"] then
|
||||||
|
data[ivm] = node["fun_caves:giant_mushroom_cap"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
elseif node_below == node["fun_caves:giant_mushroom_stem"] then
|
||||||
|
if node_above == node["air"] and math_random(3) == 1 then
|
||||||
|
data[ivm] = node["fun_caves:giant_mushroom_stem"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
else
|
||||||
|
data[ivm] = node["fun_caves:huge_mushroom_cap"]
|
||||||
|
write = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
ivm = ivm + area.ystride
|
||||||
|
index3d = index3d + csize.x
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for z = math.floor(d/2)-1, math.floor(d/2)+1, 2 do
|
return write
|
||||||
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
|
|
||||||
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['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
|
|
||||||
else
|
|
||||||
s.data[z*d*h + y*d + x + 1].param1 = 225
|
|
||||||
end
|
|
||||||
end
|
|
||||||
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")
|
|
||||||
end
|
end
|
||||||
|
|
480
deco_caves.lua
|
@ -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", ""},
|
|
||||||
},
|
|
||||||
})
|
|
255
deco_plants.lua
|
@ -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
|
|
155
deco_rocks.lua
|
@ -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)
|
|
409
decogen.lua
|
@ -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
|
@ -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 (!)
|
|
||||||
|
|
||||||
|
|
16
depends.txt
|
@ -1,17 +1,5 @@
|
||||||
default
|
default
|
||||||
|
dye
|
||||||
flowers
|
flowers
|
||||||
wool
|
vessels
|
||||||
bucket
|
|
||||||
beds
|
|
||||||
stairs
|
|
||||||
farming?
|
|
||||||
hunger?
|
|
||||||
mobs?
|
mobs?
|
||||||
mobs_monster?
|
|
||||||
mobs_slimes?
|
|
||||||
mobs_creeper?
|
|
||||||
kpgmobs?
|
|
||||||
mobs_fish?
|
|
||||||
dmobs?
|
|
||||||
3d_armor?
|
|
||||||
fun_caves_mobs?
|
|
||||||
|
|
606
dungeon.lua
|
@ -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
|
|
480
elixir.lua
|
@ -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
|
|
|
@ -1,6 +1,7 @@
|
||||||
-------------------
|
-- Fun_Caves fungal_tree.lua
|
||||||
-- Fungal Tree --
|
-- 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 = {}
|
local colors = {}
|
||||||
colors["^[colorize:#FF00FF:60"] = "dye:violet"
|
colors["^[colorize:#FF00FF:60"] = "dye:violet"
|
||||||
|
@ -9,7 +10,7 @@ colors["^[colorize:#FF4500:80"] = "dye:green"
|
||||||
colors[""] = "dye:white"
|
colors[""] = "dye:white"
|
||||||
local fungal_tree_leaves = {}
|
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"
|
newnode.description = "Dry Fiber"
|
||||||
minetest.register_node("fun_caves:dry_fiber", newnode)
|
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},
|
groups = {fleshy = 3, dig_immediate = 3, flammable = 2},
|
||||||
--on_use = minetest.item_eat(2),
|
--on_use = minetest.item_eat(2),
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
on_timer = fun_caves.soft_boom,
|
on_timer = fun_caves_mod.soft_boom,
|
||||||
on_punch = fun_caves.soft_boom,
|
on_punch = fun_caves_mod.soft_boom,
|
||||||
})
|
})
|
||||||
|
|
||||||
local fruit = minetest.get_content_id("fun_caves:fungal_tree_fruit")
|
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
|
if not (data and area and ivm and height and type(data) == 'table' and type(ivm) == 'number' and type(height) == 'number') then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
664
goblin.lua
|
@ -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
|
|
||||||
})
|
|
66
horror.lua
|
@ -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
|
@ -1,144 +1,17 @@
|
||||||
fun_caves = {}
|
-- Fun_Caves init.lua
|
||||||
fun_caves.version = "1.0"
|
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||||
fun_caves.time_factor = 10 -- affects growth abms
|
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
local f_date = io.open(fun_caves.world .. '/date.txt', 'r')
|
fun_caves_mod = {}
|
||||||
if f_date then
|
fun_caves_mod.version = "2.0"
|
||||||
local s = f_date:read('*a')
|
fun_caves_mod.time_factor = 1 -- affects growth abms
|
||||||
f_date:close()
|
fun_caves_mod.light_max = 8 -- light intensity for mushroom growth
|
||||||
for y, m, d in s:gmatch('(%d%d%d%d)(%d%d)(%d%d)') do
|
fun_caves_mod.path = minetest.get_modpath(minetest.get_current_modname())
|
||||||
local yn, mn, dn = tonumber(y), tonumber(m), tonumber(d)
|
fun_caves_mod.world = minetest.get_worldpath()
|
||||||
if yn and mn and dn then
|
|
||||||
fun_caves.date = {yn, mn, dn}
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local inp = io.open(fun_caves.world..'/fun_caves_data.txt','r')
|
function fun_caves_mod.clone_node(name)
|
||||||
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)
|
|
||||||
if not (name and type(name) == 'string') then
|
if not (name and type(name) == 'string') then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -149,324 +22,11 @@ function fun_caves.clone_node(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
fun_caves.registered_status = {}
|
minetest.register_on_mapgen_init(function(mgparams)
|
||||||
function fun_caves.register_status(def)
|
--minetest.set_mapgen_setting('mg_flags', "nocaves, nodungeons", true)
|
||||||
if not (def and fun_caves.registered_status and type(def) == 'table') then
|
minetest.set_mapgen_setting('mg_flags', "nocaves", true)
|
||||||
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
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
local hunger_mod = minetest.get_modpath("hunger")
|
dofile(fun_caves_mod.path .. "/mapgen.lua")
|
||||||
fun_caves.hunger_id = {}
|
dofile(fun_caves_mod.path .. "/abms.lua")
|
||||||
|
|
||||||
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
|
|
||||||
|
|
416
mapgen.lua
|
@ -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 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}
|
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.
|
-- This tables looks up nodes that aren't already stored.
|
||||||
|
@ -15,195 +33,9 @@ local node = setmetatable({}, {
|
||||||
})
|
})
|
||||||
|
|
||||||
local data = {}
|
local data = {}
|
||||||
local p2data = {} -- vm rotation data buffer
|
|
||||||
|
|
||||||
|
|
||||||
local biome_ids = {}
|
fun_caves_mod.cave_biomes = {
|
||||||
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 = {
|
|
||||||
algae = {
|
algae = {
|
||||||
biome_val_low = 0,
|
biome_val_low = 0,
|
||||||
biome_val_high = 0.2,
|
biome_val_high = 0.2,
|
||||||
|
@ -236,9 +68,9 @@ fun_caves.cave_biomes = {
|
||||||
biome_val_high = 99,
|
biome_val_high = 99,
|
||||||
ceiling_node = 'fun_caves:hot_cobble',
|
ceiling_node = 'fun_caves:hot_cobble',
|
||||||
floor_node = 'fun_caves:hot_cobble',
|
floor_node = 'fun_caves:hot_cobble',
|
||||||
fluid = 'default:lava_source',
|
--fluid = 'default:lava_source',
|
||||||
fluid_chance = 300,
|
--fluid_chance = 300,
|
||||||
stalagmite = fun_caves.hot_spikes,
|
stalagmite = fun_caves_mod.hot_spikes,
|
||||||
stalagmite_chance = 50,
|
stalagmite_chance = 50,
|
||||||
stone_depth = 1,
|
stone_depth = 1,
|
||||||
underwater = false,
|
underwater = false,
|
||||||
|
@ -297,8 +129,8 @@ fun_caves.cave_biomes = {
|
||||||
deco = 'fun_caves:glowing_fungal_stone',
|
deco = 'fun_caves:glowing_fungal_stone',
|
||||||
deco_chance = 50,
|
deco_chance = 50,
|
||||||
floor_node = 'fun_caves:stone_with_moss',
|
floor_node = 'fun_caves:stone_with_moss',
|
||||||
fluid = 'default:water_source',
|
--fluid = 'default:water_source',
|
||||||
fluid_chance = 300,
|
--fluid_chance = 300,
|
||||||
stalactite = 'fun_caves:stalactite_mossy',
|
stalactite = 'fun_caves:stalactite_mossy',
|
||||||
stalactite_chance = 12,
|
stalactite_chance = 12,
|
||||||
stalagmite = 'fun_caves:stalagmite_mossy',
|
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)
|
local function generate(p_minp, p_maxp, seed)
|
||||||
if not (p_minp and p_maxp and seed) then
|
if not (p_minp and p_maxp and seed) then
|
||||||
return
|
return
|
||||||
|
@ -350,177 +171,94 @@ local function generate(p_minp, p_maxp, seed)
|
||||||
end
|
end
|
||||||
|
|
||||||
vm:get_data(data)
|
vm:get_data(data)
|
||||||
p2data = vm:get_param2_data()
|
|
||||||
local heightmap
|
local heightmap
|
||||||
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
|
||||||
local csize = vector.add(vector.subtract(maxp, minp), 1)
|
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")
|
heightmap = minetest.get_mapgen_object("heightmap")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- use the same seed (based on perlin noise).
|
-- use the same seed (based on perlin noise).
|
||||||
do
|
--do
|
||||||
local seed = minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})
|
-- local seed = minetest.get_perlin(seed_noise):get2d({x=minp.x, y=minp.z})
|
||||||
if not (seed and type(seed) == 'number') then
|
-- if not (seed and type(seed) == 'number') then
|
||||||
return
|
-- return
|
||||||
end
|
-- end
|
||||||
|
|
||||||
math.randomseed(seed)
|
-- math.randomseed(seed)
|
||||||
end
|
--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
|
|
||||||
|
|
||||||
-- Correct heightmap.
|
-- Correct heightmap.
|
||||||
local index = 0
|
if maxp.y < -300 or minp.y > 300 then
|
||||||
for z = minp.z, maxp.z do
|
for i = 1, #heightmap do
|
||||||
for x = minp.x, maxp.x do
|
heightmap[i] = (maxp.y < 0) and max_depth or - max_depth
|
||||||
index = index + 1
|
end
|
||||||
|
else
|
||||||
|
local index = 0
|
||||||
|
for z = minp.z, maxp.z do
|
||||||
|
for x = minp.x, maxp.x do
|
||||||
|
index = index + 1
|
||||||
|
|
||||||
local height = heightmap[index]
|
local height = heightmap[index]
|
||||||
if height and height < maxp.y - 1 and height > minp.y then
|
if height and height < maxp.y - 1 and height > minp.y then
|
||||||
--nop
|
--nop
|
||||||
else
|
else
|
||||||
height = - max_depth
|
height = - max_depth
|
||||||
local ivm2 = area:index(x, maxp.y + 8, z)
|
local ivm2 = area:index(x, maxp.y + 8, z)
|
||||||
for y = maxp.y + 8, minp.y - 8, -1 do
|
for y = maxp.y + 8, minp.y - 8, -1 do
|
||||||
if ground_nodes[data[ivm2]] then
|
if ground_nodes[data[ivm2]] then
|
||||||
height = (y < maxp.y + 8) and y or max_depth
|
height = (y < maxp.y + 8) and y or max_depth
|
||||||
break
|
break
|
||||||
|
end
|
||||||
|
ivm2 = ivm2 - area.ystride
|
||||||
end
|
end
|
||||||
ivm2 = ivm2 - area.ystride
|
heightmap[index] = height
|
||||||
end
|
end
|
||||||
heightmap[index] = height
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local aster = false
|
|
||||||
for fake_loop = 1, 1 do
|
for fake_loop = 1, 1 do
|
||||||
if minp.y > 17200 then
|
if fun_caves_mod.cavegen and fun_caves_mod.decogen 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
|
|
||||||
local h2, write_cave
|
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
|
write = write or write_cave
|
||||||
|
|
||||||
if fun_caves.use_bi_hi then
|
|
||||||
biomemap = minetest.get_mapgen_object("biomemap")
|
|
||||||
end
|
|
||||||
|
|
||||||
local write_deco
|
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
|
write = write or write_deco
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
if write then
|
if write then
|
||||||
vm:set_data(data)
|
vm:set_data(data)
|
||||||
if write_p2 or write_p4 then
|
|
||||||
vm:set_param2_data(p2data)
|
|
||||||
end
|
|
||||||
|
|
||||||
if fun_caves.DEBUG then
|
if DEBUG then
|
||||||
vm:set_lighting({day = 15, night = 15})
|
vm:set_lighting({day = 8, night = 8})
|
||||||
else
|
else
|
||||||
-- set_lighting causes lighting artifacts,
|
vm:set_lighting({day = 0, night = 0}, minp, maxp)
|
||||||
-- but corrects the light inside trees.
|
vm:calc_lighting()
|
||||||
vm:set_lighting({day = 0, night = 0}, minp, maxp)
|
end
|
||||||
vm:calc_lighting(minp, maxp, not aster)
|
vm:update_liquids()
|
||||||
-- Does not work:
|
vm:write_to_map()
|
||||||
--vm:calc_lighting({x=minp.x,y=emin.y,z=minp.z}, maxp)
|
end
|
||||||
end
|
|
||||||
vm:update_liquids()
|
|
||||||
vm:write_to_map()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if fun_caves.path then
|
if fun_caves_mod.path then
|
||||||
dofile(fun_caves.path .. "/asteroids.lua")
|
dofile(fun_caves_mod.path .. "/cavegen.lua")
|
||||||
dofile(fun_caves.path .. "/cavegen.lua")
|
dofile(fun_caves_mod.path .. "/deco.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")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function pgenerate(...)
|
local function pgenerate(...)
|
||||||
local status, err = pcall(generate, ...)
|
--local status, err = pcall(generate, ...)
|
||||||
--local status, err = true
|
local status, err = true
|
||||||
--generate(...)
|
generate(...)
|
||||||
if not status then
|
if not status then
|
||||||
print('Fun Caves: Could not generate terrain:')
|
print('Fun Caves: Could not generate terrain:')
|
||||||
print(dump(err))
|
print(dump(err))
|
||||||
|
@ -529,5 +267,5 @@ local function pgenerate(...)
|
||||||
end
|
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)
|
table.insert(minetest.registered_on_generateds, 1, pgenerate)
|
||||||
|
|
880
mobs.lua
|
@ -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)
|
|
|
@ -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
|
|
132
models/star.x
|
@ -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
|
|
814
nodes.lua
|
@ -1,496 +1,408 @@
|
||||||
local get_node_or_nil = minetest.get_node_or_nil
|
-- Fun_Caves nodes.lua
|
||||||
local get_item_group = minetest.get_item_group
|
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
||||||
local max_depth = 31000
|
-- 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)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- dirt, cave
|
local light_max = fun_caves_mod.light_max or 10
|
||||||
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")
|
-- black (oily) sand
|
||||||
newnode.description = "Polluted Dirt"
|
local newnode = fun_caves_mod.clone_node("default:sand")
|
||||||
newnode.tiles = {"default_dirt.png^[colorize:#100020:100"}
|
newnode.description = "Black Sand"
|
||||||
newnode.groups.soil = 0
|
newnode.tiles = {"fun_caves_black_sand.png"}
|
||||||
minetest.register_node("fun_caves:polluted_dirt", newnode)
|
newnode.groups['falling_node'] = 0
|
||||||
|
minetest.register_node("fun_caves:black_sand", newnode)
|
||||||
|
|
||||||
-- ice -- add cold damage
|
-- cobble, hot - cobble with lava instead of mortar XD
|
||||||
minetest.add_group("default:ice", {surface_cold = 3})
|
minetest.register_node("fun_caves:hot_cobble", {
|
||||||
|
description = "Hot Cobble",
|
||||||
-- ice, thin -- transparent
|
tiles = {"caverealms_hot_cobble.png"},
|
||||||
minetest.register_node("fun_caves:thin_ice", {
|
|
||||||
description = "Thin Ice",
|
|
||||||
tiles = {"caverealms_thin_ice.png"},
|
|
||||||
is_ground_content = true,
|
is_ground_content = true,
|
||||||
groups = {cracky=3},
|
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
|
||||||
|
|
||||||
|
-- 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(),
|
sounds = default.node_sound_glass_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- mushroom cap, giant
|
||||||
|
local cap = {
|
||||||
|
description = "Giant Mushroom Cap",
|
||||||
|
tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = { type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-0.3, -0.25, -0.3, 0.3, 0.5, 0.3},
|
||||||
|
{-0.3, -0.25, -0.4, 0.3, 0.4, -0.3},
|
||||||
|
{-0.3, -0.25, 0.3, 0.3, 0.4, 0.4},
|
||||||
|
{-0.4, -0.25, -0.3, -0.3, 0.4, 0.3},
|
||||||
|
{0.3, -0.25, -0.3, 0.4, 0.4, 0.3},
|
||||||
|
{-0.4, -0.5, -0.4, 0.4, -0.25, 0.4},
|
||||||
|
{-0.5, -0.5, -0.4, -0.4, -0.25, 0.4},
|
||||||
|
{0.4, -0.5, -0.4, 0.5, -0.25, 0.4},
|
||||||
|
{-0.4, -0.5, -0.5, 0.4, -0.25, -0.4},
|
||||||
|
{-0.4, -0.5, 0.4, 0.4, -0.25, 0.5},
|
||||||
|
} },
|
||||||
|
light_source = light_max,
|
||||||
|
groups = {fleshy=1, falling_node = 1, dig_immediate=3, flammable=2, plant=1},
|
||||||
|
}
|
||||||
|
minetest.register_node("fun_caves:giant_mushroom_cap", cap)
|
||||||
|
|
||||||
|
-- mushroom cap, huge
|
||||||
|
minetest.register_node("fun_caves:huge_mushroom_cap", {
|
||||||
|
description = "Huge Mushroom Cap",
|
||||||
|
tiles = {"vmg_mushroom_giant_cap.png", "vmg_mushroom_giant_under.png", "vmg_mushroom_giant_cap.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = { type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-0.5, -0.5, -0.33, 0.5, -0.33, 0.33},
|
||||||
|
{-0.33, -0.5, 0.33, 0.33, -0.33, 0.5},
|
||||||
|
{-0.33, -0.5, -0.33, 0.33, -0.33, -0.5},
|
||||||
|
{-0.33, -0.33, -0.33, 0.33, -0.17, 0.33},
|
||||||
|
} },
|
||||||
|
light_source = light_max,
|
||||||
|
groups = {fleshy=1, falling_node = 1, dig_immediate=3, flammable=2, plant=1},
|
||||||
|
})
|
||||||
|
|
||||||
|
-- mushroom stem, giant or huge
|
||||||
|
minetest.register_node("fun_caves:giant_mushroom_stem", {
|
||||||
|
description = "Giant Mushroom Stem",
|
||||||
|
tiles = {"vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png", "vmg_mushroom_giant_stem.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {choppy=2, flammable=2, plant=1},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
sunlight_propagates = true,
|
||||||
|
paramtype = "light",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = { type = "fixed", fixed = { {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}, }},
|
||||||
|
})
|
||||||
|
|
||||||
|
-- obsidian, glowing
|
||||||
|
minetest.register_node("fun_caves:glow_obsidian", {
|
||||||
|
description = "Glowing Obsidian",
|
||||||
|
tiles = {"caverealms_glow_obsidian.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {stone=2, crumbly=1},
|
||||||
|
--light_source = 7,
|
||||||
|
sounds = default.node_sound_stone_defaults({
|
||||||
|
footstep = {name="default_stone_footstep", gain=0.25},
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- obsidian, glowing, 2 - has traces of lava
|
||||||
|
minetest.register_node("fun_caves:glow_obsidian_2", {
|
||||||
|
description = "Hot Glow Obsidian",
|
||||||
|
tiles = {"caverealms_glow_obsidian2.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {stone=2, crumbly=1, surface_hot=3, igniter=1},
|
||||||
|
damage_per_second = 1,
|
||||||
|
--light_source = 9,
|
||||||
|
sounds = default.node_sound_stone_defaults({
|
||||||
|
footstep = {name="default_stone_footstep", gain=0.25},
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- salt
|
||||||
|
minetest.register_node("fun_caves:stone_with_salt", {
|
||||||
|
description = "Cave Stone with Salt",
|
||||||
|
tiles = {"caverealms_salty2.png"},
|
||||||
|
paramtype = "light",
|
||||||
use_texture_alpha = true,
|
use_texture_alpha = true,
|
||||||
light_source = 1,
|
|
||||||
drawtype = "glasslike",
|
drawtype = "glasslike",
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = false,
|
||||||
freezemelt = "default:water_source",
|
is_ground_content = true,
|
||||||
paramtype = "light",
|
groups = {stone=1, crumbly=3, cracky=3},
|
||||||
|
sounds = default.node_sound_glass_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node('fun_caves:sticks_default', {
|
-- salt, radioactive ore
|
||||||
description = 'Sticks',
|
newnode = fun_caves_mod.clone_node("fun_caves:stone_with_salt")
|
||||||
drawtype = 'allfaces_optional',
|
newnode.description = "Salt With Radioactive Ore"
|
||||||
waving = 1,
|
newnode.tiles = {"fun_caves_radioactive_ore.png"}
|
||||||
visual_scale = 1.3,
|
newnode.light_source = 4
|
||||||
tiles = {'fun_caves_dry_twigs.png'},
|
minetest.register_node("fun_caves:radioactive_ore", newnode)
|
||||||
paramtype = 'light',
|
|
||||||
is_ground_content = false,
|
|
||||||
drop = 'default:stick 2',
|
|
||||||
groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1},
|
|
||||||
})
|
|
||||||
|
|
||||||
newnode = fun_caves.clone_node("default:leaves")
|
-- What's a cave without speleothems?
|
||||||
newnode.description = "Blackened Leaves"
|
local spel = {
|
||||||
newnode.tiles = {"default_leaves.png^[colorize:#100020:200"}
|
{type1="stalactite", type2="stalagmite", tile="default_stone.png"},
|
||||||
newnode.special_tiles = {"default_leaves_simple.png^[colorize:#100020:200"}
|
{type1="stalactite_slimy", type2="stalagmite_slimy", tile="default_stone.png^fun_caves_algae.png"},
|
||||||
newnode.groups = {snappy = 3, flammable = 2}
|
{type1="stalactite_mossy", type2="stalagmite_mossy", tile="default_stone.png^fun_caves_moss.png"},
|
||||||
minetest.register_node("fun_caves:leaves_black", newnode)
|
{type1="icicle_down", type2="icicle_up", desc="Icicle", tile="caverealms_thin_ice.png", drop="default:ice"},
|
||||||
|
}
|
||||||
|
|
||||||
newnode = fun_caves.clone_node("default:water_source")
|
for _, desc in pairs(spel) do
|
||||||
newnode.description = "Poisonous Water"
|
minetest.register_node("fun_caves:"..desc.type1, {
|
||||||
newnode.groups.poison = 3
|
description = (desc.desc or "Stalactite"),
|
||||||
newnode.light_source = 6
|
tiles = {desc.tile},
|
||||||
newnode.liquid_alternative_flowing = "fun_caves:water_poison_flowing"
|
is_ground_content = true,
|
||||||
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)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
--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,
|
|
||||||
--})
|
|
||||||
|
|
||||||
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',
|
|
||||||
recipe = {
|
|
||||||
'default:junglegrass', 'default:junglegrass',
|
|
||||||
'default:junglegrass', 'default:junglegrass',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
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,
|
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",
|
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,
|
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 = {
|
selection_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {-0.4, -0.5, -0.4, 0.5, -0.4, 0.4}
|
fixed = {-0.5*vs, -0.5*vs, -0.5*vs, 0.5*vs, -5/16*vs, 0.5*vs},
|
||||||
},
|
|
||||||
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
|
end
|
||||||
|
|
||||||
farming.register_plant("fun_caves:onion", {
|
fun_caves_mod.hot_spike = {}
|
||||||
description = "Onion",
|
for i = 1, #fun_caves_mod.hot_spikes do
|
||||||
inventory_image = "fun_caves_onion.png",
|
fun_caves_mod.hot_spike[fun_caves_mod.hot_spikes[i]] = i
|
||||||
steps = 3,
|
end
|
||||||
minlight = 13,
|
|
||||||
maxlight = default.LIGHT_MAX,
|
-- stone with algae
|
||||||
fertility = {"grassland"}
|
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},
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.registered_items['fun_caves:seed_onion'] = nil
|
-- stone with lichen
|
||||||
minetest.registered_nodes['fun_caves:seed_onion'] = nil
|
newnode = fun_caves_mod.clone_node("default:stone")
|
||||||
minetest.registered_craftitems['fun_caves:seed_onion'] = nil
|
newnode.description = "Cave Stone With Lichen"
|
||||||
minetest.register_alias('fun_caves:seed_onion', 'fun_caves:onion')
|
newnode.tiles = {"default_stone.png^fun_caves_lichen.png"}
|
||||||
for i = 1, 3 do
|
newnode.groups = {stone=1, cracky=3, crumbly=3}
|
||||||
local onion = minetest.registered_items['fun_caves:onion_'..i]
|
newnode.sounds = default.node_sound_dirt_defaults({
|
||||||
if onion then
|
footstep = {name="default_grass_footstep", gain=0.25},
|
||||||
onion.drop = {
|
})
|
||||||
max_items = i,
|
minetest.register_node("fun_caves:stone_with_lichen", newnode)
|
||||||
items = {
|
|
||||||
{ items = {'fun_caves:onion'}, rarity = 4 - i, },
|
-- stone with moss
|
||||||
{ items = {'fun_caves:onion'}, rarity = (4 - i) * 2, },
|
newnode = fun_caves_mod.clone_node("default:stone")
|
||||||
{ items = {'fun_caves:onion'}, rarity = (4 - i) * 4, },
|
newnode.description = "Cave Stone With Moss"
|
||||||
},
|
newnode.tiles = {"default_stone.png^fun_caves_moss.png"}
|
||||||
}
|
newnode.groups = {stone=1, cracky=3, crumbly=3}
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
minetest.register_node("fun_caves:onion", {
|
minetest.register_craft({
|
||||||
description = "Onion",
|
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",
|
drawtype = "plantlike",
|
||||||
visual_scale = 0.75,
|
|
||||||
tiles = {"fun_caves_onion.png"},
|
|
||||||
inventory_image = "fun_caves_onion.png",
|
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
sunlight_propagates = true,
|
tiles = {"vmg_mushroom_steak.png"},
|
||||||
walkable = false,
|
inventory_image = "vmg_mushroom_steak.png",
|
||||||
is_ground_content = false,
|
on_use = minetest.item_eat(4),
|
||||||
selection_box = {
|
--groups = {dig_immediate = 3, attached_node = 1},
|
||||||
type = "fixed",
|
groups = {dig_immediate = 3},
|
||||||
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({
|
minetest.register_craft({
|
||||||
type = "cooking",
|
type = "cooking",
|
||||||
cooktime = 15,
|
output = "fun_caves:mushroom_steak",
|
||||||
output = "fun_caves:apple_pie",
|
recipe = "fun_caves:huge_mushroom_cap",
|
||||||
recipe = "fun_caves:apple_pie_uncooked"
|
cooktime = 2,
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
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",
|
|
||||||
drawtype = "plantlike",
|
|
||||||
paramtype = "light",
|
|
||||||
tiles = {"fun_caves_wooden_bowl.png"},
|
|
||||||
inventory_image = "fun_caves_wooden_bowl.png",
|
|
||||||
groups = {bowl = 1, dig_immediate = 3},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = 'fun_caves:wooden_bowl 20',
|
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 = {
|
recipe = {
|
||||||
{'group:wood', '', 'group:wood'},
|
{"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"},
|
||||||
{'group:wood', '', 'group:wood'},
|
{"fun_caves:glowing_fungus", "fun_caves:glowing_fungus", "fun_caves:glowing_fungus"},
|
||||||
{'', 'group:wood', ''},
|
{"fun_caves:glowing_fungus", "vessels:glass_bottle", "fun_caves:glowing_fungus"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = 'default:diamondblock',
|
output = "fun_caves:moon_glass",
|
||||||
|
type = "shapeless",
|
||||||
recipe = {
|
recipe = {
|
||||||
{'default:coalblock', 'default:coalblock', 'default:coalblock'},
|
"fun_caves:moon_juice",
|
||||||
{'default:coalblock', 'default:mese_crystal_fragment', 'default:coalblock'},
|
"fun_caves:moon_juice",
|
||||||
{'default:coalblock', 'default:coalblock', 'default:coalblock'},
|
"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({
|
minetest.register_craft({
|
||||||
output = 'default:mese_crystal 2',
|
output = "default:cobble",
|
||||||
recipe = {
|
recipe = {
|
||||||
{'default:diamond', 'default:diamond', 'default:diamond'},
|
{"", "", ""},
|
||||||
{'default:diamond', 'default:mese_crystal', 'default:diamond'},
|
{"fun_caves:stalagmite", "fun_caves:stalagmite", ""},
|
||||||
{'default:diamond', 'default:diamond', 'default:diamond'},
|
{"fun_caves:stalagmite", "fun_caves:stalagmite", ""},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
160
pyramid.lua
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
100
skyseagen.lua
|
@ -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
|
|
546
tesseract.lua
|
@ -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)
|
|
Before Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
BIN
textures/dna.png
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 659 B |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 352 B |
Before Width: | Height: | Size: 141 B |
Before Width: | Height: | Size: 479 B |
Before Width: | Height: | Size: 541 B |
Before Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 984 B |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 818 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 152 B |
Before Width: | Height: | Size: 227 KiB |
Before Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 426 KiB |
Before Width: | Height: | Size: 397 KiB |
Before Width: | Height: | Size: 142 B |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 683 B |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 949 B |