From 79b624bc5cba666d05c30c189ef35d697f652326 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 27 Oct 2020 16:37:25 +0100 Subject: [PATCH 01/27] First Steps --- mods/CORE/mcl_enchanting/LICENSE | 674 ++++++++++++++++++ mods/CORE/mcl_enchanting/README | 5 + mods/CORE/mcl_enchanting/book.lua | 87 +++ mods/CORE/mcl_enchanting/command.lua | 40 ++ mods/CORE/mcl_enchanting/core.lua | 169 +++++ mods/CORE/mcl_enchanting/enchantments.lua | 323 +++++++++ mods/CORE/mcl_enchanting/features.lua | 120 ++++ mods/CORE/mcl_enchanting/init.lua | 15 + mods/CORE/mcl_enchanting/mod.conf | 5 + .../models/mcl_enchanting_book.b3d | Bin 0 -> 496042 bytes .../models/mcl_enchanting_book_entity.png | Bin 0 -> 875 bytes mods/CORE/mcl_enchanting/roman_numerals.lua | 34 + .../sounds/mcl_enchanting_enchant.ogg | Bin 0 -> 14918 bytes mods/CORE/mcl_enchanting/table.lua | 189 +++++ .../textures/mcl_enchanting_book_closed.png | Bin 0 -> 3370 bytes .../textures/mcl_enchanting_book_open.png | Bin 0 -> 6708 bytes .../textures/mcl_enchanting_button.png | Bin 0 -> 875 bytes .../mcl_enchanting_button_background.png | Bin 0 -> 4884 bytes .../mcl_enchanting_button_hovered.png | Bin 0 -> 876 bytes .../textures/mcl_enchanting_button_off.png | Bin 0 -> 876 bytes .../textures/mcl_enchanting_glyph_1.png | Bin 0 -> 161 bytes .../textures/mcl_enchanting_glyph_10.png | Bin 0 -> 157 bytes .../textures/mcl_enchanting_glyph_11.png | Bin 0 -> 158 bytes .../textures/mcl_enchanting_glyph_12.png | Bin 0 -> 156 bytes .../textures/mcl_enchanting_glyph_13.png | Bin 0 -> 159 bytes .../textures/mcl_enchanting_glyph_14.png | Bin 0 -> 106 bytes .../textures/mcl_enchanting_glyph_15.png | Bin 0 -> 160 bytes .../textures/mcl_enchanting_glyph_16.png | Bin 0 -> 166 bytes .../textures/mcl_enchanting_glyph_17.png | Bin 0 -> 145 bytes .../textures/mcl_enchanting_glyph_18.png | Bin 0 -> 161 bytes .../textures/mcl_enchanting_glyph_2.png | Bin 0 -> 159 bytes .../textures/mcl_enchanting_glyph_3.png | Bin 0 -> 159 bytes .../textures/mcl_enchanting_glyph_4.png | Bin 0 -> 105 bytes .../textures/mcl_enchanting_glyph_5.png | Bin 0 -> 161 bytes .../textures/mcl_enchanting_glyph_6.png | Bin 0 -> 159 bytes .../textures/mcl_enchanting_glyph_7.png | Bin 0 -> 157 bytes .../textures/mcl_enchanting_glyph_8.png | Bin 0 -> 158 bytes .../textures/mcl_enchanting_glyph_9.png | Bin 0 -> 102 bytes .../mcl_enchanting_lapis_background.png | Bin 0 -> 1666 bytes .../textures/mcl_enchanting_number_1.png | Bin 0 -> 1787 bytes .../textures/mcl_enchanting_number_1_off.png | Bin 0 -> 1660 bytes .../textures/mcl_enchanting_number_2.png | Bin 0 -> 1857 bytes .../textures/mcl_enchanting_number_2_off.png | Bin 0 -> 1661 bytes .../textures/mcl_enchanting_number_3.png | Bin 0 -> 1922 bytes .../textures/mcl_enchanting_number_3_off.png | Bin 0 -> 1661 bytes .../textures/mcl_enchanting_table_bottom.png | Bin 0 -> 298 bytes .../textures/mcl_enchanting_table_side.png | Bin 0 -> 315 bytes .../textures/mcl_enchanting_table_top.png | Bin 0 -> 340 bytes mods/ITEMS/mcl_bows/bow.lua | 2 +- mods/ITEMS/mcl_fishing/init.lua | 2 +- 50 files changed, 1663 insertions(+), 2 deletions(-) create mode 100644 mods/CORE/mcl_enchanting/LICENSE create mode 100644 mods/CORE/mcl_enchanting/README create mode 100644 mods/CORE/mcl_enchanting/book.lua create mode 100644 mods/CORE/mcl_enchanting/command.lua create mode 100644 mods/CORE/mcl_enchanting/core.lua create mode 100644 mods/CORE/mcl_enchanting/enchantments.lua create mode 100644 mods/CORE/mcl_enchanting/features.lua create mode 100644 mods/CORE/mcl_enchanting/init.lua create mode 100644 mods/CORE/mcl_enchanting/mod.conf create mode 100644 mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d create mode 100644 mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png create mode 100644 mods/CORE/mcl_enchanting/roman_numerals.lua create mode 100644 mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg create mode 100644 mods/CORE/mcl_enchanting/table.lua create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_background.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_off.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_1.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_11.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_18.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3_off.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png diff --git a/mods/CORE/mcl_enchanting/LICENSE b/mods/CORE/mcl_enchanting/LICENSE new file mode 100644 index 0000000000..9cecc1d466 --- /dev/null +++ b/mods/CORE/mcl_enchanting/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/mods/CORE/mcl_enchanting/README b/mods/CORE/mcl_enchanting/README new file mode 100644 index 0000000000..4d1d5af9d2 --- /dev/null +++ b/mods/CORE/mcl_enchanting/README @@ -0,0 +1,5 @@ +Enchanting for MineClone2 +-------------------------- + +This is a rewrite of the mtg enchanting mod. Beta Version, more features coming soon. +The textures look absolutely shit, but as far as I know I have to use the textures from Pixel Perfection so I dont get trouble with Mocrisoft. There is a version with original textures and sounds, but I can't publish that one. If you'd like to advice me how I can somehow do that anyway, please open an issue or contact me via email (eliasfleckenstein@web.de). diff --git a/mods/CORE/mcl_enchanting/book.lua b/mods/CORE/mcl_enchanting/book.lua new file mode 100644 index 0000000000..132fb880b4 --- /dev/null +++ b/mods/CORE/mcl_enchanting/book.lua @@ -0,0 +1,87 @@ +local book_animations = {["close"] = 1, ["opening"] = 2, ["open"] = 3, ["closing"] = 4} +local book_animation_steps = {0, 640, 680, 700, 740} +local book_animation_speed = 40 + +function mcl_enchanting.schedule_book_animation(self, anim) + self.scheduled_anim = {timer = self.anim_length, anim = anim} +end + +function mcl_enchanting.set_book_animation(self, anim) + local anim_index = book_animations[anim] + local start, stop = book_animation_steps[anim_index], book_animation_steps[anim_index + 1] + self.object:set_animation({x = start, y = stop}, book_animation_speed) + self.scheduled_anim = nil + self.anim_length = (stop - start) / 40 +end + +function mcl_enchanting.check_animation_schedule(self, dtime) + local schedanim = self.scheduled_anim + if schedanim then + schedanim.timer = schedanim.timer - dtime + if schedanim.timer <= 0 then + mcl_enchanting.set_book_animation(self, schedanim.anim)local pos1=self.object:get_pos() + end + end +end + +function mcl_enchanting.look_at(self, pos2) + local pos1 = self.object:get_pos() + local vec = vector.subtract(pos1, pos2) + local yaw = math.atan(vec.z / vec.x) - math.pi/2 + yaw = yaw + (pos1.x >= pos2.x and math.pi or 0) + self.object:set_yaw(yaw + math.pi) +end + +function mcl_enchanting.check_book(pos) + local obj_pos = vector.add(pos, mcl_enchanting.book_offset) + for _, obj in pairs(minetest.get_objects_inside_radius(obj_pos, 0.1)) do + local luaentity = obj:get_luaentity() + if luaentity and luaentity.name == "mcl_enchanting:book" then + if minetest.get_node(pos).name ~= "mcl_enchanting:table" then + obj:remove() + end + return + end + end + minetest.add_entity(obj_pos, "mcl_enchanting:book") +end + +minetest.register_entity("mcl_enchanting:book", { + initial_properties = { + visual = "mesh", + mesh = "mcl_enchanting_book.b3d", + visual_size = {x = 12.5, y = 12.5}, + collisionbox = {0, 0, 0}, + physical = false, + textures = {"mcl_enchanting_book_entity.png"}, + }, + player_near = false, + on_activate = function(self) + self.object:set_armor_groups({immortal = 1}) + mcl_enchanting.set_book_animation(self, "close") + mcl_enchanting.check_book(vector.subtract(self.object:get_pos(), mcl_enchanting.book_offset)) + end, + on_step = function(self, dtime) + local old_player_near = self.player_near + local player_near = false + local player + for _, obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 2.5)) do + if obj:is_player() then + player_near = true + player = obj + end + end + if player_near and not old_player_near then + mcl_enchanting.set_book_animation(self, "opening") + mcl_enchanting.schedule_book_animation(self, "open") + elseif old_player_near and not player_near then + mcl_enchanting.set_book_animation(self, "closing") + mcl_enchanting.schedule_book_animation(self, "close") + end + if player then + mcl_enchanting.look_at(self, player:get_pos()) + end + self.player_near = player_near + mcl_enchanting.check_animation_schedule(self, dtime) + end, +}) diff --git a/mods/CORE/mcl_enchanting/command.lua b/mods/CORE/mcl_enchanting/command.lua new file mode 100644 index 0000000000..28b0cadc1a --- /dev/null +++ b/mods/CORE/mcl_enchanting/command.lua @@ -0,0 +1,40 @@ +minetest.register_chatcommand("enchant", { + description = "Enchant an item." + params = " []", + privs = {give = true}, + func = function(_, param) + local sparam = param:split(" ") + local target_name = sparam[1] + local enchantment = sparam[2] + local level_str = sparam[3] + local level = tonumber(level_str or "1") + if not name or not enchantment then + return false, "Usage: /enchant []" + end + local target = minetest.get_player_by_name(name) + if not target then + return false, "Player '" .. target_name .. "' cannot be found" + end + local itemstack = target:get_wielded_item() + local can_enchant, errorstring, extra_info = mcl_enchanting.can_enchant(itemstack, enchantment, level) + if not can_enchant then + if errorstring == "enchantment invalid" then + return false, "There is no such enchantment '" .. enchantment .. "'" + elseif errorstring == "item missing" then + return false, "The target doesn't hold an item" + elseif errorstring == "item not supported" then + return false, "The selected enchantment can't be added to the target item" + elseif errorstring == "level invalid" then + return false, "'" .. level_str .. "' is not a valid number" + elseif errorstring == "level too high" + return false, "The number you have entered (" .. level_str .. ") is too big, it must be at most " .. extra_info + elseif errorstring == "level too small" + return false, "The number you have entered (" .. level_str .. ") is too small, it must be at least " .. extra_info + elseif errorstring == "incompatible" then + return false, mcl_enchanting.get_enchantment_description(enchantment, level) .. " can't be combined with " .. extra_info + end + else + target:set_wielded_item(mcl_enchanting.enchant(itemstack, enchantment, level)) + end + end +}) diff --git a/mods/CORE/mcl_enchanting/core.lua b/mods/CORE/mcl_enchanting/core.lua new file mode 100644 index 0000000000..e9fa523f2c --- /dev/null +++ b/mods/CORE/mcl_enchanting/core.lua @@ -0,0 +1,169 @@ +mcl_enchanting.total_weight = 0 +mcl_enchanting.all_item_groups = {} + +for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do + local all_item_groups = {} + for primary in pairs(enchantment_def.primary) do + all_item_groups[primary] = true + mcl_enchanting.all_item_groups[primary] = true + end + for secondary in pairs(enchantment_def.secondary) do + all_item_groups[secondary] = true + mcl_enchanting.all_item_groups[secondary] = true + end + enchantment_def.all = all_item_groups + mcl_enchanting.total_weight = mcl_enchanting.total_weight + enchantment_def.weight +end + +--[[ +minetest.register_on_mods_loaded(function() + for toolname, tooldef in pairs(minetest.registered_tools) do + for _, material in pairs(tooldef.materials) do + local full_name = toolname .. ((material == "") and "" or "_" .. material) + local old_def = minetest.registered_tools[full_name] + if not old_def then break end + mcl_enchanting.all_tools[full_name] = toolname + for _, enchantment in pairs(tooldef.enchantments) do + local enchantment_def = mcl_enchanting.enchantments[enchantment] + for lvl = 1, enchantment_def.max_level do + local new_def = table.copy(old_def) + new_def.description = minetest.colorize("#54FCFC", old_def.description) .. "\n" .. mcl_enchanting.get_enchantment_description(enchantment, lvl) + new_def.inventory_image = old_def.inventory_image .. "^[colorize:violet:50" + new_def.groups.not_in_creative_inventory = 1 + new_def.texture = old_def.texture or full_name:gsub("%:", "_") + new_def._original_tool = full_name + enchantment_def.create_itemdef(new_def, lvl) + minetest.register_tool(":" .. full_name .. "_enchanted_" .. enchantment .. "_" .. lvl, new_def) + end + end + end + end +end) +--]] + +minetest.register_on_mods_loaded(function() + for toolname, tooldef in pairs(minetest.registered_tools) do + -- quick test + local has_enchantment = false + for group, groupv in pairs(tooldef.groups) do + if groupv > 0 and mcl_enchanting.all_item_groups[group] then + has_enchantment = true + break + end + end + if not has_enchantment then + break + end + -- expensive test + has_enchantment = false + for enchantment in pairs(mcl_enchanting.enchantments) do + if mcl_enchanting.item_supports_enchantment(itemname, enchantment) then + has_enchantment = true + break + end + end + if not has_enchantment then + break + end + local new_name = toolname .. "_enchanted" + tooldef._mcl_enchanting_enchanted_tool = new_name + local new_def = table.copy(tooldef) + new_def.inventory_image = old_def.inventory_image .. "^[colorize:violet:50" + new_def.groups.not_in_creative_inventory = 1 + new_def.groups.enchanted = 1 + new_def.texture = old_def.texture or toolname:gsub("%:", "_") + new_def._mcl_enchanting_enchanted_tool = new_name + minetest.register_tool(":" .. new_name, new_def) + end +end) + +function mcl_enchanting.get_enchantments(itemstack) + return minetest.deserialize(itemstack:get_meta():get_string("mcl_enchanting:enchantments")) or {} +end + +function mcl_enchanting.set_enchantments(itemstack, enchantments, data) + return itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) +end + +function mcl_enchanting.get_enchantment(itemstack, enchantment, data) + return (data or mcl_enchanting.get_enchantments(itemstack))[enchantment] or 0 +end + +function mcl_enchanting.get_enchantment_description(enchantment, level) + local enchantment_def = mcl_enchanting.enchantments[enchantment] + return enchantment_def.name .. " " .. (enchantment_def.max_level == 1 and "" or mcl_enchanting.roman_numerals.toRoman(level)) +end + +function mcl_enchanting.get_enchanted_itemstring(itemname) + return minetest.registered_items[itemname]._mcl_enchanting_enchanted_tool +end + +function mcl_enchanting.item_supports_enchantment(itemname, enchantment) + if not mcl_enchanting.get_enchanted_itemstring(itemname) then + return false + end + local enchantment_def = mcl_enchanting.enchantments[enchantment] + for disallow in pairs(enchantment_def.disallow) do + if minetest.get_item_group(itemname, disallow) > 0 then + return false + end + end + for group in pairs(enchantment_def.all) do + if minetest.get_item_group(itemname, group) then + return true + end + end + return false +end + +function mcl_enchanting.can_enchant(itemstack, enchantment, level) + local enchantment_def = mcl_enchanting.enchantments[enchantment] + if not enchantment_def then + return false, "enchantment invalid" + end + if itemstack:get_name() == "" then + return false, "item missing" + end + if not mcl_enchanting.item_supports_enchantment(itemdef.name, enchantment) then + return false, "item not supported" + end + if not level then + return false, "level invalid" + end + if level > enchantment_def.max_level then + return false, "level too high", enchantment_def.max_level + elseif level < 1 then + return false, "level too small", 1 + end + local item_enchantments = mcl_enchanting.get_enchantments(itemstack) + local enchantment_level = item_enchantments[enchantment] + if enchantment_level then + return false, "incompatible", mcl_enchanting.get_enchantment_description(enchantment, enchantment_level) + end + for incompatible in pairs(enchantment_def.incompatible) do + local incompatible_level = item_enchantments[incompatible] + if incompatible_level then + return false, "incompatible", mcl_enchanting.get_enchantment_description(incompatible, incompatible_level) + end + end +end + +function mcl_enchanting.enchant(itemstack, enchantment, level) + local enchanted_itemstack = ItemStack(mcl_enchanting.get_enchanted_itemstring(itemstack:get_name())) + enchanted_itemstack:add_wear(itemstack:get_wear()) + enchanted_itemstack:set_meta(itemstack:get_meta()) + local enchantments = mcl_enchanting.get_enchantments(enchanted_itemstack) + enchantments[enchantment] = level + mcl_enchanting.set_enchantments(enchanted_itemstack, enchantments) + mcl_enchanting.reload_enchantments(enchanted_itemstack, enchantments) +end + +function mcl_enchanting.reload_enchantments(itemstack, echantments) + local itemdef = itemstack:get_definition() + for enchantment, level in pairs(enchantments) do + local func = mcl_enchanting.features[enchantment] + if func then + func(itemstack, level, itemdef) + end + end +end diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua new file mode 100644 index 0000000000..04783a679c --- /dev/null +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -0,0 +1,323 @@ +-- Taken from https://minecraft.gamepedia.com/Enchanting + +mcl_enchantments.enchantments = { + -- unimplemented + aqua_affinity = { + name = "Aqua Affinity", + max_level = 1, + primary = {armor_head = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 2, + description = "Increases underwater mining speed." + }, + -- unimplemented + bane_of_anthropods = { + name = "Bane of Anthropods", + max_level = 5, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {smite = true, shaprness = true}, + weight = 5, + description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites)." + }, + -- unimplemented + blast_protection = { + name = "Blast Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {fire_protection = true, protection = true, projectile_protection = true}, + weight = 2, + description = "Reduces explosion damage and knockback." + }, + -- unimplemented + curse_of_binding = { + name = "Curse of Binding", + max_level = 1, + primary = {}, + secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + disallow = {}, + incompatible = {}, + weight = 1, + description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking." + }, + -- unimplemented + curse_of_vanishing = { + name = "Curse of Vanishing", + max_level = 1, + primary = {}, + secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, + disallow = {clock = true}, + incompatible = {}, + weight = 1, + description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking." + }, + -- unimplemented + depth_strider = { + name = "Depth Strider", + max_level = 3, + primary = {}, + secondary = {armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {frost_walker = true}, + weight = 2, + description = "Increases underwater movement speed." + }, + -- unimplemented + efficiency = { + name = "Efficiency", + max_level = 5, + primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, + secondary = {shears = true}, + disallow = {}, + incompatible = {}, + weight = 10, + description = "Increases mining speed." + }, + -- unimplemented + feather_falling = { + name = "Feather Falling", + max_level = 4, + primary = {armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 5, + description = "Reduces fall damage." + }, + -- unimplemented + fire_protection = { + name = "Fire Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, protection = true, projectile_protection = true}, + weight = 5, + description = "Reduces fire damage." + }, + -- unimplemented + fortune = { + name = "Fortune", + max_level = 4, + primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, + secondary = {}, + disallow = {}, + incompatible = {silk_touch = true}, + weight = 2, + description = "Increases certain block drops." + }, + -- unimplemented + frost_walker = { + name = "Frost Walker", + max_level = 2, + primary = {}, + secondary = {armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {depth_strider = true}, + weight = 2, + description = "Turns water beneath the player into frosted ice and prevents the damage the player would take from standing on magma blocks." + }, + -- unimplemented + infinity = { + name = "Infinity", + max_level = 1, + primary = {bow = true}, + secondary = {}, + disallow = {}, + incompatible = {mending = true}, + weight = 1, + description = "Shooting consumes no regular arrows." + }, + -- unimplemented + knockback = { + name = "Knockback", + max_level = 2, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 5, + description = "Increases knockback." + }, + -- unimplemented + looting = { + name = "Looting", + max_level = 3, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases mob loot." + }, + -- unimplemented + luck_of_the_sea = { + name = "Luck of the Sea", + max_level = 3, + primary = {fishing_rod = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases rate of good loot (enchanting books, etc.)" + }, + -- unimplemented + lure = { + name = "Lure", + max_level = 3, + primary = {fishing_rod = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Decreases wait time until fish/junk/loot \"bites\"." + }, + -- unimplemented + mending = { + name = "Mending", + max_level = 1, + primary = {}, + secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, + disallow = {non_combat_armor = true, compass = true, clock = true}, + incompatible = {infinity = true}, + weight = 2, + description = "Repair the item while gaining XP orbs." + }, + -- unimplemented + power = { + name = "Power", + max_level = 5, + primary = {}, + secondary = {bow = true}, + disallow = {}, + incompatible = {}, + weight = 10, + description = "Increases arrow damage." + }, + -- unimplemented + projectile_protection = { + name = "Projectile Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, fire_protection = true, protection = true}, + weight = 5, + description = "Reduces projectile damage." + }, + -- unimplemented + protection = { + name = "Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true}, + weight = 10, + description = "Reduces most types of damage by 4% for each level." + }, + -- unimplemented + punch = { + name = "Punch", + max_level = 2, + primary = {}, + secondary = {bow = true}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases arrow knockback." + }, + -- unimplemented + respiration = { + name = "Respiration", + max_level = 3, + primary = {armor_head = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 2, + description = "Extends underwater breathing time." + }, + -- unimplemented + sharpness = { + name = "Sharpness", + max_level = 5, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {bane_of_anthropods = true, smite = true}, + weight = 5, + description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites)." + }, + -- unimplemented + silk_touch = { + name = "Silk Touch", + max_level = 1, + primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, + secondary = {shears = true}, + disallow = {}, + incompatible = {fortune = true}, + weight = 1, + description = "Mined blocks drop themselves." + }, + -- unimplemented + smite = { + name = "Sharpness", + max_level = 5, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {sharpness = true, smite = true}, + weight = 5, + description = "Increases damage to undead mobs." + }, + -- unimplemented + soul_speed = { + name = "Soul Speed", + max_level = 3, + primary = {}, + secondary = {armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {frost_walker = true}, + weight = 2, + description = "Incerases walking speed on soul sand." + }, + -- unimplemented + sweeping_edge = { + name = "Sweeping Edge", + max_level = 3, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases sweeping attack damage." + }, + -- unimplemented + thorns = { + name = "Thorns", + max_level = 3, + primary = {armor_head = true}, + secondary = {armor_torso = true, armor_legs = true, armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true}, + weight = 1, + description = "Reflects some of the damage taken when hit, at the cost of reducing durability with each proc." + }, + -- unimplemented + unbreaking = { + name = "Unbreaking", + max_level = 3, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, pickaxe = true, shovel = true, axe = true, hoe = true, sword = true, fishing_rod = true, bow = true}, + secondary = {tool = true}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 5, + description = "Increases item durability." + }, +} diff --git a/mods/CORE/mcl_enchanting/features.lua b/mods/CORE/mcl_enchanting/features.lua new file mode 100644 index 0000000000..793ff85f5e --- /dev/null +++ b/mods/CORE/mcl_enchanting/features.lua @@ -0,0 +1,120 @@ +--[[ +local pickaxes = {"mcl_tools:pick_wood", "mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} +local pickaxes_better_than_iron = {"mcl_tools:pick_iron", "mcl_tools:pick_diamond"} +local pickaxes_better_than_stone = {"mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} +local shovels = {"mcl_tools:shovel_wood", "mcl_tools:shovel_stone", "mcl_tools:shovel_gold", "mcl_tools:shovel_iron", "mcl_tools:shovel_diamond"} + +local silk_touch_tool_lists = { + ["mcl_books:bookshelf"] = true, + ["mcl_core:clay"] = true, + ["mcl_core:stone_with_coal"] = pickaxes, + ["group:coral_block"] = pickaxes, + ["group:coral"] = true, + ["group:coral_fan"] = true, + ["mcl_core:stone_with_diamond"] = pickaxes_better_than_iron, + ["mcl_core:stone_with_emerald"] = pickaxes_better_than_iron, + ["mcl_chests:ender_chest"] = pickaxes, + ["group:glass"] = true, + ["mcl_nether:glowstone"] = true, + ["mcl_core:dirt_with_grass"] = true, + ["mcl_core:gravel"] = true, + ["mcl_core:ice"] = true, + ["mcl_core:stone_with_lapis"] = pickaxes_better_than_stone, + ["group:leaves"] = true, + ["mcl_farming:melon"] = true, + ["group:huge_mushroom"] = true, + ["mcl_core:mycelium"] = true, + ["mcl_nether:quartz_ore"] = pickaxes, + ["mcl_core:packed_ice"] = true, + ["mcl_core:podzol"] = true, + ["mcl_core:stone_with_redstone"] = pickaxes_better_than_iron, + ["mcl_ocean:sea_lantern"] = true, + ["group:top_snow"] = shovels, + ["mcl_core:snowblock"] = shovels, + ["mcl_core:stone"] = pickaxes, +} + +minetest.register_on_mods_loaded(function() + local old_handle_node_drops = minetest.handle_node_drops + function minetest.handle_node_drops(pos, drops, digger) + if digger and digger:is_player() then + local wielditem = digger:get_wielded_item() + local tooldef = wielditem:get_definition() + if tooldef._silk_touch then + local nodename = minetest.get_node(pos).name + local nodedef = minetest.registered_nodes[nodename] + local silk_touch_spec = silk_touch_tool_lists[nodename] + local suitable_tool = false + local tool_list + if silk_touch_spec == true then + suitable_tool = true + elseif silk_touch_spec then + tool_list = silk_touch_spec + else + for k, v in pairs(nodedef.groups) do + if v > 0 then + local group_spec = silk_touch_tool_lists["group:" .. k] + if group_spec == true then + suitable_tool = true + elseif group_spec then + toollist = group_spec + break + end + end + end + end + if tool_list and not suitable_tool then + suitable_tool = (table.indexof(tool_list, tooldef._original_tool) ~= -1) + end + if suitable_tool then + drops = {nodename} + end + end + end + old_handle_node_drops(pos, drops, digger) + end +end) +--]] + + +--[[ + sharpness = { + name = "Sharpness", + max_level = 5, + create_itemdef = function(def, level) + def.tool_capabilities.damage_groups.fleshy = def.tool_capabilities.damage_groups.fleshy + (level + 1) / 2 + end, + }, + efficiency = { + name = "Efficiency", + max_level = 5, + create_itemdef = function(def, level) + local groupcaps = def.tool_capabilities.groupcaps + for _, groupcap in pairs(groupcaps) do + for i, t in pairs(groupcap.times) do + local m = 1 / t + m = m + math.pow(level, 2) + 1 + groupcap.times[i] = 1 / m + end + end + end, + }, + unbreaking = { + name = "Unbreaking", + max_level = 3, + create_itemdef = function(def, level) + local toolcaps = def.tool_capabilities + local armor_uses = def.groups.mcl_armor_uses + local factor = 0.5 + if toolcaps then + local groupcaps = toolcaps.groupcaps + for _, groupcap in pairs(groupcaps) do + groupcap.uses = math.floor(groupcap.uses * (1 + level)) + end + def.tool_capabilities.punch_attack_uses = math.floor(def.tool_capabilities.punch_attack_uses * (1 + level)) + elseif armor_uses then + def.groups.mcl_armor_uses = math.floor(armor_uses / (0.6 + (0.4 / (level + 1)))) + end + end + }, + },--]] diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua new file mode 100644 index 0000000000..8489ff2d4b --- /dev/null +++ b/mods/CORE/mcl_enchanting/init.lua @@ -0,0 +1,15 @@ +local modpath = minetest.get_modpath("mcl_enchanting") + +mcl_enchanting = { + lapis_itemstring = "mcl_dye:blue", + book_offset = vector.new(0, 0.75, 0), + roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 +} + +dofile(modpath .. "/enchantments.lua") +dofile(modpath .. "/features.lua") +dofile(modpath .. "/core.lua") +-- dofile(modpath .. "/ui.lua") +-- dofile(modpath .. "/fx.lua") +-- dofile(modpath .. "/book.lua") +-- dofile(modpath .. "/table.lua") diff --git a/mods/CORE/mcl_enchanting/mod.conf b/mods/CORE/mcl_enchanting/mod.conf new file mode 100644 index 0000000000..2ec29e526a --- /dev/null +++ b/mods/CORE/mcl_enchanting/mod.conf @@ -0,0 +1,5 @@ +name = mcl_enchanting +description = The rewrite of the Enchanting mod for MineClone2 +depends = mcl_sounds, mcl_formspec, mcl_dye +optional_depends = screwdriver +author = Fleckenstein diff --git a/mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d b/mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d new file mode 100644 index 0000000000000000000000000000000000000000..ecc8d91eac6a8a3efcb496e321cba8d7fde01543 GIT binary patch literal 496042 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 |+rg6tgz4_qovErQy7Z`@E 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 literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png b/mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png new file mode 100644 index 0000000000000000000000000000000000000000..fe6acf6017014dcc9276b2cab06dea1ee02c7335 GIT binary patch literal 875 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQY`6?zK#qG8~eHcB(eheoCO|{ z#S9F52SAuH>slu#P*AGGHKHUqKdq!Zu_%=xATcwqM9|=nV%0LEli9fD7gVh8JB74TXC|SbTX!m<@&F z57=Kg(H`+Xe~wkv^H+Ig|Dsc3*DaW_bKbjo>*mee`|j=R@V}SU`+sGp`}0)1{&P}P zKE~>9{ohY3|9}0ga5mDu{8dDfq`O|xqw^A<59HqAJOtN%X7I`X1BngvttT_=y?z3FDxoz z_br^RiLQU%F!#ouw>1iefj0X~&u%@p;<% zePB6pbPmvh42wYBHBI}qJ3ALW;uZLK^j)5V%*XEkA`^Z@-ed4=H170j8Px_JRA8)@t zu3i7^+%zF+kR^v$9a{n;L{8^lV`Jj8TW+~XRJ!xMmixEAAKt`mvfW>7IaEXG<+m7nr>wy3x1y#8aLJpSErS z%4&KYTG+Bljqy|B8e2w**{ZW26!-jr$Ciq&Vtc`|^;peqVFiA>0Nw<@HQ!FcjSkI;)W{YReLFkvfL_7RsGY(w zPCwQ^_?Gvyo>zUv)X9f(1uRYP$gQ<8;=BJ(>Mq;F;KOe(p7MNX)-gvauYY3<%bX3! u1kaouhA|>@94;nKuI;z|rg5RPo}qgkhsVr`avy*hgTd3)&t;ucLK6UTw}7tz literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/roman_numerals.lua b/mods/CORE/mcl_enchanting/roman_numerals.lua new file mode 100644 index 0000000000..f40c65406a --- /dev/null +++ b/mods/CORE/mcl_enchanting/roman_numerals.lua @@ -0,0 +1,34 @@ +-------------------------------------------------------------------- +--! @file +--! @brief Convert from normal numbers to Roman Numerals +--------------------------------------------------------------------- +local conversionTable = { + { number = 1000, symbol = "M" }, + { number = 900, symbol = "CM" }, + { number = 500, symbol = "D" }, + { number = 400, symbol = "CD" }, + { number = 100, symbol = "C" }, + { number = 90, symbol = "XC" }, + { number = 50, symbol = "L" }, + { number = 40, symbol = "XL" }, + { number = 10, symbol = "X" }, + { number = 9, symbol = "IX" }, + { number = 5, symbol = "V" }, + { number = 4, symbol = "IV" }, + { number = 1, symbol = "I" } +} + +return{ + toRoman = function(number) + local romanNumeral = "" + + for _,table in pairs (conversionTable) do + while(number >= table.number) do + romanNumeral = romanNumeral .. table.symbol + number = number - table.number + end + end + + return romanNumeral + end +} diff --git a/mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg b/mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg new file mode 100644 index 0000000000000000000000000000000000000000..882e9ee23f2018985157f2948615fc3a58bc9d1b GIT binary patch literal 14918 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 IA&m(}cR;q*iA zI&st3T%S$VM_)L_8XO4YlnAcoe%IPvAmAYFf_{`Q4AFUilY%Ez8bMZMtP*HtfwPUk z&yvKu9IzF$Ac7Ry9pruOQ#{GbP?m2XPn3O3h#o>rbX=YXwbYdO)so9Afl;~CR5F5Q zC>*upI(n5EP`>$bmY;C}iXC-m>ZB>-p-0ITZvmN~4S}2b6r^+T`SPcu{>B`_ABEWV zyb{7G4>FsBjMT(q7vf_4#-`SZp5oh2fVIrTNIe)G3?rbvjW44o%)q^H44PiFT+JFm ziks?77Yt5Iuk&^h(`RvGr<1@yqdH3dRj;}zt+ld0Y_DvqYz33sCZAEwfhTPP&#hr&ahb)b9Ty^mM4y8 z8eiO-dLvFu)6Mv~Owof3y&*cnVOPELkR1pr^GKLTu@0e=5-b`EB*6S+9d#ihSzc@uYgEfG?mpJJG0*Z9_j$#e*oq)o!|ff literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/table.lua b/mods/CORE/mcl_enchanting/table.lua new file mode 100644 index 0000000000..fde16f8482 --- /dev/null +++ b/mods/CORE/mcl_enchanting/table.lua @@ -0,0 +1,189 @@ +local enchanting_table_formspec = "" + .. "size[9.07,8.6;]" + .. "formspec_version[3]" + .. "label[0,0;" .. minetest.formspec_escape(minetest.colorize("#313131", "Enchant")) .. "]" + .. mcl_formspec.get_itemslot_bg(1.1, 2.4, 1, 1) + .. "image[1.1,2.4;1,1;mcl_enchanting_lapis_background.png]" + .. "list[context;lapis;1.1,2.4;1,1;]" + .. mcl_formspec.get_itemslot_bg(0.2, 2.4, 1, 1) + .. "list[context;tool;0.2,2.4;1,1;]" + .. "label[0,4;" .. minetest.formspec_escape(minetest.colorize("#313131", "Inventory")) .. "]" + .. mcl_formspec.get_itemslot_bg(0,4.5,9,3) + .. mcl_formspec.get_itemslot_bg(0,7.74,9,1) + .. "list[current_player;main;0,4.5;9,3;9]" + .. "listring[]" + .. "list[current_player;main;0,7.74;9,1;]" + .. "real_coordinates[true]" + .. "image[3.15,0.6;7.6,4.1;mcl_enchanting_button_background.png]" + +local bookshelf_positions = {{x = 1}, {x = -1}, {z = 1}, {z = -1}} + +for _, p in pairs(bookshelf_positions) do + for _, d in pairs({"x", "y", "z"}) do + p[d] = p[d] or 0 + end +end + +minetest.register_abm({ + name = "Enchanting table bookshelf particles", + interval = 0.1, + chance = 1, + nodenames = "mcl_books:bookshelf", + action = function(pos) + for _, relative_pos in pairs(bookshelf_positions) do + if minetest.get_node(vector.add(pos, vector.multiply(relative_pos, 2))).name == "mcl_enchanting:table" and minetest.get_node(vector.add(pos, relative_pos, 2)).name == "air" then + minetest.add_particle({ + pos = pos, + velocity = vector.subtract(relative_pos, vector.new(0, -2, 0)), + acceleration = {x = 0, y = -2, z = 0}, + expirationtime = 2, + size = 2, + texture = "mcl_enchanting_glyph_" .. math.random(18) .. ".png" + }) + end + end + end +}) + + +function mcl_enchanting.update_formspec(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local full_tool_name = inv:get_stack("tool", 1):get_name() + local shortened_tool_name = mcl_enchanting.all_tools[full_tool_name] + local supported_enchantments = (shortened_tool_name and mcl_enchanting.tools[shortened_tool_name].enchantments or {}) + local sup_ench = false + local formspec = enchanting_table_formspec + local e_list = minetest.deserialize(meta:get_string("enchantments")) + local y = 0.65 + for i, e in pairs(e_list) do + local enchantment_supported = table.indexof(supported_enchantments, e.enchantment) ~= -1 + sup_ench = sup_ench or enchantment_supported + local enough_lapis = inv:contains_item("lapis", ItemStack(mcl_enchanting.lapis_itemstring .. " " .. e.cost)) + local ending = (enough_lapis and enchantment_supported and "" or "_off") + local hover_ending = (enough_lapis and enchantment_supported and "_hovered" or "_off") + formspec = formspec + .. "container[3.2," .. y .. "]" + .. (enchantment_supported and "tooltip[button_" .. i .. ";" .. C("#818181") .. mcl_enchanting.get_enchantment_description(e.enchantment, e.level) .. " " .. C("#FFFFFF") .. " . . . ?\n\n" .. C(enough_lapis and "#818181" or "#FC5454") .. e.cost .. " Lapis Lazuli" .. "]" or "") + .. "style[button_" .. i .. ";bgimg=mcl_enchanting_button" .. ending .. ".png;bgimg_hovered=mcl_enchanting_button" .. hover_ending .. ".png;bgimg_pressed=mcl_enchanting_button" .. hover_ending .. ".png]" + .. "button[0,0;7.5,1.3;button_" .. i .. ";]" + .. (enchantment_supported and "image[0,0;1.3,1.3;mcl_enchanting_number_" .. i .. ending .. ".png]" or "") + .. (enchantment_supported and e.glyphs or "") + .. "container_end[]" + y = y + 1.35 + end + formspec = formspec + .. "image[" .. (sup_ench and 0.58 or 1.15) .. ",1.2;" .. (sup_ench and 2 or 0.87) .. ",1.43;mcl_enchanting_book_" .. (sup_ench and "open" or "closed") .. ".png]" + meta:set_string("formspec", formspec) +end + +function mcl_enchanting.progress_formspec_input(pos, _, fields, player) + if fields.quit then + return + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local e_list = minetest.deserialize(meta:get_string("enchantments")) + local button_pressed + for i = 1, 3 do + if fields["button_" .. i] then + button_pressed = i + end + end + if not button_pressed then return end + local e = e_list[button_pressed] + local lapis_cost = ItemStack(mcl_enchanting.lapis_itemstring .. " " .. e.cost) + if not inv:contains_item("lapis", lapis_cost) then return end + local tool_stack = inv:get_stack("tool", 1) + local full_tool_name = tool_stack:get_name() + local shortened_tool_name = mcl_enchanting.all_tools[full_tool_name] + if not shortened_tool_name then return end + if table.indexof(mcl_enchanting.tools[shortened_tool_name].enchantments, e.enchantment) == -1 then return end + local wear = tool_stack:get_wear() + inv:remove_item("lapis", lapis_cost) + local enchanted_tool_stack = ItemStack(full_tool_name .. "_enchanted_" .. e.enchantment .. "_" .. e.level) + enchanted_tool_stack:add_wear(tool_stack:get_wear()) + inv:set_stack("tool", 1, enchanted_tool_stack) + minetest.sound_play("mcl_enchanting_enchant", {to_player = player:get_player_name(), gain = 5.0}) + mcl_enchanting.add_enchantments(pos) +end + + +function mcl_enchanting.drop_inventory(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + for _, listname in ipairs({"tool", "lapis"}) do + local stack = inv:get_stack(listname, 1) + if not stack:is_empty() then + minetest.add_item(vector.add(pos, {x = math.random(0, 10) / 10 - 0.5, y = 0, z = math.random(0, 10) / 10 - 0.5}), stack) + end + end +end + +function mcl_enchanting.init_table(pos) + local inv = minetest.get_meta(pos):get_inventory() + inv:set_size("tool", 1) + inv:set_size("lapis", 1) + mcl_enchanting.add_enchantments(pos) + minetest.add_entity(vector.add(pos, mcl_enchanting.book_offset), "mcl_enchanting:book") +end + +function mcl_enchanting.add_enchantments_to_table(pos) + local meta = minetest.get_meta(pos) + local e_list = {} + for i = 1, 3 do + local e = {} + e.cost = math.random(mcl_enchanting.max_cost) + e.enchantment = mcl_enchanting.enchantment_name_list[math.random(#mcl_enchanting.enchantment_name_list)] + local max_level = mcl_enchanting.enchantments[e.enchantment].max_level + e.level = max_level + 1 - math.ceil(math.pow(math.random(math.pow(max_level, mcl_enchanting.level_rarity_grade)), 1 / mcl_enchanting.level_rarity_grade)) + e.glyphs = "" + local x = 1.3 + for i = 1, 9 do + e.glyphs = e.glyphs .. "image[".. x .. ",0.1;0.5,0.5;mcl_enchanting_glyph_" .. math.random(18) .. ".png^[colorize:#675D49:255]" + x = x + 0.6 + end + e_list[i] = e + end + meta:set_string("enchantments", minetest.serialize(e_list)) + mcl_enchanting.update_formspec(pos) +end + +minetest.register_node("mcl_enchanting:table", { + description = "Enchanting Table", + drawtype = "nodebox", + tiles = {"mcl_enchanting_table_top.png", "mcl_enchanting_table_bottom.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png"}, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.25, 0.5}, + }, + sounds = mcl_sounds.node_sound_stone_defaults(), + groups = {pickaxey = 2}, + _mcl_blast_resistance = 1200, + _mcl_hardness = 5, + on_rotate = (screwdriver or {}).rotate_simple, + on_construct = mcl_enchanting.init_table, + on_destruct = mcl_enchanting.drop_inventory, + after_destruct = mcl_enchanting.check_book, + on_receive_fields = mcl_enchanting.progress_formspec_input, + on_metadata_inventory_put = mcl_enchanting.update_formspec, + on_metadata_inventory_take = mcl_enchanting.update_formspec, + allow_metadata_inventory_put = function(_, listname, _, stack) + if listname == "lapis" then + return (stack:get_name() == mcl_enchanting.lapis_itemstring) and stack:get_count() or 0 + end + return 1 + end, + allow_metadata_inventory_move = function() + return 0 + end, +}) + +minetest.register_craft({ + output = "mcl_enchanting:table", + recipe = { + {"", "mcl_books:book", ""}, + {"mcl_core:diamond", "mcl_core:obsidian", "mcl_core:diamond"}, + {"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"} + } +}) diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..7defcbc659bb347b6768655b9960f4b194d5ac5c GIT binary patch literal 3370 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 A5&!@I literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png new file mode 100644 index 0000000000000000000000000000000000000000..7059db5fcc7c1bd610b9400ff30567517849959a GIT binary patch literal 6708 zcmV-48q4L0P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3*tavVF7g#Y6dbA-eW90#k}+@Oy?p94vXq@-uv zV=YP|nN@`)7I%*T%=*{=Zu39ETbPp}NKo<+*?Ecl(6%|NXPx@Amt1 z^R)K`$0N^oe}7Hy2W;bc{Plqx-sk=MbCbtAPI(9VnE4&hYi7p}@B7L-kazdFeSbIg z{ag!Qw)6h$?{M~g)6d^S#uzg)o_EGAZ~epnMYH((ukkPQzx9bXS)MiT`L6%tpKWJ8 zfBa#*p8jmRr@im+-%Vkjj}N3DHhQ1i_-ET43w>RY{rJ&+e_>6VpRa$u*lzDx_Fi{) zEhH?J%)6=Q9pe1N8?kHf=VOVl%)iLb`FvHr3R@g_Y~sz%*D$tPhqbp2cG_mQUFZ9- zgCz#HT;{uT!};^9`0T11UM>jwvfE`}{WQMdlY!SfkKN~5?3uTo`GzgbJT32Zmciu3 z-@eSB9{zv6J_p)cp=<34#B^-Mx}0K~Wyo{-pLgL9yI-5eW8d>-KHd83j~wgqU_53n zY_L834$-6i6LA~?Rl?@?mh-ua76Tpv?+L~;j9oM@smR#hFbJ7m>6S=x#XH#@g)D%b+qZGpQQgxGn-jvoo(4gD6O#KN-M9j>S~)<+kS@~ zciMTEU3dHR+UwQtUb8%^WmvYL^5V`FlKV@P2Y2}E!SGS z&-L`|~gdLG@&F^kfkI$JM|FSpB262qmJ_cz`)b!RzY%PpZ z3Cn1Ee*EZRuT^$x?F{%-6IMSzdcuUgR*Aw*A)DtngryDt* z#KPp;r(Me`#l_K59@uS8S641Gwh3p#etGlT>RS&^K$bu*yE~Wori?T6h|#-wjGxY{ zdF1WeB)~czuthT$vX}Mw<;@wu*5mHd7`&k2;<7D66YLU-4rB$>!_Do4tea_{u*f|` zY_4PqhN#QVzXO4G!?P+}cA~5B;k|7P^5w(+@N9dq!osBZfSFe%Hd2^oEaH5LL?4zu zAAfv=95|`U{vs&R$CFuP=sCLH(5XvCaC3#Npqd!gFkO$~=1htowt)N^KIwJb#W2;l zL6AR}b48t znL}Q44#Sms((fTl%ZU~b0PJed8b|60OL%aUXegmO{IyD&DccH=6D`}Y)3_&l>p=IJ zM);s<6x-Kgm^(I@1_8`QVu{Ks0;=>M5Y?5e|=NqN9<}8EZ^297rF%MMza+qwC zzS{`EWgE#g}J+Px%htgde{fGm=Ly_>tfi!OT%fRLx`G$kTP4iggFHtkDfB%pR z<|YG9jbjlcHA&SYQyejM(u>l-0YaH1!0Epv)YB^EVuj^%_9(`DudA)#mpPIIp_r(=p;V#2|Fxrf{$vhxGPGgV}d zi;SEhvlvJpG8GtRvyc6u9eI>B6Br#d9V=U6h79P>cYM9*`W$?{@Or=%8-2moIFX8# zNoVKX;jXZp|AC#N5s$Ah>6YpAGvS1O$cAyrjG5P1ewNl-6=s$hT&y`^x>*qOFxwMj zXcant>EST3C8f_kra@I$R(+Psj3?(8QHvhPb{-t9ckTnCFNET7(hW&6uy1OBxLM%= z>YXbJO92;=2l6*r@}hwP_HGWifKK7n2y+LN$WAA&csZChQweDThjEiOs1Gq*7R#{Y z9c&=0Sb7j&D7CcES?sl6Vc|4=NGiL>5mDF*_`!ZyH-F&PM1 zhk!y#v7o*{Si}(@sVyms&@*y0f)1DokU@oR;oiI{2;sgV9fLI7hRrN~MG;Mb#!1+G z@;-vh%KHqf5<7UwyJfUMX_GzmGCaKvSB;XlEwyt;4n2R1bF8TT-YJgDdZ zo1^dUfsAnfdHiJr<@tF=w6uQwdz>HICU-VguBmw3{LT4o8#}ipekyqcXhgY}=wz%k z2rMKjQUoi#P=Z1|+fJ8_19VNjwSYqt6FJ3H9hUc@cAr;#pdw$^l4z2(Nq&V#B?Bqm zvUK=?KLqif+Qt(2%arM+GTxdO>~F$!lsxH_*K`3ddmM9xAhn72>s#8HD2B`mxc$sm z|28-sJn3^Rbh*kJVgh+c_CPuNq+(4Y!TZog>%?9$`LdX05&h;?M@FU{OSpNNAlsB= zTB$E#LmP2T1TR^4f=`RcMs0^IQIS#FY{6ATdZB>nPZ`5M!7J*JT44&nCTbR&o;N!&GHIIHZt000VV%gm^LgVZZ-bME ztk^=a18+)$VS{?miK4rUi7~#!p0cb@Y8^;0mNgR*QRgr|EsAaiDE#%~q)JELqdAAG zmka`XSiPLz=0iZ{Zpn+L+&}D=9pInwpOZYX9mxp7QW&y=1Yb|IT085QR6Cornm7sH zi$_lZ5CPq-OOo`7W*mjJ1OArDe9Q1tjaQ+7Zw(efG46fs!5l!gNE7(_o)J|?^r48g}pzO+?(1YAo4 z^2`QD*gmmSUVVUzr4XtOs*NZsC1HU9g2Cpw4$naBKgu`5ls{9pp*E#grPMugLd_ge z0VY7xAdy_1Dk~0B)S^vycVVQGC>apy<8%j4s^jh%zwmB?ol%V;hY$oghdT3fB}f2j zZ?}#8IZDETA_y0)bo5jjusSnrJm3UL! z(RVw=)j(T7;KN4>(=gbpGprgip`@FsQs^<4t6e(fm_41+kK*NcDNhUhXHgYZ+@yAn zXgi>HTNO198HTuQCvTBq1(GBq*=&mW5wOD;lW4k&K6Y#Cs$5dDEo3&v&XQBa-<434 zu)lf??dZUYWczx0EXg4(EppH^pj~w!6_OppQ#mUwirFv+cA-=i_ow&q_ovj??Sg*5 zpWl=9&DCh|9VI+yRmo>m+zb!00_8vi1(XO&)h;S_Ctx=VW$$FHSB!6E2gV%zrK2Nw z(FtwAr;Wg@*lY?xI)Nh{+l45?f7Ymypd&RvTDAO2C*7vGrNGU{UZFfkNm&Tvx{xiY zI-gbPqwaxR@(%V8?*have*iIi?dGT$HM%Nt2qrq|+Q+LJy}*Eyf6nWQ{f6OIuOEhks#PZzidsTd zEd~hGnSRPmvGKTW{eTi|-)*A^8xO?*sxHex1n;jzmM>RvoeY^K^s;~=MBAz3i5@-+ zUKAU<9@ zoU1RV%u@tljhhJ+H893fNH2Z=l~Y;aPAhXyjGVl5x^#(iNEuW$6fd z5aG1*etYWdFX}cZ0vk_JUJ|H%8(61(H4ljGQwam#K)82cDUlS|J_t(X0<2J&!7EhR z%Mvv1RHAOn5B)+u1#P1u#`qqJn**77l{N}J-Wn%n>#x?c*IdBEGu3IJqPdKRR8@%a(P}=$K)g# zNo^a26Iu$TI~~|*8sK0nyofUa=nbY%mC`8u6L=YfyJbU}K2m&;4?eCwk%;49L679u zqJqq-qAoZjs#XG$Z~~fD!`R!G_{!+wb5yO3m~`EuquQ~}ZD*c(wK>&!4?*!u?}rbV z03}*M*NNz(4nyzvlogMtapTox8EUU%Xvl7QZ&Agm6%q!y4eQqCu!y4nFQqd4Rg87d zt$u`EK*@{V#JfYhl4+iTe8Ng%&O&t;_> zQ_ijvC7@fl%9d)4f;m3~rrL~Tvtd>SUkR+m_ko?EX%Nm7bk+sx`vIs9L>{WmszBED4SBD_51NO4PSEZja`y;{Hru^X6~PIujJ0+2U9*8TlqJ8;itm z2dQu76}6xU+IGO%w^gZvt5N7XO0<;FT2v46#nSzWHpkJ~_Csf zP%xnNYoub~BiF1L0A$jq)ynJQyC&6qC;^e8M%1K=i%=luSW%74*#@=d(Gr6&eHiue zVGU4f275afcKIVAM!m_lk_n2|s3Wzfk7^NEd=50Ml%=Eq6yd0ouZTPOR;T*?jQD&z zFf;im{GpZrT6Qa7)Dj5Pj-&AmC_wPdC{q)fB1N)9q`2B8sd(BkM#c}6Qz#Fl6L5|| zLo$iql++SkHu_u{hy>6%gvHM~z|uM2l{CZ}f*oJRLBU43<-(IZfQwLsqa$QZ>`-s# zLgHJB*Wyp9q=I@rt(P(_pKPe}Y7)kE&x?KbCS;H@^FsvNiD;~Xio_+~De*fa8WOGc zaY^}p>Pl;5z%J+ARp5)5)d!NQ=10W)t5T+fXs4e|!2k>4TzpUm^=CO%^!#2$|EY+M zim#&Hz(60VtsPlg(RnIT1n^@8={6BRH4sTlIbHtV|1zfm7Ec502;wEqQdZWO$c6m} z0ZuMb^u<;3ZNoa%kcOGi^yqgGX{!yfFGE1JlNWG4fH8q3U#){IqZ*a|J?7ovHe*p+ zM`$&57eU#KR=>U36}G&fJtxMzmZ?EeiTCuX z04n%sXN4gw*>M`GyB4fSz}esS>!P`)Q5xPt;+iLWII>(3M6w;#p%Z^TueOn{qg<+# zf;_Uw*hU_WK=}NvXN35BkL`ayibcC1g;5vDES0SO9Lo9iWsovZ-`82JwLv69O>Wg!jykX_I^^J|qYkqI90 z@>CAAp&IWL13LCpse5z^QHEmTJ%zx|>Ek|v@$Hc@)UvEMK8l*h5-S}zQMzA1_3~6| zs1mhT#4nh7I{fI!JlsDbmaq;fq4Nn{tpg&c0k=bFclBo|j@rCYqw~PeYNhGAgqyR1 zIMY<%K{8Mm8xnRN373w$200CR!L}Fl+L7Zr|HI??Yvs$=Xwh_ZNQV5%s5Qla*=opO zUD0(T^q7tbZnx2oll^byKVEf9a1}{OW2JFX=BQ+yn<6K4VsA5=vR5OG1o$Th&{VzjOb5hf8NhgZu9Om`2L%h|5(t?RZrPpc>j#%*Ti*b);g+6$PowEnqYhSPN=c=O?_n zx(R&X_SdWwVRD7aV?`Yr*q)|zUjTU66IA06mIwst*3%d`b)1!!5R2$0N6~$Na?8A` z!s8aG9b38z0g8ccXW-lt(5mlImHLY38iu+xf=AIb3mFg4UDQCgtwV5W7jfZQpL!BT z0V&+RcR6tKxGhifSv!K)I-?ysQ>W-|jn3S2Na`ITdI7kgLv|DeHi5ycj_7sReeS?4 zQlyH-F!_=$qRcoQ-v1a8%(NF0=7EH?uip3ZR+U1|d$xDl68DAkSbjcm2N`d~eJ&y_uiFARU6&lxEU>yl&@R{__N98Ih;@aFRK6Dn?j5d%ym5nNhUzec zTlbp9Q&fX7Toz-l$97oiJeg{|>(+@|KyABpH1sK~r)Q3pVkp;_Ma+={@3^VSOB#%y; z{GyN`WJN3B9^?4;eu6Y4@mRC&Wi^N^Jo%hw>MWjp`IBo^_b=EN%98?gckH4Qm^K9A zN0HqYX6mpBMXAJXV`WHf|51a>YYceGxLYzQdY6^i+d1ud)aW=+&Qe_4lq7+Iv!J3B z;ncahTw`^)Vgg>>5-R8}$(B=HX-DsoV!M(3uA2{z`STK9O%=@EA?jL3B^)FznLyUj z<;82Aa{$qGf2Te54jJDep?L6$O_HJJ=GMG7Wpo#71ziGr9r%amai!}#icGcdai0#t zO_0gmJ;K3xs?tl;jj(tN7G&CMBguvCK#%8KmjvW45lsc%xyYn0u1ZcEcKV2xaZ8>m znSc#4jDY2(s`I{Sb;tzNF3j0-)^WdZ__@dQqkPOF5!o!$x;m(3TCHl`f!h9Drn9nI|bw(Z7X0rM{ ze+H~iB>M?*2g#zP_WQWt=#u$)*;Kte#HAQp2PgM7+a3B`fKV;jh1--0$YMNms}&QU zRP2wQp#73o`aO8Lz9V_UZ8Yc{pI1;|A(eYc)O-n0U5Wj7FN*$l5!7H?^`rlE8T9L= z&+^;7&n?hqfd2yk#}UoLxRg}@000JJOGiWi000000Qp0^e*gdg32;bRa{vGizyJUa zzyWI3i3tDz00(qQO+^Rf2M`J$BwzLyA^-pZLPP@GeFL^j* zw)C>*&{C5_L$pXxn~Q%ya}NXPV@X${p}rq@c5X`Usy{Lj!Yt4UtV#0an4pEPGn}9 ziMd$-UheLxJv{#Lws&$&Ev_Oosuk-uuPhHAk`Dk;a^sa{3i)FIR^rP5G^!N@b4Zlj z0Jc!G@k*&!W<9w9l8@e#YLz$vf}#t6Qn8GpYQx}<6jh_wYE#%du|BWUpKqj+KN7pUS6Y!&`8XaA? zvd&O6Mo@HNbo(qW&07toO#Ezi6O%3!jo}z|0G}TQO=B?f0KNg);)3w^stEc30000< KMNUMnLSTZ1$^#$( literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png new file mode 100644 index 0000000000000000000000000000000000000000..92674cae1a0dd1d994a7d8e3b7187365b2446a73 GIT binary patch literal 875 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 atDwU5iWgR9N7^^@1!$`3sZ_umUjGl^IQTvQ literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png new file mode 100644 index 0000000000000000000000000000000000000000..d733e4e5e8230ea24a83c2b870e1b1ffd3fb32d6 GIT binary patch literal 876 zcmV-y1C#uTP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=H2lH4E+h4-8yM?exn;y4&gRc?^u=Yg62n@OsY z$|8$4WrJn$0DXe)aQ^r{!Z%!0B!;Bsx#S#irIHF)G(29{RZ~ps8TZ>q{bUcf4~&+e zmg_a2+rPrD_YRh}{dl$qYg@;+(1-9AlsPh^vHg4t314>F@1g8|H9ah6-=p#RtjG1~ z^*tGa(G_~aflnccc={YguDjwkJV`Q~NMu>2J&AuEyKrm11n<^*iCwJQF3+I|F>ioInt`xxi7x|%W~mBU`t$5K`cjtFOx)h(kKZbjQx zDJYI5HW2Hed7!jFg&5Hul&DjsLFcL)HB2$_$%dM_u`HX5ap5KtL7IgIn-u9m9Gn`c z3Cw((3$1a>8n2OK18S#xy3m`GgmM(AY86 z72j3DL*B#(umXa*!t7XJjmIT%DBW{Q7H5H<#uVbUHOTrFK!`B5VlpHk5HpEVrfAGY zgg83*RLqoU-PeEzdKmnpiTmY-Vo7s*5LA&u;EsycRBkBTP#!7K)crYQ>-x(iOcc zJZe4okRu&>%26BAr=_MXH*4NXtDU=aZ2z9Sh3>uddeVthI@76VKJE0goOK}A zhKw|H7%)aXdJDaU{!1bJeJJ54 zH;$4BR!G@;00006VoOIv00000008+zyMF)x010qNS#tmYE+YT{E+YYWr9XB6000Mc zNliru zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=H2lH4E+h4-8yM?exn;y4&gRc?^u=Yg62n@OsY z$|8$4WrJn$0DXe)aQ^r{!Z%!0B!;Bsx#S#irIHF)G(29{RZ~ps8TZ>q{bUcf4~&+e zmg_a2+rPrD_YRh}{dl$qYg@;+(1-9AlsPh^vHg4t314>F@1g8|H9ah6-=p#RtjG1~ z^*tGa(G_~aflnccc={YguDjwkJV`Q~NMu>2UB$nSUAQ%0f_H1Z#4grtm*-G~n72cI ziP5%`ejU3Np~o4~edMPPpp)a{^%%R+eT?&3T}>I0%3&|+V=1czM}#xU>XuOqx1w#U z6coo28;Et#JWyJoLX2n+O4O;+pmWuY8m5@|WJAr|SeDJjxNwt+Ak9L9O^Wm&4o(f! z1ZKX?h1R%bjn~LAawm8)L5$GjQwd)g|EAo8#+a!~6#W(}%!_AEV;Ym(e8LMrXzZBk zitj4nA#dUXSOGy@VRkIA#^aJWl5ASJ z9BBx)y`cywtvsvLib*JJ?TU$o$1swpLY6L&N`55 zLq-}p^048fjC!NCsXkMq7jnO+Mw{9smX@F0sljaaAwlyv(a8+NI1z~3B!GnG$t*gh z#FN})77JrjD1#d5gwtsf1Hp6>>!2IEJGtL-3!46j8~=)2nCSimxiHafa-X?Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl2}{WECbNYB ug+x4E978y+C;vEn;6Opc!G^~6Mn(of6ULwNaXWQ^@(iA?elF{r5}E)T9wi?D literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png new file mode 100644 index 0000000000000000000000000000000000000000..d002147f50c9623f1e7db05d3d933a475f0e2c8a GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl35!YvuDh!T q6cX@saSY+Op1dL90fRFe8y^F+3PYr=Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl35&9bP0l+XkKppqlY literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png new file mode 100644 index 0000000000000000000000000000000000000000..dc5dd1d2020d45f601c6c35d85d3544f1c545eda GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl35%$7Uio+g pD8%pS;uyklJvkvkfWgUtlY!BP!STn3m!d!^22WQ%mvv4FO#ozwB8vb3 literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png new file mode 100644 index 0000000000000000000000000000000000000000..45c6d5a638c7400da787ccb7fd9a6e35b940879d GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl3Cro!KA2bo t6cX}uaSY+Oo}7^IAt52*2lEjg2KEL<*B4TkCjn&{JYD@<);T3K0RZxnB?tfj literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png new file mode 100644 index 0000000000000000000000000000000000000000..68623878a089023b3da3a4fa6f2e27d51190cccd GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK xgTu2MX+VyUr;B3<$MxiZgan2pW;RAPMh4~@hKX8Q${^DiJYD@<);T3K0RS^>7Dxa9 literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png new file mode 100644 index 0000000000000000000000000000000000000000..0db3a9ea2739d4e4e685eab827b48de850773799 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwX{0G4WdzViJif|TqL>4nJ za0`PlBg3pY5H=O_6ICX!cu%^-iXct3h8>fIEHXsPfh@W9TgufnT^gK00Nfe tm_0xK*c{AAFuec( literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png new file mode 100644 index 0000000000000000000000000000000000000000..d10a72b7559894c14779dcbb7240107b9dda2475 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwX{0G4WdzViJif|TqL>4nJ za0`PlBg3pY5H=O_6ICX!qO^yK5w~!LdKphjv*Y^OS=zpGAIZfUbN$X-aVmR zt~D>6_c|FVdQ&MBb@ E0J*#}+5i9m literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png new file mode 100644 index 0000000000000000000000000000000000000000..2b374e881679f09485473f69066efd0522e7986e GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*ZZ@dAqwX{0G4WdzViJif|TqL>4nJ za0`PlBg3pY5H=O_6ICX!qV2wE)V_zh2%V4978y+C;#~W-~RCb|NkZR;%ffM i&rC}?!1zLuk-_$zF#oTOE4KnwGI+ZBxvX4nJ za0`PlBg3pY5H=O_6ICX!m<+Om1ZC#^*mi1LpZM2p4lkKV8C(M;o!g1hOWm1 xe0QK|HXG;n@f&E{+;B4C~}^EXf@gQu&X%Q~loCID?HE@A)x literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png new file mode 100644 index 0000000000000000000000000000000000000000..eb1e74fbcb8e6fca93aaf269e1d5cefa7672a43e GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl2}`hMa;%#M s6cX}uaSY+Oo-B}%kgy^#f$@+O1Ir#p!5d|kFMzTPp00i_>zopr0IJ<14gdfE literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png new file mode 100644 index 0000000000000000000000000000000000000000..e82145e5c27dfbe25ae08937e6d8534a88b4a4f6 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl35y%-P%f(i t3JH0-IEHXsPri`wAmIXo6Du1p14{|R$+qLCegS0}JYD@<);T3K0RYkhB!d6| literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png new file mode 100644 index 0000000000000000000000000000000000000000..e93f2383071de536b4692bf350c7b4ff49118968 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK wgTu2MX+Vykr;B3<$Mxh73{H#+AqfQx4D39Nf=Ojnc|b`9Pgg&ebxsLQ05>%kM*si- literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png new file mode 100644 index 0000000000000000000000000000000000000000..f0635bf2b39cf3fdce8fc7e42516f5392ca5bd55 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl2}|in_JmXb ug+x4E978y+CkG@1BnTutNJvOr!N|b8hT&$)-p>L+c?M5cKbLh*2~7Y24kTm% literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png new file mode 100644 index 0000000000000000000000000000000000000000..c93976cfba6fd5ce800ea5a08a0b0cd39daeddfc GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl2}>B*@6Or^ s6cX}uaSY+Oo}7>nz~IEp#>mFVz-+@XQT$WxZlElKr>mdKI;Vst0E`VGN&o-= literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png new file mode 100644 index 0000000000000000000000000000000000000000..1e4ff024898eb70b7e3d7ee370ee36ad456f7e53 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl3CoEpJ(Vm0 q3JG|+IEHXsPo9tvkQl&ln1z952E$+GT77Mx9D}E;pUXO@geCx386kB5 literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2b86c16525bd26662ac61021db2bb0fb7d7656 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|Y3?y$c)pCP40X`wFK>Fgv=lzMPzCadZNswPK zgTu2MX&_FLx4R2N2dk_Hki%Kv5n0T@z%2~Ij105pNB{-dOFVsD*&nbl35%(PzWI~| r6cY4waSY+Oo-B~S;KUOS%)_uy=irGOKuHEqS3j3^P6Fgv=lzMPzCadZNswPK ugTu2MX+RF2r;B3<$Mxh72?Y&@xEMI+Fdp>!^l3g&hQZU-&t;ucLK6TsjT$Hb literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png new file mode 100644 index 0000000000000000000000000000000000000000..1a224f35f327c5bcffe422cb6e70fef4552232c7 GIT binary patch literal 1666 zcmV-|27UR7P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|ck|ZY#{O1%t0ul(pad<}f20p%%N7Z!q^p1DO z`{M`~(FLeflE{>x+VsEv9Oe&POl*x8jUk0#arxvEXAGj<*Y3&sbw3k(4W8uYe!vhp z^lnc>Kl&MR`FKJ7k(Xz=(R%E}W9YJc47%x=F*thh7;?Pjbmk_V_p*Oj&iReX>#>ym z=ymQDU^Ia}$A-HjXK|0yi`&19pW;p~K#3sBPF%vBoxaD;+`|{}?$HZ&HXpfrhQioz z6v7KeM^5q{yM@pTYnSJz2LMy;T}xRbC<0FJ)@uPx@e_=7 zwS*S2#0th5*eqz(P$CA}gFH3LG^nq>QbmZKJ1ctT%5KS`Q%+pnq`=QcgB3J1<06=- zV9i0ycPzC0rsc0vgy%-kWP-8D;-_Zb3BS{BLu1U;C9?6x3UTqwX@oJEn|Ek|5E=(l zS@^DI9`eRM5bMC8ESMt}m~Gi6iqJ=Hxy7@Co>*_}E)CLl3;-hd76d~M4A?+UD3DcV zB?68S{A5JV&T|0+B*Kl%05=Ympd5Mn#yd(&mxZ?&TMLK~7f?2F77EDnUXVZPBXTH< z6K_N$h)R?sIk@11gb*~$Ju0hHucAR!qbAMKMIR-Gs4>PAbK>N%g-HrYO^PX{oZ&RX zbjI5m8aWp(uJ|G)6fLo&k}J}u`YJV4t+A$>8#mWb{w*{$EwMYhqcL=UwZn%8pNuX37Xr9OwPa_?COM5JV_?vCVi|OE_rctkyczMo#2f#JIWwvI9n6_Y-C^!C zZ*N#@d7UV35j3lCVrt#M#s-BRGsis7q;L1;-x~O@8XDsB8sj+ox_74L-+=Ut=$(6) z+ZvT#{h)|^SSp1mH812*3P{;3b4Zd>W3^^KQ9(IKUiu>z*RuP?P|cUfyo6TEnxz=K zZl@I&j==?X3C>@TaoN!h3R=9RW2MdWGoRS2q~55DuIc18!(&q7B)ZabA2Yt3vX3;1;1LY$s%bBE0~AE@!E65`A3gLctY zBWSy&J2~*B(s|1=Q7{*hbs|}>MaGF_*sG5?JI-nYAr)>8p8z#K$^0{rK@MBk&=1$f zrJNoie8xJ`ff_q6^7G`)%2XO}|iBANBJLgbCZW;3L+Z(#GX?TsX4isy1JT z+B<3UO4_t$I8=Q%%Mrd=!_nso54Zb&BK=`w`yl)3dkK5lg*k^=oc*f#P{TMd;Qvd;QG3X;R|-7z=IsOOIbA6rhpHA6{{Pf;Z8TL2U(P|O zdDwBTwawDmm2>g}`)8ptPF@h)d}lv;lb!Ff%RHr*eND5KWuF*&mv!cQN6_a3&-|3T zZ=NFjzoCKew`BeX=^ya&0F=<$00006VoOIv00000008+zyMF)x010qNS#tmYE+YT{ zE+YYWr9XB6000McNliruSn3It z2sf1EqT!ZA1ojc!{0hN=dsDk`i{HTQ)|RHm8a%||jG%g>65`IJggbL;Fh#rb8td7f z_vQEhzwh(>;je4S@3LGjyUsLCo9mbT;83o{-C&oSQJRC}6I!p^6n6#~hT$(TflaHA z=-soinnFDHkZlzaQRYMfUa(xMGip~^>zL?N2Ch$kduTlJrTY^x-t7>D^HpO5PRQ)kh#JaZ77Z9=&kqjq&H zwx=Laz_Ivvf}>2s1-k?;v?kH?_o|%nz~nHH!4q~x`Db(&LI11107I93GQU9S>i_@% M07*qoM6N<$f(rE}w*UYD literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ecd6b11207d578fdfb5715e348e0d2967f719a95 GIT binary patch literal 1787 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4n7yk)B1(c1%M}WW^3yVNQWZ)n z3sMzQD>Bm<7%FbPofciBqRHd>Kk}#!qbJ9aA`dyi&CQYjVmw|wEV?P17hYe|GWkSH zNLTj-##J%@-`{`u@1X0=MclJ=o=MoQo8bJcsqN=ytL#sSw%@z=o7}r`_bc;Zl@(8G zdTW1+-}rh>u{GEJ-mTbG(Z{!4aING%B{TEljk;~EE&kST%cqy`7kamBbH1$ITff&; zHT;|>Gq`LMkH>o0%rldHvWNR!i@Ilv@WC(_)d!kM=Zl}OJKO#wHkyCu=hWLzbG7F5 z-&VAHl5yK}{`0)l7mc@4pP0*g?dAKZSDtJly?Fj+ZAGQvi*G$+mu-qFu$kZ$c~{Bn z(AtdUp+;SaU7|;%GUPO_2CBJjV`t3@$q0xqUD_qUT<*7GruOMgGgZ#Tq$+W2zVJXL za+WajWUeeGYV9xwmeoQ;f}YxkEFa zJQI#%a7un25?&WxSpNFh{YFuND^t@Bvvk}0bvnP?wk@Sl?8i#}bMvE{gKjf<2p$V# zab{w&o223Tsnb$Wv7gP3b>e0gJBNmlofD-Kly7i$_CCMyVsggMO`kH4U1So_61;uP zVFg1NN7vWMO^LjsqP%{gi`7ieMlCubV0vuEBb&uulSC#hn-R2WO0eO^gsh8`W~OS- z-28y!vP^N&&7yNl6D}~lY`VuPw^XL)gdm^oqltXhp8~a}`SXTmuUQ#&cB@I=r44_h zb55FO@0{u<>%Fplo$a?PYoEulUAr|wu&vMH(uRrdJA-bA+z(pJUNk>=v2U&r_i6pR zD-O=N(6tdXtt{O6qYKBQjo>FJe!IsW!KHQDRj{L62=Ylmf$eD5`2wqgkI32_DH zG8=1aUq`D*KlixE@a%-h+`O#vlHxv9rFmAmvkRm51iS8;QqtGcF>lWF3#)tYA6WGI z(q^EpQ7{?;!yp7qd2c5Gy}?)#?NMQuIx|P1-Q)An|9s=$}`A%x;TbNTux3{VEDl0aq(hqgMt7RhP0xB df`F4d8MLDq;)48|d4LKTJYD@<);T3K0RT%A)`0*3 literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png new file mode 100644 index 0000000000000000000000000000000000000000..60d755e94e83122f726fbd67e971472d151b2964 GIT binary patch literal 1660 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4nC?`CM3e+2mMat#<)>xlq$-qD z7NjbqR%E6zFjU-nJ3VmHV-23R`<6%L7(F>UA15$}7B}1e`^%S8phO{X?uuBj0hRva!_d^V=tUNL~I{?$o>R%gdj>iFV&|H#2tq z`;!7a%Pt7>-Dy>M^zyRfy4{b=Y&?zTaBS1k+NblW_RXQYHJtbER&~a%xvh78A%|gp z`yZjjx$1xI%Cw#IugEFe*CrJ4e^f0?Hj!T(zk0Q%a**X4SKDcuq6%yTPH9U?9xc$m zwav@1Q0F7dMz&e(rzBShDBo%pGF@e|V*Rfr!ofawZUz|7*E#(xDdxwNPKC2h&Awe* z7{qkcS8$%GIp2D1M`~~Rq~s@VA5xlbEcvmt<$cfo;Jk%~X|IG__b0bje)O^RNuD&@ zzk-pYS2j5IW2|b;so6g`*EB3xXJ9QB@wm`a#!G&uYWL;?{>fY)Z%L)(ax1to#9 z33SYK(F`_8Q+AS(tamMV0$P%{k2$Vj z3iImvv+>D^g{u~6uE+`tzP`xR+b^>C+_dMCp}smZqs)xACtW={d3CyZxqckC_(8#C zs^Z*7y*0NcUEq4zbx%}ot6a^AiF~%765HjUu28@9+-Lc`pIa`UFS>TjS87}R>9bCs z!=m0^ndoI(`gUjZ_qZzA6I&IPd1WhadWahX}?(x>V2R}##s zJucYzl^8J_`msDR<5XB!Y1Hkf`BBAu=FvkpL{2SmvwCPU>xhFvX_9Qo=HCk6z4II| z?|*d6URhjim%XE&Ps!{%;d%E1vP)|hpI|a6f7p{brLmcp@2+B|mLR^8#-p1P6*U>7{&pj?O zJUbyWH!rKaq_|I2X`Yqt?84|h!LECzl=Ss<%$qa)!s_1p2Nu1)v>B*t6pV(zFbDxt z-rEU4Z!new`2{mLJi7rb;~5x}yxm;OkH}&M2EKhD%=pS_;{l)`dx@v7 zEBh060WK@PoPB)4Kp|dF7sn8Z%gG56tS5j*2rw|dnf|y6D8b
gTe~DWM4f&V`s| literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a90100f127a66ff6995951a786d95f503194bbbb GIT binary patch literal 1857 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>a7?B1(c1%M}WW^3yVNQWZ)n z3sMzQD>Bm<7%FbPo#tKkM2n~G`I<+1jGi0^iwydUtJwGc`Q5CkzB1&}OO^{SQxWuHi4=?#604H2E;oJORKE3H((}{PPM;32kl*gK zr~Bfx$##8ryDrFXo&8)~|5fU%(l^I4GJERQt!wGHEDn=Se$G<~*i$H2kQoP~Ebawqr9^dOx`=s(q$A{Z*pW+G@^B zOm>qrTt6Mlap_2An%^{YGmD)=L&(mF(h15pIFEHM&+jpe+O?*pt8fcLi`Nk~PlXT$ zZ5G#m5gsQNE?RVOWmd@LC6V4!Bo-Z$&^>3oYDR>?){L~1o2II0s`wg4dTB17WXauU zaMp14Y0c*`Tyw-`=t;yb2t0MLUFP8hWx28?%JNHlZ>wi zonBk=%44bAu5UNiE}vH|d19-gGLLNG4G-o1qQKiB@j;8Ni{1w>_RSUI_C7yvg=0>c zvEyfpizj)GSO|37R%vK?cJhomSEKsQlV{S8Eel{Xy~Mfvq6%BnLgCj7y6+0_EZ=F# zTYt3ozS48GUGEiugzr1k?d(^gBA3t8aVQo)H=|0@;>Lmt!4E^8)n8hk{XLY~zO9a@ zcJ{)=Cu!aNvzCV6caF@D;t&zB|MUNOFo9~?6CiYllM$|j&w9kpo_4E2C{hs%8PxcGDs-F?IXAc%-cdMpZ zedrguc4^Q4h5v&7o|rK8vCq79l^Hva{8(mp^v8zB1?H#zZmoBz*lj3vD?jOb#@_W; z|Ic~wuKR?Z(mQ95dvO;-cWY1LZ?E4|cHiOO@eB5OC)n(AHvN|8x!I(CJ>ktZU}j_p z@Ck7R=1m)GYhOpJNI&dB#OnGl70KLIj666=m;PC7Qup(k$O!9VjVd!9$^#F1>3p^r= z85sEXfiUAMr;P`Ig6t)pzOL*~*af&OMbCblVgnS?^>lFzk+__kut4*{vj-1c1Q|YA xTo7HzU9gC=KuPi-;}mB@p(Qh#fxwH8jUnhB!{+>BrS3qD44$rjF6*2UngBU70q6h# literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png new file mode 100644 index 0000000000000000000000000000000000000000..9ba41bd557bb184a5c4aa77a4bc9e2df37357682 GIT binary patch literal 1661 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 Tx{3S+pjHM?S3j3^P6xlq$-qD z7NjbqR%E6zFjU-nJ3VmHV-23R`<6%L7(F>UA15$}7B}1e`JJ!j&MVsc zY~Nq)H@_|(ytGaJ{I`VX*FNfg3Aoo}weJG)N#<^!4S#LjHOok8>fyL6$(pNKk25cva#eS+ zM4s#IFinj<)p-in96mc(GK(g;R0k|_o67d}tIf+JBEscnHZ%RFr4}3N)tqvfkhbuk znrjpT_cY-vENT0mJ7wS5bjmjw6kZ{MwEVh^6KWRGG01DJ#1^Mri^^Nw*RsnOEphIzx$)55@>S;-%gZa%?cRRbJZEd+ zi#A`_Gd0Y*bV-nZZ1uZqd#A^-7v-MtaCVn7tC@lOdc8Y&MXS{vN`FSw$Z?>)o8^;KZ{;9Ljj+;5$t#0*q!)0 zDf+^f^*cVEKhfIx&VK^8@LjdVt%4=kKTDo|j+Bw?AAj zTEV@y^`2Ay!tEELU+8}MFDUinW5fPg59L){Cb}9M_tY>jFf#=Bgt!9Jy^XcCucK9@ zpL<+ncy>Z$ZeCV-NpYX5(mX5O*@e-2f?fAaDe3F!m^Wwoh1I?H4=j3pX){pQC>RZa zVGshQytfm8-e4>V@(X5gcy z_7YEDSN13D0$f%y^V#d8fkM2VE{-7*my;7DSWf_r5MW?@GyQQDP=dkJ)z4*}Q$iB} D1cs%A literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..ef4cc8a156fe05f7188ea48189f9fdb5df8cd93f GIT binary patch literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Ea{HEjtmSN`?>!lvI6;>1s;*b z3=Dh+L6~vJ#O${~L8%hgh?3y^w370~qEv=}#LT=BJwMkFg)(D3Q$0figD*u3fvT2y zx;Tbd_)nc=$amO)!?k#N$?F$uy{E}6l&$*TJ>|v1`T1`&R<$TG*VXVu&U^h>Kl;(P z)msm_967t0^UdvVfA^&B_;pN?N2k%FzgN+zhEGJ0t2k7YpLI#+swMXd_@{_Zk6O-T zbzopr04q*zg#Z8m literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png new file mode 100644 index 0000000000000000000000000000000000000000..858b9e3dc277f5ece9e924828de4bfbd637ac761 GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b z3=Dh+L6~vJ#O${~L8%hgh?3y^w370~qEv=}#LT=BJwMkFg)(D3Q$0figD*u3fvUE9 zx;Tbd_`jWG$bHCxr}cAuN%5M=8nH_zFV^MA7(4O z5x-pcUVXK82lg~oy zqo(V-7#=VD*L@(Rbx*j7@Z^~bUOAT8NFA5r2(g{FVdQ I&MBb@0HD`+`2YX_ literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png new file mode 100644 index 0000000000000000000000000000000000000000..95b45c70e6cabffbfcbc3a80c37bbcdb539dc8f0 GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L0m@TF)WP}K!b z7sn6_|JI3$e1{waT&u+kPFVTy@^u~+_mpDc3py@3f#q;)z?@d*4<~N>h->72+BEm( zzwMh_A8ojQVrA|>K}n4l+rL_=*XPb&pWk>q$4GXm@QN4DQ#r-d?nH)&)^PZJC|#l| zlf`oA<>Hrj_uiZT_36etbHk5IYah|{?BMKkTfkP#ac#|!Dwe+GWqg*;E}WY1pjIR2 zX>@^Jpnh^j%m?R_jN;7`tQG&U$3NNdGIZtS1I`b*7flR%QFkrwp?K1qc`OUd6V_P1 iS)$E(mO=A^nSM|dbMXFOmv#XC#^CAd=d#Wzp$Py4M}i*! literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 9f49eb158f..8231c8ed6c 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -119,7 +119,7 @@ S("The speed and damage of the arrow increases the longer you charge. The regula range = 1, -- Trick to disable digging as well on_use = function() end, - groups = {weapon=1,weapon_ranged=1}, + groups = {weapon=1,weapon_ranged=1,bow=1}, }) -- Iterates through player inventory and resets all the bows in "charging" state back to their original stage diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index d019289d03..a05a0b774e 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -312,7 +312,7 @@ minetest.register_tool("mcl_fishing:fishing_rod", { _tt_help = S("Catches fish in water"), _doc_items_longdesc = S("Fishing rods can be used to catch fish."), _doc_items_usagehelp = S("Rightclick to launch the bobber. When it sinks right-click again to reel in an item. Who knows what you're going to catch?"), - groups = { tool=1 }, + groups = { tool=1, fishing_rod=1 }, inventory_image = "mcl_fishing_fishing_rod.png", wield_image = "mcl_fishing_fishing_rod.png^[transformR270", wield_scale = { x = 1.5, y = 1.5, z = 1 }, From 1cef707c6c853d9d62df599ca1dcb4b6ed0b5c6f Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 27 Oct 2020 18:19:49 +0100 Subject: [PATCH 02/27] /enchant working --- .../LICENSE | 0 .../README | 0 .../book.lua | 0 .../command.lua | 11 +-- .../core.lua | 76 ++++++++++-------- .../enchantments.lua | 32 ++++++-- .../features.lua | 4 + .../init.lua | 1 + .../mod.conf | 2 +- .../models/mcl_enchanting_book.b3d | Bin .../models/mcl_enchanting_book_entity.png | Bin .../roman_numerals.lua | 0 .../sounds/mcl_enchanting_enchant.ogg | Bin .../table.lua | 0 .../textures/mcl_enchanting_book_closed.png | Bin .../textures/mcl_enchanting_book_open.png | Bin .../textures/mcl_enchanting_button.png | Bin .../mcl_enchanting_button_background.png | Bin .../mcl_enchanting_button_hovered.png | Bin .../textures/mcl_enchanting_button_off.png | Bin .../textures/mcl_enchanting_glyph_1.png | Bin .../textures/mcl_enchanting_glyph_10.png | Bin .../textures/mcl_enchanting_glyph_11.png | Bin .../textures/mcl_enchanting_glyph_12.png | Bin .../textures/mcl_enchanting_glyph_13.png | Bin .../textures/mcl_enchanting_glyph_14.png | Bin .../textures/mcl_enchanting_glyph_15.png | Bin .../textures/mcl_enchanting_glyph_16.png | Bin .../textures/mcl_enchanting_glyph_17.png | Bin .../textures/mcl_enchanting_glyph_18.png | Bin .../textures/mcl_enchanting_glyph_2.png | Bin .../textures/mcl_enchanting_glyph_3.png | Bin .../textures/mcl_enchanting_glyph_4.png | Bin .../textures/mcl_enchanting_glyph_5.png | Bin .../textures/mcl_enchanting_glyph_6.png | Bin .../textures/mcl_enchanting_glyph_7.png | Bin .../textures/mcl_enchanting_glyph_8.png | Bin .../textures/mcl_enchanting_glyph_9.png | Bin .../mcl_enchanting_lapis_background.png | Bin .../textures/mcl_enchanting_number_1.png | Bin .../textures/mcl_enchanting_number_1_off.png | Bin .../textures/mcl_enchanting_number_2.png | Bin .../textures/mcl_enchanting_number_2_off.png | Bin .../textures/mcl_enchanting_number_3.png | Bin .../textures/mcl_enchanting_number_3_off.png | Bin .../textures/mcl_enchanting_table_bottom.png | Bin .../textures/mcl_enchanting_table_side.png | Bin .../textures/mcl_enchanting_table_top.png | Bin mods/ITEMS/mcl_bows/bow.lua | 2 +- 49 files changed, 81 insertions(+), 47 deletions(-) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/LICENSE (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/README (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/book.lua (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/command.lua (85%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/core.lua (71%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/enchantments.lua (93%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/features.lua (99%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/init.lua (94%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/mod.conf (75%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/models/mcl_enchanting_book.b3d (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/models/mcl_enchanting_book_entity.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/roman_numerals.lua (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/sounds/mcl_enchanting_enchant.ogg (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/table.lua (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_book_closed.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_book_open.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_button.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_button_background.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_button_hovered.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_button_off.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_1.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_10.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_11.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_12.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_13.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_14.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_15.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_16.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_17.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_18.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_2.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_3.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_4.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_5.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_6.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_7.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_8.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_glyph_9.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_lapis_background.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_number_1.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_number_1_off.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_number_2.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_number_2_off.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_number_3.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_number_3_off.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_table_bottom.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_table_side.png (100%) rename mods/CORE/{mcl_enchanting => _mcl_enchanting}/textures/mcl_enchanting_table_top.png (100%) diff --git a/mods/CORE/mcl_enchanting/LICENSE b/mods/CORE/_mcl_enchanting/LICENSE similarity index 100% rename from mods/CORE/mcl_enchanting/LICENSE rename to mods/CORE/_mcl_enchanting/LICENSE diff --git a/mods/CORE/mcl_enchanting/README b/mods/CORE/_mcl_enchanting/README similarity index 100% rename from mods/CORE/mcl_enchanting/README rename to mods/CORE/_mcl_enchanting/README diff --git a/mods/CORE/mcl_enchanting/book.lua b/mods/CORE/_mcl_enchanting/book.lua similarity index 100% rename from mods/CORE/mcl_enchanting/book.lua rename to mods/CORE/_mcl_enchanting/book.lua diff --git a/mods/CORE/mcl_enchanting/command.lua b/mods/CORE/_mcl_enchanting/command.lua similarity index 85% rename from mods/CORE/mcl_enchanting/command.lua rename to mods/CORE/_mcl_enchanting/command.lua index 28b0cadc1a..e93a3979c7 100644 --- a/mods/CORE/mcl_enchanting/command.lua +++ b/mods/CORE/_mcl_enchanting/command.lua @@ -1,5 +1,5 @@ minetest.register_chatcommand("enchant", { - description = "Enchant an item." + description = "Enchant an item.", params = " []", privs = {give = true}, func = function(_, param) @@ -8,10 +8,10 @@ minetest.register_chatcommand("enchant", { local enchantment = sparam[2] local level_str = sparam[3] local level = tonumber(level_str or "1") - if not name or not enchantment then + if not target_name or not enchantment then return false, "Usage: /enchant []" end - local target = minetest.get_player_by_name(name) + local target = minetest.get_player_by_name(target_name) if not target then return false, "Player '" .. target_name .. "' cannot be found" end @@ -26,15 +26,16 @@ minetest.register_chatcommand("enchant", { return false, "The selected enchantment can't be added to the target item" elseif errorstring == "level invalid" then return false, "'" .. level_str .. "' is not a valid number" - elseif errorstring == "level too high" + elseif errorstring == "level too high" then return false, "The number you have entered (" .. level_str .. ") is too big, it must be at most " .. extra_info - elseif errorstring == "level too small" + elseif errorstring == "level too small" then return false, "The number you have entered (" .. level_str .. ") is too small, it must be at least " .. extra_info elseif errorstring == "incompatible" then return false, mcl_enchanting.get_enchantment_description(enchantment, level) .. " can't be combined with " .. extra_info end else target:set_wielded_item(mcl_enchanting.enchant(itemstack, enchantment, level)) + return true, "Enchanting succeded" end end }) diff --git a/mods/CORE/mcl_enchanting/core.lua b/mods/CORE/_mcl_enchanting/core.lua similarity index 71% rename from mods/CORE/mcl_enchanting/core.lua rename to mods/CORE/_mcl_enchanting/core.lua index e9fa523f2c..52cbe53b34 100644 --- a/mods/CORE/mcl_enchanting/core.lua +++ b/mods/CORE/_mcl_enchanting/core.lua @@ -42,38 +42,43 @@ end) --]] minetest.register_on_mods_loaded(function() + local register_list = {} for toolname, tooldef in pairs(minetest.registered_tools) do - -- quick test - local has_enchantment = false + if tooldef.groups.enchanted then + break + end + local quick_test = false for group, groupv in pairs(tooldef.groups) do - if groupv > 0 and mcl_enchanting.all_item_groups[group] then - has_enchantment = true + if groupv > 0 and mcl_enchanting.all_item_groups[group] then + quick_test = true break end end - if not has_enchantment then - break - end - -- expensive test - has_enchantment = false - for enchantment in pairs(mcl_enchanting.enchantments) do - if mcl_enchanting.item_supports_enchantment(itemname, enchantment) then - has_enchantment = true - break + if quick_test then + --print(toolname) + local expensive_test = false + for enchantment in pairs(mcl_enchanting.enchantments) do + if mcl_enchanting.item_supports_enchantment(toolname, enchantment, true) then + -- print("\tSupports " .. enchantment) + expensive_test = true + break + end + end + if expensive_test then + local new_name = toolname .. "_enchanted" + minetest.override_item(toolname, {_mcl_enchanting_enchanted_tool = new_name}) + local new_def = table.copy(tooldef) + new_def.inventory_image = tooldef.inventory_image .. "^[colorize:purple:50" + new_def.groups.not_in_creative_inventory = 1 + new_def.groups.enchanted = 1 + new_def.texture = tooldef.texture or toolname:gsub("%:", "_") + new_def._mcl_enchanting_enchanted_tool = new_name + register_list[":" .. new_name] = new_def end end - if not has_enchantment then - break - end - local new_name = toolname .. "_enchanted" - tooldef._mcl_enchanting_enchanted_tool = new_name - local new_def = table.copy(tooldef) - new_def.inventory_image = old_def.inventory_image .. "^[colorize:violet:50" - new_def.groups.not_in_creative_inventory = 1 - new_def.groups.enchanted = 1 - new_def.texture = old_def.texture or toolname:gsub("%:", "_") - new_def._mcl_enchanting_enchanted_tool = new_name - minetest.register_tool(":" .. new_name, new_def) + end + for new_name, new_def in pairs(register_list) do + minetest.register_tool(new_name, new_def) end end) @@ -91,15 +96,16 @@ end function mcl_enchanting.get_enchantment_description(enchantment, level) local enchantment_def = mcl_enchanting.enchantments[enchantment] - return enchantment_def.name .. " " .. (enchantment_def.max_level == 1 and "" or mcl_enchanting.roman_numerals.toRoman(level)) + return enchantment_def.name .. (enchantment_def.max_level == 1 and "" or " " .. mcl_enchanting.roman_numerals.toRoman(level)) end function mcl_enchanting.get_enchanted_itemstring(itemname) - return minetest.registered_items[itemname]._mcl_enchanting_enchanted_tool + local def = minetest.registered_items[itemname] + return def and def._mcl_enchanting_enchanted_tool end -function mcl_enchanting.item_supports_enchantment(itemname, enchantment) - if not mcl_enchanting.get_enchanted_itemstring(itemname) then +function mcl_enchanting.item_supports_enchantment(itemname, enchantment, early) + if not early and not mcl_enchanting.get_enchanted_itemstring(itemname) then return false end local enchantment_def = mcl_enchanting.enchantments[enchantment] @@ -109,7 +115,7 @@ function mcl_enchanting.item_supports_enchantment(itemname, enchantment) end end for group in pairs(enchantment_def.all) do - if minetest.get_item_group(itemname, group) then + if minetest.get_item_group(itemname, group) > 0 then return true end end @@ -124,7 +130,7 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) if itemstack:get_name() == "" then return false, "item missing" end - if not mcl_enchanting.item_supports_enchantment(itemdef.name, enchantment) then + if not mcl_enchanting.item_supports_enchantment(itemstack:get_name(), enchantment) then return false, "item not supported" end if not level then @@ -146,19 +152,19 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) return false, "incompatible", mcl_enchanting.get_enchantment_description(incompatible, incompatible_level) end end + return true end function mcl_enchanting.enchant(itemstack, enchantment, level) - local enchanted_itemstack = ItemStack(mcl_enchanting.get_enchanted_itemstring(itemstack:get_name())) - enchanted_itemstack:add_wear(itemstack:get_wear()) - enchanted_itemstack:set_meta(itemstack:get_meta()) + local enchanted_itemstack = ItemStack({name = mcl_enchanting.get_enchanted_itemstring(itemstack:get_name()), wear = itemstack:get_wear(), metadata = itemstack:get_metadata()}) local enchantments = mcl_enchanting.get_enchantments(enchanted_itemstack) enchantments[enchantment] = level mcl_enchanting.set_enchantments(enchanted_itemstack, enchantments) mcl_enchanting.reload_enchantments(enchanted_itemstack, enchantments) + return enchanted_itemstack end -function mcl_enchanting.reload_enchantments(itemstack, echantments) +function mcl_enchanting.reload_enchantments(itemstack, enchantments) local itemdef = itemstack:get_definition() for enchantment, level in pairs(enchantments) do local func = mcl_enchanting.features[enchantment] diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/_mcl_enchanting/enchantments.lua similarity index 93% rename from mods/CORE/mcl_enchanting/enchantments.lua rename to mods/CORE/_mcl_enchanting/enchantments.lua index 04783a679c..13e09928bd 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/_mcl_enchanting/enchantments.lua @@ -1,6 +1,6 @@ -- Taken from https://minecraft.gamepedia.com/Enchanting -mcl_enchantments.enchantments = { +mcl_enchanting.enchantments = { -- unimplemented aqua_affinity = { name = "Aqua Affinity", @@ -90,6 +90,17 @@ mcl_enchantments.enchantments = { description = "Reduces fall damage." }, -- unimplemented + fire_aspect = { + name = "Fire Aspect", + max_level = 2, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Sets target on fire." + }, + -- unimplemented fire_protection = { name = "Fire Protection", max_level = 4, @@ -101,6 +112,17 @@ mcl_enchantments.enchantments = { description = "Reduces fire damage." }, -- unimplemented + flame = { + name = "Flame", + max_level = 1, + primary = {bow = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Arrows set target on fire." + }, + -- unimplemented fortune = { name = "Fortune", max_level = 4, @@ -190,7 +212,7 @@ mcl_enchantments.enchantments = { }, -- unimplemented power = { - name = "Power", + name = "Power", max_level = 5, primary = {}, secondary = {bow = true}, @@ -267,12 +289,12 @@ mcl_enchantments.enchantments = { }, -- unimplemented smite = { - name = "Sharpness", + name = "Smite", max_level = 5, primary = {sword = true}, secondary = {axe = true}, disallow = {}, - incompatible = {sharpness = true, smite = true}, + incompatible = {bane_of_anthropods = true, sharpness = true}, weight = 5, description = "Increases damage to undead mobs." }, @@ -292,7 +314,7 @@ mcl_enchantments.enchantments = { name = "Sweeping Edge", max_level = 3, primary = {sword = true}, - secondary = {axe = true}, + secondary = {}, disallow = {}, incompatible = {}, weight = 2, diff --git a/mods/CORE/mcl_enchanting/features.lua b/mods/CORE/_mcl_enchanting/features.lua similarity index 99% rename from mods/CORE/mcl_enchanting/features.lua rename to mods/CORE/_mcl_enchanting/features.lua index 793ff85f5e..f12abe0972 100644 --- a/mods/CORE/mcl_enchanting/features.lua +++ b/mods/CORE/_mcl_enchanting/features.lua @@ -1,3 +1,6 @@ +mcl_enchanting.features = {} + + --[[ local pickaxes = {"mcl_tools:pick_wood", "mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} local pickaxes_better_than_iron = {"mcl_tools:pick_iron", "mcl_tools:pick_diamond"} @@ -118,3 +121,4 @@ end) end }, },--]] + diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/_mcl_enchanting/init.lua similarity index 94% rename from mods/CORE/mcl_enchanting/init.lua rename to mods/CORE/_mcl_enchanting/init.lua index 8489ff2d4b..4d693f952d 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/_mcl_enchanting/init.lua @@ -9,6 +9,7 @@ mcl_enchanting = { dofile(modpath .. "/enchantments.lua") dofile(modpath .. "/features.lua") dofile(modpath .. "/core.lua") +dofile(modpath .. "/command.lua") -- dofile(modpath .. "/ui.lua") -- dofile(modpath .. "/fx.lua") -- dofile(modpath .. "/book.lua") diff --git a/mods/CORE/mcl_enchanting/mod.conf b/mods/CORE/_mcl_enchanting/mod.conf similarity index 75% rename from mods/CORE/mcl_enchanting/mod.conf rename to mods/CORE/_mcl_enchanting/mod.conf index 2ec29e526a..237db41186 100644 --- a/mods/CORE/mcl_enchanting/mod.conf +++ b/mods/CORE/_mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = The rewrite of the Enchanting mod for MineClone2 -depends = mcl_sounds, mcl_formspec, mcl_dye +depends = mcl_formspec, _mcl_autogroup optional_depends = screwdriver author = Fleckenstein diff --git a/mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d b/mods/CORE/_mcl_enchanting/models/mcl_enchanting_book.b3d similarity index 100% rename from mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d rename to mods/CORE/_mcl_enchanting/models/mcl_enchanting_book.b3d diff --git a/mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png b/mods/CORE/_mcl_enchanting/models/mcl_enchanting_book_entity.png similarity index 100% rename from mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png rename to mods/CORE/_mcl_enchanting/models/mcl_enchanting_book_entity.png diff --git a/mods/CORE/mcl_enchanting/roman_numerals.lua b/mods/CORE/_mcl_enchanting/roman_numerals.lua similarity index 100% rename from mods/CORE/mcl_enchanting/roman_numerals.lua rename to mods/CORE/_mcl_enchanting/roman_numerals.lua diff --git a/mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg b/mods/CORE/_mcl_enchanting/sounds/mcl_enchanting_enchant.ogg similarity index 100% rename from mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg rename to mods/CORE/_mcl_enchanting/sounds/mcl_enchanting_enchant.ogg diff --git a/mods/CORE/mcl_enchanting/table.lua b/mods/CORE/_mcl_enchanting/table.lua similarity index 100% rename from mods/CORE/mcl_enchanting/table.lua rename to mods/CORE/_mcl_enchanting/table.lua diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_closed.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_closed.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_open.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_open.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_background.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_background.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_background.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_background.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_hovered.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_hovered.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_off.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_off.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_off.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_off.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_1.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_1.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_1.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_1.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_10.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_10.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_11.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_11.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_11.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_11.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_12.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_12.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_13.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_13.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_14.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_14.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_15.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_15.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_16.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_16.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_17.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_17.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_18.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_18.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_18.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_18.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_2.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_2.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_3.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_3.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_4.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_4.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_5.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_5.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_6.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_6.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_7.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_7.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_8.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_8.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_9.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_9.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_lapis_background.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_lapis_background.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1_off.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1_off.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2_off.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2_off.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3_off.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3_off.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3_off.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3_off.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_bottom.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_bottom.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_side.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_side.png diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png b/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_top.png similarity index 100% rename from mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png rename to mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_top.png diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 8231c8ed6c..0368a4215b 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -156,7 +156,7 @@ for level=0, 2 do wield_scale = { x = 1.8, y = 1.8, z = 1 }, stack_max = 1, range = 0, -- Pointing range to 0 to prevent punching with bow :D - groups = {not_in_creative_inventory=1, not_in_craft_guide=1}, + groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1}, on_drop = function(itemstack, dropper, pos) reset_bow_state(dropper) itemstack:set_name("mcl_bows:bow") From a76fb8dd57f563d13c132f6852d210d5d98ed530 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 27 Oct 2020 19:53:49 +0100 Subject: [PATCH 03/27] Added tt support, made enchanted bows function properly --- mods/CORE/_mcl_enchanting/core.lua | 13 +++--- mods/CORE/_mcl_enchanting/init.lua | 1 + mods/CORE/_mcl_enchanting/mod.conf | 2 +- mods/CORE/_mcl_enchanting/tt.lua | 15 +++++++ mods/HELP/mcl_tt/snippets_base.lua | 16 +++---- mods/HELP/tt/API.md | 11 ++++- mods/HELP/tt/init.lua | 71 +++++++++++++++++++----------- mods/ITEMS/mcl_bows/bow.lua | 47 ++++++++++++++++---- 8 files changed, 126 insertions(+), 50 deletions(-) create mode 100644 mods/CORE/_mcl_enchanting/tt.lua diff --git a/mods/CORE/_mcl_enchanting/core.lua b/mods/CORE/_mcl_enchanting/core.lua index 52cbe53b34..38a5e1767e 100644 --- a/mods/CORE/_mcl_enchanting/core.lua +++ b/mods/CORE/_mcl_enchanting/core.lua @@ -86,7 +86,7 @@ function mcl_enchanting.get_enchantments(itemstack) return minetest.deserialize(itemstack:get_meta():get_string("mcl_enchanting:enchantments")) or {} end -function mcl_enchanting.set_enchantments(itemstack, enchantments, data) +function mcl_enchanting.set_enchantments(itemstack, enchantments) return itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) end @@ -156,12 +156,12 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) end function mcl_enchanting.enchant(itemstack, enchantment, level) - local enchanted_itemstack = ItemStack({name = mcl_enchanting.get_enchanted_itemstring(itemstack:get_name()), wear = itemstack:get_wear(), metadata = itemstack:get_metadata()}) - local enchantments = mcl_enchanting.get_enchantments(enchanted_itemstack) + itemstack:set_name(mcl_enchanting.get_enchanted_itemstring(itemstack:get_name())) + local enchantments = mcl_enchanting.get_enchantments(itemstack) enchantments[enchantment] = level - mcl_enchanting.set_enchantments(enchanted_itemstack, enchantments) - mcl_enchanting.reload_enchantments(enchanted_itemstack, enchantments) - return enchanted_itemstack + mcl_enchanting.set_enchantments(itemstack, enchantments) + mcl_enchanting.reload_enchantments(itemstack, enchantments) + return itemstack end function mcl_enchanting.reload_enchantments(itemstack, enchantments) @@ -172,4 +172,5 @@ function mcl_enchanting.reload_enchantments(itemstack, enchantments) func(itemstack, level, itemdef) end end + tt.reload_itemstack_description(itemstack) end diff --git a/mods/CORE/_mcl_enchanting/init.lua b/mods/CORE/_mcl_enchanting/init.lua index 4d693f952d..80b171db1a 100644 --- a/mods/CORE/_mcl_enchanting/init.lua +++ b/mods/CORE/_mcl_enchanting/init.lua @@ -10,6 +10,7 @@ dofile(modpath .. "/enchantments.lua") dofile(modpath .. "/features.lua") dofile(modpath .. "/core.lua") dofile(modpath .. "/command.lua") +dofile(modpath .. "/tt.lua") -- dofile(modpath .. "/ui.lua") -- dofile(modpath .. "/fx.lua") -- dofile(modpath .. "/book.lua") diff --git a/mods/CORE/_mcl_enchanting/mod.conf b/mods/CORE/_mcl_enchanting/mod.conf index 237db41186..8dfe4e94fd 100644 --- a/mods/CORE/_mcl_enchanting/mod.conf +++ b/mods/CORE/_mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = The rewrite of the Enchanting mod for MineClone2 -depends = mcl_formspec, _mcl_autogroup +depends = mcl_formspec, tt optional_depends = screwdriver author = Fleckenstein diff --git a/mods/CORE/_mcl_enchanting/tt.lua b/mods/CORE/_mcl_enchanting/tt.lua new file mode 100644 index 0000000000..41ceb6249d --- /dev/null +++ b/mods/CORE/_mcl_enchanting/tt.lua @@ -0,0 +1,15 @@ +function mcl_enchanting.enchantments_snippet(_, _, itemstack) + if not itemstack then + return + end + local enchantments = mcl_enchanting.get_enchantments(itemstack) + local text = "" + for enchantment, level in pairs(enchantments) do + text = text .. mcl_enchanting.get_enchantment_description(enchantment, level) .. "\n" + end + if text ~= "" then + return text, false + end +end + +table.insert(tt.registered_snippets, 1, mcl_enchanting.enchantments_snippet) diff --git a/mods/HELP/mcl_tt/snippets_base.lua b/mods/HELP/mcl_tt/snippets_base.lua index 376f00f2c9..a3470b5c14 100644 --- a/mods/HELP/mcl_tt/snippets_base.lua +++ b/mods/HELP/mcl_tt/snippets_base.lua @@ -35,12 +35,12 @@ local function newline(str) end -- Digging capabilities of tool -tt.register_snippet(function(itemstring) +tt.register_snippet(function(itemstring, toolcaps) local def = minetest.registered_items[itemstring] - if not def.tool_capabilities then + if not toolcaps then return end - local groupcaps = def.tool_capabilities.groupcaps + local groupcaps = toolcaps.groupcaps if not groupcaps then return end @@ -105,8 +105,8 @@ tt.register_snippet(function(itemstring) -- Capabilities minestring = minestring .. capstr -- Max. drop level - local mdl = def.tool_capabilities.max_drop_level - if not def.tool_capabilities.max_drop_level then + local mdl = toolcaps.max_drop_level + if not toolcaps.max_drop_level then mdl = 0 end minestring = minestring .. S("Block breaking strength: @1", mdl) @@ -114,8 +114,8 @@ tt.register_snippet(function(itemstring) local weaponstring = "" -- Weapon stats - if def.tool_capabilities.damage_groups then - for group, damage in pairs(def.tool_capabilities.damage_groups) do + if toolcaps.damage_groups then + for group, damage in pairs(toolcaps.damage_groups) do local msg if group == "fleshy" then if damage >= 0 then @@ -127,7 +127,7 @@ tt.register_snippet(function(itemstring) weaponstring = newline(weaponstring) weaponstring = weaponstring .. msg end - local full_punch_interval = def.tool_capabilities.full_punch_interval + local full_punch_interval = toolcaps.full_punch_interval if not full_punch_interval then full_punch_interval = 1 end diff --git a/mods/HELP/tt/API.md b/mods/HELP/tt/API.md index a510553ce1..37f34d335c 100644 --- a/mods/HELP/tt/API.md +++ b/mods/HELP/tt/API.md @@ -13,8 +13,9 @@ Once this mod had overwritten the `description` field of an item was overwritten ## `tt.register_snippet(func)` Register a custom snippet function. -`func` is a function of the form `func(itemstring)`. -It will be called for (nearly) every itemstring. +`func` is a function of the form `func(itemstring, tool_capabilities, itemstack)`. +It will be called for (nearly) every itemstring at startup and when `tt.reload_itemstack_description` is called for an itemstack. +The `itemstack` parameter is only present when the snippet is called via `tt.reload_itemstack_description` and contains the itemstack. Returns: Two values, the first one is required. 1st return value: A string you want to append to this item or `nil` if nothing shall be appended. @@ -29,3 +30,9 @@ tt.register_snippet(function(itemstring) end end) ``` + +## `tt.reload_itemstack_description(itemstack)` + +This function will dynamically reload the itemstack description, +it becomes handy when `ìtemstack:get_meta():set_tool_capabilities(...)` was used +or if some snippets are based on metadata. diff --git a/mods/HELP/tt/init.lua b/mods/HELP/tt/init.lua index a79bf27b59..d1bb6d6b8b 100644 --- a/mods/HELP/tt/init.lua +++ b/mods/HELP/tt/init.lua @@ -14,33 +14,41 @@ dofile(minetest.get_modpath(minetest.get_current_modname()).."/snippets.lua") -- Apply item description updates +local function apply_snippets(desc, itemstring, toolcaps, itemstack) + local first = true + -- Apply snippets + for s=1, #tt.registered_snippets do + local str, snippet_color = tt.registered_snippets[s](itemstring, toolcaps, itemstack) + if snippet_color == nil then + snippet_color = tt.COLOR_DEFAULT + elseif snippet_color == false then + snippet_color = false + end + if str then + if first then + first = false + end + desc = desc .. "\n" + if snippet_color then + desc = desc .. minetest.colorize(snippet_color, str) + else + desc = desc .. str + end + end + end + return desc +end + +local function should_change(itemstring, def) + return itemstring ~= "" and itemstring ~= "air" and itemstring ~= "ignore" and itemstring ~= "unknown" and def ~= nil and def.description ~= nil and def.description ~= "" and def._tt_ignore ~= true +end + local function append_snippets() for itemstring, def in pairs(minetest.registered_items) do - if itemstring ~= "" and itemstring ~= "air" and itemstring ~= "ignore" and itemstring ~= "unknown" and def ~= nil and def.description ~= nil and def.description ~= "" and def._tt_ignore ~= true then - local desc = def.description - local orig_desc = desc - local first = true - -- Apply snippets - for s=1, #tt.registered_snippets do - local str, snippet_color = tt.registered_snippets[s](itemstring) - if snippet_color == nil then - snippet_color = tt.COLOR_DEFAULT - elseif snippet_color == false then - snippet_color = false - end - if str then - if first then - first = false - end - desc = desc .. "\n" - if snippet_color then - desc = desc .. minetest.colorize(snippet_color, str) - else - desc = desc .. str - end - end - end - if desc ~= def.description then + if should_change(itemstring, def) then + local orig_desc = def.description + local desc = apply_snippets(orig_desc, itemstring, def.tool_capabilities, nil) + if desc ~= orig_desc then minetest.override_item(itemstring, { description = desc, _tt_original_description = orig_desc }) end end @@ -48,3 +56,16 @@ local function append_snippets() end minetest.register_on_mods_loaded(append_snippets) + +tt.reload_itemstack_description = function(itemstack) + local itemstring = itemstack:get_name() + local def = itemstack:get_definition() + if should_change(itemstring, def) then + local meta = itemstack:get_meta() + local orig_desc = def._tt_original_description + local desc = apply_snippets(orig_desc, itemstring, itemstack:get_tool_capabilities(), itemstack) + if desc ~= orig_desc then + meta:set_string("description", desc) + end + end +end diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 0368a4215b..dc7334f312 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -130,6 +130,9 @@ local reset_bows = function(player) if stack:get_name()=="mcl_bows:bow_0" or stack:get_name()=="mcl_bows:bow_1" or stack:get_name()=="mcl_bows:bow_2" then stack:set_name("mcl_bows:bow") list[place] = stack + elseif stack:get_name()=="mcl_bows:bow_0_enchanted" or stack:get_name()=="mcl_bows:bow_1_enchanted" or stack:get_name()=="mcl_bows:bow_2_enchanted" then + stack:set_name("mcl_bows:bow_enchanted") + list[place] = stack end end inv:set_list("main", list) @@ -159,7 +162,11 @@ for level=0, 2 do groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1}, on_drop = function(itemstack, dropper, pos) reset_bow_state(dropper) - itemstack:set_name("mcl_bows:bow") + if minetest.get_item_group(itemstack:get_name(), "enchanted") > 0 then + itemstack:set_name("mcl_bows:bow_enchanted") + else + itemstack:set_name("mcl_bows:bow") + end minetest.item_drop(itemstack, dropper, pos) itemstack:take_item() return itemstack @@ -176,9 +183,11 @@ controls.register_on_release(function(player, key, time) if key~="RMB" then return end local inv = minetest.get_inventory({type="player", name=player:get_player_name()}) local wielditem = player:get_wielded_item() - if (wielditem:get_name()=="mcl_bows:bow_0" or wielditem:get_name()=="mcl_bows:bow_1" or wielditem:get_name()=="mcl_bows:bow_2") then + if (wielditem:get_name()=="mcl_bows:bow_0" or wielditem:get_name()=="mcl_bows:bow_1" or wielditem:get_name()=="mcl_bows:bow_2" or + wielditem:get_name()=="mcl_bows:bow_0_enchanted" or wielditem:get_name()=="mcl_bows:bow_1_enchanted" or wielditem:get_name()=="mcl_bows:bow_2_enchanted") then local has_shot = false - + + local enchanted = minetest.get_item_group(wielditem:get_name(), "enchanted") > 0 local speed, damage local p_load = bow_load[player:get_player_name()] local charge @@ -217,8 +226,13 @@ controls.register_on_release(function(player, key, time) end has_shot = player_shoot_arrow(wielditem, player, speed, damage, is_critical) - - wielditem:set_name("mcl_bows:bow") + + if enchanted then + wielditem:set_name("mcl_bows:bow_enchanted") + else + wielditem:set_name("mcl_bows:bow") + end + if has_shot and not minetest.is_creative_enabled(player:get_player_name()) then wielditem:add_wear(65535/BOW_DURABILITY) end @@ -235,8 +249,13 @@ controls.register_on_hold(function(player, key, time) end local inv = minetest.get_inventory({type="player", name=name}) local wielditem = player:get_wielded_item() - if bow_load[name] == nil and wielditem:get_name()=="mcl_bows:bow" and (creative or get_arrow(player)) then - wielditem:set_name("mcl_bows:bow_0") + if bow_load[name] == nil and (wielditem:get_name()=="mcl_bows:bow" or wielditem:get_name()=="mcl_bows:bow_enchanted") and (creative or get_arrow(player)) then + local enchanted = (wielditem:get_name()=="mcl_bows:bow_enchanted") + if enchanted then + wielditem:set_name("mcl_bows:bow_0_enchanted") + else + wielditem:set_name("mcl_bows:bow_0") + end player:set_wielded_item(wielditem) if minetest.get_modpath("playerphysics") then -- Slow player down when using bow @@ -249,12 +268,18 @@ controls.register_on_hold(function(player, key, time) if type(bow_load[name]) == "number" then if wielditem:get_name() == "mcl_bows:bow_0" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_HALF then wielditem:set_name("mcl_bows:bow_1") + elseif wielditem:get_name() == "mcl_bows:bow_0_enchanted" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_HALF then + wielditem:set_name("mcl_bows:bow_1_enchanted") elseif wielditem:get_name() == "mcl_bows:bow_1" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_FULL then wielditem:set_name("mcl_bows:bow_2") + elseif wielditem:get_name() == "mcl_bows:bow_1_enchanted" and minetest.get_us_time() - bow_load[name] >= BOW_CHARGE_TIME_FULL then + wielditem:set_name("mcl_bows:bow_2_enchanted") end else if wielditem:get_name() == "mcl_bows:bow_0" or wielditem:get_name() == "mcl_bows:bow_1" or wielditem:get_name() == "mcl_bows:bow_2" then wielditem:set_name("mcl_bows:bow") + elseif wielditem:get_name() == "mcl_bows:bow_0_enchanted" or wielditem:get_name() == "mcl_bows:bow_1_enchanted" or wielditem:get_name() == "mcl_bows:bow_2_enchanted" then + wielditem:set_name("mcl_bows:bow_enchanted") end end player:set_wielded_item(wielditem) @@ -270,7 +295,7 @@ minetest.register_globalstep(function(dtime) local wielditem = player:get_wielded_item() local wieldindex = player:get_wield_index() local controls = player:get_player_control() - if type(bow_load[name]) == "number" and ((wielditem:get_name()~="mcl_bows:bow_0" and wielditem:get_name()~="mcl_bows:bow_1" and wielditem:get_name()~="mcl_bows:bow_2") or wieldindex ~= bow_index[name]) then + if type(bow_load[name]) == "number" and ((wielditem:get_name()~="mcl_bows:bow_0" and wielditem:get_name()~="mcl_bows:bow_1" and wielditem:get_name()~="mcl_bows:bow_2" and wielditem:get_name()~="mcl_bows:bow_0_enchanted" and wielditem:get_name()~="mcl_bows:bow_1_enchanted" and wielditem:get_name()~="mcl_bows:bow_2_enchanted") or wieldindex ~= bow_index[name]) then reset_bow_state(player, true) end end @@ -309,6 +334,12 @@ minetest.register_craft({ burntime = 15, }) +minetest.register_craft({ + type = "fuel", + recipe = "mcl_bows:bow_enchanted", + burntime = 15, +}) + -- Add entry aliases for the Help if minetest.get_modpath("doc") then doc.add_entry_alias("tools", "mcl_bows:bow", "tools", "mcl_bows:bow_0") From 76303ae1948c0e5ff7fa79d41c5a8929107a8ed3 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 27 Oct 2020 20:02:46 +0100 Subject: [PATCH 04/27] Working Infinity Enchantment --- mods/CORE/_mcl_enchanting/enchantments.lua | 1 - mods/ITEMS/mcl_bows/bow.lua | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mods/CORE/_mcl_enchanting/enchantments.lua b/mods/CORE/_mcl_enchanting/enchantments.lua index 13e09928bd..4aab62f683 100644 --- a/mods/CORE/_mcl_enchanting/enchantments.lua +++ b/mods/CORE/_mcl_enchanting/enchantments.lua @@ -144,7 +144,6 @@ mcl_enchanting.enchantments = { weight = 2, description = "Turns water beneath the player into frosted ice and prevents the damage the player would take from standing on magma blocks." }, - -- unimplemented infinity = { name = "Infinity", max_level = 1, diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index dc7334f312..21b55c31ba 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -76,6 +76,7 @@ end local player_shoot_arrow = function(itemstack, player, power, damage, is_critical) local arrow_stack, arrow_stack_id = get_arrow(player) local arrow_itemstring + local has_infinity_enchantment = rawget(_G, "mcl_enchanting") and mcl_enchanting.get_enchantment(player:get_wielded_item(), "infinity") > 0 if minetest.is_creative_enabled(player:get_player_name()) then if arrow_stack then @@ -88,7 +89,9 @@ local player_shoot_arrow = function(itemstack, player, power, damage, is_critica return false end arrow_itemstring = arrow_stack:get_name() - arrow_stack:take_item() + if not has_infinity_enchantment then + arrow_stack:take_item() + end local inv = player:get_inventory() inv:set_stack("main", arrow_stack_id, arrow_stack) end From 26f3d821a4db723ffc416db374071ff21faa414a Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sun, 1 Nov 2020 13:44:05 +0100 Subject: [PATCH 05/27] Proper anvil naming support --- mods/CORE/_mcl_enchanting/enchantments.lua | 344 ---------- mods/CORE/_mcl_enchanting/features.lua | 124 ---- .../LICENSE | 0 .../README | 0 .../core.lua => mcl_enchanting/api.lua} | 210 ++++--- .../book.lua | 0 .../command.lua | 0 mods/CORE/mcl_enchanting/enchantments.lua | 591 ++++++++++++++++++ .../init.lua | 9 +- .../mod.conf | 0 .../models/mcl_enchanting_book.b3d | Bin .../models/mcl_enchanting_book_entity.png | Bin .../roman_numerals.lua | 0 .../sounds/mcl_enchanting_enchant.ogg | Bin .../table.lua | 0 .../textures/mcl_enchanting_book_closed.png | Bin .../textures/mcl_enchanting_book_open.png | Bin .../textures/mcl_enchanting_button.png | Bin .../mcl_enchanting_button_background.png | Bin .../mcl_enchanting_button_hovered.png | Bin .../textures/mcl_enchanting_button_off.png | Bin .../textures/mcl_enchanting_glyph_1.png | Bin .../textures/mcl_enchanting_glyph_10.png | Bin .../textures/mcl_enchanting_glyph_11.png | Bin .../textures/mcl_enchanting_glyph_12.png | Bin .../textures/mcl_enchanting_glyph_13.png | Bin .../textures/mcl_enchanting_glyph_14.png | Bin .../textures/mcl_enchanting_glyph_15.png | Bin .../textures/mcl_enchanting_glyph_16.png | Bin .../textures/mcl_enchanting_glyph_17.png | Bin .../textures/mcl_enchanting_glyph_18.png | Bin .../textures/mcl_enchanting_glyph_2.png | Bin .../textures/mcl_enchanting_glyph_3.png | Bin .../textures/mcl_enchanting_glyph_4.png | Bin .../textures/mcl_enchanting_glyph_5.png | Bin .../textures/mcl_enchanting_glyph_6.png | Bin .../textures/mcl_enchanting_glyph_7.png | Bin .../textures/mcl_enchanting_glyph_8.png | Bin .../textures/mcl_enchanting_glyph_9.png | Bin .../mcl_enchanting_lapis_background.png | Bin .../textures/mcl_enchanting_number_1.png | Bin .../textures/mcl_enchanting_number_1_off.png | Bin .../textures/mcl_enchanting_number_2.png | Bin .../textures/mcl_enchanting_number_2_off.png | Bin .../textures/mcl_enchanting_number_3.png | Bin .../textures/mcl_enchanting_number_3_off.png | Bin .../textures/mcl_enchanting_table_bottom.png | Bin .../textures/mcl_enchanting_table_side.png | Bin .../textures/mcl_enchanting_table_top.png | Bin .../tt.lua | 2 +- mods/HELP/tt/init.lua | 6 +- mods/ITEMS/mcl_anvils/depends.txt | 1 + mods/ITEMS/mcl_anvils/init.lua | 13 +- mods/ITEMS/mcl_bows/bow.lua | 8 +- mods/ITEMS/mcl_bows/depends.txt | 1 + mods/PLAYER/mcl_death_drop/depends.txt | 1 + mods/PLAYER/mcl_death_drop/init.lua | 2 +- 57 files changed, 734 insertions(+), 578 deletions(-) delete mode 100644 mods/CORE/_mcl_enchanting/enchantments.lua delete mode 100644 mods/CORE/_mcl_enchanting/features.lua rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/LICENSE (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/README (100%) rename mods/CORE/{_mcl_enchanting/core.lua => mcl_enchanting/api.lua} (64%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/book.lua (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/command.lua (100%) create mode 100644 mods/CORE/mcl_enchanting/enchantments.lua rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/init.lua (76%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/mod.conf (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/models/mcl_enchanting_book.b3d (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/models/mcl_enchanting_book_entity.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/roman_numerals.lua (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/sounds/mcl_enchanting_enchant.ogg (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/table.lua (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_book_closed.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_book_open.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_button.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_button_background.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_button_hovered.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_button_off.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_1.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_10.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_11.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_12.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_13.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_14.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_15.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_16.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_17.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_18.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_2.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_3.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_4.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_5.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_6.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_7.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_8.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_glyph_9.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_lapis_background.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_number_1.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_number_1_off.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_number_2.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_number_2_off.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_number_3.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_number_3_off.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_table_bottom.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_table_side.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/textures/mcl_enchanting_table_top.png (100%) rename mods/CORE/{_mcl_enchanting => mcl_enchanting}/tt.lua (78%) diff --git a/mods/CORE/_mcl_enchanting/enchantments.lua b/mods/CORE/_mcl_enchanting/enchantments.lua deleted file mode 100644 index 4aab62f683..0000000000 --- a/mods/CORE/_mcl_enchanting/enchantments.lua +++ /dev/null @@ -1,344 +0,0 @@ --- Taken from https://minecraft.gamepedia.com/Enchanting - -mcl_enchanting.enchantments = { - -- unimplemented - aqua_affinity = { - name = "Aqua Affinity", - max_level = 1, - primary = {armor_head = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {}, - weight = 2, - description = "Increases underwater mining speed." - }, - -- unimplemented - bane_of_anthropods = { - name = "Bane of Anthropods", - max_level = 5, - primary = {sword = true}, - secondary = {axe = true}, - disallow = {}, - incompatible = {smite = true, shaprness = true}, - weight = 5, - description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites)." - }, - -- unimplemented - blast_protection = { - name = "Blast Protection", - max_level = 4, - primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {fire_protection = true, protection = true, projectile_protection = true}, - weight = 2, - description = "Reduces explosion damage and knockback." - }, - -- unimplemented - curse_of_binding = { - name = "Curse of Binding", - max_level = 1, - primary = {}, - secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, - disallow = {}, - incompatible = {}, - weight = 1, - description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking." - }, - -- unimplemented - curse_of_vanishing = { - name = "Curse of Vanishing", - max_level = 1, - primary = {}, - secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, - disallow = {clock = true}, - incompatible = {}, - weight = 1, - description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking." - }, - -- unimplemented - depth_strider = { - name = "Depth Strider", - max_level = 3, - primary = {}, - secondary = {armor_feet = true}, - disallow = {non_combat_armor = true}, - incompatible = {frost_walker = true}, - weight = 2, - description = "Increases underwater movement speed." - }, - -- unimplemented - efficiency = { - name = "Efficiency", - max_level = 5, - primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, - secondary = {shears = true}, - disallow = {}, - incompatible = {}, - weight = 10, - description = "Increases mining speed." - }, - -- unimplemented - feather_falling = { - name = "Feather Falling", - max_level = 4, - primary = {armor_feet = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {}, - weight = 5, - description = "Reduces fall damage." - }, - -- unimplemented - fire_aspect = { - name = "Fire Aspect", - max_level = 2, - primary = {sword = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Sets target on fire." - }, - -- unimplemented - fire_protection = { - name = "Fire Protection", - max_level = 4, - primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {blast_protection = true, protection = true, projectile_protection = true}, - weight = 5, - description = "Reduces fire damage." - }, - -- unimplemented - flame = { - name = "Flame", - max_level = 1, - primary = {bow = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Arrows set target on fire." - }, - -- unimplemented - fortune = { - name = "Fortune", - max_level = 4, - primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, - secondary = {}, - disallow = {}, - incompatible = {silk_touch = true}, - weight = 2, - description = "Increases certain block drops." - }, - -- unimplemented - frost_walker = { - name = "Frost Walker", - max_level = 2, - primary = {}, - secondary = {armor_feet = true}, - disallow = {non_combat_armor = true}, - incompatible = {depth_strider = true}, - weight = 2, - description = "Turns water beneath the player into frosted ice and prevents the damage the player would take from standing on magma blocks." - }, - infinity = { - name = "Infinity", - max_level = 1, - primary = {bow = true}, - secondary = {}, - disallow = {}, - incompatible = {mending = true}, - weight = 1, - description = "Shooting consumes no regular arrows." - }, - -- unimplemented - knockback = { - name = "Knockback", - max_level = 2, - primary = {sword = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 5, - description = "Increases knockback." - }, - -- unimplemented - looting = { - name = "Looting", - max_level = 3, - primary = {sword = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Increases mob loot." - }, - -- unimplemented - luck_of_the_sea = { - name = "Luck of the Sea", - max_level = 3, - primary = {fishing_rod = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Increases rate of good loot (enchanting books, etc.)" - }, - -- unimplemented - lure = { - name = "Lure", - max_level = 3, - primary = {fishing_rod = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Decreases wait time until fish/junk/loot \"bites\"." - }, - -- unimplemented - mending = { - name = "Mending", - max_level = 1, - primary = {}, - secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, - disallow = {non_combat_armor = true, compass = true, clock = true}, - incompatible = {infinity = true}, - weight = 2, - description = "Repair the item while gaining XP orbs." - }, - -- unimplemented - power = { - name = "Power", - max_level = 5, - primary = {}, - secondary = {bow = true}, - disallow = {}, - incompatible = {}, - weight = 10, - description = "Increases arrow damage." - }, - -- unimplemented - projectile_protection = { - name = "Projectile Protection", - max_level = 4, - primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {blast_protection = true, fire_protection = true, protection = true}, - weight = 5, - description = "Reduces projectile damage." - }, - -- unimplemented - protection = { - name = "Protection", - max_level = 4, - primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true}, - weight = 10, - description = "Reduces most types of damage by 4% for each level." - }, - -- unimplemented - punch = { - name = "Punch", - max_level = 2, - primary = {}, - secondary = {bow = true}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Increases arrow knockback." - }, - -- unimplemented - respiration = { - name = "Respiration", - max_level = 3, - primary = {armor_head = true}, - secondary = {}, - disallow = {non_combat_armor = true}, - incompatible = {}, - weight = 2, - description = "Extends underwater breathing time." - }, - -- unimplemented - sharpness = { - name = "Sharpness", - max_level = 5, - primary = {sword = true}, - secondary = {axe = true}, - disallow = {}, - incompatible = {bane_of_anthropods = true, smite = true}, - weight = 5, - description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites)." - }, - -- unimplemented - silk_touch = { - name = "Silk Touch", - max_level = 1, - primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, - secondary = {shears = true}, - disallow = {}, - incompatible = {fortune = true}, - weight = 1, - description = "Mined blocks drop themselves." - }, - -- unimplemented - smite = { - name = "Smite", - max_level = 5, - primary = {sword = true}, - secondary = {axe = true}, - disallow = {}, - incompatible = {bane_of_anthropods = true, sharpness = true}, - weight = 5, - description = "Increases damage to undead mobs." - }, - -- unimplemented - soul_speed = { - name = "Soul Speed", - max_level = 3, - primary = {}, - secondary = {armor_feet = true}, - disallow = {non_combat_armor = true}, - incompatible = {frost_walker = true}, - weight = 2, - description = "Incerases walking speed on soul sand." - }, - -- unimplemented - sweeping_edge = { - name = "Sweeping Edge", - max_level = 3, - primary = {sword = true}, - secondary = {}, - disallow = {}, - incompatible = {}, - weight = 2, - description = "Increases sweeping attack damage." - }, - -- unimplemented - thorns = { - name = "Thorns", - max_level = 3, - primary = {armor_head = true}, - secondary = {armor_torso = true, armor_legs = true, armor_feet = true}, - disallow = {non_combat_armor = true}, - incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true}, - weight = 1, - description = "Reflects some of the damage taken when hit, at the cost of reducing durability with each proc." - }, - -- unimplemented - unbreaking = { - name = "Unbreaking", - max_level = 3, - primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, pickaxe = true, shovel = true, axe = true, hoe = true, sword = true, fishing_rod = true, bow = true}, - secondary = {tool = true}, - disallow = {non_combat_armor = true}, - incompatible = {}, - weight = 5, - description = "Increases item durability." - }, -} diff --git a/mods/CORE/_mcl_enchanting/features.lua b/mods/CORE/_mcl_enchanting/features.lua deleted file mode 100644 index f12abe0972..0000000000 --- a/mods/CORE/_mcl_enchanting/features.lua +++ /dev/null @@ -1,124 +0,0 @@ -mcl_enchanting.features = {} - - ---[[ -local pickaxes = {"mcl_tools:pick_wood", "mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} -local pickaxes_better_than_iron = {"mcl_tools:pick_iron", "mcl_tools:pick_diamond"} -local pickaxes_better_than_stone = {"mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} -local shovels = {"mcl_tools:shovel_wood", "mcl_tools:shovel_stone", "mcl_tools:shovel_gold", "mcl_tools:shovel_iron", "mcl_tools:shovel_diamond"} - -local silk_touch_tool_lists = { - ["mcl_books:bookshelf"] = true, - ["mcl_core:clay"] = true, - ["mcl_core:stone_with_coal"] = pickaxes, - ["group:coral_block"] = pickaxes, - ["group:coral"] = true, - ["group:coral_fan"] = true, - ["mcl_core:stone_with_diamond"] = pickaxes_better_than_iron, - ["mcl_core:stone_with_emerald"] = pickaxes_better_than_iron, - ["mcl_chests:ender_chest"] = pickaxes, - ["group:glass"] = true, - ["mcl_nether:glowstone"] = true, - ["mcl_core:dirt_with_grass"] = true, - ["mcl_core:gravel"] = true, - ["mcl_core:ice"] = true, - ["mcl_core:stone_with_lapis"] = pickaxes_better_than_stone, - ["group:leaves"] = true, - ["mcl_farming:melon"] = true, - ["group:huge_mushroom"] = true, - ["mcl_core:mycelium"] = true, - ["mcl_nether:quartz_ore"] = pickaxes, - ["mcl_core:packed_ice"] = true, - ["mcl_core:podzol"] = true, - ["mcl_core:stone_with_redstone"] = pickaxes_better_than_iron, - ["mcl_ocean:sea_lantern"] = true, - ["group:top_snow"] = shovels, - ["mcl_core:snowblock"] = shovels, - ["mcl_core:stone"] = pickaxes, -} - -minetest.register_on_mods_loaded(function() - local old_handle_node_drops = minetest.handle_node_drops - function minetest.handle_node_drops(pos, drops, digger) - if digger and digger:is_player() then - local wielditem = digger:get_wielded_item() - local tooldef = wielditem:get_definition() - if tooldef._silk_touch then - local nodename = minetest.get_node(pos).name - local nodedef = minetest.registered_nodes[nodename] - local silk_touch_spec = silk_touch_tool_lists[nodename] - local suitable_tool = false - local tool_list - if silk_touch_spec == true then - suitable_tool = true - elseif silk_touch_spec then - tool_list = silk_touch_spec - else - for k, v in pairs(nodedef.groups) do - if v > 0 then - local group_spec = silk_touch_tool_lists["group:" .. k] - if group_spec == true then - suitable_tool = true - elseif group_spec then - toollist = group_spec - break - end - end - end - end - if tool_list and not suitable_tool then - suitable_tool = (table.indexof(tool_list, tooldef._original_tool) ~= -1) - end - if suitable_tool then - drops = {nodename} - end - end - end - old_handle_node_drops(pos, drops, digger) - end -end) ---]] - - ---[[ - sharpness = { - name = "Sharpness", - max_level = 5, - create_itemdef = function(def, level) - def.tool_capabilities.damage_groups.fleshy = def.tool_capabilities.damage_groups.fleshy + (level + 1) / 2 - end, - }, - efficiency = { - name = "Efficiency", - max_level = 5, - create_itemdef = function(def, level) - local groupcaps = def.tool_capabilities.groupcaps - for _, groupcap in pairs(groupcaps) do - for i, t in pairs(groupcap.times) do - local m = 1 / t - m = m + math.pow(level, 2) + 1 - groupcap.times[i] = 1 / m - end - end - end, - }, - unbreaking = { - name = "Unbreaking", - max_level = 3, - create_itemdef = function(def, level) - local toolcaps = def.tool_capabilities - local armor_uses = def.groups.mcl_armor_uses - local factor = 0.5 - if toolcaps then - local groupcaps = toolcaps.groupcaps - for _, groupcap in pairs(groupcaps) do - groupcap.uses = math.floor(groupcap.uses * (1 + level)) - end - def.tool_capabilities.punch_attack_uses = math.floor(def.tool_capabilities.punch_attack_uses * (1 + level)) - elseif armor_uses then - def.groups.mcl_armor_uses = math.floor(armor_uses / (0.6 + (0.4 / (level + 1)))) - end - end - }, - },--]] - diff --git a/mods/CORE/_mcl_enchanting/LICENSE b/mods/CORE/mcl_enchanting/LICENSE similarity index 100% rename from mods/CORE/_mcl_enchanting/LICENSE rename to mods/CORE/mcl_enchanting/LICENSE diff --git a/mods/CORE/_mcl_enchanting/README b/mods/CORE/mcl_enchanting/README similarity index 100% rename from mods/CORE/_mcl_enchanting/README rename to mods/CORE/mcl_enchanting/README diff --git a/mods/CORE/_mcl_enchanting/core.lua b/mods/CORE/mcl_enchanting/api.lua similarity index 64% rename from mods/CORE/_mcl_enchanting/core.lua rename to mods/CORE/mcl_enchanting/api.lua index 38a5e1767e..a646134992 100644 --- a/mods/CORE/_mcl_enchanting/core.lua +++ b/mods/CORE/mcl_enchanting/api.lua @@ -1,87 +1,3 @@ -mcl_enchanting.total_weight = 0 -mcl_enchanting.all_item_groups = {} - -for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do - local all_item_groups = {} - for primary in pairs(enchantment_def.primary) do - all_item_groups[primary] = true - mcl_enchanting.all_item_groups[primary] = true - end - for secondary in pairs(enchantment_def.secondary) do - all_item_groups[secondary] = true - mcl_enchanting.all_item_groups[secondary] = true - end - enchantment_def.all = all_item_groups - mcl_enchanting.total_weight = mcl_enchanting.total_weight + enchantment_def.weight -end - ---[[ -minetest.register_on_mods_loaded(function() - for toolname, tooldef in pairs(minetest.registered_tools) do - for _, material in pairs(tooldef.materials) do - local full_name = toolname .. ((material == "") and "" or "_" .. material) - local old_def = minetest.registered_tools[full_name] - if not old_def then break end - mcl_enchanting.all_tools[full_name] = toolname - for _, enchantment in pairs(tooldef.enchantments) do - local enchantment_def = mcl_enchanting.enchantments[enchantment] - for lvl = 1, enchantment_def.max_level do - local new_def = table.copy(old_def) - new_def.description = minetest.colorize("#54FCFC", old_def.description) .. "\n" .. mcl_enchanting.get_enchantment_description(enchantment, lvl) - new_def.inventory_image = old_def.inventory_image .. "^[colorize:violet:50" - new_def.groups.not_in_creative_inventory = 1 - new_def.texture = old_def.texture or full_name:gsub("%:", "_") - new_def._original_tool = full_name - enchantment_def.create_itemdef(new_def, lvl) - minetest.register_tool(":" .. full_name .. "_enchanted_" .. enchantment .. "_" .. lvl, new_def) - end - end - end - end -end) ---]] - -minetest.register_on_mods_loaded(function() - local register_list = {} - for toolname, tooldef in pairs(minetest.registered_tools) do - if tooldef.groups.enchanted then - break - end - local quick_test = false - for group, groupv in pairs(tooldef.groups) do - if groupv > 0 and mcl_enchanting.all_item_groups[group] then - quick_test = true - break - end - end - if quick_test then - --print(toolname) - local expensive_test = false - for enchantment in pairs(mcl_enchanting.enchantments) do - if mcl_enchanting.item_supports_enchantment(toolname, enchantment, true) then - -- print("\tSupports " .. enchantment) - expensive_test = true - break - end - end - if expensive_test then - local new_name = toolname .. "_enchanted" - minetest.override_item(toolname, {_mcl_enchanting_enchanted_tool = new_name}) - local new_def = table.copy(tooldef) - new_def.inventory_image = tooldef.inventory_image .. "^[colorize:purple:50" - new_def.groups.not_in_creative_inventory = 1 - new_def.groups.enchanted = 1 - new_def.texture = tooldef.texture or toolname:gsub("%:", "_") - new_def._mcl_enchanting_enchanted_tool = new_name - register_list[":" .. new_name] = new_def - end - end - end - for new_name, new_def in pairs(register_list) do - minetest.register_tool(new_name, new_def) - end -end) - function mcl_enchanting.get_enchantments(itemstack) return minetest.deserialize(itemstack:get_meta():get_string("mcl_enchanting:enchantments")) or {} end @@ -90,8 +6,12 @@ function mcl_enchanting.set_enchantments(itemstack, enchantments) return itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) end -function mcl_enchanting.get_enchantment(itemstack, enchantment, data) - return (data or mcl_enchanting.get_enchantments(itemstack))[enchantment] or 0 +function mcl_enchanting.get_enchantment(itemstack, enchantment) + return mcl_enchanting.get_enchantments(itemstack)[enchantment] or 0 +end + +function mcl_enchanting.has_enchantment(itemstack, enchantment) + return mcl_enchanting.get_enchantment(itemstack, enchantment) > 0 end function mcl_enchanting.get_enchantment_description(enchantment, level) @@ -99,16 +19,32 @@ function mcl_enchanting.get_enchantment_description(enchantment, level) return enchantment_def.name .. (enchantment_def.max_level == 1 and "" or " " .. mcl_enchanting.roman_numerals.toRoman(level)) end +function mcl_enchanting.get_colorized_enchantment_description(enchantment, level) + return minetest.colorize(mcl_enchanting.enchantments[enchantment].curse and "#FC5454" or "#A8A8A8", mcl_enchanting.get_enchantment_description(enchantment, level)) +end + function mcl_enchanting.get_enchanted_itemstring(itemname) - local def = minetest.registered_items[itemname] + local def = minetest.registered_items[itemname] return def and def._mcl_enchanting_enchanted_tool end +function mcl_enchanting.is_enchanted_def(itemname) + return minetest.get_item_group(itemname, "enchanted") > 0 +end + +function mcl_enchanting.is_enchanted(itemstack) + return mcl_enchanting.is_enchanted_def(itemstack:get_name()) +end + function mcl_enchanting.item_supports_enchantment(itemname, enchantment, early) if not early and not mcl_enchanting.get_enchanted_itemstring(itemname) then return false end local enchantment_def = mcl_enchanting.enchantments[enchantment] + local tooldef = minetest.registered_tools[itemname] + if not tooldef and enchantment_def.requires_tool then + return false + end for disallow in pairs(enchantment_def.disallow) do if minetest.get_item_group(itemname, disallow) > 0 then return false @@ -167,10 +103,104 @@ end function mcl_enchanting.reload_enchantments(itemstack, enchantments) local itemdef = itemstack:get_definition() for enchantment, level in pairs(enchantments) do - local func = mcl_enchanting.features[enchantment] - if func then - func(itemstack, level, itemdef) + local enchantment_def = mcl_enchanting.enchantments[enchantment] + if enchantment_def.on_enchant then + enchantment_def.on_enchant(itemstack, level, itemdef) end end tt.reload_itemstack_description(itemstack) end + +function mcl_enchanting.initialize() + local tool_list = {} + local item_list = {} + for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do + local all_item_groups = {} + for primary in pairs(enchantment_def.primary) do + all_item_groups[primary] = true + mcl_enchanting.all_item_groups[primary] = true + end + for secondary in pairs(enchantment_def.secondary) do + all_item_groups[secondary] = true + mcl_enchanting.all_item_groups[secondary] = true + end + enchantment_def.all = all_item_groups + mcl_enchanting.total_weight = mcl_enchanting.total_weight + enchantment_def.weight + end + for itemname, itemdef in pairs(minetest.registered_items) do + if itemdef.groups.enchanted then + break + end + local quick_test = false + for group, groupv in pairs(itemdef.groups) do + if groupv > 0 and mcl_enchanting.all_item_groups[group] then + quick_test = true + break + end + end + if quick_test then + if mcl_enchanting.debug then + print(itemname) + end + local expensive_test = false + for enchantment in pairs(mcl_enchanting.enchantments) do + if mcl_enchanting.item_supports_enchantment(itemname, enchantment, true) then + expensive_test = true + if mcl_enchanting.debug then + print("\tSupports " .. enchantment) + else + break + end + end + end + if expensive_test then + local tooldef = minetest.registered_tools[itemname] + local new_name = itemname .. "_enchanted" + minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) + local new_def = table.copy(itemdef) + new_def.inventory_image = itemdef.inventory_image .. "^[colorize:purple:50" + new_def.groups.not_in_creative_inventory = 1 + new_def.groups.enchanted = 1 + new_def.texture = itemdef.texture or itemname:gsub("%:", "_") + new_def._mcl_enchanting_enchanted_tool = new_name + local register_list = item_list + if tooldef then + register_list = tool_list + end + register_list[":" .. new_name] = new_def + end + end + end + for new_name, new_def in pairs(item_list) do + minetest.register_craftitem(new_name, new_def) + end + for new_name, new_def in pairs(tool_list) do + minetest.register_tool(new_name, new_def) + end +end + +--[[ +minetest.register_on_mods_loaded(function() + for toolname, tooldef in pairs(minetest.registered_tools) do + for _, material in pairs(tooldef.materials) do + local full_name = toolname .. ((material == "") and "" or "_" .. material) + local old_def = minetest.registered_tools[full_name] + if not old_def then break end + mcl_enchanting.all_tools[full_name] = toolname + for _, enchantment in pairs(tooldef.enchantments) do + local enchantment_def = mcl_enchanting.enchantments[enchantment] + for lvl = 1, enchantment_def.max_level do + local new_def = table.copy(old_def) + new_def.description = minetest.colorize("#54FCFC", old_def.description) .. "\n" .. mcl_enchanting.get_enchantment_description(enchantment, lvl) + new_def.inventory_image = old_def.inventory_image .. "^[colorize:violet:50" + new_def.groups.not_in_creative_inventory = 1 + new_def.texture = old_def.texture or full_name:gsub("%:", "_") + new_def._original_tool = full_name + enchantment_def.create_itemdef(new_def, lvl) + minetest.register_tool(":" .. full_name .. "_enchanted_" .. enchantment .. "_" .. lvl, new_def) + end + end + end + end +end) +--]] diff --git a/mods/CORE/_mcl_enchanting/book.lua b/mods/CORE/mcl_enchanting/book.lua similarity index 100% rename from mods/CORE/_mcl_enchanting/book.lua rename to mods/CORE/mcl_enchanting/book.lua diff --git a/mods/CORE/_mcl_enchanting/command.lua b/mods/CORE/mcl_enchanting/command.lua similarity index 100% rename from mods/CORE/_mcl_enchanting/command.lua rename to mods/CORE/mcl_enchanting/command.lua diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua new file mode 100644 index 0000000000..dfe5559cb9 --- /dev/null +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -0,0 +1,591 @@ +-- Taken from https://minecraft.gamepedia.com/Enchanting + +-- unimplemented +mcl_enchanting.enchantments.aqua_affinity = { + name = "Aqua Affinity", + max_level = 1, + primary = {armor_head = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 2, + description = "Increases underwater mining speed.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.bane_of_anthropods = { + name = "Bane of Anthropods", + max_level = 5, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {smite = true, shaprness = true}, + weight = 5, + description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites).", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.blast_protection = { + name = "Blast Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {fire_protection = true, protection = true, projectile_protection = true}, + weight = 2, + description = "Reduces explosion damage and knockback.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.curse_of_binding = { + name = "Curse of Binding", + max_level = 1, + primary = {}, + secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + disallow = {}, + incompatible = {}, + weight = 1, + description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking.", + curse = true, + on_enchant = function() end, + requires_tool = false, +} + +-- implemented in mcl_death_drop +mcl_enchanting.enchantments.curse_of_vanishing = { + name = "Curse of Vanishing", + max_level = 1, + primary = {}, + secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, + disallow = {clock = true}, + incompatible = {}, + weight = 1, + description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking.", + curse = true, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.depth_strider = { + name = "Depth Strider", + max_level = 3, + primary = {}, + secondary = {armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {frost_walker = true}, + weight = 2, + description = "Increases underwater movement speed.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.efficiency = { + name = "Efficiency", + max_level = 5, + primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, + secondary = {shears = true}, + disallow = {}, + incompatible = {}, + weight = 10, + description = "Increases mining speed.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.feather_falling = { + name = "Feather Falling", + max_level = 4, + primary = {armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 5, + description = "Reduces fall damage.",curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.fire_aspect = { + name = "Fire Aspect", + max_level = 2, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Sets target on fire.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.fire_protection = { + name = "Fire Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, protection = true, projectile_protection = true}, + weight = 5, + description = "Reduces fire damage.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.flame = { + name = "Flame", + max_level = 1, + primary = {bow = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Arrows set target on fire.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.fortune = { + name = "Fortune", + max_level = 4, + primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, + secondary = {}, + disallow = {}, + incompatible = {silk_touch = true}, + weight = 2, + description = "Increases certain block drops.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.frost_walker = { + name = "Frost Walker", + max_level = 2, + primary = {}, + secondary = {armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {depth_strider = true}, + weight = 2, + description = "Turns water beneath the player into frosted ice and prevents the damage the player would take from standing on magma blocks.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- implemented in mcl_bows +mcl_enchanting.enchantments.infinity = { + name = "Infinity", + max_level = 1, + primary = {bow = true}, + secondary = {}, + disallow = {}, + incompatible = {mending = true}, + weight = 1, + description = "Shooting consumes no regular arrows.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.knockback = { + name = "Knockback", + max_level = 2, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 5, + description = "Increases knockback.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.looting = { + name = "Looting", + max_level = 3, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases mob loot.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.luck_of_the_sea = { + name = "Luck of the Sea", + max_level = 3, + primary = {fishing_rod = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases rate of good loot (enchanting books, etc.)", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.lure = { + name = "Lure", + max_level = 3, + primary = {fishing_rod = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Decreases wait time until fish/junk/loot \"bites\".", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.mending = { + name = "Mending", + max_level = 1, + primary = {}, + secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, + disallow = {non_combat_armor = true, compass = true, clock = true}, + incompatible = {infinity = true}, + weight = 2, + description = "Repair the item while gaining XP orbs.", + curse = false, + on_enchant = function() end, + requires_tool = true, +} + +-- unimplemented +mcl_enchanting.enchantments.power = { + name = "Power", + max_level = 5, + primary = {}, + secondary = {bow = true}, + disallow = {}, + incompatible = {}, + weight = 10, + description = "Increases arrow damage.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.projectile_protection = { + name = "Projectile Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, fire_protection = true, protection = true}, + weight = 5, + description = "Reduces projectile damage.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.protection = { + name = "Protection", + max_level = 4, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true}, + weight = 10, + description = "Reduces most types of damage by 4% for each level.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.punch = { + name = "Punch", + max_level = 2, + primary = {}, + secondary = {bow = true}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases arrow knockback.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.respiration = { + name = "Respiration", + max_level = 3, + primary = {armor_head = true}, + secondary = {}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 2, + description = "Extends underwater breathing time.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.sharpness = { + name = "Sharpness", + max_level = 5, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {bane_of_anthropods = true, smite = true}, + weight = 5, + description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites).", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.silk_touch = { + name = "Silk Touch", + max_level = 1, + primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, + secondary = {shears = true}, + disallow = {}, + incompatible = {fortune = true}, + weight = 1, + description = "Mined blocks drop themselves.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + + +-- unimplemented +mcl_enchanting.enchantments.smite = { + name = "Smite", + max_level = 5, + primary = {sword = true}, + secondary = {axe = true}, + disallow = {}, + incompatible = {bane_of_anthropods = true, sharpness = true}, + weight = 5, + description = "Increases damage to undead mobs.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.soul_speed = { + name = "Soul Speed", + max_level = 3, + primary = {}, + secondary = {armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {frost_walker = true}, + weight = 2, + description = "Incerases walking speed on soul sand.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.sweeping_edge = { + name = "Sweeping Edge", + max_level = 3, + primary = {sword = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Increases sweeping attack damage.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.thorns = { + name = "Thorns", + max_level = 3, + primary = {armor_head = true}, + secondary = {armor_torso = true, armor_legs = true, armor_feet = true}, + disallow = {non_combat_armor = true}, + incompatible = {blast_protection = true, fire_protection = true, projectile_protection = true}, + weight = 1, + description = "Reflects some of the damage taken when hit, at the cost of reducing durability with each proc.", + curse = false, + on_enchant = function() end, + requires_tool = false, +} + +-- unimplemented +mcl_enchanting.enchantments.unbreaking = { + name = "Unbreaking", + max_level = 3, + primary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, pickaxe = true, shovel = true, axe = true, hoe = true, sword = true, fishing_rod = true, bow = true}, + secondary = {tool = true}, + disallow = {non_combat_armor = true}, + incompatible = {}, + weight = 5, + description = "Increases item durability.", + curse = false, + on_enchant = function() end, + requires_tool = true, +} + + + +--[[ +local pickaxes = {"mcl_tools:pick_wood", "mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} +local pickaxes_better_than_iron = {"mcl_tools:pick_iron", "mcl_tools:pick_diamond"} +local pickaxes_better_than_stone = {"mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} +local shovels = {"mcl_tools:shovel_wood", "mcl_tools:shovel_stone", "mcl_tools:shovel_gold", "mcl_tools:shovel_iron", "mcl_tools:shovel_diamond"} + +local silk_touch_tool_lists = { + ["mcl_books:bookshelf"] = true, + ["mcl_core:clay"] = true, + ["mcl_core:stone_with_coal"] = pickaxes, + ["group:coral_block"] = pickaxes, + ["group:coral"] = true, + ["group:coral_fan"] = true, + ["mcl_core:stone_with_diamond"] = pickaxes_better_than_iron, + ["mcl_core:stone_with_emerald"] = pickaxes_better_than_iron, + ["mcl_chests:ender_chest"] = pickaxes, + ["group:glass"] = true, + ["mcl_nether:glowstone"] = true, + ["mcl_core:dirt_with_grass"] = true, + ["mcl_core:gravel"] = true, + ["mcl_core:ice"] = true, + ["mcl_core:stone_with_lapis"] = pickaxes_better_than_stone, + ["group:leaves"] = true, + ["mcl_farming:melon"] = true, + ["group:huge_mushroom"] = true, + ["mcl_core:mycelium"] = true, + ["mcl_nether:quartz_ore"] = pickaxes, + ["mcl_core:packed_ice"] = true, + ["mcl_core:podzol"] = true, + ["mcl_core:stone_with_redstone"] = pickaxes_better_than_iron, + ["mcl_ocean:sea_lantern"] = true, + ["group:top_snow"] = shovels, + ["mcl_core:snowblock"] = shovels, + ["mcl_core:stone"] = pickaxes, +} + +minetest.register_on_mods_loaded(function() + local old_handle_node_drops = minetest.handle_node_drops + function minetest.handle_node_drops(pos, drops, digger) + if digger and digger:is_player() then + local wielditem = digger:get_wielded_item() + local tooldef = wielditem:get_definition() + if tooldef._silk_touch then + local nodename = minetest.get_node(pos).name + local nodedef = minetest.registered_nodes[nodename] + local silk_touch_spec = silk_touch_tool_lists[nodename] + local suitable_tool = false + local tool_list + if silk_touch_spec == true then + suitable_tool = true + elseif silk_touch_spec then + tool_list = silk_touch_spec + else + for k, v in pairs(nodedef.groups) do + if v > 0 then + local group_spec = silk_touch_tool_lists["group:" .. k] + if group_spec == true then + suitable_tool = true + elseif group_spec then + toollist = group_spec + break + end + end + end + end + if tool_list and not suitable_tool then + suitable_tool = (table.indexof(tool_list, tooldef._original_tool) ~= -1) + end + if suitable_tool then + drops = {nodename} + end + end + end + old_handle_node_drops(pos, drops, digger) + end +end) +--]] + + +--[[ + sharpness = { + name = "Sharpness", + max_level = 5, + create_itemdef = function(def, level) + def.tool_capabilities.damage_groups.fleshy = def.tool_capabilities.damage_groups.fleshy + (level + 1) / 2 + end, + }, + efficiency = { + name = "Efficiency", + max_level = 5, + create_itemdef = function(def, level) + local groupcaps = def.tool_capabilities.groupcaps + for _, groupcap in pairs(groupcaps) do + for i, t in pairs(groupcap.times) do + local m = 1 / t + m = m + math.pow(level, 2) + 1 + groupcap.times[i] = 1 / m + end + end + end, + }, + unbreaking = { + name = "Unbreaking", + max_level = 3, + create_itemdef = function(def, level) + local toolcaps = def.tool_capabilities + local armor_uses = def.groups.mcl_armor_uses + local factor = 0.5 + if toolcaps then + local groupcaps = toolcaps.groupcaps + for _, groupcap in pairs(groupcaps) do + groupcap.uses = math.floor(groupcap.uses * (1 + level)) + end + def.tool_capabilities.punch_attack_uses = math.floor(def.tool_capabilities.punch_attack_uses * (1 + level)) + elseif armor_uses then + def.groups.mcl_armor_uses = math.floor(armor_uses / (0.6 + (0.4 / (level + 1)))) + end + end + }, + },--]] + + diff --git a/mods/CORE/_mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua similarity index 76% rename from mods/CORE/_mcl_enchanting/init.lua rename to mods/CORE/mcl_enchanting/init.lua index 80b171db1a..5921d77d3b 100644 --- a/mods/CORE/_mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -4,14 +4,19 @@ mcl_enchanting = { lapis_itemstring = "mcl_dye:blue", book_offset = vector.new(0, 0.75, 0), roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 + enchantments = {}, + total_weight = 0, + all_item_groups = {}, + debug = true, } +dofile(modpath .. "/api.lua") dofile(modpath .. "/enchantments.lua") -dofile(modpath .. "/features.lua") -dofile(modpath .. "/core.lua") dofile(modpath .. "/command.lua") dofile(modpath .. "/tt.lua") -- dofile(modpath .. "/ui.lua") -- dofile(modpath .. "/fx.lua") -- dofile(modpath .. "/book.lua") -- dofile(modpath .. "/table.lua") + +minetest.register_on_mods_loaded(mcl_enchanting.initialize) diff --git a/mods/CORE/_mcl_enchanting/mod.conf b/mods/CORE/mcl_enchanting/mod.conf similarity index 100% rename from mods/CORE/_mcl_enchanting/mod.conf rename to mods/CORE/mcl_enchanting/mod.conf diff --git a/mods/CORE/_mcl_enchanting/models/mcl_enchanting_book.b3d b/mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d similarity index 100% rename from mods/CORE/_mcl_enchanting/models/mcl_enchanting_book.b3d rename to mods/CORE/mcl_enchanting/models/mcl_enchanting_book.b3d diff --git a/mods/CORE/_mcl_enchanting/models/mcl_enchanting_book_entity.png b/mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png similarity index 100% rename from mods/CORE/_mcl_enchanting/models/mcl_enchanting_book_entity.png rename to mods/CORE/mcl_enchanting/models/mcl_enchanting_book_entity.png diff --git a/mods/CORE/_mcl_enchanting/roman_numerals.lua b/mods/CORE/mcl_enchanting/roman_numerals.lua similarity index 100% rename from mods/CORE/_mcl_enchanting/roman_numerals.lua rename to mods/CORE/mcl_enchanting/roman_numerals.lua diff --git a/mods/CORE/_mcl_enchanting/sounds/mcl_enchanting_enchant.ogg b/mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg similarity index 100% rename from mods/CORE/_mcl_enchanting/sounds/mcl_enchanting_enchant.ogg rename to mods/CORE/mcl_enchanting/sounds/mcl_enchanting_enchant.ogg diff --git a/mods/CORE/_mcl_enchanting/table.lua b/mods/CORE/mcl_enchanting/table.lua similarity index 100% rename from mods/CORE/_mcl_enchanting/table.lua rename to mods/CORE/mcl_enchanting/table.lua diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_closed.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_closed.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_closed.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_open.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_book_open.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_open.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_button.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_background.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_background.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_background.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_background.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_hovered.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_hovered.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_hovered.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_off.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_off.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_button_off.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_button_off.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_1.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_1.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_1.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_1.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_10.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_10.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_10.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_11.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_11.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_11.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_11.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_12.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_12.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_12.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_13.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_13.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_13.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_14.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_14.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_14.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_15.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_15.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_15.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_16.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_16.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_16.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_17.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_17.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_17.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_18.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_18.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_18.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_18.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_2.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_2.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_2.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_3.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_3.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_3.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_4.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_4.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_4.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_5.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_5.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_5.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_6.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_6.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_6.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_7.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_7.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_7.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_8.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_8.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_8.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_9.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_glyph_9.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_lapis_background.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_lapis_background.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_lapis_background.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1_off.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_1_off.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_1_off.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2_off.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_2_off.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_2_off.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3_off.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3_off.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_number_3_off.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3_off.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_bottom.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_bottom.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_bottom.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_side.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_side.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_side.png diff --git a/mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_top.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png similarity index 100% rename from mods/CORE/_mcl_enchanting/textures/mcl_enchanting_table_top.png rename to mods/CORE/mcl_enchanting/textures/mcl_enchanting_table_top.png diff --git a/mods/CORE/_mcl_enchanting/tt.lua b/mods/CORE/mcl_enchanting/tt.lua similarity index 78% rename from mods/CORE/_mcl_enchanting/tt.lua rename to mods/CORE/mcl_enchanting/tt.lua index 41ceb6249d..f9b8e34c1d 100644 --- a/mods/CORE/_mcl_enchanting/tt.lua +++ b/mods/CORE/mcl_enchanting/tt.lua @@ -5,7 +5,7 @@ function mcl_enchanting.enchantments_snippet(_, _, itemstack) local enchantments = mcl_enchanting.get_enchantments(itemstack) local text = "" for enchantment, level in pairs(enchantments) do - text = text .. mcl_enchanting.get_enchantment_description(enchantment, level) .. "\n" + text = text .. mcl_enchanting.get_colorized_enchantment_description(enchantment, level) .. "\n" end if text ~= "" then return text, false diff --git a/mods/HELP/tt/init.lua b/mods/HELP/tt/init.lua index d1bb6d6b8b..a2b747ce83 100644 --- a/mods/HELP/tt/init.lua +++ b/mods/HELP/tt/init.lua @@ -60,8 +60,10 @@ minetest.register_on_mods_loaded(append_snippets) tt.reload_itemstack_description = function(itemstack) local itemstring = itemstack:get_name() local def = itemstack:get_definition() - if should_change(itemstring, def) then - local meta = itemstack:get_meta() + local meta = itemstack:get_meta() + if def._mcl_generate_description then + def._mcl_generate_description(itemstack) + elseif should_change(itemstring, def) and meta:get_string("name") == "" then local orig_desc = def._tt_original_description local desc = apply_snippets(orig_desc, itemstring, itemstack:get_tool_capabilities(), itemstack) if desc ~= orig_desc then diff --git a/mods/ITEMS/mcl_anvils/depends.txt b/mods/ITEMS/mcl_anvils/depends.txt index 98a3e017eb..c17e5a0b20 100644 --- a/mods/ITEMS/mcl_anvils/depends.txt +++ b/mods/ITEMS/mcl_anvils/depends.txt @@ -3,3 +3,4 @@ mcl_formspec mcl_sounds mcl_core? screwdriver? +tt diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index ce74a10d9d..fbc1c9d03c 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -170,23 +170,16 @@ local function update_anvil_slots(meta) new_name = string.sub(new_name, 1, MAX_NAME_LENGTH) -- Don't rename if names are identical if new_name ~= old_name then + -- Save the raw name internally + meta:set_string("name", new_name) -- Rename item if new_name == "" then - -- Empty name - if name_item:get_definition()._mcl_generate_description then - -- _mcl_generate_description(itemstack): If defined, set custom item description of itemstack. - name_item:get_definition()._mcl_generate_description(name_item) - else - -- Otherwise, just clear description - meta:set_string("description", "") - end + tt.reload_itemstack_description(name_item) else -- Custom name set. Colorize it! -- This makes the name visually different from unnamed items meta:set_string("description", minetest.colorize(NAME_COLOR, new_name)) end - -- Save the raw name internally, too - meta:set_string("name", new_name) new_output = name_item elseif just_rename then new_output = "" diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 21b55c31ba..53776df3b6 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -76,7 +76,7 @@ end local player_shoot_arrow = function(itemstack, player, power, damage, is_critical) local arrow_stack, arrow_stack_id = get_arrow(player) local arrow_itemstring - local has_infinity_enchantment = rawget(_G, "mcl_enchanting") and mcl_enchanting.get_enchantment(player:get_wielded_item(), "infinity") > 0 + local has_infinity_enchantment = mcl_enchanting.has_enchantment(player:get_wielded_item(), "infinity") if minetest.is_creative_enabled(player:get_player_name()) then if arrow_stack then @@ -165,7 +165,7 @@ for level=0, 2 do groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1}, on_drop = function(itemstack, dropper, pos) reset_bow_state(dropper) - if minetest.get_item_group(itemstack:get_name(), "enchanted") > 0 then + if mcl_enchanting.is_enchanted(itemstack) then itemstack:set_name("mcl_bows:bow_enchanted") else itemstack:set_name("mcl_bows:bow") @@ -190,7 +190,7 @@ controls.register_on_release(function(player, key, time) wielditem:get_name()=="mcl_bows:bow_0_enchanted" or wielditem:get_name()=="mcl_bows:bow_1_enchanted" or wielditem:get_name()=="mcl_bows:bow_2_enchanted") then local has_shot = false - local enchanted = minetest.get_item_group(wielditem:get_name(), "enchanted") > 0 + local enchanted = mcl_enchanting.is_enchanted(wielditem) local speed, damage local p_load = bow_load[player:get_player_name()] local charge @@ -253,7 +253,7 @@ controls.register_on_hold(function(player, key, time) local inv = minetest.get_inventory({type="player", name=name}) local wielditem = player:get_wielded_item() if bow_load[name] == nil and (wielditem:get_name()=="mcl_bows:bow" or wielditem:get_name()=="mcl_bows:bow_enchanted") and (creative or get_arrow(player)) then - local enchanted = (wielditem:get_name()=="mcl_bows:bow_enchanted") + local enchanted = mcl_enchanting.is_enchanted(wielditem) if enchanted then wielditem:set_name("mcl_bows:bow_0_enchanted") else diff --git a/mods/ITEMS/mcl_bows/depends.txt b/mods/ITEMS/mcl_bows/depends.txt index 130c4aceae..a797e71843 100644 --- a/mods/ITEMS/mcl_bows/depends.txt +++ b/mods/ITEMS/mcl_bows/depends.txt @@ -8,3 +8,4 @@ doc? doc_identifier? mesecons_button? mcl_particles +mcl_enchanting diff --git a/mods/PLAYER/mcl_death_drop/depends.txt b/mods/PLAYER/mcl_death_drop/depends.txt index 2bbf820fd6..4c2d1c21fd 100644 --- a/mods/PLAYER/mcl_death_drop/depends.txt +++ b/mods/PLAYER/mcl_death_drop/depends.txt @@ -1 +1,2 @@ mcl_armor +mcl_enchanting diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index 54672a5db1..adad4b1e71 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -23,7 +23,7 @@ minetest.register_on_dieplayer(function(player) local z = math.random(0, 9)/3 pos.x = pos.x + x pos.z = pos.z + z - if not void_deadly and drop then + if not void_deadly and drop and mcl_enchanting.get_enchantment(stack, "curse_of_vanishing") > 0 then local def = minetest.registered_items[stack:get_name()] if def and def.on_drop then stack = def.on_drop(stack, player, pos) From 3fd1963da9c87aa91b5f1fcaa15c44cd508caac3 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sun, 1 Nov 2020 14:23:43 +0100 Subject: [PATCH 06/27] Compass support --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/CORE/mcl_enchanting/tt.lua | 5 ++++- mods/HELP/tt/init.lua | 27 ++++++++++++++++++++--- mods/ITEMS/mcl_compass/depends.txt | 1 + mods/ITEMS/mcl_compass/init.lua | 8 +++++-- mods/PLAYER/mcl_death_drop/init.lua | 2 +- 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index dfe5559cb9..ee007b91d7 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -275,7 +275,7 @@ mcl_enchanting.enchantments.mending = { max_level = 1, primary = {}, secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, - disallow = {non_combat_armor = true, compass = true, clock = true}, + disallow = {}, incompatible = {infinity = true}, weight = 2, description = "Repair the item while gaining XP orbs.", diff --git a/mods/CORE/mcl_enchanting/tt.lua b/mods/CORE/mcl_enchanting/tt.lua index f9b8e34c1d..e6529b0586 100644 --- a/mods/CORE/mcl_enchanting/tt.lua +++ b/mods/CORE/mcl_enchanting/tt.lua @@ -8,7 +8,10 @@ function mcl_enchanting.enchantments_snippet(_, _, itemstack) text = text .. mcl_enchanting.get_colorized_enchantment_description(enchantment, level) .. "\n" end if text ~= "" then - return text, false + if not itemstack:get_definition()._tt_original_description then + text = text:sub(1, text:len() - 1) + end + return text, false end end diff --git a/mods/HELP/tt/init.lua b/mods/HELP/tt/init.lua index a2b747ce83..aa42290bb3 100644 --- a/mods/HELP/tt/init.lua +++ b/mods/HELP/tt/init.lua @@ -14,6 +14,22 @@ dofile(minetest.get_modpath(minetest.get_current_modname()).."/snippets.lua") -- Apply item description updates +local function equals(t1, t2) + for k, v in pairs(t1) do + local equal + local v2 = rawget(t2, k) + if type(v) == "table" then + equal = equals(v, v2) + else + equal = (v == v2) + end + if not equal then + return false + end + end + return true +end + local function apply_snippets(desc, itemstring, toolcaps, itemstack) local first = true -- Apply snippets @@ -61,11 +77,16 @@ tt.reload_itemstack_description = function(itemstack) local itemstring = itemstack:get_name() local def = itemstack:get_definition() local meta = itemstack:get_meta() - if def._mcl_generate_description then + if def and def._mcl_generate_description then def._mcl_generate_description(itemstack) elseif should_change(itemstring, def) and meta:get_string("name") == "" then - local orig_desc = def._tt_original_description - local desc = apply_snippets(orig_desc, itemstring, itemstack:get_tool_capabilities(), itemstack) + local toolcaps = itemstack:get_tool_capabilities() + local hand_toolcaps = ItemStack(""):get_tool_capabilities() + if equals(toolcaps, hand_toolcaps) then + toolcaps = nil + end + local orig_desc = def._tt_original_description or def.description + local desc = apply_snippets(orig_desc, itemstring, toolcaps or def.tool_capabilities, itemstack) if desc ~= orig_desc then meta:set_string("description", desc) end diff --git a/mods/ITEMS/mcl_compass/depends.txt b/mods/ITEMS/mcl_compass/depends.txt index 53261d53c9..0389d3050a 100644 --- a/mods/ITEMS/mcl_compass/depends.txt +++ b/mods/ITEMS/mcl_compass/depends.txt @@ -2,3 +2,4 @@ mcl_core mcl_worlds mesecons doc? +mcl_enchanting diff --git a/mods/ITEMS/mcl_compass/init.lua b/mods/ITEMS/mcl_compass/init.lua index 7a23cc50d3..1b2810de69 100644 --- a/mods/ITEMS/mcl_compass/init.lua +++ b/mods/ITEMS/mcl_compass/init.lua @@ -56,8 +56,12 @@ minetest.register_globalstep(function(dtime) for j,stack in ipairs(player:get_inventory():get_list("main")) do if minetest.get_item_group(stack:get_name(), "compass") ~= 0 and minetest.get_item_group(stack:get_name(), "compass")-1 ~= compass_image then - local count = stack:get_count() - player:get_inventory():set_stack("main", j, ItemStack("mcl_compass:"..compass_image.." "..count)) + local itemname = "mcl_compass:"..compass_image + if mcl_enchanting.is_enchanted(stack) then + itemname = itemname .. "_enchanted" + end + stack:set_name(itemname) + player:get_inventory():set_stack("main", j, stack) end end end diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index adad4b1e71..4e0fa6e629 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -23,7 +23,7 @@ minetest.register_on_dieplayer(function(player) local z = math.random(0, 9)/3 pos.x = pos.x + x pos.z = pos.z + z - if not void_deadly and drop and mcl_enchanting.get_enchantment(stack, "curse_of_vanishing") > 0 then + if not void_deadly and drop and mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then local def = minetest.registered_items[stack:get_name()] if def and def.on_drop then stack = def.on_drop(stack, player, pos) From 3791f8983ee45482806537061a102e33f4401c93 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sun, 1 Nov 2020 15:15:44 +0100 Subject: [PATCH 07/27] Combine tools in anvil --- mods/CORE/mcl_enchanting/api.lua | 61 +++++++++++++++++++++++++------ mods/ITEMS/mcl_anvils/depends.txt | 1 + mods/ITEMS/mcl_anvils/init.lua | 16 ++++---- 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/mods/CORE/mcl_enchanting/api.lua b/mods/CORE/mcl_enchanting/api.lua index a646134992..907fb63dd3 100644 --- a/mods/CORE/mcl_enchanting/api.lua +++ b/mods/CORE/mcl_enchanting/api.lua @@ -3,7 +3,15 @@ function mcl_enchanting.get_enchantments(itemstack) end function mcl_enchanting.set_enchantments(itemstack, enchantments) - return itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) + itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) + local itemdef = itemstack:get_definition() + for enchantment, level in pairs(enchantments) do + local enchantment_def = mcl_enchanting.enchantments[enchantment] + if enchantment_def.on_enchant then + enchantment_def.on_enchant(itemstack, level, itemdef) + end + end + tt.reload_itemstack_description(itemstack) end function mcl_enchanting.get_enchantment(itemstack, enchantment) @@ -41,8 +49,8 @@ function mcl_enchanting.item_supports_enchantment(itemname, enchantment, early) return false end local enchantment_def = mcl_enchanting.enchantments[enchantment] - local tooldef = minetest.registered_tools[itemname] - if not tooldef and enchantment_def.requires_tool then + local itemdef = minetest.registered_items[itemname] + if itemdef.type ~= "tool" and enchantment_def.requires_tool then return false end for disallow in pairs(enchantment_def.disallow) do @@ -96,19 +104,49 @@ function mcl_enchanting.enchant(itemstack, enchantment, level) local enchantments = mcl_enchanting.get_enchantments(itemstack) enchantments[enchantment] = level mcl_enchanting.set_enchantments(itemstack, enchantments) - mcl_enchanting.reload_enchantments(itemstack, enchantments) return itemstack end -function mcl_enchanting.reload_enchantments(itemstack, enchantments) - local itemdef = itemstack:get_definition() - for enchantment, level in pairs(enchantments) do +function mcl_enchanting.combine(itemstack, combine_with) + local itemname = itemstack:get_name() + local enchanted_itemname = mcl_enchanting.get_enchanted_itemstring(itemname) + if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_with:get_name()) then + return false + end + local enchantments = mcl_enchanting.get_enchantments(itemstack) + for enchantment, combine_level in pairs(mcl_enchanting.get_enchantments(combine_with)) do local enchantment_def = mcl_enchanting.enchantments[enchantment] - if enchantment_def.on_enchant then - enchantment_def.on_enchant(itemstack, level, itemdef) + local enchantment_level = enchantments[combine_enchantment] + if enchantment_level then + if enchantment_level == combine_level then + enchantment_level = math.min(enchantment_level + 1, enchantment_def.max_level) + end + elseif mcl_enchanting.item_supports_enchantment(itemname, enchantment) then + local supported = true + for incompatible in pairs(enchantment_def.incompatible) do + if enchantments[incompatible] then + supported = false + break + end + end + if supported then + enchantment_level = combine_level + end + end + enchantments[enchantment] = enchantment_level + end + local any_enchantment = false + for enchantment, enchantment_level in pairs(enchantments) do + if enchantment_level > 0 then + any_enchantment = true + break end end - tt.reload_itemstack_description(itemstack) + if any_enchantment then + itemstack:set_name(enchanted_itemname) + end + mcl_enchanting.set_enchantments(itemstack, enchantments) + return true end function mcl_enchanting.initialize() @@ -154,7 +192,6 @@ function mcl_enchanting.initialize() end end if expensive_test then - local tooldef = minetest.registered_tools[itemname] local new_name = itemname .. "_enchanted" minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) local new_def = table.copy(itemdef) @@ -164,7 +201,7 @@ function mcl_enchanting.initialize() new_def.texture = itemdef.texture or itemname:gsub("%:", "_") new_def._mcl_enchanting_enchanted_tool = new_name local register_list = item_list - if tooldef then + if itemdef.type == "tool" then register_list = tool_list end register_list[":" .. new_name] = new_def diff --git a/mods/ITEMS/mcl_anvils/depends.txt b/mods/ITEMS/mcl_anvils/depends.txt index c17e5a0b20..89b87aa2d6 100644 --- a/mods/ITEMS/mcl_anvils/depends.txt +++ b/mods/ITEMS/mcl_anvils/depends.txt @@ -4,3 +4,4 @@ mcl_sounds mcl_core? screwdriver? tt +mcl_enchanting diff --git a/mods/ITEMS/mcl_anvils/init.lua b/mods/ITEMS/mcl_anvils/init.lua index fbc1c9d03c..bf912c7a0f 100644 --- a/mods/ITEMS/mcl_anvils/init.lua +++ b/mods/ITEMS/mcl_anvils/init.lua @@ -42,9 +42,6 @@ end -- needs to be used up to repair the tool. local function get_consumed_materials(tool, material) local wear = tool:get_wear() - if wear == 0 then - return 0 - end local health = (MAX_WEAR - wear) local matsize = material:get_count() local materials_used = 0 @@ -103,12 +100,15 @@ local function update_anvil_slots(meta) return math.max(0, math.min(MAX_WEAR, MAX_WEAR - new_health)) end - -- Same tool twice - if input1:get_name() == input2:get_name() and def1.type == "tool" and (input1:get_wear() > 0 or input2:get_wear() > 0) then + local can_combine = mcl_enchanting.combine(input1, input2) + + if can_combine then -- Add tool health together plus a small bonus - -- TODO: Combine tool enchantments - local new_wear = calculate_repair(input1:get_wear(), input2:get_wear(), SAME_TOOL_REPAIR_BOOST) - input1:set_wear(new_wear) + if def1.type == "tool" and def2.type == "tool" then + local new_wear = calculate_repair(input1:get_wear(), input2:get_wear(), SAME_TOOL_REPAIR_BOOST) + input1:set_wear(new_wear) + end + name_item = input1 new_output = name_item -- Tool + repair item From e09ecb5431f4664e3d11a2a24fa7a40dedff3059 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sun, 1 Nov 2020 17:24:57 +0100 Subject: [PATCH 08/27] Enchanted Books; Fishing Rod Support; Curse of Binding --- mods/CORE/mcl_enchanting/api.lua | 101 +++++++++--------- mods/CORE/mcl_enchanting/book.lua | 94 ++-------------- mods/CORE/mcl_enchanting/enchantments.lua | 8 +- mods/CORE/mcl_enchanting/init.lua | 3 +- mods/CORE/mcl_enchanting/mod.conf | 2 +- mods/CORE/mcl_enchanting/table_book.lua | 87 +++++++++++++++ .../mcl_enchanting_book_enchanted.png | Bin 0 -> 386 bytes mods/ITEMS/mcl_armor/armor.lua | 3 + mods/ITEMS/mcl_bows/bow.lua | 8 +- mods/ITEMS/mcl_fishing/init.lua | 4 +- 10 files changed, 155 insertions(+), 155 deletions(-) create mode 100644 mods/CORE/mcl_enchanting/table_book.lua create mode 100644 mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_enchanted.png diff --git a/mods/CORE/mcl_enchanting/api.lua b/mods/CORE/mcl_enchanting/api.lua index 907fb63dd3..1581225627 100644 --- a/mods/CORE/mcl_enchanting/api.lua +++ b/mods/CORE/mcl_enchanting/api.lua @@ -5,16 +5,21 @@ end function mcl_enchanting.set_enchantments(itemstack, enchantments) itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) local itemdef = itemstack:get_definition() - for enchantment, level in pairs(enchantments) do - local enchantment_def = mcl_enchanting.enchantments[enchantment] - if enchantment_def.on_enchant then - enchantment_def.on_enchant(itemstack, level, itemdef) + if itemstack:get_name() ~= "mcl_enchanting:book_enchanted" then + for enchantment, level in pairs(enchantments) do + local enchantment_def = mcl_enchanting.enchantments[enchantment] + if enchantment_def.on_enchant then + enchantment_def.on_enchant(itemstack, level, itemdef) + end end end tt.reload_itemstack_description(itemstack) end function mcl_enchanting.get_enchantment(itemstack, enchantment) + if itemstack:get_name() == "mcl_enchanting:book_enchanted" then + return 0 + end return mcl_enchanting.get_enchantments(itemstack)[enchantment] or 0 end @@ -45,6 +50,9 @@ function mcl_enchanting.is_enchanted(itemstack) end function mcl_enchanting.item_supports_enchantment(itemname, enchantment, early) + if itemname == "mcl_enchanting:book_enchanted" then + return true, true + end if not early and not mcl_enchanting.get_enchanted_itemstring(itemname) then return false end @@ -58,9 +66,14 @@ function mcl_enchanting.item_supports_enchantment(itemname, enchantment, early) return false end end - for group in pairs(enchantment_def.all) do + for group in pairs(enchantment_def.primary) do if minetest.get_item_group(itemname, group) > 0 then - return true + return true, true + end + end + for group in pairs(enchantment_def.secondary) do + if minetest.get_item_group(itemname, group) > 0 then + return true, false end end return false @@ -71,7 +84,8 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) if not enchantment_def then return false, "enchantment invalid" end - if itemstack:get_name() == "" then + local itemname = itemstack:get_name() + if itemname == "" then return false, "item missing" end if not mcl_enchanting.item_supports_enchantment(itemstack:get_name(), enchantment) then @@ -90,10 +104,12 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) if enchantment_level then return false, "incompatible", mcl_enchanting.get_enchantment_description(enchantment, enchantment_level) end - for incompatible in pairs(enchantment_def.incompatible) do - local incompatible_level = item_enchantments[incompatible] - if incompatible_level then - return false, "incompatible", mcl_enchanting.get_enchantment_description(incompatible, incompatible_level) + if itemname ~= "mcl_enchanting:book_enchanted" then + for incompatible in pairs(enchantment_def.incompatible) do + local incompatible_level = item_enchantments[incompatible] + if incompatible_level then + return false, "incompatible", mcl_enchanting.get_enchantment_description(incompatible, incompatible_level) + end end end return true @@ -109,17 +125,20 @@ end function mcl_enchanting.combine(itemstack, combine_with) local itemname = itemstack:get_name() + local combine_name = combine_with:get_name() local enchanted_itemname = mcl_enchanting.get_enchanted_itemstring(itemname) - if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_with:get_name()) then + if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and combine_name ~= "mcl_enchanting:book_enchanted" then return false end local enchantments = mcl_enchanting.get_enchantments(itemstack) for enchantment, combine_level in pairs(mcl_enchanting.get_enchantments(combine_with)) do local enchantment_def = mcl_enchanting.enchantments[enchantment] - local enchantment_level = enchantments[combine_enchantment] + local enchantment_level = enchantments[enchantment] if enchantment_level then if enchantment_level == combine_level then enchantment_level = math.min(enchantment_level + 1, enchantment_def.max_level) + else + enchantment_level = math.max(enchantment_level, combine_level) end elseif mcl_enchanting.item_supports_enchantment(itemname, enchantment) then local supported = true @@ -133,7 +152,9 @@ function mcl_enchanting.combine(itemstack, combine_with) enchantment_level = combine_level end end - enchantments[enchantment] = enchantment_level + if enchantment_level and enchantment_level > 0 then + enchantments[enchantment] = enchantment_level + end end local any_enchantment = false for enchantment, enchantment_level in pairs(enchantments) do @@ -150,28 +171,24 @@ function mcl_enchanting.combine(itemstack, combine_with) end function mcl_enchanting.initialize() - local tool_list = {} - local item_list = {} + local all_groups = {} for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do - local all_item_groups = {} for primary in pairs(enchantment_def.primary) do - all_item_groups[primary] = true - mcl_enchanting.all_item_groups[primary] = true + all_groups[primary] = true end for secondary in pairs(enchantment_def.secondary) do - all_item_groups[secondary] = true - mcl_enchanting.all_item_groups[secondary] = true + all_groups[secondary] = true end - enchantment_def.all = all_item_groups - mcl_enchanting.total_weight = mcl_enchanting.total_weight + enchantment_def.weight end + local register_tool_list = {} + local register_item_list = {} for itemname, itemdef in pairs(minetest.registered_items) do if itemdef.groups.enchanted then break end local quick_test = false for group, groupv in pairs(itemdef.groups) do - if groupv > 0 and mcl_enchanting.all_item_groups[group] then + if groupv > 0 and all_groups[group] then quick_test = true break end @@ -196,48 +213,26 @@ function mcl_enchanting.initialize() minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) local new_def = table.copy(itemdef) new_def.inventory_image = itemdef.inventory_image .. "^[colorize:purple:50" + if new_def.wield_image then + new_def.wield_image = new_def.wield_image .. "^[colorize:purple:50" + end new_def.groups.not_in_creative_inventory = 1 new_def.groups.enchanted = 1 new_def.texture = itemdef.texture or itemname:gsub("%:", "_") new_def._mcl_enchanting_enchanted_tool = new_name - local register_list = item_list + local register_list = register_item_list if itemdef.type == "tool" then - register_list = tool_list + register_list = register_tool_list end register_list[":" .. new_name] = new_def end end end - for new_name, new_def in pairs(item_list) do + for new_name, new_def in pairs(register_item_list) do minetest.register_craftitem(new_name, new_def) end - for new_name, new_def in pairs(tool_list) do + for new_name, new_def in pairs(register_tool_list) do minetest.register_tool(new_name, new_def) end end ---[[ -minetest.register_on_mods_loaded(function() - for toolname, tooldef in pairs(minetest.registered_tools) do - for _, material in pairs(tooldef.materials) do - local full_name = toolname .. ((material == "") and "" or "_" .. material) - local old_def = minetest.registered_tools[full_name] - if not old_def then break end - mcl_enchanting.all_tools[full_name] = toolname - for _, enchantment in pairs(tooldef.enchantments) do - local enchantment_def = mcl_enchanting.enchantments[enchantment] - for lvl = 1, enchantment_def.max_level do - local new_def = table.copy(old_def) - new_def.description = minetest.colorize("#54FCFC", old_def.description) .. "\n" .. mcl_enchanting.get_enchantment_description(enchantment, lvl) - new_def.inventory_image = old_def.inventory_image .. "^[colorize:violet:50" - new_def.groups.not_in_creative_inventory = 1 - new_def.texture = old_def.texture or full_name:gsub("%:", "_") - new_def._original_tool = full_name - enchantment_def.create_itemdef(new_def, lvl) - minetest.register_tool(":" .. full_name .. "_enchanted_" .. enchantment .. "_" .. lvl, new_def) - end - end - end - end -end) ---]] diff --git a/mods/CORE/mcl_enchanting/book.lua b/mods/CORE/mcl_enchanting/book.lua index 132fb880b4..7b0ee50801 100644 --- a/mods/CORE/mcl_enchanting/book.lua +++ b/mods/CORE/mcl_enchanting/book.lua @@ -1,87 +1,9 @@ -local book_animations = {["close"] = 1, ["opening"] = 2, ["open"] = 3, ["closing"] = 4} -local book_animation_steps = {0, 640, 680, 700, 740} -local book_animation_speed = 40 - -function mcl_enchanting.schedule_book_animation(self, anim) - self.scheduled_anim = {timer = self.anim_length, anim = anim} -end - -function mcl_enchanting.set_book_animation(self, anim) - local anim_index = book_animations[anim] - local start, stop = book_animation_steps[anim_index], book_animation_steps[anim_index + 1] - self.object:set_animation({x = start, y = stop}, book_animation_speed) - self.scheduled_anim = nil - self.anim_length = (stop - start) / 40 -end - -function mcl_enchanting.check_animation_schedule(self, dtime) - local schedanim = self.scheduled_anim - if schedanim then - schedanim.timer = schedanim.timer - dtime - if schedanim.timer <= 0 then - mcl_enchanting.set_book_animation(self, schedanim.anim)local pos1=self.object:get_pos() - end - end -end - -function mcl_enchanting.look_at(self, pos2) - local pos1 = self.object:get_pos() - local vec = vector.subtract(pos1, pos2) - local yaw = math.atan(vec.z / vec.x) - math.pi/2 - yaw = yaw + (pos1.x >= pos2.x and math.pi or 0) - self.object:set_yaw(yaw + math.pi) -end - -function mcl_enchanting.check_book(pos) - local obj_pos = vector.add(pos, mcl_enchanting.book_offset) - for _, obj in pairs(minetest.get_objects_inside_radius(obj_pos, 0.1)) do - local luaentity = obj:get_luaentity() - if luaentity and luaentity.name == "mcl_enchanting:book" then - if minetest.get_node(pos).name ~= "mcl_enchanting:table" then - obj:remove() - end - return - end - end - minetest.add_entity(obj_pos, "mcl_enchanting:book") -end - -minetest.register_entity("mcl_enchanting:book", { - initial_properties = { - visual = "mesh", - mesh = "mcl_enchanting_book.b3d", - visual_size = {x = 12.5, y = 12.5}, - collisionbox = {0, 0, 0}, - physical = false, - textures = {"mcl_enchanting_book_entity.png"}, - }, - player_near = false, - on_activate = function(self) - self.object:set_armor_groups({immortal = 1}) - mcl_enchanting.set_book_animation(self, "close") - mcl_enchanting.check_book(vector.subtract(self.object:get_pos(), mcl_enchanting.book_offset)) - end, - on_step = function(self, dtime) - local old_player_near = self.player_near - local player_near = false - local player - for _, obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 2.5)) do - if obj:is_player() then - player_near = true - player = obj - end - end - if player_near and not old_player_near then - mcl_enchanting.set_book_animation(self, "opening") - mcl_enchanting.schedule_book_animation(self, "open") - elseif old_player_near and not player_near then - mcl_enchanting.set_book_animation(self, "closing") - mcl_enchanting.schedule_book_animation(self, "close") - end - if player then - mcl_enchanting.look_at(self, player:get_pos()) - end - self.player_near = player_near - mcl_enchanting.check_animation_schedule(self, dtime) - end, +minetest.register_craftitem("mcl_enchanting:book_enchanted", { + description = "Enchanted Book", + inventory_image = "mcl_enchanting_book_enchanted.png^[colorize:purple:50", + groups = {enchanted = 1, not_in_creative_inventory = 1}, + _mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted", + stack_max = 1, }) + +minetest.registered_items["mcl_books:book"]._mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted" diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index ee007b91d7..b5452f96e7 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -1,7 +1,7 @@ -- Taken from https://minecraft.gamepedia.com/Enchanting --- unimplemented -mcl_enchanting.enchantments.aqua_affinity = { +-- requires engine change +--[[mcl_enchanting.enchantments.aqua_affinity = { name = "Aqua Affinity", max_level = 1, primary = {armor_head = true}, @@ -13,7 +13,7 @@ mcl_enchanting.enchantments.aqua_affinity = { curse = false, on_enchant = function() end, requires_tool = false, -} +}]]-- -- unimplemented mcl_enchanting.enchantments.bane_of_anthropods = { @@ -45,7 +45,7 @@ mcl_enchanting.enchantments.blast_protection = { requires_tool = false, } --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.curse_of_binding = { name = "Curse of Binding", max_level = 1, diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua index 5921d77d3b..1611557cef 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -5,8 +5,6 @@ mcl_enchanting = { book_offset = vector.new(0, 0.75, 0), roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 enchantments = {}, - total_weight = 0, - all_item_groups = {}, debug = true, } @@ -14,6 +12,7 @@ dofile(modpath .. "/api.lua") dofile(modpath .. "/enchantments.lua") dofile(modpath .. "/command.lua") dofile(modpath .. "/tt.lua") +dofile(modpath .. "/book.lua") -- dofile(modpath .. "/ui.lua") -- dofile(modpath .. "/fx.lua") -- dofile(modpath .. "/book.lua") diff --git a/mods/CORE/mcl_enchanting/mod.conf b/mods/CORE/mcl_enchanting/mod.conf index 8dfe4e94fd..3680b4fa97 100644 --- a/mods/CORE/mcl_enchanting/mod.conf +++ b/mods/CORE/mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = The rewrite of the Enchanting mod for MineClone2 -depends = mcl_formspec, tt +depends = mcl_formspec, tt, mcl_books optional_depends = screwdriver author = Fleckenstein diff --git a/mods/CORE/mcl_enchanting/table_book.lua b/mods/CORE/mcl_enchanting/table_book.lua new file mode 100644 index 0000000000..132fb880b4 --- /dev/null +++ b/mods/CORE/mcl_enchanting/table_book.lua @@ -0,0 +1,87 @@ +local book_animations = {["close"] = 1, ["opening"] = 2, ["open"] = 3, ["closing"] = 4} +local book_animation_steps = {0, 640, 680, 700, 740} +local book_animation_speed = 40 + +function mcl_enchanting.schedule_book_animation(self, anim) + self.scheduled_anim = {timer = self.anim_length, anim = anim} +end + +function mcl_enchanting.set_book_animation(self, anim) + local anim_index = book_animations[anim] + local start, stop = book_animation_steps[anim_index], book_animation_steps[anim_index + 1] + self.object:set_animation({x = start, y = stop}, book_animation_speed) + self.scheduled_anim = nil + self.anim_length = (stop - start) / 40 +end + +function mcl_enchanting.check_animation_schedule(self, dtime) + local schedanim = self.scheduled_anim + if schedanim then + schedanim.timer = schedanim.timer - dtime + if schedanim.timer <= 0 then + mcl_enchanting.set_book_animation(self, schedanim.anim)local pos1=self.object:get_pos() + end + end +end + +function mcl_enchanting.look_at(self, pos2) + local pos1 = self.object:get_pos() + local vec = vector.subtract(pos1, pos2) + local yaw = math.atan(vec.z / vec.x) - math.pi/2 + yaw = yaw + (pos1.x >= pos2.x and math.pi or 0) + self.object:set_yaw(yaw + math.pi) +end + +function mcl_enchanting.check_book(pos) + local obj_pos = vector.add(pos, mcl_enchanting.book_offset) + for _, obj in pairs(minetest.get_objects_inside_radius(obj_pos, 0.1)) do + local luaentity = obj:get_luaentity() + if luaentity and luaentity.name == "mcl_enchanting:book" then + if minetest.get_node(pos).name ~= "mcl_enchanting:table" then + obj:remove() + end + return + end + end + minetest.add_entity(obj_pos, "mcl_enchanting:book") +end + +minetest.register_entity("mcl_enchanting:book", { + initial_properties = { + visual = "mesh", + mesh = "mcl_enchanting_book.b3d", + visual_size = {x = 12.5, y = 12.5}, + collisionbox = {0, 0, 0}, + physical = false, + textures = {"mcl_enchanting_book_entity.png"}, + }, + player_near = false, + on_activate = function(self) + self.object:set_armor_groups({immortal = 1}) + mcl_enchanting.set_book_animation(self, "close") + mcl_enchanting.check_book(vector.subtract(self.object:get_pos(), mcl_enchanting.book_offset)) + end, + on_step = function(self, dtime) + local old_player_near = self.player_near + local player_near = false + local player + for _, obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 2.5)) do + if obj:is_player() then + player_near = true + player = obj + end + end + if player_near and not old_player_near then + mcl_enchanting.set_book_animation(self, "opening") + mcl_enchanting.schedule_book_animation(self, "open") + elseif old_player_near and not player_near then + mcl_enchanting.set_book_animation(self, "closing") + mcl_enchanting.schedule_book_animation(self, "close") + end + if player then + mcl_enchanting.look_at(self, player:get_pos()) + end + self.player_near = player_near + mcl_enchanting.check_animation_schedule(self, dtime) + end, +}) diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_enchanted.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_book_enchanted.png new file mode 100644 index 0000000000000000000000000000000000000000..5cd46d8b6137783ba928a278326be75473ed6db6 GIT binary patch literal 386 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucL8%hgh?3y^w370~qEv=}#LT=BJwMkFg)(D3 zQ$0figD*u3fvP@wx;Tbd_%EHjo9mE+fa`a2rm#heT6>c=Z0It(*0i8?iD>r0Q(8A} zvQ|58*dY9e-|>I?SH3%?lX@R07kC&MKYypD!q&d^TRK;_>zd^g*6m#16Q{~ z7E9S3JDJcVcUZ%(C@t~6ab^O)kfG$(H;dxS_XzJ~IQKz? z!F+O_tCPy#ZClzyZ+Z#{tSVpTY^2Y9>F@y4U*%A-8GT3ReeNs}j)n_b};MjF=YT>i4UH`vMU-6%@X_x2Z8`9TAI$3Is?<}A9 d#qydBL-UUm#@8J;{{TJD;OXk;vd$@?2>|nrmtg<^ literal 0 HcmV?d00001 diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index 326aad6efa..b9aa1b2719 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -418,6 +418,9 @@ minetest.register_on_joinplayer(function(player) end end, allow_take = function(inv, listname, index, stack, player) + if mcl_enchanting.has_enchantment(stack, "curse_of_binding") and not minetest.settings:get_bool("creative") then + return 0 + end return stack:get_count() end, allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 53776df3b6..cf7efb623e 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -333,13 +333,7 @@ end minetest.register_craft({ type = "fuel", - recipe = "mcl_bows:bow", - burntime = 15, -}) - -minetest.register_craft({ - type = "fuel", - recipe = "mcl_bows:bow_enchanted", + recipe = "group:bow", burntime = 15, }) diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index 5b37473508..833dded521 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -177,7 +177,7 @@ local bobber_on_step = function(self, dtime) if self._tick % 5 == 0 and self.player ~= nil and player ~= nil then --Destroy bobber if item not wielded. local wield = player:get_wielded_item() - if ((not wield) or (wield:get_name() ~= "mcl_fishing:fishing_rod")) then + if ((not wield) or (minetest.get_item_groups(wield:get_name(), "fishing_rod") <= 0)) then self.object:remove() return end @@ -343,7 +343,7 @@ minetest.register_craft({ }) minetest.register_craft({ type = "fuel", - recipe = "mcl_fishing:fishing_rod", + recipe = "group:fishing_rod", burntime = 15, }) From 04d8d999e2dbe6ee2fddc72dfb214737b5dbe6fe Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 13:38:17 +0100 Subject: [PATCH 09/27] Efficiency & Unbreaking --- mods/CORE/_mcl_autogroup/init.lua | 25 ++++++- mods/CORE/mcl_enchanting/enchantments.lua | 72 ++++++------------- .../mcl_enchanting/{api.lua => engine.lua} | 3 + mods/CORE/mcl_enchanting/init.lua | 2 +- mods/PLAYER/mcl_death_drop/init.lua | 2 +- 5 files changed, 48 insertions(+), 56 deletions(-) rename mods/CORE/mcl_enchanting/{api.lua => engine.lua} (98%) diff --git a/mods/CORE/_mcl_autogroup/init.lua b/mods/CORE/_mcl_autogroup/init.lua index 16fa14c5fd..509542353f 100644 --- a/mods/CORE/_mcl_autogroup/init.lua +++ b/mods/CORE/_mcl_autogroup/init.lua @@ -18,7 +18,7 @@ digging times in seconds. These digging times can be then added verbatim into th Example: mcl_autogroup.digtimes.pickaxey_dig_diamond[1] = 0.2 -→ This menas that when a node has been assigned the group “pickaxey_dig_diamond=1”, it can be dug by the +→ This means that when a node has been assigned the group “pickaxey_dig_diamond=1”, it can be dug by the diamond pickaxe in 0.2 seconds. @@ -44,6 +44,7 @@ local divisors = { ["shearsy_wool"] = 5, ["swordy_cobweb"] = 15, } +local max_efficiency_level = 5 mcl_autogroup = {} mcl_autogroup.digtimes = {} @@ -53,11 +54,19 @@ for m=1, #materials do for g=1, #basegroups do mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m]] = {} mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {} + for e=1, max_efficiency_level do + mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {} + mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {} + end end end for g=1, #minigroups do mcl_autogroup.digtimes[minigroups[g].."_dig"] = {} mcl_autogroup.creativetimes[minigroups[g].."_dig"] = {} + for e=1, max_efficiency_level do + mcl_autogroup.digtimes[minigroups[g].."_dig_efficiency_"..e] = {} + mcl_autogroup.creativetimes[minigroups[g].."_dig_efficiency_"..e] = {} + end end local overwrite = function() @@ -80,7 +89,7 @@ local overwrite = function() groups_changed = true end - local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating) + local function calculate_group(hardness, material, diggroup, newgroups, actual_rating, expected_rating, efficiency) local time, validity_factor if actual_rating >= expected_rating then -- Valid tool @@ -89,7 +98,11 @@ local overwrite = function() -- Wrong tool (higher digging time) validity_factor = 5 end - time = (hardness * validity_factor) / divisors[material] + local speed_multiplier = divisors[material] + if efficiency then + speed_multiplier = speed_multiplier + efficiency * efficiency + 1 + end + time = (hardness * validity_factor) / speed_multiplier if time <= 0.05 then time = 0 else @@ -113,6 +126,9 @@ local overwrite = function() for g=1,#materials do local diggroup = basegroup.."_dig_"..materials[g] newgroups = calculate_group(hardness, materials[g], diggroup, newgroups, g, ndef.groups[basegroup]) + for e=1,max_efficiency_level do + newgroups = calculate_group(hardness, materials[g], diggroup .. "_efficiency_" .. e, newgroups, g, ndef.groups[basegroup], e) + end groups_changed = true end end @@ -134,6 +150,9 @@ local overwrite = function() or (ndef.groups[minigroup] and minigroup ~= "swordy_cobweb" and minigroup ~= "shearsy_wool") then newgroups = calculate_group(hardness, minigroup, diggroup, newgroups, ar, 1) + for e=1,max_efficiency_level do + newgroups = calculate_group(hardness, minigroup, diggroup .. "_efficiency_" .. e, newgroups, ar, 1, e) + end groups_changed = true end end diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index b5452f96e7..63316b8d8b 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -90,7 +90,7 @@ mcl_enchanting.enchantments.depth_strider = { requires_tool = false, } --- unimplemented +-- implemented via on_enchant mcl_enchanting.enchantments.efficiency = { name = "Efficiency", max_level = 5, @@ -101,7 +101,17 @@ mcl_enchanting.enchantments.efficiency = { weight = 10, description = "Increases mining speed.", curse = false, - on_enchant = function() end, + on_enchant = function(itemstack, level, itemdef) + local tool_capabilities = itemstack:get_tool_capabilities() + local groupcaps = {} + for group, capability in pairs(tool_capabilities.groupcaps) do + local groupname = group .. "_efficiency_" .. level + capability.times = mcl_autogroup.digtimes[groupname] + groupcaps[groupname] = capability + end + tool_capabilities.groupcaps = groupcaps + itemstack:get_meta():set_tool_capabilities(tool_capabilities) + end, requires_tool = false, } @@ -450,7 +460,7 @@ mcl_enchanting.enchantments.thorns = { requires_tool = false, } --- unimplemented +-- implemented via on_enchant; Unimplemented for Bows, Armor and Fishing Rods mcl_enchanting.enchantments.unbreaking = { name = "Unbreaking", max_level = 3, @@ -461,12 +471,17 @@ mcl_enchanting.enchantments.unbreaking = { weight = 5, description = "Increases item durability.", curse = false, - on_enchant = function() end, + on_enchant = function(itemstack, level, itemdef) + local new_capabilities = itemstack:get_tool_capabilities() + for group, capability in pairs(new_capabilities.groupcaps) do + capability.uses = capability.uses * (1 + level) + end + new_capabilities.punch_attack_uses = new_capabilities.punch_attack_uses * (1 + level) + itemstack:get_meta():set_tool_capabilities(new_capabilities) + end, requires_tool = true, } - - --[[ local pickaxes = {"mcl_tools:pick_wood", "mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} local pickaxes_better_than_iron = {"mcl_tools:pick_iron", "mcl_tools:pick_diamond"} @@ -544,48 +559,3 @@ minetest.register_on_mods_loaded(function() end end) --]] - - ---[[ - sharpness = { - name = "Sharpness", - max_level = 5, - create_itemdef = function(def, level) - def.tool_capabilities.damage_groups.fleshy = def.tool_capabilities.damage_groups.fleshy + (level + 1) / 2 - end, - }, - efficiency = { - name = "Efficiency", - max_level = 5, - create_itemdef = function(def, level) - local groupcaps = def.tool_capabilities.groupcaps - for _, groupcap in pairs(groupcaps) do - for i, t in pairs(groupcap.times) do - local m = 1 / t - m = m + math.pow(level, 2) + 1 - groupcap.times[i] = 1 / m - end - end - end, - }, - unbreaking = { - name = "Unbreaking", - max_level = 3, - create_itemdef = function(def, level) - local toolcaps = def.tool_capabilities - local armor_uses = def.groups.mcl_armor_uses - local factor = 0.5 - if toolcaps then - local groupcaps = toolcaps.groupcaps - for _, groupcap in pairs(groupcaps) do - groupcap.uses = math.floor(groupcap.uses * (1 + level)) - end - def.tool_capabilities.punch_attack_uses = math.floor(def.tool_capabilities.punch_attack_uses * (1 + level)) - elseif armor_uses then - def.groups.mcl_armor_uses = math.floor(armor_uses / (0.6 + (0.4 / (level + 1)))) - end - end - }, - },--]] - - diff --git a/mods/CORE/mcl_enchanting/api.lua b/mods/CORE/mcl_enchanting/engine.lua similarity index 98% rename from mods/CORE/mcl_enchanting/api.lua rename to mods/CORE/mcl_enchanting/engine.lua index 1581225627..349e8882a7 100644 --- a/mods/CORE/mcl_enchanting/api.lua +++ b/mods/CORE/mcl_enchanting/engine.lua @@ -6,6 +6,9 @@ function mcl_enchanting.set_enchantments(itemstack, enchantments) itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) local itemdef = itemstack:get_definition() if itemstack:get_name() ~= "mcl_enchanting:book_enchanted" then + if itemdef.tool_capabilities then + itemstack:get_meta():set_tool_capabilities(itemdef.tool_capabilities) + end for enchantment, level in pairs(enchantments) do local enchantment_def = mcl_enchanting.enchantments[enchantment] if enchantment_def.on_enchant then diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua index 1611557cef..2181ef978d 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -8,7 +8,7 @@ mcl_enchanting = { debug = true, } -dofile(modpath .. "/api.lua") +dofile(modpath .. "/engine.lua") dofile(modpath .. "/enchantments.lua") dofile(modpath .. "/command.lua") dofile(modpath .. "/tt.lua") diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index 4e0fa6e629..56e6ea5227 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -23,7 +23,7 @@ minetest.register_on_dieplayer(function(player) local z = math.random(0, 9)/3 pos.x = pos.x + x pos.z = pos.z + z - if not void_deadly and drop and mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then + if not void_deadly and drop and not mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then local def = minetest.registered_items[stack:get_name()] if def and def.on_drop then stack = def.on_drop(stack, player, pos) From a516eccd6d6f5363b9613da6e4add9a46b4b96a8 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 15:09:11 +0100 Subject: [PATCH 10/27] Unbreaking for Bows --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/ITEMS/mcl_bows/bow.lua | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 63316b8d8b..07d302e3a5 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -460,7 +460,7 @@ mcl_enchanting.enchantments.thorns = { requires_tool = false, } --- implemented via on_enchant; Unimplemented for Bows, Armor and Fishing Rods +-- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows, unimplemented Armor and Fishing Rods mcl_enchanting.enchantments.unbreaking = { name = "Unbreaking", max_level = 3, diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index cf7efb623e..efa3caeb5c 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -237,7 +237,12 @@ controls.register_on_release(function(player, key, time) end if has_shot and not minetest.is_creative_enabled(player:get_player_name()) then - wielditem:add_wear(65535/BOW_DURABILITY) + local durability = BOW_DURABILITY + local unbreaking = mcl_enchanting.get_enchantment(wielditem, "unbreaking") + if unbreaking > 0 then + durability = durability * (unbreaking + 1) + end + wielditem:add_wear(65535/durability) end player:set_wielded_item(wielditem) reset_bow_state(player, true) From afa11c07230831207d4fb0002ecdc4e9927a1eeb Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 15:33:05 +0100 Subject: [PATCH 11/27] Unbreaking for armor --- mods/HELP/mcl_tt/depends.txt | 1 + mods/HELP/mcl_tt/snippets_mcl.lua | 8 +++++++- mods/ITEMS/mcl_armor/armor.lua | 4 ++++ mods/ITEMS/mcl_armor/depends.txt | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mods/HELP/mcl_tt/depends.txt b/mods/HELP/mcl_tt/depends.txt index c49c556e0e..12e5a198da 100644 --- a/mods/HELP/mcl_tt/depends.txt +++ b/mods/HELP/mcl_tt/depends.txt @@ -1 +1,2 @@ tt +mcl_enchanting diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 569dbe6866..6e28035020 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -25,7 +25,7 @@ tt.register_snippet(function(itemstring) end return s end) -tt.register_snippet(function(itemstring) +tt.register_snippet(function(itemstring, _, itemstack) local def = minetest.registered_items[itemstring] local s = "" local use = minetest.get_item_group(itemstring, "mcl_armor_uses") @@ -34,6 +34,12 @@ tt.register_snippet(function(itemstring) s = s .. S("Armor points: @1", pts) s = s .. "\n" end + if itemstack then + local unbreaking = mcl_enchanting.get_enchantment(itemstack, "unbreaking") + if unbreaking > 0 then + use = math.floor(use / (0.6 + 0.4 / (unbreaking + 1))) + end + end if use > 0 then s = s .. S("Armor durability: @1", use) end diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index b9aa1b2719..5387aa701b 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -518,6 +518,10 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) if stack:get_count() > 0 then -- Damage armor local use = stack:get_definition().groups["mcl_armor_uses"] or 0 + local unbreaking = mcl_enchanting.get_enchantment(stack, "unbreaking") + if unbreaking > 0 then + use = use / (0.6 + 0.4 / (unbreaking + 1)) + end if use > 0 then local wear = armor_damage * math.floor(65536/use) stack:add_wear(wear) diff --git a/mods/ITEMS/mcl_armor/depends.txt b/mods/ITEMS/mcl_armor/depends.txt index e57f69dfb3..067cf61b11 100644 --- a/mods/ITEMS/mcl_armor/depends.txt +++ b/mods/ITEMS/mcl_armor/depends.txt @@ -3,3 +3,4 @@ mcl_player mcl_fire? ethereal? bakedclay? +mcl_enchanting From 22083a0ff59d9bdd99ecad58be2e1fcf0b6efefd Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 17:22:03 +0100 Subject: [PATCH 12/27] Armor textures support --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/CORE/mcl_enchanting/engine.lua | 4 ++-- mods/CORE/mcl_enchanting/init.lua | 2 +- mods/ITEMS/mcl_armor/armor.lua | 8 +++++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 07d302e3a5..e48e845727 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -460,7 +460,7 @@ mcl_enchanting.enchantments.thorns = { requires_tool = false, } --- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows, unimplemented Armor and Fishing Rods +-- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows; for armor implemented in mcl_armor and mcl_tt; unimplemented for Fishing Rods mcl_enchanting.enchantments.unbreaking = { name = "Unbreaking", max_level = 3, diff --git a/mods/CORE/mcl_enchanting/engine.lua b/mods/CORE/mcl_enchanting/engine.lua index 349e8882a7..ae04e3ed65 100644 --- a/mods/CORE/mcl_enchanting/engine.lua +++ b/mods/CORE/mcl_enchanting/engine.lua @@ -215,9 +215,9 @@ function mcl_enchanting.initialize() local new_name = itemname .. "_enchanted" minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) local new_def = table.copy(itemdef) - new_def.inventory_image = itemdef.inventory_image .. "^[colorize:purple:50" + new_def.inventory_image = itemdef.inventory_image .. "^[brighten^[colorize:purple:50" if new_def.wield_image then - new_def.wield_image = new_def.wield_image .. "^[colorize:purple:50" + new_def.wield_image = new_def.wield_image .. "^[brighten^[colorize:purple:50" end new_def.groups.not_in_creative_inventory = 1 new_def.groups.enchanted = 1 diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua index 2181ef978d..2398dc8b49 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -5,7 +5,7 @@ mcl_enchanting = { book_offset = vector.new(0, 0.75, 0), roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 enchantments = {}, - debug = true, + debug = false, } dofile(modpath .. "/engine.lua") diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index 5387aa701b..6f95baa72c 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -119,7 +119,7 @@ armor.set_player_armor = function(self, player) local textures = {} local physics_o = {speed=1,gravity=1,jump=1} local material = {type=nil, count=1} - local preview = armor:get_preview(name) or "character_preview.png" + local preview for _,v in ipairs(self.elements) do elements[v] = false end @@ -136,8 +136,9 @@ armor.set_player_armor = function(self, player) local level = def.groups["armor_"..k] if level then local texture = def.texture or item:gsub("%:", "_") - table.insert(textures, texture..".png") - preview = preview.."^"..texture.."_preview.png" + local enchanted = mcl_enchanting.is_enchanted_def(item) + table.insert(textures, "("..texture..".png"..(enchanted and "^[brighten^[colorize:purple:50" or "")..")") + preview = "(player.png^[opacity:0^"..texture.."_preview.png"..(enchanted and "^[brighten^[colorize:purple:50" or "")..")"..(preview and "^"..preview or "") armor_level = armor_level + level items = items + 1 mcl_armor_points = mcl_armor_points + (def.groups["mcl_armor_points"] or 0) @@ -161,6 +162,7 @@ armor.set_player_armor = function(self, player) end end end + preview = (armor:get_preview(name) or "character_preview.png")..(preview and "^"..preview or "") if minetest.get_modpath("shields") then armor_level = armor_level * 0.9 end From b89ffb12f2859801d227be98ebeeab0c1363ab6e Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 17:38:51 +0100 Subject: [PATCH 13/27] Unbreaking for fishing rods --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/ITEMS/mcl_fishing/init.lua | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index e48e845727..dd505e9606 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -460,7 +460,7 @@ mcl_enchanting.enchantments.thorns = { requires_tool = false, } --- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows; for armor implemented in mcl_armor and mcl_tt; unimplemented for Fishing Rods +-- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows; for armor implemented in mcl_armor and mcl_tt; for fishing rods implemented in mcl_fishing mcl_enchanting.enchantments.unbreaking = { name = "Unbreaking", max_level = 3, diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index 833dded521..b7e1ba73ae 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -32,16 +32,20 @@ local fish = function(itemstack, player) local num = 0 local ent = nil local noent = true - + + + local durability = 65 + local unbreaking = mcl_enchanting.get_enchantment(itemstack, "unbreaking") + if unbreaking > 0 then + durability = durability * (unbreaking + 1) + end + --Check for bobber if so handle. for n = 1, #objs do ent = objs[n]:get_luaentity() if ent then if ent.player and ent.objtype=="fishing" then if (player:get_player_name() == ent.player) then - if mcl_experience.throw_experience then - mcl_experience.throw_experience(pos, math.random(1,6)) - end noent = false if ent._dive == true then local itemname @@ -104,10 +108,13 @@ local fish = function(itemstack, player) if inv:room_for_item("main", item) then inv:add_item("main", item) end + if mcl_experience.throw_experience then + mcl_experience.throw_experience(pos, math.random(1,6)) + end if not minetest.is_creative_enabled(player:get_player_name()) then local idef = itemstack:get_definition() - itemstack:add_wear(65535/65) -- 65 uses + itemstack:add_wear(65535/durability) -- 65 uses if itemstack:get_count() == 0 and idef.sound and idef.sound.breaks then minetest.sound_play(idef.sound.breaks, {pos=player:get_pos(), gain=0.5}, true) end @@ -121,7 +128,7 @@ local fish = function(itemstack, player) if def.walkable then if not minetest.is_creative_enabled(player:get_player_name()) then local idef = itemstack:get_definition() - itemstack:add_wear((65535/65)*2) -- if so and not creative then wear double like in MC. + itemstack:add_wear((65535/durability)*2) -- if so and not creative then wear double like in MC. if itemstack:get_count() == 0 and idef.sound and idef.sound.breaks then minetest.sound_play(idef.sound.breaks, {pos=player:get_pos(), gain=0.5}, true) end @@ -177,7 +184,7 @@ local bobber_on_step = function(self, dtime) if self._tick % 5 == 0 and self.player ~= nil and player ~= nil then --Destroy bobber if item not wielded. local wield = player:get_wielded_item() - if ((not wield) or (minetest.get_item_groups(wield:get_name(), "fishing_rod") <= 0)) then + if ((not wield) or (minetest.get_item_group(wield:get_name(), "fishing_rod") <= 0)) then self.object:remove() return end From 8a406ad968647dbc7fa5b8ff55c0f25acffda252 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 17:58:13 +0100 Subject: [PATCH 14/27] Sharpness --- mods/CORE/mcl_enchanting/enchantments.lua | 46 +++++++++++++---------- mods/CORE/mcl_enchanting/engine.lua | 2 +- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index dd505e9606..2ceaf3b452 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -69,7 +69,7 @@ mcl_enchanting.enchantments.curse_of_vanishing = { disallow = {clock = true}, incompatible = {}, weight = 1, - description = "Except when in creative mode, items cannot be removed from armor slots except due to death or breaking.", + description = "Item destroyed on death.", curse = true, on_enchant = function() end, requires_tool = false, @@ -101,7 +101,7 @@ mcl_enchanting.enchantments.efficiency = { weight = 10, description = "Increases mining speed.", curse = false, - on_enchant = function(itemstack, level, itemdef) + on_enchant = function(itemstack, level) local tool_capabilities = itemstack:get_tool_capabilities() local groupcaps = {} for group, capability in pairs(tool_capabilities.groupcaps) do @@ -129,8 +129,8 @@ mcl_enchanting.enchantments.feather_falling = { requires_tool = false, } --- unimplemented -mcl_enchanting.enchantments.fire_aspect = { +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.fire_aspect = { name = "Fire Aspect", max_level = 2, primary = {sword = true}, @@ -142,7 +142,7 @@ mcl_enchanting.enchantments.fire_aspect = { curse = false, on_enchant = function() end, requires_tool = false, -} +}]]-- -- unimplemented mcl_enchanting.enchantments.fire_protection = { @@ -159,8 +159,8 @@ mcl_enchanting.enchantments.fire_protection = { requires_tool = false, } --- unimplemented -mcl_enchanting.enchantments.flame = { +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.flame = { name = "Flame", max_level = 1, primary = {bow = true}, @@ -172,7 +172,7 @@ mcl_enchanting.enchantments.flame = { curse = false, on_enchant = function() end, requires_tool = false, -} +}]]-- -- unimplemented mcl_enchanting.enchantments.fortune = { @@ -369,7 +369,7 @@ mcl_enchanting.enchantments.respiration = { requires_tool = false, } --- unimplemented +-- implemented via on_enchant mcl_enchanting.enchantments.sharpness = { name = "Sharpness", max_level = 5, @@ -378,9 +378,17 @@ mcl_enchanting.enchantments.sharpness = { disallow = {}, incompatible = {bane_of_anthropods = true, smite = true}, weight = 5, - description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites).", + description = "Increases damage.", curse = false, - on_enchant = function() end, + on_enchant = function(itemstack, level) + local tool_capabilities = itemstack:get_tool_capabilities() + local damage_groups = {} + for group, damage in pairs(tool_capabilities.damage_groups) do + damage_groups[group] = damage + level * 0.5 + end + tool_capabilities.damage_groups = damage_groups + itemstack:get_meta():set_tool_capabilities(tool_capabilities) + end, requires_tool = false, } @@ -430,8 +438,8 @@ mcl_enchanting.enchantments.soul_speed = { requires_tool = false, } --- unimplemented -mcl_enchanting.enchantments.sweeping_edge = { +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.sweeping_edge = { name = "Sweeping Edge", max_level = 3, primary = {sword = true}, @@ -443,7 +451,7 @@ mcl_enchanting.enchantments.sweeping_edge = { curse = false, on_enchant = function() end, requires_tool = false, -} +}]]-- -- unimplemented mcl_enchanting.enchantments.thorns = { @@ -471,13 +479,13 @@ mcl_enchanting.enchantments.unbreaking = { weight = 5, description = "Increases item durability.", curse = false, - on_enchant = function(itemstack, level, itemdef) - local new_capabilities = itemstack:get_tool_capabilities() - for group, capability in pairs(new_capabilities.groupcaps) do + on_enchant = function(itemstack, level) + local tool_capabilities = itemstack:get_tool_capabilities() + for group, capability in pairs(tool_capabilities.groupcaps) do capability.uses = capability.uses * (1 + level) end - new_capabilities.punch_attack_uses = new_capabilities.punch_attack_uses * (1 + level) - itemstack:get_meta():set_tool_capabilities(new_capabilities) + tool_capabilities.punch_attack_uses = tool_capabilities.punch_attack_uses * (1 + level) + itemstack:get_meta():set_tool_capabilities(tool_capabilities) end, requires_tool = true, } diff --git a/mods/CORE/mcl_enchanting/engine.lua b/mods/CORE/mcl_enchanting/engine.lua index ae04e3ed65..f77e3dff93 100644 --- a/mods/CORE/mcl_enchanting/engine.lua +++ b/mods/CORE/mcl_enchanting/engine.lua @@ -12,7 +12,7 @@ function mcl_enchanting.set_enchantments(itemstack, enchantments) for enchantment, level in pairs(enchantments) do local enchantment_def = mcl_enchanting.enchantments[enchantment] if enchantment_def.on_enchant then - enchantment_def.on_enchant(itemstack, level, itemdef) + enchantment_def.on_enchant(itemstack, level) end end end From 7c28bf850790ac177199dc6b13c8ac68b1bac5d1 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 2 Nov 2020 19:09:23 +0100 Subject: [PATCH 15/27] Silk Touch --- mods/CORE/mcl_enchanting/enchantments.lua | 81 +---------------------- mods/CORE/mcl_enchanting/engine.lua | 4 +- mods/ENTITIES/mcl_item_entity/depends.txt | 1 + mods/ENTITIES/mcl_item_entity/init.lua | 32 ++++++--- mods/ITEMS/mcl_armor/armor.lua | 6 +- mods/ITEMS/mcl_books/init.lua | 1 + mods/ITEMS/mcl_chests/init.lua | 1 + mods/ITEMS/mcl_core/nodes_base.lua | 17 +++++ mods/ITEMS/mcl_core/nodes_glass.lua | 2 + mods/ITEMS/mcl_core/nodes_trees.lua | 1 + mods/ITEMS/mcl_farming/melon.lua | 1 + mods/ITEMS/mcl_mushrooms/huge.lua | 1 + mods/ITEMS/mcl_nether/init.lua | 2 + mods/ITEMS/mcl_ocean/corals.lua | 4 ++ mods/ITEMS/mcl_ocean/prismarine.lua | 1 + mods/ITEMS/xpanes/init.lua | 3 + 16 files changed, 62 insertions(+), 96 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 2ceaf3b452..b1ac63561b 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -392,7 +392,7 @@ mcl_enchanting.enchantments.sharpness = { requires_tool = false, } --- unimplemented +-- implemented in mcl_item_entity mcl_enchanting.enchantments.silk_touch = { name = "Silk Touch", max_level = 1, @@ -407,7 +407,6 @@ mcl_enchanting.enchantments.silk_touch = { requires_tool = false, } - -- unimplemented mcl_enchanting.enchantments.smite = { name = "Smite", @@ -489,81 +488,3 @@ mcl_enchanting.enchantments.unbreaking = { end, requires_tool = true, } - ---[[ -local pickaxes = {"mcl_tools:pick_wood", "mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} -local pickaxes_better_than_iron = {"mcl_tools:pick_iron", "mcl_tools:pick_diamond"} -local pickaxes_better_than_stone = {"mcl_tools:pick_stone", "mcl_tools:pick_gold", "mcl_tools:pick_iron", "mcl_tools:pick_diamond"} -local shovels = {"mcl_tools:shovel_wood", "mcl_tools:shovel_stone", "mcl_tools:shovel_gold", "mcl_tools:shovel_iron", "mcl_tools:shovel_diamond"} - -local silk_touch_tool_lists = { - ["mcl_books:bookshelf"] = true, - ["mcl_core:clay"] = true, - ["mcl_core:stone_with_coal"] = pickaxes, - ["group:coral_block"] = pickaxes, - ["group:coral"] = true, - ["group:coral_fan"] = true, - ["mcl_core:stone_with_diamond"] = pickaxes_better_than_iron, - ["mcl_core:stone_with_emerald"] = pickaxes_better_than_iron, - ["mcl_chests:ender_chest"] = pickaxes, - ["group:glass"] = true, - ["mcl_nether:glowstone"] = true, - ["mcl_core:dirt_with_grass"] = true, - ["mcl_core:gravel"] = true, - ["mcl_core:ice"] = true, - ["mcl_core:stone_with_lapis"] = pickaxes_better_than_stone, - ["group:leaves"] = true, - ["mcl_farming:melon"] = true, - ["group:huge_mushroom"] = true, - ["mcl_core:mycelium"] = true, - ["mcl_nether:quartz_ore"] = pickaxes, - ["mcl_core:packed_ice"] = true, - ["mcl_core:podzol"] = true, - ["mcl_core:stone_with_redstone"] = pickaxes_better_than_iron, - ["mcl_ocean:sea_lantern"] = true, - ["group:top_snow"] = shovels, - ["mcl_core:snowblock"] = shovels, - ["mcl_core:stone"] = pickaxes, -} - -minetest.register_on_mods_loaded(function() - local old_handle_node_drops = minetest.handle_node_drops - function minetest.handle_node_drops(pos, drops, digger) - if digger and digger:is_player() then - local wielditem = digger:get_wielded_item() - local tooldef = wielditem:get_definition() - if tooldef._silk_touch then - local nodename = minetest.get_node(pos).name - local nodedef = minetest.registered_nodes[nodename] - local silk_touch_spec = silk_touch_tool_lists[nodename] - local suitable_tool = false - local tool_list - if silk_touch_spec == true then - suitable_tool = true - elseif silk_touch_spec then - tool_list = silk_touch_spec - else - for k, v in pairs(nodedef.groups) do - if v > 0 then - local group_spec = silk_touch_tool_lists["group:" .. k] - if group_spec == true then - suitable_tool = true - elseif group_spec then - toollist = group_spec - break - end - end - end - end - if tool_list and not suitable_tool then - suitable_tool = (table.indexof(tool_list, tooldef._original_tool) ~= -1) - end - if suitable_tool then - drops = {nodename} - end - end - end - old_handle_node_drops(pos, drops, digger) - end -end) ---]] diff --git a/mods/CORE/mcl_enchanting/engine.lua b/mods/CORE/mcl_enchanting/engine.lua index f77e3dff93..40c600dbdb 100644 --- a/mods/CORE/mcl_enchanting/engine.lua +++ b/mods/CORE/mcl_enchanting/engine.lua @@ -215,9 +215,9 @@ function mcl_enchanting.initialize() local new_name = itemname .. "_enchanted" minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) local new_def = table.copy(itemdef) - new_def.inventory_image = itemdef.inventory_image .. "^[brighten^[colorize:purple:50" + new_def.inventory_image = itemdef.inventory_image .. "^[colorize:white:50^[colorize:purple:50" if new_def.wield_image then - new_def.wield_image = new_def.wield_image .. "^[brighten^[colorize:purple:50" + new_def.wield_image = new_def.wield_image .. "^[colorize:white:50^[colorize:purple:50" end new_def.groups.not_in_creative_inventory = 1 new_def.groups.enchanted = 1 diff --git a/mods/ENTITIES/mcl_item_entity/depends.txt b/mods/ENTITIES/mcl_item_entity/depends.txt index ca0f0433f1..f80274858f 100644 --- a/mods/ENTITIES/mcl_item_entity/depends.txt +++ b/mods/ENTITIES/mcl_item_entity/depends.txt @@ -1 +1,2 @@ flowlib +mcl_enchanting diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 0481b53404..8d451f9b05 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -225,14 +225,9 @@ function minetest.handle_node_drops(pos, drops, digger) -- Check if node will yield its useful drop by the digger's tool local dug_node = minetest.get_node(pos) local toolcaps + local tool if digger ~= nil then - if mcl_experience.throw_experience then - local experience_amount = minetest.get_item_group(dug_node.name,"xp") - if experience_amount > 0 then - mcl_experience.throw_experience(pos, experience_amount) - end - end - local tool = digger:get_wielded_item() + tool = digger:get_wielded_item() toolcaps = tool:get_tool_capabilities() if not check_can_drop(dug_node.name, toolcaps) then @@ -240,12 +235,13 @@ function minetest.handle_node_drops(pos, drops, digger) end end - --[[ Special node drops when dug by shears by reading _mcl_shears_drop + --[[ Special node drops when dug by shears by reading _mcl_shears_drop or with a silk touch tool reading _mcl_silk_touch_drop from the node definition. - Definition of _mcl_shears_drop: - * true: Drop itself when dug by shears - * table: Drop every itemstring in this table when dub by shears + Definition of _mcl_shears_drop / _mcl_silk_touch_drop: + * true: Drop itself when dug by shears / silk touch tool + * table: Drop every itemstring in this table when dug by shears _mcl_silk_touch_drop ]] + local silk_touch_drop = false local nodedef = minetest.registered_nodes[dug_node.name] if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then if nodedef._mcl_shears_drop == true then @@ -253,8 +249,22 @@ function minetest.handle_node_drops(pos, drops, digger) else drops = nodedef._mcl_shears_drop end + elseif tool and mcl_enchanting.has_enchantment(tool, "silk_touch") and nodedef._mcl_silk_touch_drop then + silk_touch_drop = true + if nodedef._mcl_silk_touch_drop == true then + drops = { dug_node.name } + else + drops = nodedef._mcl_silk_touch_drop + end end + if digger and mcl_experience.throw_experience and not silk_touch_drop then + local experience_amount = minetest.get_item_group(dug_node.name,"xp") + if experience_amount > 0 then + mcl_experience.throw_experience(pos, experience_amount) + end + end + for _,item in ipairs(drops) do local count if type(item) == "string" then diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index 6f95baa72c..ee0f95ceff 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -136,9 +136,9 @@ armor.set_player_armor = function(self, player) local level = def.groups["armor_"..k] if level then local texture = def.texture or item:gsub("%:", "_") - local enchanted = mcl_enchanting.is_enchanted_def(item) - table.insert(textures, "("..texture..".png"..(enchanted and "^[brighten^[colorize:purple:50" or "")..")") - preview = "(player.png^[opacity:0^"..texture.."_preview.png"..(enchanted and "^[brighten^[colorize:purple:50" or "")..")"..(preview and "^"..preview or "") + local enchanted_addition = (mcl_enchanting.is_enchanted_def(item) and "^[colorize:white:50^[colorize:purple:50" or "") + table.insert(textures, "("..texture..".png"..enchanted_addition..")") + preview = "(player.png^[opacity:0^"..texture.."_preview.png"..enchanted_addition..")"..(preview and "^"..preview or "") armor_level = armor_level + level items = items + 1 mcl_armor_points = mcl_armor_points + (def.groups["mcl_armor_points"] or 0) diff --git a/mods/ITEMS/mcl_books/init.lua b/mods/ITEMS/mcl_books/init.lua index cf4daf0ba6..0be575939b 100644 --- a/mods/ITEMS/mcl_books/init.lua +++ b/mods/ITEMS/mcl_books/init.lua @@ -344,6 +344,7 @@ minetest.register_node("mcl_books:bookshelf", { sounds = wood_sound, _mcl_blast_resistance = 1.5, _mcl_hardness = 1.5, + _mcl_silk_touch_drop = true, }) minetest.register_craft({ diff --git a/mods/ITEMS/mcl_chests/init.lua b/mods/ITEMS/mcl_chests/init.lua index d1966e190a..3d5fbbca37 100644 --- a/mods/ITEMS/mcl_chests/init.lua +++ b/mods/ITEMS/mcl_chests/init.lua @@ -746,6 +746,7 @@ minetest.register_node("mcl_chests:ender_chest", { end, _mcl_blast_resistance = 3000, _mcl_hardness = 22.5, + _mcl_silk_touch_drop = true, on_rotate = simple_rotate, }) diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index 978dde6487..b8ddabf97e 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -22,6 +22,7 @@ minetest.register_node("mcl_core:stone", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 6, _mcl_hardness = 1.5, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_core:stone_with_coal", { @@ -36,6 +37,7 @@ minetest.register_node("mcl_core:stone_with_coal", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_core:stone_with_iron", { @@ -49,6 +51,7 @@ minetest.register_node("mcl_core:stone_with_iron", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) @@ -63,6 +66,7 @@ minetest.register_node("mcl_core:stone_with_gold", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) local redstone_timer = 68.28 @@ -95,6 +99,7 @@ minetest.register_node("mcl_core:stone_with_redstone", { on_walk_over = redstone_ore_activate, -- Uses walkover mod _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) local redstone_ore_reactivate = function(pos) @@ -133,6 +138,7 @@ minetest.register_node("mcl_core:stone_with_redstone_lit", { end, _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = "mcl_core:stone_with_redstone", }) minetest.register_node("mcl_core:stone_with_lapis", { @@ -168,6 +174,7 @@ minetest.register_node("mcl_core:stone_with_emerald", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_core:stone_with_diamond", { @@ -181,6 +188,7 @@ minetest.register_node("mcl_core:stone_with_diamond", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_core:stonebrick", { @@ -346,6 +354,7 @@ minetest.register_node("mcl_core:dirt_with_grass", { _mcl_snowed = "mcl_core:dirt_with_grass_snow", _mcl_blast_resistance = 0.5, _mcl_hardness = 0.6, + _mcl_silk_touch_drop = true, }) mcl_core.register_snowed_node("mcl_core:dirt_with_grass_snow", "mcl_core:dirt_with_grass", nil, nil, true) @@ -389,6 +398,7 @@ minetest.register_node("mcl_core:mycelium", { _mcl_snowed = "mcl_core:mycelium_snow", _mcl_blast_resistance = 0.5, _mcl_hardness = 0.6, + _mcl_silk_touch_drop = true, }) mcl_core.register_snowed_node("mcl_core:mycelium_snow", "mcl_core:mycelium") @@ -405,6 +415,7 @@ minetest.register_node("mcl_core:podzol", { _mcl_snowed = "mcl_core:podzol_snow", _mcl_blast_resistance = 0.5, _mcl_hardness = 0.6, + _mcl_silk_touch_drop = true, }) mcl_core.register_snowed_node("mcl_core:podzol_snow", "mcl_core:podzol") @@ -452,6 +463,7 @@ minetest.register_node("mcl_core:gravel", { }), _mcl_blast_resistance = 0.6, _mcl_hardness = 0.6, + _mcl_silk_touch_drop = true, }) -- sandstone -- @@ -594,6 +606,7 @@ minetest.register_node("mcl_core:clay", { sounds = mcl_sounds.node_sound_dirt_defaults(), _mcl_blast_resistance = 0.6, _mcl_hardness = 0.6, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_core:brick_block", { @@ -776,6 +789,7 @@ minetest.register_node("mcl_core:ice", { end, _mcl_blast_resistance = 0.5, _mcl_hardness = 0.5, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_core:packed_ice", { @@ -789,6 +803,7 @@ minetest.register_node("mcl_core:packed_ice", { sounds = mcl_sounds.node_sound_glass_defaults(), _mcl_blast_resistance = 0.5, _mcl_hardness = 0.5, + _mcl_silk_touch_drop = true, }) -- Frosted Ice (4 nodes) @@ -972,6 +987,7 @@ for i=1,8 do drop = "mcl_throwing:snowball "..(i+1), _mcl_blast_resistance = 0.1, _mcl_hardness = 0.1, + _mcl_silk_touch_drop = true, }) end @@ -989,6 +1005,7 @@ minetest.register_node("mcl_core:snowblock", { drop = "mcl_throwing:snowball 4", _mcl_blast_resistance = 0.2, _mcl_hardness = 0.2, + _mcl_silk_touch_drop = true, }) -- Add entry aliases for the Help diff --git a/mods/ITEMS/mcl_core/nodes_glass.lua b/mods/ITEMS/mcl_core/nodes_glass.lua index 87e9a7863f..83d2c10656 100644 --- a/mods/ITEMS/mcl_core/nodes_glass.lua +++ b/mods/ITEMS/mcl_core/nodes_glass.lua @@ -16,6 +16,7 @@ minetest.register_node("mcl_core:glass", { drop = "", _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, + _mcl_silk_touch_drop = true, }) ------------------------ @@ -51,6 +52,7 @@ function mcl_core.add_stained_glass(desc, recipeitem, colorgroup, color) drop = "", _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, + _mcl_silk_touch_drop = true, }) minetest.register_craft({ diff --git a/mods/ITEMS/mcl_core/nodes_trees.lua b/mods/ITEMS/mcl_core/nodes_trees.lua index 8955ff645d..732eb2e434 100644 --- a/mods/ITEMS/mcl_core/nodes_trees.lua +++ b/mods/ITEMS/mcl_core/nodes_trees.lua @@ -110,6 +110,7 @@ local register_leaves = function(subname, description, longdesc, tiles, drop1, d sounds = mcl_sounds.node_sound_leaves_defaults(), _mcl_blast_resistance = 0.2, _mcl_hardness = 0.2, + _mcl_silk_touch_drop = true, }) end diff --git a/mods/ITEMS/mcl_farming/melon.lua b/mods/ITEMS/mcl_farming/melon.lua index 43ff7b0f89..587b8a6e52 100644 --- a/mods/ITEMS/mcl_farming/melon.lua +++ b/mods/ITEMS/mcl_farming/melon.lua @@ -35,6 +35,7 @@ local melon_base_def = { sounds = mcl_sounds.node_sound_wood_defaults(), _mcl_blast_resistance = 1, _mcl_hardness = 1, + _mcl_silk_touch_drop = true, } -- Drop proabilities for melon stem diff --git a/mods/ITEMS/mcl_mushrooms/huge.lua b/mods/ITEMS/mcl_mushrooms/huge.lua index 6f962b27f9..12b00db8c3 100644 --- a/mods/ITEMS/mcl_mushrooms/huge.lua +++ b/mods/ITEMS/mcl_mushrooms/huge.lua @@ -6,6 +6,7 @@ local template = { is_ground_content = true, _mcl_blast_resistance = 0.2, _mcl_hardness = 0.2, + _mcl_silk_touch_drop = true, } local red = table.copy(template) diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index aac92839a1..f026b6dbec 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -27,6 +27,7 @@ minetest.register_node("mcl_nether:glowstone", { sounds = mcl_sounds.node_sound_glass_defaults(), _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_nether:quartz_ore", { @@ -40,6 +41,7 @@ minetest.register_node("mcl_nether:quartz_ore", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_silk_touch_drop = true, }) -- For eternal fire on top of netherrack and magma blocks diff --git a/mods/ITEMS/mcl_ocean/corals.lua b/mods/ITEMS/mcl_ocean/corals.lua index f04a023167..f3de5968eb 100644 --- a/mods/ITEMS/mcl_ocean/corals.lua +++ b/mods/ITEMS/mcl_ocean/corals.lua @@ -91,6 +91,7 @@ for c=1, #corals do drop = "mcl_ocean:dead_"..id.."_coral_block", _mcl_hardness = 1.5, _mcl_blast_resistance = 6, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_ocean:dead_"..id.."_coral_block", { description = corals[c][3], @@ -135,6 +136,7 @@ for c=1, #corals do end, _mcl_hardness = 0, _mcl_blast_resistance = 0, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_ocean:dead_"..id.."_coral", { description = corals[c][5], @@ -202,6 +204,7 @@ for c=1, #corals do end, _mcl_hardness = 0, _mcl_blast_resistance = 0, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_ocean:dead_"..id.."_coral_fan", { description = corals[c][7], @@ -234,6 +237,7 @@ for c=1, #corals do end, _mcl_hardness = 0, _mcl_blast_resistance = 0, + _mcl_silk_touch_drop = true, }) if mod_doc then diff --git a/mods/ITEMS/mcl_ocean/prismarine.lua b/mods/ITEMS/mcl_ocean/prismarine.lua index 5840d59ce9..77d4f8e347 100644 --- a/mods/ITEMS/mcl_ocean/prismarine.lua +++ b/mods/ITEMS/mcl_ocean/prismarine.lua @@ -21,6 +21,7 @@ minetest.register_node("mcl_ocean:sea_lantern", { sounds = mcl_sounds.node_sound_glass_defaults(), _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, + _mcl_silk_touch_drop = true, }) minetest.register_node("mcl_ocean:prismarine", { diff --git a/mods/ITEMS/xpanes/init.lua b/mods/ITEMS/xpanes/init.lua index b98d65e38b..4ecac8c6e9 100644 --- a/mods/ITEMS/xpanes/init.lua +++ b/mods/ITEMS/xpanes/init.lua @@ -127,6 +127,7 @@ function xpanes.register_pane(name, def) connect_sides = { "left", "right" }, _mcl_blast_resistance = def._mcl_blast_resistance, _mcl_hardness = def._mcl_hardness, + _mcl_silk_touch_drop = def._mcl_silk_touch_drop, }) local groups = table.copy(def.groups) @@ -155,6 +156,7 @@ function xpanes.register_pane(name, def) drop = drop, _mcl_blast_resistance = def._mcl_blast_resistance, _mcl_hardness = def._mcl_hardness, + _mcl_silk_touch_drop = def._mcl_silk_touch_drop, }) minetest.register_craft({ @@ -204,6 +206,7 @@ local pane = function(description, node, append) drop = "", _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, + _mcl_silk_touch_drop = true, }) if mod_doc and not is_canonical then From 2b55dac7d2462a77d13001ee45b73820cb19f56b Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 4 Nov 2020 11:29:44 +0100 Subject: [PATCH 16/27] Fixed Curse of Binding bypass in rightclick handler --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/ITEMS/mcl_armor/armor.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index b1ac63561b..f6a37f482c 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -431,7 +431,7 @@ mcl_enchanting.enchantments.soul_speed = { disallow = {non_combat_armor = true}, incompatible = {frost_walker = true}, weight = 2, - description = "Incerases walking speed on soul sand.", + description = "Increases walking speed on soul sand.", curse = false, on_enchant = function() end, requires_tool = false, diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index ee0f95ceff..d00348b139 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -75,7 +75,7 @@ function armor.on_armor_use(itemstack, user, pointed_thing) armor:update_inventory(user) armor:play_equip_sound(itemstack_single, user) itemstack:take_item() - elseif itemstack:get_count() <= 1 then + elseif itemstack:get_count() <= 1 and not mcl_enchanting.has_enchantment(itemstack_slot, "curse_of_binding") then armor_inv:set_stack("armor", slot, itemstack_single) player_inv:set_stack("armor", slot, itemstack_single) armor:set_player_armor(user) From cdafb1a07e907d96b11614ef8b678d09cb15d9aa Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 4 Nov 2020 12:00:42 +0100 Subject: [PATCH 17/27] Knockback --- mods/CORE/mcl_enchanting/enchantments.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index f6a37f482c..b70cb19cf9 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -219,7 +219,7 @@ mcl_enchanting.enchantments.infinity = { requires_tool = false, } --- unimplemented +-- implemented via minetest.calculate_knockback mcl_enchanting.enchantments.knockback = { name = "Knockback", max_level = 2, @@ -234,6 +234,16 @@ mcl_enchanting.enchantments.knockback = { requires_tool = false, } +local old_calculate_knockback = minetest.calculate_knockback +function minetest.calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, distance, damage) + local knockback = old_calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, distance, damage) + if hitter and hitter:is_player() then + local wielditem = hitter:get_wielded_item() + knockback = knockback + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + end + return knockback +end + -- unimplemented mcl_enchanting.enchantments.looting = { name = "Looting", From bbc6db489e01e31836706e244253d5b8aea7ad1d Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 5 Nov 2020 15:25:44 +0100 Subject: [PATCH 18/27] Power --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/ITEMS/mcl_bows/bow.lua | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index b70cb19cf9..f232f11d1d 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -304,7 +304,7 @@ mcl_enchanting.enchantments.mending = { requires_tool = true, } --- unimplemented +-- implemented in mcl_bows mcl_enchanting.enchantments.power = { name = "Power", max_level = 5, diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index efa3caeb5c..4942d81a8f 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -33,7 +33,7 @@ local bow_load = {} -- Another player table, this one stores the wield index of the bow being charged local bow_index = {} -mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damage, is_critical) +mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damage, is_critical, bow_stack) local obj = minetest.add_entity({x=pos.x,y=pos.y,z=pos.z}, arrow_item.."_entity") if power == nil then power = BOW_MAX_SPEED --19 @@ -41,6 +41,12 @@ mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damag if damage == nil then damage = 3 end + if bow_stack then + local power_level = mcl_enchanting.get_enchantment(bow_stack, "power") + if power_level > 0 then + damage = damage + (power_level + 1) / 4 + end + end obj:set_velocity({x=dir.x*power, y=dir.y*power, z=dir.z*power}) obj:set_acceleration({x=0, y=-GRAVITY, z=0}) obj:set_yaw(yaw-math.pi/2) @@ -102,7 +108,7 @@ local player_shoot_arrow = function(itemstack, player, power, damage, is_critica local dir = player:get_look_dir() local yaw = player:get_look_horizontal() - mcl_bows.shoot_arrow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, dir, yaw, player, power, damage, is_critical) + mcl_bows.shoot_arrow(arrow_itemstring, {x=playerpos.x,y=playerpos.y+1.5,z=playerpos.z}, dir, yaw, player, power, damage, is_critical, player:get_wielded_item()) return true end From 4d37e309e7c53b3396a917149c2099f9e5a5ad8d Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 5 Nov 2020 16:05:42 +0100 Subject: [PATCH 19/27] FrostWalker --- mods/CORE/mcl_enchanting/enchantments.lua | 19 ++++++++++++++++++- mods/CORE/mcl_enchanting/init.lua | 1 - mods/CORE/mcl_enchanting/mod.conf | 2 +- mods/CORE/walkover/init.lua | 11 +++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index f232f11d1d..01b1bd9a48 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -189,7 +189,7 @@ mcl_enchanting.enchantments.fortune = { requires_tool = false, } --- unimplemented +-- implemented using walkover.register_global mcl_enchanting.enchantments.frost_walker = { name = "Frost Walker", max_level = 2, @@ -204,6 +204,23 @@ mcl_enchanting.enchantments.frost_walker = { requires_tool = false, } +walkover.register_global(function(pos, _, player) + local boots = player:get_inventory():get_stack("armor", 5) + local frost_walker = mcl_enchanting.get_enchantment(boots, "frost_walker") + if frost_walker <= 0 then + return + end + local radius = frost_walker + 2 + local minp = {x = pos.x - radius, y = pos.y, z = pos.z - radius} + local maxp = {x = pos.x + radius, y = pos.y, z = pos.z + radius} + local positions = minetest.find_nodes_in_area_under_air(minp, maxp, "mcl_core:water_source") + for _, p in ipairs(positions) do + if vector.distance(pos, p) <= radius then + minetest.set_node(p, {name = "mcl_core:frosted_ice_0"}) + end + end +end) + -- implemented in mcl_bows mcl_enchanting.enchantments.infinity = { name = "Infinity", diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua index 2398dc8b49..1d4a9f7c3e 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -1,7 +1,6 @@ local modpath = minetest.get_modpath("mcl_enchanting") mcl_enchanting = { - lapis_itemstring = "mcl_dye:blue", book_offset = vector.new(0, 0.75, 0), roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 enchantments = {}, diff --git a/mods/CORE/mcl_enchanting/mod.conf b/mods/CORE/mcl_enchanting/mod.conf index 3680b4fa97..fef460ab12 100644 --- a/mods/CORE/mcl_enchanting/mod.conf +++ b/mods/CORE/mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = The rewrite of the Enchanting mod for MineClone2 -depends = mcl_formspec, tt, mcl_books +depends = mcl_formspec, tt, mcl_books, walkover optional_depends = screwdriver author = Fleckenstein diff --git a/mods/CORE/walkover/init.lua b/mods/CORE/walkover/init.lua index 1e2749ff50..6bbd505d28 100644 --- a/mods/CORE/walkover/init.lua +++ b/mods/CORE/walkover/init.lua @@ -1,4 +1,11 @@ -- register extra flavours of a base nodedef +walkover = {} +walkover.registered_globals = {} + +function walkover.register_global(func) + table.insert(walkover.registered_globals, func) +end + local timer = 0 minetest.register_globalstep(function(dtime) timer = timer + dtime; @@ -10,11 +17,15 @@ minetest.register_globalstep(function(dtime) if loc ~= nil then local nodeiamon = minetest.get_node(loc) + if nodeiamon ~= nil then local def = minetest.registered_nodes[nodeiamon.name] if def ~= nil and def.on_walk_over ~= nil then def.on_walk_over(loc, nodeiamon, player) end + for _, func in ipairs(walkover.registered_globals) do + func(loc, nodeiamon, player) + end end end end From 86b2cd70f907dccb161bbdbb99e1770647ba2a76 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Fri, 6 Nov 2020 13:46:52 +0100 Subject: [PATCH 20/27] Fortune --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/ENTITIES/mcl_item_entity/init.lua | 68 ++++++++++++++++++++++- mods/ITEMS/mcl_core/nodes_base.lua | 43 +++++++++++++- mods/ITEMS/mcl_core/nodes_trees.lua | 52 +++++++++-------- mods/ITEMS/mcl_farming/melon.lua | 7 +++ mods/ITEMS/mcl_flowers/init.lua | 19 ++++++- mods/ITEMS/mcl_nether/init.lua | 8 +++ mods/ITEMS/mcl_nether/nether_wart.lua | 6 ++ mods/ITEMS/mcl_ocean/prismarine.lua | 7 +++ 9 files changed, 183 insertions(+), 29 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 01b1bd9a48..c143044a09 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -189,7 +189,7 @@ mcl_enchanting.enchantments.fortune = { requires_tool = false, } --- implemented using walkover.register_global +-- implemented via walkover.register_global mcl_enchanting.enchantments.frost_walker = { name = "Frost Walker", max_level = 2, diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 8d451f9b05..6413481320 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -212,6 +212,50 @@ local check_can_drop = function(node_name, tool_capabilities) end end +-- Stupid workaround to get drops from a drop table: +-- Create a temporary table in minetest.registered_nodes that contains the proper drops, +-- because unfortunately minetest.get_node_drops needs the drop table to be inside a registered node definition +-- (very ugly) + +local tmp_id = 0 + +local function get_drops(drop, toolname, param2, paramtype2) + tmp_id = tmp_id + 1 + local tmp_node_name = "mcl_item_entity:" .. tmp_id + minetest.registered_nodes[tmp_node_name] = { + name = tmp_node_name, + drop = drop, + paramtype2 = paramtype2 + } + local drops = minetest.get_node_drops({name = tmp_node_name, param2 = param2}, toolname) + minetest.registered_nodes[tmp_node_name] = nil + return drops +end + +local function discrete_uniform_distribution(drops, min_count, max_count, cap) + local new_drops = table.copy(drops) + for i, item in ipairs(drops) do + local new_item = ItemStack(item) + local multiplier = math.random(min_count, max_count) + if cap then + multiplier = math.min(cap, multiplier) + end + new_item:set_count(multiplier * new_item:get_count()) + new_drops[i] = new_item + end + return new_drops +end + +local function get_fortune_drops(fortune_drops, fortune_level) + local drop + local i = fortune_level + repeat + drop = fortune_drops[i] + i = i - 1 + until drop or i < 1 + return drop or {} +end + function minetest.handle_node_drops(pos, drops, digger) -- NOTE: This function override allows digger to be nil. -- This means there is no digger. This is a special case which allows this function to be called @@ -241,6 +285,9 @@ function minetest.handle_node_drops(pos, drops, digger) * true: Drop itself when dug by shears / silk touch tool * table: Drop every itemstring in this table when dug by shears _mcl_silk_touch_drop ]] + + local enchantments = tool and mcl_enchanting.get_enchantments(tool, "silk_touch") + local silk_touch_drop = false local nodedef = minetest.registered_nodes[dug_node.name] if toolcaps ~= nil and toolcaps.groupcaps and toolcaps.groupcaps.shearsy_dig and nodedef._mcl_shears_drop then @@ -249,7 +296,7 @@ function minetest.handle_node_drops(pos, drops, digger) else drops = nodedef._mcl_shears_drop end - elseif tool and mcl_enchanting.has_enchantment(tool, "silk_touch") and nodedef._mcl_silk_touch_drop then + elseif tool and enchantments.silk_touch and nodedef._mcl_silk_touch_drop then silk_touch_drop = true if nodedef._mcl_silk_touch_drop == true then drops = { dug_node.name } @@ -257,6 +304,25 @@ function minetest.handle_node_drops(pos, drops, digger) drops = nodedef._mcl_silk_touch_drop end end + + if tool and nodedef._mcl_fortune_drop and enchantments.fortune then + local fortune_level = enchantments.fortune + local fortune_drop = nodedef._mcl_fortune_drop + if fortune_drop.discrete_uniform_distribution then + local min_count = fortune_drop.min_count + local max_count = fortune_drop.max_count + fortune_level * (fortune_drop.factor or 1) + local chance = fortune_drop.chance or fortune_drop.get_chance and fortune_drop.get_chance(fortune_level) + if not chance or math.random() < chance then + drops = discrete_uniform_distribution(fortune_drop.multiply and drops or fortune_drop.items, min_count, max_count, fortune_drop.cap) + elseif fortune_drop.override then + drops = {} + end + else + -- Fixed Behavior + local drop = get_fortune_drops(fortune_drops, fortune_level) + drops = get_drops(drop, tool:get_name(), dug_node.param2, nodedef.paramtype2) + end + end if digger and mcl_experience.throw_experience and not silk_touch_drop then local experience_amount = minetest.get_item_group(dug_node.name,"xp") diff --git a/mods/ITEMS/mcl_core/nodes_base.lua b/mods/ITEMS/mcl_core/nodes_base.lua index b8ddabf97e..f9ac0e01e1 100644 --- a/mods/ITEMS/mcl_core/nodes_base.lua +++ b/mods/ITEMS/mcl_core/nodes_base.lua @@ -10,6 +10,14 @@ else ice_drawtype = "normal" end +mcl_core.fortune_drop_ore = { + discrete_uniform_distribution = true, + min_count = 2, + max_count = 1, + get_chance = function (fortune_level) return 1 - 2 / (fortune_level + 2) end, + multiply = true, +} + minetest.register_node("mcl_core:stone", { description = S("Stone"), _doc_items_longdesc = S("One of the most common blocks in the world, almost the entire underground consists of stone. It sometimes contains ores. Stone may be created when water meets lava."), @@ -38,6 +46,7 @@ minetest.register_node("mcl_core:stone_with_coal", { _mcl_blast_resistance = 3, _mcl_hardness = 3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = mcl_core.fortune_drop_ore, }) minetest.register_node("mcl_core:stone_with_iron", { @@ -100,6 +109,12 @@ minetest.register_node("mcl_core:stone_with_redstone", { _mcl_blast_resistance = 3, _mcl_hardness = 3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { + discrete_uniform_distribution = true, + items = {"mesecons:redstone"}, + min_count = 4, + max_count = 5, + } }) local redstone_ore_reactivate = function(pos) @@ -138,7 +153,13 @@ minetest.register_node("mcl_core:stone_with_redstone_lit", { end, _mcl_blast_resistance = 3, _mcl_hardness = 3, - _mcl_silk_touch_drop = "mcl_core:stone_with_redstone", + _mcl_silk_touch_drop = {"mcl_core:stone_with_redstone"}, + _mcl_fortune_drop = { + discrete_uniform_distribution = true, + items = {"mesecons:redstone"}, + min_count = 4, + max_count = 5, + } }) minetest.register_node("mcl_core:stone_with_lapis", { @@ -161,6 +182,7 @@ minetest.register_node("mcl_core:stone_with_lapis", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 3, _mcl_hardness = 3, + _mcl_fortune_drop = mcl_core.fortune_drop_ore, }) minetest.register_node("mcl_core:stone_with_emerald", { @@ -175,6 +197,7 @@ minetest.register_node("mcl_core:stone_with_emerald", { _mcl_blast_resistance = 3, _mcl_hardness = 3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = mcl_core.fortune_drop_ore, }) minetest.register_node("mcl_core:stone_with_diamond", { @@ -189,6 +212,7 @@ minetest.register_node("mcl_core:stone_with_diamond", { _mcl_blast_resistance = 3, _mcl_hardness = 3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = mcl_core.fortune_drop_ore, }) minetest.register_node("mcl_core:stonebrick", { @@ -464,6 +488,23 @@ minetest.register_node("mcl_core:gravel", { _mcl_blast_resistance = 0.6, _mcl_hardness = 0.6, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { + [1] = { + max_items = 1, + items = { + {items = {'mcl_core:flint'},rarity = 7}, + {items = {'mcl_core:gravel'}} + } + }, + [2] = { + max_items = 1, + items = { + {items = {'mcl_core:flint'},rarity = 4}, + {items = {'mcl_core:gravel'}} + } + }, + [3] = "mcl_core:flint" + }, }) -- sandstone -- diff --git a/mods/ITEMS/mcl_core/nodes_trees.lua b/mods/ITEMS/mcl_core/nodes_trees.lua index 732eb2e434..3a8aef8d03 100644 --- a/mods/ITEMS/mcl_core/nodes_trees.lua +++ b/mods/ITEMS/mcl_core/nodes_trees.lua @@ -63,35 +63,39 @@ local register_wooden_planks = function(subname, description, tiles) }) end -local register_leaves = function(subname, description, longdesc, tiles, drop1, drop1_rarity, drop2, drop2_rarity, leafdecay_distance) +local register_leaves = function(subname, description, longdesc, tiles, sapling, drop_apples, sapling_chances, leafdecay_distance) local drop if leafdecay_distance == nil then leafdecay_distance = 4 end - if drop2 then - drop = { + local apple_chances = {200, 180, 160, 120, 40} + local stick_chances = {50, 45, 30, 35, 10} + + local function get_drops(fortune_level) + local drop = { max_items = 1, items = { { - items = {drop1}, - rarity = drop1_rarity, + items = {sapling}, + rarity = sapling_chances[fortune_level + 1] or sapling_chances[fortune_level] }, { - items = {drop2}, - rarity = drop2_rarity, + items = {"mcl_core:stick 1"}, + rarity = stick_chances[fortune_level + 1] }, - } - } - else - drop = { - max_items = 1, - items = { { - items = {drop1}, - rarity = drop1_rarity, + items = {"mcl_core:stick 2"}, + rarity = stick_chances[fortune_level + 1] }, } - } + } + if drop_apples then + table.insert(drop.items, { + items = {"mcl_core:apple"}, + rarity = apple_chances[fortune_level + 1] + }) + end + return drop end minetest.register_node("mcl_core:"..subname, { @@ -105,12 +109,13 @@ local register_leaves = function(subname, description, longdesc, tiles, drop1, d paramtype = "light", stack_max = 64, groups = {handy=1,shearsy=1,swordy=1, leafdecay=leafdecay_distance, flammable=2, leaves=1, deco_block=1, dig_by_piston=1, fire_encouragement=30, fire_flammability=60}, - drop = drop, + drop = get_drops(0), _mcl_shears_drop = true, sounds = mcl_sounds.node_sound_leaves_defaults(), _mcl_blast_resistance = 0.2, _mcl_hardness = 0.2, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { get_drops(1), get_drops(2), get_drops(3), get_drops(4) }, }) end @@ -197,12 +202,13 @@ register_sapling("birchsapling", S("Birch Sapling"), "mcl_core_sapling_birch.png", {-4/16, -0.5, -4/16, 4/16, 0.5, 4/16}) -register_leaves("leaves", S("Oak Leaves"), S("Oak leaves are grown from oak trees."), {"default_leaves.png"}, "mcl_core:sapling", 20, "mcl_core:apple", 200) -register_leaves("darkleaves", S("Dark Oak Leaves"), S("Dark oak leaves are grown from dark oak trees."), {"mcl_core_leaves_big_oak.png"}, "mcl_core:darksapling", 20, "mcl_core:apple", 200) -register_leaves("jungleleaves", S("Jungle Leaves"), S("Jungle leaves are grown from jungle trees."), {"default_jungleleaves.png"}, "mcl_core:junglesapling", 40) -register_leaves("acacialeaves", S("Acacia Leaves"), S("Acacia leaves are grown from acacia trees."), {"default_acacia_leaves.png"}, "mcl_core:acaciasapling", 20) -register_leaves("spruceleaves", S("Spruce Leaves"), S("Spruce leaves are grown from spruce trees."), {"mcl_core_leaves_spruce.png"}, "mcl_core:sprucesapling", 20) -register_leaves("birchleaves", S("Birch Leaves"), S("Birch leaves are grown from birch trees."), {"mcl_core_leaves_birch.png"}, "mcl_core:birchsapling", 20) +register_leaves("leaves", S("Oak Leaves"), S("Oak leaves are grown from oak trees."), {"default_leaves.png"}, "mcl_core:sapling", true, {20, 16, 12, 10}) +register_leaves("darkleaves", S("Dark Oak Leaves"), S("Dark oak leaves are grown from dark oak trees."), {"mcl_core_leaves_big_oak.png"}, "mcl_core:darksapling", true, {20, 16, 12, 10}) +register_leaves("jungleleaves", S("Jungle Leaves"), S("Jungle leaves are grown from jungle trees."), {"default_jungleleaves.png"}, "mcl_core:junglesapling", false, {40, 26, 32, 24, 10}) +register_leaves("acacialeaves", S("Acacia Leaves"), S("Acacia leaves are grown from acacia trees."), {"default_acacia_leaves.png"}, "mcl_core:acaciasapling", false, {20, 16, 12, 10}) +register_leaves("spruceleaves", S("Spruce Leaves"), S("Spruce leaves are grown from spruce trees."), {"mcl_core_leaves_spruce.png"}, "mcl_core:sprucesapling", false, {20, 16, 12, 10}) +register_leaves("birchleaves", S("Birch Leaves"), S("Birch leaves are grown from birch trees."), {"mcl_core_leaves_birch.png"}, "mcl_core:birchsapling", false, {20, 16, 12, 10}) + -- Node aliases diff --git a/mods/ITEMS/mcl_farming/melon.lua b/mods/ITEMS/mcl_farming/melon.lua index 587b8a6e52..38b4c713c3 100644 --- a/mods/ITEMS/mcl_farming/melon.lua +++ b/mods/ITEMS/mcl_farming/melon.lua @@ -36,6 +36,13 @@ local melon_base_def = { _mcl_blast_resistance = 1, _mcl_hardness = 1, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { + discrete_uniform_distribution = true, + items = {"mcl_farming:melon_item"}, + min_count = 3, + max_count = 7, + cap = 9, + } } -- Drop proabilities for melon stem diff --git a/mods/ITEMS/mcl_flowers/init.lua b/mods/ITEMS/mcl_flowers/init.lua index 5b630d5623..42deede2f5 100644 --- a/mods/ITEMS/mcl_flowers/init.lua +++ b/mods/ITEMS/mcl_flowers/init.lua @@ -98,6 +98,16 @@ local wheat_seed_drop = { } } +local fortune_wheat_seed_drop = { + discrete_uniform_distribution = true, + items = {"mcl_farming:wheat_seeds"}, + chance = 1 / 8, + min_count = 1, + max_count = 1, + factor = 2, + overwrite = true, +} + -- CHECKME: How does tall grass behave when pushed by a piston? --- Tall Grass --- @@ -126,6 +136,7 @@ local def_tallgrass = { sounds = mcl_sounds.node_sound_leaves_defaults(), drop = wheat_seed_drop, _mcl_shears_drop = true, + _mcl_fortune_drop = fortune_wheat_seed_drop, node_placement_prediction = "", on_place = on_place_flower, _mcl_blast_resistance = 0, @@ -148,7 +159,7 @@ def_fern.selection_box = { minetest.register_node("mcl_flowers:fern", def_fern) -local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_img, selbox_radius, selbox_top_height, drop, shears_drop, is_flower, grass_color) +local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_img, selbox_radius, selbox_top_height, drop, shears_drop, is_flower, grass_color, fortune_drop) if not inv_img then inv_img = top_img end @@ -200,6 +211,7 @@ local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_im buildable_to = true, drop = drop_bottom, _mcl_shears_drop = shears_drop, + _mcl_fortune_drop = fortune_drop, node_placement_prediction = "", selection_box = { type = "fixed", @@ -305,6 +317,7 @@ local function add_large_plant(name, desc, longdesc, bottom_img, top_img, inv_im }, drop = drop_top, _mcl_shears_drop = shears_drop, + _mcl_fortune_drop = fortune_drop, after_destruct = function(pos, oldnode) -- Remove bottom half of flower (if it exists) local top = pos @@ -334,8 +347,8 @@ add_large_plant("sunflower", S("Sunflower"), S("A sunflower is a large plant whi local longdesc_grass = S("Double tallgrass a variant of tall grass and occupies two blocks. It can be harvested for wheat seeds.") local longdesc_fern = S("Large fern is a variant of fern and occupies two blocks. It can be harvested for wheat seeds.") -add_large_plant("double_grass", S("Double Tallgrass"), longdesc_grass, "mcl_flowers_double_plant_grass_bottom.png", "mcl_flowers_double_plant_grass_top.png", "mcl_flowers_double_plant_grass_inv.png", 6/16, 4/16, wheat_seed_drop, {"mcl_flowers:tallgrass 2"}, false, true) -add_large_plant("double_fern", S("Large Fern"), longdesc_fern, "mcl_flowers_double_plant_fern_bottom.png", "mcl_flowers_double_plant_fern_top.png", "mcl_flowers_double_plant_fern_inv.png", 5/16, 5/16, wheat_seed_drop, {"mcl_flowers:fern 2"}, false, true) +add_large_plant("double_grass", S("Double Tallgrass"), longdesc_grass, "mcl_flowers_double_plant_grass_bottom.png", "mcl_flowers_double_plant_grass_top.png", "mcl_flowers_double_plant_grass_inv.png", 6/16, 4/16, wheat_seed_drop, {"mcl_flowers:tallgrass 2"}, false, true, nil, fortune_wheat_seed_drop) +add_large_plant("double_fern", S("Large Fern"), longdesc_fern, "mcl_flowers_double_plant_fern_bottom.png", "mcl_flowers_double_plant_fern_top.png", "mcl_flowers_double_plant_fern_inv.png", 5/16, 5/16, wheat_seed_drop, {"mcl_flowers:fern 2"}, false, true, nil, fortune_wheat_seed_drop) minetest.register_abm({ label = "Pop out flowers", diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index f026b6dbec..71221cc5c3 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -28,6 +28,13 @@ minetest.register_node("mcl_nether:glowstone", { _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { + discrete_uniform_distribution = true, + items = {"mcl_nether:glowstone_dust"}, + min_count = 2, + max_count = 4, + cap = 4, + } }) minetest.register_node("mcl_nether:quartz_ore", { @@ -42,6 +49,7 @@ minetest.register_node("mcl_nether:quartz_ore", { _mcl_blast_resistance = 3, _mcl_hardness = 3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = mcl_core.fortune_drop_ore }) -- For eternal fire on top of netherrack and magma blocks diff --git a/mods/ITEMS/mcl_nether/nether_wart.lua b/mods/ITEMS/mcl_nether/nether_wart.lua index 354fa6139a..681abe0947 100644 --- a/mods/ITEMS/mcl_nether/nether_wart.lua +++ b/mods/ITEMS/mcl_nether/nether_wart.lua @@ -93,6 +93,12 @@ minetest.register_node("mcl_nether:nether_wart", { }, groups = {dig_immediate=3, not_in_creative_inventory=1,plant=1,attached_node=1,dig_by_water=1,destroy_by_lava_flow=1,dig_by_piston=1}, sounds = mcl_sounds.node_sound_leaves_defaults(), + _mcl_fortune_drop = { + discrete_uniform_distribution = true, + items = {"mcl_nether:nether_wart_item"}, + min_count = 2, + max_count = 4, + } }) minetest.register_craftitem("mcl_nether:nether_wart_item", { diff --git a/mods/ITEMS/mcl_ocean/prismarine.lua b/mods/ITEMS/mcl_ocean/prismarine.lua index 77d4f8e347..647e87fe1e 100644 --- a/mods/ITEMS/mcl_ocean/prismarine.lua +++ b/mods/ITEMS/mcl_ocean/prismarine.lua @@ -22,6 +22,13 @@ minetest.register_node("mcl_ocean:sea_lantern", { _mcl_blast_resistance = 0.3, _mcl_hardness = 0.3, _mcl_silk_touch_drop = true, + _mcl_fortune_drop = { + discrete_uniform_distribution = true, + items = {"mcl_ocean:prismarine_crystals"}, + min_count = 2, + max_count = 3, + cap = 5, + } }) minetest.register_node("mcl_ocean:prismarine", { From 494ffb41d3751e3f39c5fc6e5991522eee6bd227 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Fri, 6 Nov 2020 15:05:31 +0100 Subject: [PATCH 21/27] Punch --- mods/CORE/mcl_enchanting/enchantments.lua | 10 ++++++++-- mods/ITEMS/mcl_bows/arrow.lua | 11 ++--------- mods/ITEMS/mcl_bows/bow.lua | 11 ++++++++--- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index c143044a09..1da48f795c 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -174,7 +174,7 @@ mcl_enchanting.enchantments.fire_protection = { requires_tool = false, }]]-- --- unimplemented +-- implemented in mcl_item_entity mcl_enchanting.enchantments.fortune = { name = "Fortune", max_level = 4, @@ -254,9 +254,15 @@ mcl_enchanting.enchantments.knockback = { local old_calculate_knockback = minetest.calculate_knockback function minetest.calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, distance, damage) local knockback = old_calculate_knockback(player, hitter, time_from_last_punch, tool_capabilities, dir, distance, damage) + local luaentity + if hitter then + luaentity = hitter:get_luaentity() + end if hitter and hitter:is_player() then local wielditem = hitter:get_wielded_item() knockback = knockback + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + elseif luaentity and luaentity._knockback then + knockback = knockback + luaentity._knockback end return knockback end @@ -366,7 +372,7 @@ mcl_enchanting.enchantments.protection = { requires_tool = false, } --- unimplemented +-- implemented via minetest.calculate_knockback (together with the Knockback enchantment) and mcl_bows mcl_enchanting.enchantments.punch = { name = "Punch", max_level = 2, diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 89f3405f36..0f603015e1 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -239,16 +239,9 @@ ARROW_ENTITY.on_step = function(self, dtime) end -- Punch target object but avoid hurting enderman. - if lua then - if lua.name ~= "mobs_mc:enderman" then - damage_particles(self.object:get_pos(), self._is_critical) - obj:punch(self.object, 1.0, { - full_punch_interval=1.0, - damage_groups={fleshy=self._damage}, - }, nil) - end - else + if not lua or lua.name ~= "mobs_mc:enderman" then damage_particles(self.object:get_pos(), self._is_critical) + self.object:set_pos(vector.subtract(obj:get_pos(), vector.multiply(vector.normalize(self.object:get_velocity()), 2))) obj:punch(self.object, 1.0, { full_punch_interval=1.0, damage_groups={fleshy=self._damage}, diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 4942d81a8f..fa2c2c5304 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -41,10 +41,14 @@ mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damag if damage == nil then damage = 3 end + local knockback if bow_stack then - local power_level = mcl_enchanting.get_enchantment(bow_stack, "power") - if power_level > 0 then - damage = damage + (power_level + 1) / 4 + local enchantments = mcl_enchanting.get_enchantments(bow_stack) + if enchantments.power then + damage = damage + (enchantments.power + 1) / 4 + end + if enchantments.punch then + knockback = enchantments.punch * 3 end end obj:set_velocity({x=dir.x*power, y=dir.y*power, z=dir.z*power}) @@ -55,6 +59,7 @@ mcl_bows.shoot_arrow = function(arrow_item, pos, dir, yaw, shooter, power, damag le._damage = damage le._is_critical = is_critical le._startpos = pos + le._knockback = knockback minetest.sound_play("mcl_bows_bow_shoot", {pos=pos}, true) if shooter ~= nil and shooter:is_player() then if obj:get_luaentity().player == "" then From 479dfd6c0dc8a2bf547b15ea156b306f44012df6 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 9 Nov 2020 10:50:27 +0100 Subject: [PATCH 22/27] Soul Speed --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/PLAYER/mcl_playerplus/depends.txt | 1 + mods/PLAYER/mcl_playerplus/init.lua | 14 ++++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 1da48f795c..7ef5f7fe96 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -455,7 +455,7 @@ mcl_enchanting.enchantments.smite = { requires_tool = false, } --- unimplemented +-- implemented in mcl_playerplus mcl_enchanting.enchantments.soul_speed = { name = "Soul Speed", max_level = 3, diff --git a/mods/PLAYER/mcl_playerplus/depends.txt b/mods/PLAYER/mcl_playerplus/depends.txt index 6bbe4cbdb8..7a259f8c17 100644 --- a/mods/PLAYER/mcl_playerplus/depends.txt +++ b/mods/PLAYER/mcl_playerplus/depends.txt @@ -7,3 +7,4 @@ playerphysics mcl_playerinfo mcl_weather mcl_spawn +mcl_enchanting diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 74d87c6c92..f18e6adfcf 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -106,15 +106,21 @@ minetest.register_globalstep(function(dtime) -- set defaults def.speed = 1 - -- Standing on soul sand? If so, walk slower + -- Standing on soul sand? If so, walk slower (unless player wears Soul Speed boots) if node_stand == "mcl_nether:soul_sand" then -- TODO: Tweak walk speed -- TODO: Also slow down mobs -- Slow down even more when soul sand is above certain block - if node_stand_below == "mcl_core:ice" or node_stand_below == "mcl_core:packed_ice" or node_stand_below == "mcl_core:slimeblock" or node_stand_below == "mcl_core:water_source" then - playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.1) + local boots = player:get_inventory():get_stack("armor", 5) + local soul_speed = mcl_enchanting.get_enchantment(boots, "soul_speed") + if soul_speed > 0 then + playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", soul_speed * 0.105 + 1.3) else - playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.4) + if node_stand_below == "mcl_core:ice" or node_stand_below == "mcl_core:packed_ice" or node_stand_below == "mcl_core:slimeblock" or node_stand_below == "mcl_core:water_source" then + playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.1) + else + playerphysics.add_physics_factor(player, "speed", "mcl_playerplus:surface", 0.4) + end end else -- Reset speed decrease From 3d7bb69e81aab3791f2a190cbcbd68a717cd4c56 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 9 Nov 2020 18:59:08 +0100 Subject: [PATCH 23/27] Bane of Arthropods; Smite; Lure --- mods/CORE/_mcl_autogroup/init.lua | 5 ++-- mods/CORE/mcl_enchanting/enchantments.lua | 36 +++++++++++------------ mods/CORE/mcl_enchanting/engine.lua | 7 ++++- mods/CORE/mcl_enchanting/init.lua | 2 ++ mods/ENTITIES/mobs_mc/endermite.lua | 2 +- mods/ENTITIES/mobs_mc/horse.lua | 2 ++ mods/ENTITIES/mobs_mc/silverfish.lua | 1 + mods/ENTITIES/mobs_mc/skeleton+stray.lua | 1 + mods/ENTITIES/mobs_mc/skeleton_wither.lua | 1 + mods/ENTITIES/mobs_mc/spider.lua | 1 + mods/ENTITIES/mobs_mc/villager_zombie.lua | 2 +- mods/ENTITIES/mobs_mc/wither.lua | 2 +- mods/ENTITIES/mobs_mc/zombie.lua | 2 +- mods/ENTITIES/mobs_mc/zombiepig.lua | 2 +- mods/HELP/mcl_tt/snippets_base.lua | 2 +- mods/ITEMS/mcl_fishing/depends.txt | 1 + mods/ITEMS/mcl_fishing/init.lua | 36 +++++++++++------------ 17 files changed, 60 insertions(+), 45 deletions(-) diff --git a/mods/CORE/_mcl_autogroup/init.lua b/mods/CORE/_mcl_autogroup/init.lua index 509542353f..aabfa5906e 100644 --- a/mods/CORE/_mcl_autogroup/init.lua +++ b/mods/CORE/_mcl_autogroup/init.lua @@ -56,7 +56,6 @@ for m=1, #materials do mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m]] = {} for e=1, max_efficiency_level do mcl_autogroup.digtimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {} - mcl_autogroup.creativetimes[basegroups[g].."_dig_"..materials[m].."_efficiency_"..e] = {} end end end @@ -109,7 +108,9 @@ local overwrite = function() time = math.ceil(time * 20) / 20 end table.insert(mcl_autogroup.digtimes[diggroup], time) - table.insert(mcl_autogroup.creativetimes[diggroup], 0) + if not efficiency then + table.insert(mcl_autogroup.creativetimes[diggroup], 0) + end newgroups[diggroup] = #mcl_autogroup.digtimes[diggroup] return newgroups end diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 7ef5f7fe96..4301c5642a 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -15,9 +15,17 @@ requires_tool = false, }]]-- --- unimplemented -mcl_enchanting.enchantments.bane_of_anthropods = { - name = "Bane of Anthropods", +local function increase_damage(damage_group, factor) + return function(itemstack, level) + local tool_capabilities = itemstack:get_tool_capabilities() + tool_capabilities.damage_groups[damage_group] = (tool_capabilities.damage_groups[damage_group] or 0) + level * factor + itemstack:get_meta():set_tool_capabilities(tool_capabilities) + end +end + +-- implemented via on_enchant and additions in mobs_mc; Slowness IV part unimplemented +mcl_enchanting.enchantments.bane_of_arthropods = { + name = "Bane of Arthropods", max_level = 5, primary = {sword = true}, secondary = {axe = true}, @@ -26,7 +34,7 @@ mcl_enchanting.enchantments.bane_of_anthropods = { weight = 5, description = "Increases damage and applies Slowness IV to arthropod mobs (spiders, cave spiders, silverfish and endermites).", curse = false, - on_enchant = function() end, + on_enchant = increase_damage("anthropod", 2.5), requires_tool = false, } @@ -297,7 +305,7 @@ mcl_enchanting.enchantments.luck_of_the_sea = { requires_tool = false, } --- unimplemented +-- implemented in mcl_fishing mcl_enchanting.enchantments.lure = { name = "Lure", max_level = 3, @@ -409,19 +417,11 @@ mcl_enchanting.enchantments.sharpness = { primary = {sword = true}, secondary = {axe = true}, disallow = {}, - incompatible = {bane_of_anthropods = true, smite = true}, + incompatible = {bane_of_arthropods = true, smite = true}, weight = 5, description = "Increases damage.", curse = false, - on_enchant = function(itemstack, level) - local tool_capabilities = itemstack:get_tool_capabilities() - local damage_groups = {} - for group, damage in pairs(tool_capabilities.damage_groups) do - damage_groups[group] = damage + level * 0.5 - end - tool_capabilities.damage_groups = damage_groups - itemstack:get_meta():set_tool_capabilities(tool_capabilities) - end, + on_enchant = increase_damage("fleshy", 0.5), requires_tool = false, } @@ -440,18 +440,18 @@ mcl_enchanting.enchantments.silk_touch = { requires_tool = false, } --- unimplemented +-- implemented via on_enchant and additions in mobs_mc mcl_enchanting.enchantments.smite = { name = "Smite", max_level = 5, primary = {sword = true}, secondary = {axe = true}, disallow = {}, - incompatible = {bane_of_anthropods = true, sharpness = true}, + incompatible = {bane_of_arthropods = true, sharpness = true}, weight = 5, description = "Increases damage to undead mobs.", curse = false, - on_enchant = function() end, + on_enchant = increase_damage("undead", 2.5), requires_tool = false, } diff --git a/mods/CORE/mcl_enchanting/engine.lua b/mods/CORE/mcl_enchanting/engine.lua index 40c600dbdb..fa809cfac7 100644 --- a/mods/CORE/mcl_enchanting/engine.lua +++ b/mods/CORE/mcl_enchanting/engine.lua @@ -175,7 +175,11 @@ end function mcl_enchanting.initialize() local all_groups = {} + local weighted = {} + local accum_weight = 0 for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do + accum_weight = accum_weight + enchantment_def.weight + weighted[#weighted + 1] = {enchantment = enchantment, weight = accum_weight} for primary in pairs(enchantment_def.primary) do all_groups[primary] = true end @@ -183,6 +187,8 @@ function mcl_enchanting.initialize() all_groups[secondary] = true end end + mcl_enchanting.accumulated_weight = accum_weight + mcl_enchanting.accumulated_weight = weighted local register_tool_list = {} local register_item_list = {} for itemname, itemdef in pairs(minetest.registered_items) do @@ -238,4 +244,3 @@ function mcl_enchanting.initialize() minetest.register_tool(new_name, new_def) end end - diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua index 1d4a9f7c3e..f0f7a95138 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -4,6 +4,8 @@ mcl_enchanting = { book_offset = vector.new(0, 0.75, 0), roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 enchantments = {}, + weighted_enchantments = {}, + accumulated_weight = 0, debug = false, } diff --git a/mods/ENTITIES/mobs_mc/endermite.lua b/mods/ENTITIES/mobs_mc/endermite.lua index 3fb0c1ebf2..256ad4963d 100644 --- a/mods/ENTITIES/mobs_mc/endermite.lua +++ b/mods/ENTITIES/mobs_mc/endermite.lua @@ -10,7 +10,7 @@ mobs:register_mob("mobs_mc:endermite", { passive = false, hp_min = 8, hp_max = 8, - armor = 100, + armor = {fleshy = 100, arthropod = 100}, group_attack = true, collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2}, visual = "mesh", diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index fd4926d2fb..95cba7aca9 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -352,6 +352,7 @@ mobs:register_mob("mobs_mc:horse", horse) -- Skeleton horse local skeleton_horse = table.copy(horse) skeleton_horse.breath_max = -1 +skeleton_horse.armor = {undead = 100, fleshy = 100} skeleton_horse.textures = {{"blank.png", "mobs_mc_horse_skeleton.png", "blank.png"}} skeleton_horse.drops = { {name = mobs_mc.items.bone, @@ -371,6 +372,7 @@ mobs:register_mob("mobs_mc:skeleton_horse", skeleton_horse) -- Zombie horse local zombie_horse = table.copy(horse) zombie_horse.breath_max = -1 +zombie_horse.armor = {undead = 100, fleshy = 100} zombie_horse.textures = {{"blank.png", "mobs_mc_horse_zombie.png", "blank.png"}} zombie_horse.drops = { {name = mobs_mc.items.rotten_flesh, diff --git a/mods/ENTITIES/mobs_mc/silverfish.lua b/mods/ENTITIES/mobs_mc/silverfish.lua index ca45734457..d4ae7ca332 100644 --- a/mods/ENTITIES/mobs_mc/silverfish.lua +++ b/mods/ENTITIES/mobs_mc/silverfish.lua @@ -12,6 +12,7 @@ mobs:register_mob("mobs_mc:silverfish", { reach = 1, hp_min = 8, hp_max = 8, + armor = {fleshy = 100, arthropod = 100}, collisionbox = {-0.4, -0.01, -0.4, 0.4, 0.44, 0.4}, visual = "mesh", mesh = "mobs_mc_silverfish.b3d", diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index 3192a6c011..104ee4f579 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -18,6 +18,7 @@ local skeleton = { hp_min = 20, hp_max = 20, breath_max = -1, + armor = {undead = 100, fleshy = 100}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3}, pathfinding = 1, group_attack = true, diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index f2bf2abbc1..c9e087db3c 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -15,6 +15,7 @@ mobs:register_mob("mobs_mc:witherskeleton", { hp_min = 20, hp_max = 20, breath_max = -1, + armor = {undead = 100, fleshy = 100}, pathfinding = 1, group_attack = true, collisionbox = {-0.35, -0.01, -0.35, 0.35, 2.39, 0.35}, diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index 5c92657af5..f4206d2ac3 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -23,6 +23,7 @@ local spider = { reach = 2, hp_min = 16, hp_max = 16, + armor = {fleshy = 100, arthropod = 100}, collisionbox = {-0.7, -0.01, -0.7, 0.7, 0.89, 0.7}, visual = "mesh", mesh = "mobs_mc_spider.b3d", diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index 66af8f2277..6f7e3e5aaf 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -18,7 +18,7 @@ mobs:register_mob("mobs_mc:villager_zombie", { hp_min = 20, hp_max = 20, breath_max = -1, - armor = 90, + armor = {undead = 90, fleshy = 90}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_villager_zombie.b3d", diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 6af50efff0..e3604f947f 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -14,7 +14,7 @@ mobs:register_mob("mobs_mc:wither", { spawn_class = "hostile", hp_max = 300, hp_min = 300, - armor = 80, + armor = {undead = 80, fleshy = 80}, -- This deviates from MC Wiki's size, which makes no sense collisionbox = {-0.9, 0.4, -0.9, 0.9, 2.45, 0.9}, visual = "mesh", diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index 416be8a3a0..94b441bfe2 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -44,7 +44,7 @@ local zombie = { hp_min = 20, hp_max = 20, breath_max = -1, - armor = 90, + armor = {undead = 90, fleshy = 90}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.94, 0.3}, visual = "mesh", mesh = "mobs_mc_zombie.b3d", diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index 577a49afc0..3a3364560e 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -18,7 +18,7 @@ local pigman = { hp_min = 20, hp_max = 20, breath_max = -1, - armor = 90, + armor = {undead = 90, fleshy = 90}, attack_type = "dogfight", group_attack = { "mobs_mc:pigman", "mobs_mc:baby_pigman" }, damage = 9, diff --git a/mods/HELP/mcl_tt/snippets_base.lua b/mods/HELP/mcl_tt/snippets_base.lua index a3470b5c14..8242f2c19a 100644 --- a/mods/HELP/mcl_tt/snippets_base.lua +++ b/mods/HELP/mcl_tt/snippets_base.lua @@ -116,7 +116,7 @@ tt.register_snippet(function(itemstring, toolcaps) -- Weapon stats if toolcaps.damage_groups then for group, damage in pairs(toolcaps.damage_groups) do - local msg + local msg = "" if group == "fleshy" then if damage >= 0 then msg = S("Damage: @1", damage) diff --git a/mods/ITEMS/mcl_fishing/depends.txt b/mods/ITEMS/mcl_fishing/depends.txt index 93ef0bf523..bbc3c6ad81 100644 --- a/mods/ITEMS/mcl_fishing/depends.txt +++ b/mods/ITEMS/mcl_fishing/depends.txt @@ -2,3 +2,4 @@ mcl_core mcl_sounds mcl_loot mcl_mobs +mcl_enchanting diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index b7e1ba73ae..ac64f07d99 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -18,8 +18,8 @@ local bobber_ENTITY={ _lastpos={}, _dive = false, - _waittick = nil, - _tick = 0, + _waittime = nil, + _time = 0, player=nil, _oldy = nil, objtype="fishing", @@ -179,11 +179,10 @@ local bobber_on_step = function(self, dtime) self.object:remove() return end - + local wield = player:get_wielded_item() --Check if player is nearby - if self._tick % 5 == 0 and self.player ~= nil and player ~= nil then + if self.player ~= nil and player ~= nil then --Destroy bobber if item not wielded. - local wield = player:get_wielded_item() if ((not wield) or (minetest.get_item_group(wield:get_name(), "fishing_rod") <= 0)) then self.object:remove() return @@ -232,33 +231,34 @@ local bobber_on_step = function(self, dtime) pos = {x=epos["x"]+math.random(-1,1)*math.random()/2,y=epos["y"]+0.1,z=epos["z"]+math.random(-1,1)*math.random()/2}, velocity = {x=0, y=4, z=0}, acceleration = {x=0, y=-5, z=0}, - expirationtime = math.random(), - size = math.random()+0.5, + expirationtime = math.random() * 0.5, + size = math.random(), collisiondetection = true, vertical = false, texture = "mcl_particles_bubble.png", }) end - if self._tick ~= self._waittick then - self._tick = self._tick + 1 + if self._time < self._waittime then + self._time = self._time + dtime else - self._waittick = nil - self._tick = 0 + self._waittime = 0 + self._time = 0 self._dive = false end - else if self._waittick == nil then + else if not self._waittime or self._waittime <= 0 then -- wait for random number of ticks. - self._waittick = math.random(50,333) + local lure_enchantment = wield and mcl_enchanting.get_enchantment(wield, "lure") or 0 + self._waittime = math.random(5, 30) - lure_enchantment * 5 else - if self._tick ~= self._waittick then - self._tick = self._tick + 1 + if self._time < self._waittime then + self._time = self._time + dtime else - --wait time is over time to dive. + -- wait time is over time to dive. self._dive = true self.object:set_velocity({x=0,y=-2,z=0}) self.object:set_acceleration({x=0,y=5,z=0}) - self._waittick = 30 - self._tick = 0 + self._waittime = 0.8 + self._time = 0 end end end From b9e5a991e2575edfefebfc447dd27ea9d6f810fb Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 10 Nov 2020 13:58:39 +0100 Subject: [PATCH 24/27] Protection --- mods/CORE/mcl_enchanting/enchantments.lua | 2 +- mods/ITEMS/mcl_armor/armor.lua | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index 4301c5642a..a90088cd42 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -365,7 +365,7 @@ mcl_enchanting.enchantments.projectile_protection = { requires_tool = false, } --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.protection = { name = "Protection", max_level = 4, diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index d00348b139..a4b7974d5c 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -515,14 +515,15 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) local total_points = 0 local total_toughness = 0 + local protection_reduction = 0 for i=1, 6 do local stack = player_inv:get_stack("armor", i) if stack:get_count() > 0 then -- Damage armor local use = stack:get_definition().groups["mcl_armor_uses"] or 0 - local unbreaking = mcl_enchanting.get_enchantment(stack, "unbreaking") - if unbreaking > 0 then - use = use / (0.6 + 0.4 / (unbreaking + 1)) + local enchantments = mcl_enchanting.get_enchantments(stack) + if enchantments.unbreaking > 0 then + use = use / (0.6 + 0.4 / (enchantments.unbreaking + 1)) end if use > 0 then local wear = armor_damage * math.floor(65536/use) @@ -542,13 +543,20 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) local tough = stack:get_definition().groups["mcl_armor_toughness"] or 0 total_points = total_points + pts total_toughness = total_toughness + tough + if enchantments.protection then + protection_reduction = protection_reduction + enchantments.protection * 0.04 + end + -- if enchantments.blast_protection and then + -- protection_reduction = protection_reduction + enchantments.blast_protection * 0.08 + -- end end end local damage = math.abs(hp_change) -- Damage calculation formula (from ) damage = damage * (1 - math.min(20, math.max((total_points/5), total_points - damage / (2+(total_toughness/4)))) / 25) - damage = math.floor(damage+0.5) + damage = damage * (1 - math.min(1, protection_reduction)) + damage = math.floor(damage+0.5) hp_change = -math.abs(damage) From b53ae0df1917a55338489d65a4dd9c8d06787f0d Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Fri, 13 Nov 2020 09:44:42 +0100 Subject: [PATCH 25/27] Fix armor runtime error --- mods/ITEMS/mcl_armor/armor.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index a4b7974d5c..331a18b353 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -522,7 +522,7 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) -- Damage armor local use = stack:get_definition().groups["mcl_armor_uses"] or 0 local enchantments = mcl_enchanting.get_enchantments(stack) - if enchantments.unbreaking > 0 then + if enchantments.unbreaking then use = use / (0.6 + 0.4 / (enchantments.unbreaking + 1)) end if use > 0 then From a3cf6b0e5d8d446a39d5326415413b090c4583ff Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Fri, 13 Nov 2020 12:21:36 +0100 Subject: [PATCH 26/27] Blast Protection; Fire Protection; Projectile Protection; Feather Falling; Thorns --- mods/CORE/mcl_enchanting/enchantments.lua | 26 ++--- mods/CORE/mcl_explosions/init.lua | 10 +- mods/ENTITIES/mobs_mc/blaze.lua | 3 + mods/ENTITIES/mobs_mc/ghast.lua | 3 + mods/ITEMS/mcl_armor/armor.lua | 111 +++++++++++++++++----- mods/ITEMS/mcl_bows/arrow.lua | 6 +- 6 files changed, 116 insertions(+), 43 deletions(-) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index a90088cd42..c03cf99889 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -1,5 +1,13 @@ -- Taken from https://minecraft.gamepedia.com/Enchanting +local function increase_damage(damage_group, factor) + return function(itemstack, level) + local tool_capabilities = itemstack:get_tool_capabilities() + tool_capabilities.damage_groups[damage_group] = (tool_capabilities.damage_groups[damage_group] or 0) + level * factor + itemstack:get_meta():set_tool_capabilities(tool_capabilities) + end +end + -- requires engine change --[[mcl_enchanting.enchantments.aqua_affinity = { name = "Aqua Affinity", @@ -15,14 +23,6 @@ requires_tool = false, }]]-- -local function increase_damage(damage_group, factor) - return function(itemstack, level) - local tool_capabilities = itemstack:get_tool_capabilities() - tool_capabilities.damage_groups[damage_group] = (tool_capabilities.damage_groups[damage_group] or 0) + level * factor - itemstack:get_meta():set_tool_capabilities(tool_capabilities) - end -end - -- implemented via on_enchant and additions in mobs_mc; Slowness IV part unimplemented mcl_enchanting.enchantments.bane_of_arthropods = { name = "Bane of Arthropods", @@ -38,7 +38,7 @@ mcl_enchanting.enchantments.bane_of_arthropods = { requires_tool = false, } --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.blast_protection = { name = "Blast Protection", max_level = 4, @@ -123,7 +123,7 @@ mcl_enchanting.enchantments.efficiency = { requires_tool = false, } --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.feather_falling = { name = "Feather Falling", max_level = 4, @@ -152,7 +152,7 @@ mcl_enchanting.enchantments.feather_falling = { requires_tool = false, }]]-- --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.fire_protection = { name = "Fire Protection", max_level = 4, @@ -350,7 +350,7 @@ mcl_enchanting.enchantments.power = { requires_tool = false, } --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.projectile_protection = { name = "Projectile Protection", max_level = 4, @@ -485,7 +485,7 @@ mcl_enchanting.enchantments.soul_speed = { requires_tool = false, }]]-- --- unimplemented +-- implemented in mcl_armor mcl_enchanting.enchantments.thorns = { name = "Thorns", max_level = 3, diff --git a/mods/CORE/mcl_explosions/init.lua b/mods/CORE/mcl_explosions/init.lua index fdf1d6ad16..293fdba838 100644 --- a/mods/CORE/mcl_explosions/init.lua +++ b/mods/CORE/mcl_explosions/init.lua @@ -284,8 +284,14 @@ local function trace_explode(pos, strength, raydirs, radius, drop_chance, fire, impact = 0 end local damage = math.floor((impact * impact + impact) * 7 * strength + 1) - if mod_death_messages and obj:is_player() then - mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", obj:get_player_name())) + if obj:is_player() then + local name = obj:get_player_name() + if mod_death_messages then + mcl_death_messages.player_damage(obj, S("@1 was caught in an explosion.", name)) + end + if rawget(_G, "armor") and armor.last_damage_types then + armor.last_damage_types[name] = "explosion" + end end local source = puncher if not source then diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index cbba537ddb..d281a59ed5 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -83,6 +83,9 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { -- Direct hit, no fire... just plenty of pain hit_player = function(self, player) + if rawget(_G, "armor") and armor.last_damage_types then + armor.last_damage_types[player:get_player_name()] = "fireball" + end player:punch(self.object, 1.0, { full_punch_interval = 1.0, damage_groups = {fleshy = 5}, diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index 27998d170d..2b39b59376 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -71,6 +71,9 @@ mobs:register_arrow("mobs_mc:fireball", { velocity = 15, hit_player = function(self, player) + if rawget(_G, "armor") and armor.last_damage_types then + armor.last_damage_types[player:get_player_name()] = "fireball" + end player:punch(self.object, 1.0, { full_punch_interval = 1.0, damage_groups = {fleshy = 6}, diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index 331a18b353..0c57186b77 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -18,6 +18,7 @@ armor = { .."listring[current_player;craft]", textures = {}, default_skin = "character", + last_damage_types = {}, } if minetest.get_modpath("mcl_skins") then @@ -497,12 +498,15 @@ end) minetest.register_on_player_hpchange(function(player, hp_change, reason) local name, player_inv, armor_inv = armor:get_valid_player(player, "[on_hpchange]") if name and hp_change < 0 then - + local damage_type = armor.last_damage_types[name] + armor.last_damage_types[name] = nil + -- Armor doesn't protect from set_hp (commands like /kill), - -- falling and drowning damage. - if reason.type == "set_hp" or reason.type == "drown" or reason.type == "fall" then + if reason.type == "set_hp" then return hp_change end + + local regular_reduction = reason.type ~= "drown" and reason.type ~= "fall" -- Account for potion effects (armor doesn't save the target) if reason.other == "poison" or reason.other == "harming" then @@ -512,21 +516,68 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) local heal_max = 0 local items = 0 local armor_damage = math.max(1, math.floor(math.abs(hp_change)/4)) - + local total_points = 0 local total_toughness = 0 - local protection_reduction = 0 + local epf = 0 + local thorns_damage = 0 + local thorns_damage_regular = 0 for i=1, 6 do local stack = player_inv:get_stack("armor", i) if stack:get_count() > 0 then + local enchantments = mcl_enchanting.get_enchantments(stack) + local pts = stack:get_definition().groups["mcl_armor_points"] or 0 + local tough = stack:get_definition().groups["mcl_armor_toughness"] or 0 + total_points = total_points + pts + total_toughness = total_toughness + tough + + local protection_level = enchantments.protection or 0 + if protection_level > 0 then + epf = epf + protection_level * 1 + end + local blast_protection_level = enchantments.blast_protection or 0 + if blast_protection_level > 0 and damage_type == "explosion" then + epf = epf + blast_protection_level * 2 + end + local fire_protection_level = enchantments.fire_protection or 0 + if fire_protection_level > 0 and (damage_type == "fireball" or reason.type == "node_damage" and + (reason.node == "mcl_fire:fire" or reason.node == "mcl_core:lava_source" or reason.node == "mcl_core:lava_flowing")) then + epf = epf + fire_protection_level * 2 + end + local projectile_protection_level = enchantments.projectile_protection or 0 + if projectile_protection_level and (damage_type == "projectile" or damage_type == "fireball") then + epf = epf + projectile_protection_level * 2 + end + local feather_falling_level = enchantments.feather_falling or 0 + if feather_falling_level and reason.type == "fall" then + epf = epf + feather_falling_level * 3 + end + + local did_thorns_damage = false + local thorns_level = enchantments.thorns or 0 + if thorns_level then + if thorns_level > 10 then + thorns_damage = thorns_damage + thorns_level - 10 + did_thorns_damage = true + elseif thorns_damage_regular < 4 and thorns_level * 0.15 > math.random() then + local thorns_damage_regular_new = math.min(4, thorns_damage_regular + math.random(4)) + thorns_damage = thorns_damage + thorns_damage_regular_new - thorns_damage_regular + thorns_damage_regular = thorns_damage_regular_new + did_thorns_damage = true + end + end + -- Damage armor local use = stack:get_definition().groups["mcl_armor_uses"] or 0 - local enchantments = mcl_enchanting.get_enchantments(stack) - if enchantments.unbreaking then - use = use / (0.6 + 0.4 / (enchantments.unbreaking + 1)) - end - if use > 0 then + if use > 0 and regular_reduction then + local unbreaking_level = enchantments.unbreaking or 0 + if unbreaking_level > 0 then + use = use / (0.6 + 0.4 / (unbreaking_level + 1)) + end local wear = armor_damage * math.floor(65536/use) + if did_thorns_damage then + wear = wear * 3 + end stack:add_wear(wear) end @@ -538,26 +589,34 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) armor:set_player_armor(player) armor:update_inventory(player) end - - local pts = stack:get_definition().groups["mcl_armor_points"] or 0 - local tough = stack:get_definition().groups["mcl_armor_toughness"] or 0 - total_points = total_points + pts - total_toughness = total_toughness + tough - if enchantments.protection then - protection_reduction = protection_reduction + enchantments.protection * 0.04 - end - -- if enchantments.blast_protection and then - -- protection_reduction = protection_reduction + enchantments.blast_protection * 0.08 - -- end end end local damage = math.abs(hp_change) - - -- Damage calculation formula (from ) - damage = damage * (1 - math.min(20, math.max((total_points/5), total_points - damage / (2+(total_toughness/4)))) / 25) - damage = damage * (1 - math.min(1, protection_reduction)) + + if regular_reduction then + -- Damage calculation formula (from ) + damage = damage * (1 - math.min(20, math.max((total_points/5), total_points - damage / (2+(total_toughness/4)))) / 25) + end + damage = damage * (1 - (math.min(20, epf) / 25)) damage = math.floor(damage+0.5) - + + if reason.type == "punch" and thorns_damage > 0 then + local obj = reason.object + if obj then + local luaentity = obj:get_luaentity() + if luaentity then + local shooter = obj._shooter + if shooter then + obj = shooter + end + end + obj:punch(player, 1.0, { + full_punch_interval=1.0, + damage_groups = {fleshy = thorns_damage}, + }) + end + end + hp_change = -math.abs(damage) armor.def[name].count = items diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 0f603015e1..1bc17354cd 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -240,12 +240,14 @@ ARROW_ENTITY.on_step = function(self, dtime) -- Punch target object but avoid hurting enderman. if not lua or lua.name ~= "mobs_mc:enderman" then + if obj:is_player() and rawget(_G, "armor") and armor.last_damage_types then + armor.last_damage_types[obj:get_player_name()] = "projectile" + end damage_particles(self.object:get_pos(), self._is_critical) - self.object:set_pos(vector.subtract(obj:get_pos(), vector.multiply(vector.normalize(self.object:get_velocity()), 2))) obj:punch(self.object, 1.0, { full_punch_interval=1.0, damage_groups={fleshy=self._damage}, - }, nil) + }, self.object:get_velocity()) end From ed738da01628f269e6dc7c067419067a87998157 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 25 Nov 2020 12:47:27 +0100 Subject: [PATCH 27/27] Added Enchanting Table --- mods/CORE/mcl_enchanting/README | 5 - mods/CORE/mcl_enchanting/book.lua | 9 - mods/CORE/mcl_enchanting/command.lua | 41 -- mods/CORE/mcl_enchanting/enchantments.lua | 209 ++++++++- mods/CORE/mcl_enchanting/engine.lua | 497 ++++++++++++++++++---- mods/CORE/mcl_enchanting/init.lua | 264 +++++++++++- mods/CORE/mcl_enchanting/mod.conf | 4 +- mods/CORE/mcl_enchanting/table.lua | 189 -------- mods/CORE/mcl_enchanting/table_book.lua | 87 ---- mods/CORE/mcl_enchanting/tt.lua | 18 - mods/HELP/tt/init.lua | 23 +- mods/HUD/mcl_inventory/depends.txt | 1 + mods/HUD/mcl_inventory/init.lua | 15 +- mods/ITEMS/mcl_armor/armor.lua | 2 +- mods/ITEMS/mcl_armor/init.lua | 40 +- mods/ITEMS/mcl_books/init.lua | 3 +- mods/ITEMS/mcl_bows/bow.lua | 10 +- mods/ITEMS/mcl_compass/init.lua | 4 +- mods/ITEMS/mcl_farming/hoes.lua | 10 +- mods/ITEMS/mcl_farming/pumpkin.lua | 1 + mods/ITEMS/mcl_fire/flint_and_steel.lua | 2 +- mods/ITEMS/mcl_fishing/init.lua | 2 +- mods/ITEMS/mcl_heads/init.lua | 2 +- mods/ITEMS/mcl_tools/init.lua | 40 +- mods/ITEMS/screwdriver/init.lua | 2 +- 25 files changed, 952 insertions(+), 528 deletions(-) delete mode 100644 mods/CORE/mcl_enchanting/README delete mode 100644 mods/CORE/mcl_enchanting/book.lua delete mode 100644 mods/CORE/mcl_enchanting/command.lua delete mode 100644 mods/CORE/mcl_enchanting/table.lua delete mode 100644 mods/CORE/mcl_enchanting/table_book.lua delete mode 100644 mods/CORE/mcl_enchanting/tt.lua diff --git a/mods/CORE/mcl_enchanting/README b/mods/CORE/mcl_enchanting/README deleted file mode 100644 index 4d1d5af9d2..0000000000 --- a/mods/CORE/mcl_enchanting/README +++ /dev/null @@ -1,5 +0,0 @@ -Enchanting for MineClone2 --------------------------- - -This is a rewrite of the mtg enchanting mod. Beta Version, more features coming soon. -The textures look absolutely shit, but as far as I know I have to use the textures from Pixel Perfection so I dont get trouble with Mocrisoft. There is a version with original textures and sounds, but I can't publish that one. If you'd like to advice me how I can somehow do that anyway, please open an issue or contact me via email (eliasfleckenstein@web.de). diff --git a/mods/CORE/mcl_enchanting/book.lua b/mods/CORE/mcl_enchanting/book.lua deleted file mode 100644 index 7b0ee50801..0000000000 --- a/mods/CORE/mcl_enchanting/book.lua +++ /dev/null @@ -1,9 +0,0 @@ -minetest.register_craftitem("mcl_enchanting:book_enchanted", { - description = "Enchanted Book", - inventory_image = "mcl_enchanting_book_enchanted.png^[colorize:purple:50", - groups = {enchanted = 1, not_in_creative_inventory = 1}, - _mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted", - stack_max = 1, -}) - -minetest.registered_items["mcl_books:book"]._mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted" diff --git a/mods/CORE/mcl_enchanting/command.lua b/mods/CORE/mcl_enchanting/command.lua deleted file mode 100644 index e93a3979c7..0000000000 --- a/mods/CORE/mcl_enchanting/command.lua +++ /dev/null @@ -1,41 +0,0 @@ -minetest.register_chatcommand("enchant", { - description = "Enchant an item.", - params = " []", - privs = {give = true}, - func = function(_, param) - local sparam = param:split(" ") - local target_name = sparam[1] - local enchantment = sparam[2] - local level_str = sparam[3] - local level = tonumber(level_str or "1") - if not target_name or not enchantment then - return false, "Usage: /enchant []" - end - local target = minetest.get_player_by_name(target_name) - if not target then - return false, "Player '" .. target_name .. "' cannot be found" - end - local itemstack = target:get_wielded_item() - local can_enchant, errorstring, extra_info = mcl_enchanting.can_enchant(itemstack, enchantment, level) - if not can_enchant then - if errorstring == "enchantment invalid" then - return false, "There is no such enchantment '" .. enchantment .. "'" - elseif errorstring == "item missing" then - return false, "The target doesn't hold an item" - elseif errorstring == "item not supported" then - return false, "The selected enchantment can't be added to the target item" - elseif errorstring == "level invalid" then - return false, "'" .. level_str .. "' is not a valid number" - elseif errorstring == "level too high" then - return false, "The number you have entered (" .. level_str .. ") is too big, it must be at most " .. extra_info - elseif errorstring == "level too small" then - return false, "The number you have entered (" .. level_str .. ") is too small, it must be at least " .. extra_info - elseif errorstring == "incompatible" then - return false, mcl_enchanting.get_enchantment_description(enchantment, level) .. " can't be combined with " .. extra_info - end - else - target:set_wielded_item(mcl_enchanting.enchant(itemstack, enchantment, level)) - return true, "Enchanting succeded" - end - end -}) diff --git a/mods/CORE/mcl_enchanting/enchantments.lua b/mods/CORE/mcl_enchanting/enchantments.lua index c03cf99889..4ed94a0b37 100644 --- a/mods/CORE/mcl_enchanting/enchantments.lua +++ b/mods/CORE/mcl_enchanting/enchantments.lua @@ -21,6 +21,8 @@ end curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{1, 41}}, }]]-- -- implemented via on_enchant and additions in mobs_mc; Slowness IV part unimplemented @@ -36,6 +38,8 @@ mcl_enchanting.enchantments.bane_of_arthropods = { curse = false, on_enchant = increase_damage("anthropod", 2.5), requires_tool = false, + treasure = false, + power_range_table = {{5, 25}, {13, 33}, {21, 41}, {29, 49}, {37, 57}}, } -- implemented in mcl_armor @@ -51,8 +55,27 @@ mcl_enchanting.enchantments.blast_protection = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{5, 13}, {13, 21}, {21, 29}, {29, 37}}, } +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.channeling = { + name = "Channeling", + max_level = 1, + primary = {trident = true}, + secondary = {}, + disallow = {}, + incompatible = {riptide = true}, + weight = 1, + description = "Trident \"channels\" a bolt of lightning toward a hit entity. Functions only during thunderstorms and if target is unobstructed with opaque blocks.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{25, 50}}, +}]]-- + -- implemented in mcl_armor mcl_enchanting.enchantments.curse_of_binding = { name = "Curse of Binding", @@ -66,6 +89,8 @@ mcl_enchanting.enchantments.curse_of_binding = { curse = true, on_enchant = function() end, requires_tool = false, + treasure = true, + power_range_table = {{25, 50}}, } -- implemented in mcl_death_drop @@ -74,17 +99,19 @@ mcl_enchanting.enchantments.curse_of_vanishing = { max_level = 1, primary = {}, secondary = {armor_head = true, armor_torso = true, armor_legs = true, armor_feet = true, tool = true, weapon = true}, - disallow = {clock = true}, + disallow = {}, incompatible = {}, weight = 1, description = "Item destroyed on death.", curse = true, on_enchant = function() end, requires_tool = false, + treasure = true, + power_range_table = {{25, 50}}, } -- unimplemented -mcl_enchanting.enchantments.depth_strider = { +--[[mcl_enchanting.enchantments.depth_strider = { name = "Depth Strider", max_level = 3, primary = {}, @@ -96,7 +123,9 @@ mcl_enchanting.enchantments.depth_strider = { curse = false, on_enchant = function() end, requires_tool = false, -} + treasure = false, + power_range_table = {{10, 25}, {20, 35}, {30, 45}}, +}]]-- -- implemented via on_enchant mcl_enchanting.enchantments.efficiency = { @@ -121,6 +150,8 @@ mcl_enchanting.enchantments.efficiency = { itemstack:get_meta():set_tool_capabilities(tool_capabilities) end, requires_tool = false, + treasure = false, + power_range_table = {{1, 61}, {11, 71}, {21, 81}, {31, 91}, {41, 101}}, } -- implemented in mcl_armor @@ -135,6 +166,8 @@ mcl_enchanting.enchantments.feather_falling = { description = "Reduces fall damage.",curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{5, 11}, {11, 17}, {17, 23}, {23, 29}}, } -- requires missing MineClone2 feature @@ -150,6 +183,8 @@ mcl_enchanting.enchantments.feather_falling = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{10, 61}, {30, 71}}, }]]-- -- implemented in mcl_armor @@ -165,6 +200,8 @@ mcl_enchanting.enchantments.fire_protection = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{10, 18}, {18, 26}, {26, 34}, {34, 42}}, } -- requires missing MineClone2 feature @@ -180,12 +217,14 @@ mcl_enchanting.enchantments.fire_protection = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{20, 50}}, }]]-- -- implemented in mcl_item_entity mcl_enchanting.enchantments.fortune = { name = "Fortune", - max_level = 4, + max_level = 3, primary = {pickaxe = true, shovel = true, axe = true, hoe = true}, secondary = {}, disallow = {}, @@ -195,6 +234,8 @@ mcl_enchanting.enchantments.fortune = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{15, 61}, {24, 71}, {33, 81}}, } -- implemented via walkover.register_global @@ -210,6 +251,8 @@ mcl_enchanting.enchantments.frost_walker = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = true, + power_range_table = {{10, 25}, {20, 35}}, } walkover.register_global(function(pos, _, player) @@ -229,6 +272,23 @@ walkover.register_global(function(pos, _, player) end end) +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.impaling = { + name = "Impaling", + max_level = 5, + primary = {trident = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 2, + description = "Trident deals additional damage to mobs that spawn naturally in the ocean.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{1, 21}, {9, 29}, {17, 37}, {25, 45}, {33, 53}}, +}]]-- + -- implemented in mcl_bows mcl_enchanting.enchantments.infinity = { name = "Infinity", @@ -242,6 +302,8 @@ mcl_enchanting.enchantments.infinity = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{20, 50}}, } -- implemented via minetest.calculate_knockback @@ -257,6 +319,8 @@ mcl_enchanting.enchantments.knockback = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{5, 61}, {25, 71}}, } local old_calculate_knockback = minetest.calculate_knockback @@ -276,7 +340,7 @@ function minetest.calculate_knockback(player, hitter, time_from_last_punch, tool end -- unimplemented -mcl_enchanting.enchantments.looting = { +--[[mcl_enchanting.enchantments.looting = { name = "Looting", max_level = 3, primary = {sword = true}, @@ -288,10 +352,29 @@ mcl_enchanting.enchantments.looting = { curse = false, on_enchant = function() end, requires_tool = false, -} + treasure = false, + power_range_table = {{15, 61}, {24, 71}, {33, 81}}, +}]]-- + +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.loyalty = { + name = "Loyalty", + max_level = 3, + primary = {trident = true}, + secondary = {}, + disallow = {}, + incompatible = {riptide = true}, + weight = 5, + description = "Trident returns after being thrown. Higher levels reduce return time.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{12, 50}, {19, 50}, {26, 50}}, +}]]-- -- unimplemented -mcl_enchanting.enchantments.luck_of_the_sea = { +--[[mcl_enchanting.enchantments.luck_of_the_sea = { name = "Luck of the Sea", max_level = 3, primary = {fishing_rod = true}, @@ -303,7 +386,9 @@ mcl_enchanting.enchantments.luck_of_the_sea = { curse = false, on_enchant = function() end, requires_tool = false, -} + treasure = false, + power_range_table = {{15, 61}, {24, 71}, {33, 81}}, +}]]-- -- implemented in mcl_fishing mcl_enchanting.enchantments.lure = { @@ -318,10 +403,12 @@ mcl_enchanting.enchantments.lure = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{15, 61}, {24, 71}, {33, 81}}, } -- unimplemented -mcl_enchanting.enchantments.mending = { +--[[mcl_enchanting.enchantments.mending = { name = "Mending", max_level = 1, primary = {}, @@ -333,14 +420,50 @@ mcl_enchanting.enchantments.mending = { curse = false, on_enchant = function() end, requires_tool = true, -} + treasure = true, + power_range_table = {{25, 75}}, +}]]-- + +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.multishot = { + name = "Multishot", + max_level = 1, + primary = {crossbow = true}, + secondary = {}, + disallow = {}, + incompatible = {piercing = true}, + weight = 2, + description = "Shoot 3 arrows at the cost of one.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{20, 50}}, +}]]-- + +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.piercing = { + name = "Piercing", + max_level = 4, + primary = {crossbow = true}, + secondary = {}, + disallow = {}, + incompatible = {multishot = true}, + weight = 10, + description = "Arrows pass through multiple entities.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{1, 50}, {11, 50}, {21, 50}, {31, 50}}, +}]]-- -- implemented in mcl_bows mcl_enchanting.enchantments.power = { name = "Power", max_level = 5, - primary = {}, - secondary = {bow = true}, + primary = {bow = true}, + secondary = {}, disallow = {}, incompatible = {}, weight = 10, @@ -348,6 +471,8 @@ mcl_enchanting.enchantments.power = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{1, 16}, {11, 26}, {21, 36}, {31, 46}, {41, 56}}, } -- implemented in mcl_armor @@ -363,6 +488,8 @@ mcl_enchanting.enchantments.projectile_protection = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{1, 16}, {11, 26}, {21, 36}, {31, 46}, {41, 56}}, } -- implemented in mcl_armor @@ -378,6 +505,8 @@ mcl_enchanting.enchantments.protection = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{1, 12}, {12, 23}, {23, 34}, {34, 45}}, } -- implemented via minetest.calculate_knockback (together with the Knockback enchantment) and mcl_bows @@ -393,10 +522,29 @@ mcl_enchanting.enchantments.punch = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{12, 37}, {32, 57}}, } +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.quick_charge = { + name = "Quick Charge", + max_level = 3, + primary = {crossbow = true}, + secondary = {}, + disallow = {}, + incompatible = {}, + weight = 5, + description = "Decreases crossbow charging time.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{12, 50}, {32, 50}, {52, 50}}, +}]]-- + -- unimplemented -mcl_enchanting.enchantments.respiration = { +--[[mcl_enchanting.enchantments.respiration = { name = "Respiration", max_level = 3, primary = {armor_head = true}, @@ -408,7 +556,26 @@ mcl_enchanting.enchantments.respiration = { curse = false, on_enchant = function() end, requires_tool = false, -} + treasure = false, + power_range_table = {{10, 40}, {20, 50}, {30, 60}}, +}]]-- + +-- requires missing MineClone2 feature +--[[mcl_enchanting.enchantments.riptide = { + name = "Riptide", + max_level = 3, + primary = {trident = true}, + secondary = {}, + disallow = {}, + incompatible = {channeling = true, loyalty = true}, + weight = 2, + description = "Trident launches player with itself when thrown. Functions only in water or rain.", + curse = false, + on_enchant = function() end, + requires_tool = false, + treasure = false, + power_range_table = {{17, 50}, {24, 50}, {31, 50}}, +}]]-- -- implemented via on_enchant mcl_enchanting.enchantments.sharpness = { @@ -423,6 +590,8 @@ mcl_enchanting.enchantments.sharpness = { curse = false, on_enchant = increase_damage("fleshy", 0.5), requires_tool = false, + treasure = false, + power_range_table = {{1, 21}, {12, 32}, {23, 43}, {34, 54}, {45, 65}}, } -- implemented in mcl_item_entity @@ -438,6 +607,8 @@ mcl_enchanting.enchantments.silk_touch = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{15, 61}}, } -- implemented via on_enchant and additions in mobs_mc @@ -453,6 +624,8 @@ mcl_enchanting.enchantments.smite = { curse = false, on_enchant = increase_damage("undead", 2.5), requires_tool = false, + treasure = false, + power_range_table = {{5, 25}, {13, 33}, {21, 41}, {29, 49}, {37, 57}}, } -- implemented in mcl_playerplus @@ -468,6 +641,8 @@ mcl_enchanting.enchantments.soul_speed = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = true, + power_range_table = {{10, 25}, {20, 35}, {30, 45}}, } -- requires missing MineClone2 feature @@ -483,6 +658,8 @@ mcl_enchanting.enchantments.soul_speed = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{5, 20}, {14, 29}, {23, 38}}, }]]-- -- implemented in mcl_armor @@ -498,6 +675,8 @@ mcl_enchanting.enchantments.thorns = { curse = false, on_enchant = function() end, requires_tool = false, + treasure = false, + power_range_table = {{10, 61}, {30, 71}, {50, 81}}, } -- for tools & weapons implemented via on_enchant; for bows implemented in mcl_bows; for armor implemented in mcl_armor and mcl_tt; for fishing rods implemented in mcl_fishing @@ -520,4 +699,6 @@ mcl_enchanting.enchantments.unbreaking = { itemstack:get_meta():set_tool_capabilities(tool_capabilities) end, requires_tool = true, + treasure = false, + power_range_table = {{5, 61}, {13, 71}, {21, 81}}, } diff --git a/mods/CORE/mcl_enchanting/engine.lua b/mods/CORE/mcl_enchanting/engine.lua index fa809cfac7..1202ec70df 100644 --- a/mods/CORE/mcl_enchanting/engine.lua +++ b/mods/CORE/mcl_enchanting/engine.lua @@ -1,3 +1,7 @@ +function mcl_enchanting.is_book(itemname) + return itemname == "mcl_books:book" or itemname == "mcl_enchanting:book_enchanted" +end + function mcl_enchanting.get_enchantments(itemstack) return minetest.deserialize(itemstack:get_meta():get_string("mcl_enchanting:enchantments")) or {} end @@ -5,7 +9,7 @@ end function mcl_enchanting.set_enchantments(itemstack, enchantments) itemstack:get_meta():set_string("mcl_enchanting:enchantments", minetest.serialize(enchantments)) local itemdef = itemstack:get_definition() - if itemstack:get_name() ~= "mcl_enchanting:book_enchanted" then + if not mcl_enchanting.is_book(itemstack:get_name()) then if itemdef.tool_capabilities then itemstack:get_meta():set_tool_capabilities(itemdef.tool_capabilities) end @@ -20,9 +24,6 @@ function mcl_enchanting.set_enchantments(itemstack, enchantments) end function mcl_enchanting.get_enchantment(itemstack, enchantment) - if itemstack:get_name() == "mcl_enchanting:book_enchanted" then - return 0 - end return mcl_enchanting.get_enchantments(itemstack)[enchantment] or 0 end @@ -44,22 +45,34 @@ function mcl_enchanting.get_enchanted_itemstring(itemname) return def and def._mcl_enchanting_enchanted_tool end -function mcl_enchanting.is_enchanted_def(itemname) +function mcl_enchanting.set_enchanted_itemstring(itemstack) + itemstack:set_name(mcl_enchanting.get_enchanted_itemstring(itemstack:get_name())) +end + +function mcl_enchanting.is_enchanted(itemname) return minetest.get_item_group(itemname, "enchanted") > 0 end -function mcl_enchanting.is_enchanted(itemstack) - return mcl_enchanting.is_enchanted_def(itemstack:get_name()) +function mcl_enchanting.is_enchantable(itemname) + return mcl_enchanting.get_enchantability(itemname) > 0 +end + +function mcl_enchanting.can_enchant_freshly(itemname) + return mcl_enchanting.is_enchantable(itemname) and not mcl_enchanting.is_enchanted(itemname) +end + +function mcl_enchanting.get_enchantability(itemname) + return minetest.get_item_group(itemname, "enchantability") end function mcl_enchanting.item_supports_enchantment(itemname, enchantment, early) - if itemname == "mcl_enchanting:book_enchanted" then - return true, true - end - if not early and not mcl_enchanting.get_enchanted_itemstring(itemname) then + if not mcl_enchanting.is_enchantable(itemname) then return false end local enchantment_def = mcl_enchanting.enchantments[enchantment] + if mcl_enchanting.is_book(itemname) then + return true, (not enchantment_def.treasure) + end local itemdef = minetest.registered_items[itemname] if itemdef.type ~= "tool" and enchantment_def.requires_tool then return false @@ -91,7 +104,8 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) if itemname == "" then return false, "item missing" end - if not mcl_enchanting.item_supports_enchantment(itemstack:get_name(), enchantment) then + local supported, primary = mcl_enchanting.item_supports_enchantment(itemstack:get_name(), enchantment) + if not supported then return false, "item not supported" end if not level then @@ -107,7 +121,7 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) if enchantment_level then return false, "incompatible", mcl_enchanting.get_enchantment_description(enchantment, enchantment_level) end - if itemname ~= "mcl_enchanting:book_enchanted" then + if not mcl_enchanting.is_book(itemname) then for incompatible in pairs(enchantment_def.incompatible) do local incompatible_level = item_enchantments[incompatible] if incompatible_level then @@ -115,11 +129,11 @@ function mcl_enchanting.can_enchant(itemstack, enchantment, level) end end end - return true + return true, nil, nil, primary end function mcl_enchanting.enchant(itemstack, enchantment, level) - itemstack:set_name(mcl_enchanting.get_enchanted_itemstring(itemstack:get_name())) + mcl_enchanting.set_enchanted_itemstring(itemstack) local enchantments = mcl_enchanting.get_enchantments(itemstack) enchantments[enchantment] = level mcl_enchanting.set_enchantments(itemstack, enchantments) @@ -130,7 +144,7 @@ function mcl_enchanting.combine(itemstack, combine_with) local itemname = itemstack:get_name() local combine_name = combine_with:get_name() local enchanted_itemname = mcl_enchanting.get_enchanted_itemstring(itemname) - if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and combine_name ~= "mcl_enchanting:book_enchanted" then + if enchanted_itemname ~= mcl_enchanting.get_enchanted_itemstring(combine_name) and not mcl_enchanting.is_book(itemname) then return false end local enchantments = mcl_enchanting.get_enchantments(itemstack) @@ -173,68 +187,44 @@ function mcl_enchanting.combine(itemstack, combine_with) return true end -function mcl_enchanting.initialize() - local all_groups = {} - local weighted = {} - local accum_weight = 0 - for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do - accum_weight = accum_weight + enchantment_def.weight - weighted[#weighted + 1] = {enchantment = enchantment, weight = accum_weight} - for primary in pairs(enchantment_def.primary) do - all_groups[primary] = true - end - for secondary in pairs(enchantment_def.secondary) do - all_groups[secondary] = true - end +function mcl_enchanting.enchantments_snippet(_, _, itemstack) + if not itemstack then + return end - mcl_enchanting.accumulated_weight = accum_weight - mcl_enchanting.accumulated_weight = weighted + local enchantments = mcl_enchanting.get_enchantments(itemstack) + local text = "" + for enchantment, level in pairs(enchantments) do + text = text .. mcl_enchanting.get_colorized_enchantment_description(enchantment, level) .. "\n" + end + if text ~= "" then + if not itemstack:get_definition()._tt_original_description then + text = text:sub(1, text:len() - 1) + end + return text, false + end +end + +function mcl_enchanting.initialize() local register_tool_list = {} local register_item_list = {} for itemname, itemdef in pairs(minetest.registered_items) do - if itemdef.groups.enchanted then - break - end - local quick_test = false - for group, groupv in pairs(itemdef.groups) do - if groupv > 0 and all_groups[group] then - quick_test = true - break + if mcl_enchanting.can_enchant_freshly(itemname) then + local new_name = itemname .. "_enchanted" + minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) + local new_def = table.copy(itemdef) + new_def.inventory_image = itemdef.inventory_image .. mcl_enchanting.overlay + if new_def.wield_image then + new_def.wield_image = new_def.wield_image .. mcl_enchanting.overlay end - end - if quick_test then - if mcl_enchanting.debug then - print(itemname) - end - local expensive_test = false - for enchantment in pairs(mcl_enchanting.enchantments) do - if mcl_enchanting.item_supports_enchantment(itemname, enchantment, true) then - expensive_test = true - if mcl_enchanting.debug then - print("\tSupports " .. enchantment) - else - break - end - end - end - if expensive_test then - local new_name = itemname .. "_enchanted" - minetest.override_item(itemname, {_mcl_enchanting_enchanted_tool = new_name}) - local new_def = table.copy(itemdef) - new_def.inventory_image = itemdef.inventory_image .. "^[colorize:white:50^[colorize:purple:50" - if new_def.wield_image then - new_def.wield_image = new_def.wield_image .. "^[colorize:white:50^[colorize:purple:50" - end - new_def.groups.not_in_creative_inventory = 1 - new_def.groups.enchanted = 1 - new_def.texture = itemdef.texture or itemname:gsub("%:", "_") - new_def._mcl_enchanting_enchanted_tool = new_name - local register_list = register_item_list - if itemdef.type == "tool" then - register_list = register_tool_list - end - register_list[":" .. new_name] = new_def + new_def.groups.not_in_creative_inventory = 1 + new_def.groups.enchanted = 1 + new_def.texture = itemdef.texture or itemname:gsub("%:", "_") + new_def._mcl_enchanting_enchanted_tool = new_name + local register_list = register_item_list + if itemdef.type == "tool" then + register_list = register_tool_list end + register_list[":" .. new_name] = new_def end end for new_name, new_def in pairs(register_item_list) do @@ -244,3 +234,366 @@ function mcl_enchanting.initialize() minetest.register_tool(new_name, new_def) end end + +function mcl_enchanting.get_possible_enchantments(itemstack, enchantment_level, treasure) + local possible_enchantments, weights, accum_weight = {}, {}, 0 + for enchantment, enchantment_def in pairs(mcl_enchanting.enchantments) do + local supported, _, _, primary = mcl_enchanting.can_enchant(itemstack, enchantment, 1) + if primary or treasure then + table.insert(possible_enchantments, enchantment) + accum_weight = accum_weight + enchantment_def.weight + weights[enchantment] = accum_weight + end + end + return possible_enchantments, weights, accum_weight +end + +function mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance) + local itemname = itemstack:get_name() + if not mcl_enchanting.can_enchant_freshly(itemname) then + return + end + itemstack = ItemStack(itemstack) + local enchantability = minetest.get_item_group(itemname, "enchantability") + enchantability = 1 + math.random(0, math.floor(enchantability / 4)) + math.random(0, math.floor(enchantability / 4)) + enchantment_level = enchantment_level + enchantability + enchantment_level = enchantment_level + enchantment_level * (math.random() + math.random() - 1) * 0.15 + enchantment_level = math.max(math.floor(enchantment_level + 0.5), 1) + local enchantments = {} + local description + enchantment_level = enchantment_level * 2 + repeat + enchantment_level = math.floor(enchantment_level / 2) + if enchantment_level == 0 then + break + end + local possible, weights, accum_weight = mcl_enchanting.get_possible_enchantments(itemstack, enchantment_level, treasure) + local selected_enchantment, enchantment_power + if #possible > 0 then + local r = math.random(accum_weight) + for _, enchantment in ipairs(possible) do + if weights[enchantment] >= r then + selected_enchantment = enchantment + break + end + end + local enchantment_def = mcl_enchanting.enchantments[selected_enchantment] + local power_range_table = enchantment_def.power_range_table + for i = enchantment_def.max_level, 1, -1 do + local power_range = power_range_table[i] + if enchantment_level >= power_range[1] and enchantment_level <= power_range[2] then + enchantment_power = i + break + end + end + if not description then + if not enchantment_power then + return + end + description = mcl_enchanting.get_enchantment_description(selected_enchantment, enchantment_power) + end + if enchantment_power then + enchantments[selected_enchantment] = enchantment_power + mcl_enchanting.enchant(itemstack, selected_enchantment, enchantment_power) + end + else + break + end + until not no_reduced_bonus_chance and math.random() >= (enchantment_level + 1) / 50 + return enchantments, description +end + +function mcl_enchanting.enchant_randomly(itemstack, enchantment_level, treasure, no_reduced_bonus_chance) + local enchantments = mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level, treasure, no_reduced_bonus_chance) + if enchantments then + mcl_enchanting.set_enchanted_itemstring(itemstack) + mcl_enchanting.set_enchantments(itemstack, enchantments) + end + return itemstack +end + +function mcl_enchanting.get_randomly_enchanted_book(enchantment_level, treasure, no_reduced_bonus_chance) + return mcl_enchanting.enchant_randomly(enchantment_level, treasure, no_reduced_bonus_chance) +end + +function mcl_enchanting.get_random_glyph_row() + local glyphs = "" + local x = 1.3 + for i = 1, 9 do + glyphs = glyphs .. "image[".. x .. ",0.1;0.5,0.5;mcl_enchanting_glyph_" .. math.random(18) .. ".png^[colorize:#675D49:255]" + x = x + 0.6 + end + return glyphs +end + +function mcl_enchanting.generate_random_table_slots(itemstack, num_bookshelves) + local base = math.random(8) + math.floor(num_bookshelves / 2) + math.random(0, num_bookshelves) + local required_levels = { + math.max(base / 3, 1), + (base * 2) / 3 + 1, + math.max(base, num_bookshelves * 2) + } + local slots = {} + for i, enchantment_level in ipairs(required_levels) do + local slot = false + local enchantments, description = mcl_enchanting.generate_random_enchantments(itemstack, enchantment_level) + if enchantments then + slot = { + enchantments = enchantments, + description = description, + glyphs = mcl_enchanting.get_random_glyph_row(), + level_requirement = math.max(i, math.floor(enchantment_level)), + } + end + slots[i] = slot + end + return slots +end + +function mcl_enchanting.get_table_slots(player, itemstack, num_bookshelves) + if not mcl_enchanting.can_enchant_freshly(itemstack:get_name()) then + return {false, false, false} + end + local itemname = itemstack:get_name() + local meta = player:get_meta() + local player_slots = minetest.deserialize(meta:get_string("mcl_enchanting:slots")) or {} + local player_bookshelves_slots = player_slots[num_bookshelves] or {} + local player_bookshelves_item_slots = player_bookshelves_slots[itemname] + if player_bookshelves_item_slots then + return player_bookshelves_item_slots + else + player_bookshelves_item_slots = mcl_enchanting.generate_random_table_slots(itemstack, num_bookshelves) + if player_bookshelves_item_slots then + player_bookshelves_slots[itemname] = player_bookshelves_item_slots + player_slots[num_bookshelves] = player_bookshelves_slots + meta:set_string("mcl_enchanting:slots", minetest.serialize(player_slots)) + return player_bookshelves_item_slots + else + return {false, false, false} + end + end +end + +function mcl_enchanting.reset_table_slots(player) + player:get_meta():set_string("mcl_enchanting:slots", "") +end + +function mcl_enchanting.show_enchanting_formspec(player) + local C = minetest.get_color_escape_sequence + local name = player:get_player_name() + local meta = player:get_meta() + local inv = player:get_inventory() + local num_bookshelves = meta:get_int("mcl_enchanting:num_bookshelves") + local table_name = meta:get_string("mcl_enchanting:table_name") + local formspec = "" + .. "size[9.07,8.6;]" + .. "formspec_version[3]" + .. "label[0,0;" .. C("#313131") .. table_name .. "]" + .. mcl_formspec.get_itemslot_bg(0.2, 2.4, 1, 1) + .. "list[detached:" .. name .. "_enchanting;enchanting;0.2,2.4;1,1;1]" + .. mcl_formspec.get_itemslot_bg(1.1, 2.4, 1, 1) + .. "image[1.1,2.4;1,1;mcl_enchanting_lapis_background.png]" + .. "list[detached:" .. name .. "_enchanting;enchanting;1.1,2.4;1,1;2]" + .. "label[0,4;" .. C("#313131") .. "Inventory]" + .. mcl_formspec.get_itemslot_bg(0, 4.5, 9, 3) + .. mcl_formspec.get_itemslot_bg(0, 7.74, 9, 1) + .. "list[current_player;main;0,4.5;9,3;9]" + .. "listring[detached:" .. name .. "_enchanting;enchanting]" + .. "listring[current_player;main]" + .. "list[current_player;main;0,7.74;9,1;]" + .. "real_coordinates[true]" + .. "image[3.15,0.6;7.6,4.1;mcl_enchanting_button_background.png]" + local itemstack = inv:get_stack("enchanting_item", 1) + local player_levels = mcl_experience.get_player_xp_level(player) + local y = 0.65 + local any_enchantment = false + local table_slots = mcl_enchanting.get_table_slots(player, itemstack, num_bookshelves) + for i, slot in ipairs(table_slots) do + any_enchantment = any_enchantment or slot + local enough_lapis = inv:contains_item("enchanting_lapis", ItemStack({name = "mcl_dye:blue", count = i})) + local enough_levels = slot and slot.level_requirement <= player_levels + local can_enchant = (slot and enough_lapis and enough_levels) + local ending = (can_enchant and "" or "_off") + local hover_ending = (can_enchant and "_hovered" or "_off") + formspec = formspec + .. "container[3.2," .. y .. "]" + .. (slot and "tooltip[button_" .. i .. ";" .. C("#818181") .. slot.description .. " " .. C("#FFFFFF") .. " . . . ?\n\n" .. (enough_levels and C(enough_lapis and "#818181" or "#FC5454") .. i .. " Lapis Lazuli\n" .. C("#818181") .. i .. " Enchantment Levels" or C("#FC5454") .. "Level Requirement: " .. slot.level_requirement) .. "]" or "") + .. "style[button_" .. i .. ";bgimg=mcl_enchanting_button" .. ending .. ".png;bgimg_hovered=mcl_enchanting_button" .. hover_ending .. ".png;bgimg_pressed=mcl_enchanting_button" .. hover_ending .. ".png]" + .. "button[0,0;7.5,1.3;button_" .. i .. ";]" + .. (slot and "image[0,0;1.3,1.3;mcl_enchanting_number_" .. i .. ending .. ".png]" or "") + .. (slot and "label[7.2,1.1;" .. C(can_enchant and "#80FF20" or "#407F10") .. slot.level_requirement .. "]" or "") + .. (slot and slot.glyphs or "") + .. "container_end[]" + y = y + 1.35 + end + formspec = formspec + .. "image[" .. (any_enchantment and 0.58 or 1.15) .. ",1.2;" .. (any_enchantment and 2 or 0.87) .. ",1.43;mcl_enchanting_book_" .. (any_enchantment and "open" or "closed") .. ".png]" + minetest.show_formspec(name, "mcl_enchanting:table", formspec) +end + +function mcl_enchanting.handle_formspec_fields(player, formname, fields) + if formname == "mcl_enchanting:table" then + local button_pressed + for i = 1, 3 do + if fields["button_" .. i] then + button_pressed = i + end + end + if not button_pressed then return end + local name = player:get_player_name() + local inv = player:get_inventory() + local meta = player:get_meta() + local num_bookshelfes = meta:get_int("mcl_enchanting:num_bookshelves") + local itemstack = inv:get_stack("enchanting_item", 1) + local cost = ItemStack({name = "mcl_dye:blue", count = button_pressed}) + if not inv:contains_item("enchanting_lapis", cost) then + return + end + local slots = mcl_enchanting.get_table_slots(player, itemstack, num_bookshelfes) + local slot = slots[button_pressed] + if not slot then + return + end + local player_level = mcl_experience.get_player_xp_level(player) + if player_level < slot.level_requirement then + return + end + mcl_experience.set_player_xp_level(player, player_level - button_pressed) + inv:remove_item("enchanting_lapis", cost) + mcl_enchanting.set_enchanted_itemstring(itemstack) + mcl_enchanting.set_enchantments(itemstack, slot.enchantments) + inv:set_stack("enchanting_item", 1, itemstack) + minetest.sound_play("mcl_enchanting_enchant", {to_player = name, gain = 5.0}) + mcl_enchanting.reset_table_slots(player) + mcl_enchanting.reload_inventory(player) + mcl_enchanting.show_enchanting_formspec(player) + end +end + +function mcl_enchanting.initialize_player(player) + local player_inv = player:get_inventory() + player_inv:set_size("enchanting_lapis", 1) + player_inv:set_size("enchanting_item", 1) + local name = player:get_player_name() + local detached_inv = minetest.create_detached_inventory(name .. "_enchanting", { + allow_put = function(inv, listname, index, stack, player) + if player:get_player_name() ~= name then + return 0 + end + if stack:get_name() == "mcl_dye:blue" and index ~= 2 then + return math.min(inv:get_stack(listname, 3):get_free_space(), stack:get_count()) + elseif index ~= 3 and inv:get_stack(listname, 2):get_count() == 0 then + return 1 + else + return 0 + end + end, + allow_take = function(inv, listname, index, stack, player) + if player:get_player_name() ~= name or index == 1 then + return 0 + end + return stack:get_count() + end, + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return 0 + end, + on_put = function(inv, listname, index, stack, player) + local result_list + if index == 1 then + if stack:get_name() == "mcl_dye:blue" then + result_list = "lapis" + stack:add_item(inv:get_stack(listname, 3)) + inv:set_stack(listname, 1, nil) + inv:set_stack(listname, 3, stack) + else + result_list = "item" + inv:set_stack(listname, 1, nil) + inv:set_stack(listname, 2, stack) + end + elseif index == 2 then + result_list = "item" + elseif index == 3 then + result_list = "lapis" + stack = inv:get_stack(listname, 3) + end + player:get_inventory():set_stack("enchanting_" .. result_list, 1, stack) + mcl_enchanting.show_enchanting_formspec(player) + end, + on_take = function(inv, listname, index, stack, player) + local result_list + if index == 2 then + result_list = "item" + elseif index == 3 then + result_list = "lapis" + end + player:get_inventory():set_stack("enchanting_" .. result_list, 1, nil) + mcl_enchanting.show_enchanting_formspec(player) + end + }, name) + detached_inv:set_size("enchanting", 3) + mcl_enchanting.reload_inventory(player) +end + +function mcl_enchanting.reload_inventory(player) + local player_inv = player:get_inventory() + local detached_inv = minetest.get_inventory({type = "detached", name = player:get_player_name() .. "_enchanting"}) + detached_inv:set_stack("enchanting", 2, player_inv:get_stack("enchanting_item", 1)) + detached_inv:set_stack("enchanting", 3, player_inv:get_stack("enchanting_lapis", 1)) +end + +function mcl_enchanting.schedule_book_animation(self, anim) + self.scheduled_anim = {timer = self.anim_length, anim = anim} +end + +function mcl_enchanting.set_book_animation(self, anim) + local anim_index = mcl_enchanting.book_animations[anim] + local start, stop = mcl_enchanting.book_animation_steps[anim_index], mcl_enchanting.book_animation_steps[anim_index + 1] + self.object:set_animation({x = start, y = stop}, mcl_enchanting.book_animation_speed) + self.scheduled_anim = nil + self.anim_length = (stop - start) / 40 +end + +function mcl_enchanting.check_animation_schedule(self, dtime) + local schedanim = self.scheduled_anim + if schedanim then + schedanim.timer = schedanim.timer - dtime + if schedanim.timer <= 0 then + mcl_enchanting.set_book_animation(self, schedanim.anim) + end + end +end + +function mcl_enchanting.look_at(self, pos2) + local pos1 = self.object:get_pos() + local vec = vector.subtract(pos1, pos2) + local yaw = math.atan(vec.z / vec.x) - math.pi/2 + yaw = yaw + (pos1.x >= pos2.x and math.pi or 0) + self.object:set_yaw(yaw + math.pi) +end + +function mcl_enchanting.check_book(pos) + local obj_pos = vector.add(pos, mcl_enchanting.book_offset) + for _, obj in pairs(minetest.get_objects_inside_radius(obj_pos, 0.1)) do + local luaentity = obj:get_luaentity() + if luaentity and luaentity.name == "mcl_enchanting:book" then + if minetest.get_node(pos).name ~= "mcl_enchanting:table" then + obj:remove() + end + return + end + end + minetest.add_entity(obj_pos, "mcl_enchanting:book") +end + +function mcl_enchanting.get_bookshelves(pos) + local absolute, relative = {}, {} + for i, rp in ipairs(mcl_enchanting.bookshelf_positions) do + local airp = vector.add(pos, mcl_enchanting.air_positions[i]) + local ap = vector.add(pos, rp) + if minetest.get_node(ap).name == "mcl_books:bookshelf" and minetest.get_node(airp).name == "air" then + table.insert(absolute, ap) + table.insert(relative, rp) + end + end + return absolute, relative +end diff --git a/mods/CORE/mcl_enchanting/init.lua b/mods/CORE/mcl_enchanting/init.lua index f0f7a95138..d1f351b629 100644 --- a/mods/CORE/mcl_enchanting/init.lua +++ b/mods/CORE/mcl_enchanting/init.lua @@ -2,21 +2,265 @@ local modpath = minetest.get_modpath("mcl_enchanting") mcl_enchanting = { book_offset = vector.new(0, 0.75, 0), + book_animations = {["close"] = 1, ["opening"] = 2, ["open"] = 3, ["closing"] = 4}, + book_animation_steps = {0, 640, 680, 700, 740}, + book_animation_speed = 40, roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 enchantments = {}, - weighted_enchantments = {}, - accumulated_weight = 0, - debug = false, + overlay = "^[colorize:white:50^[colorize:purple:50", + bookshelf_positions = { + {x = -2, y = 0, z = -2}, {x = -2, y = 1, z = -2}, + {x = -1, y = 0, z = -2}, {x = -1, y = 1, z = -2}, + {x = 0, y = 0, z = -2}, {x = 0, y = 1, z = -2}, + {x = 1, y = 0, z = -2}, {x = 1, y = 1, z = -2}, + {x = 2, y = 0, z = -2}, {x = 2, y = 1, z = -2}, + {x = -2, y = 0, z = 2}, {x = -2, y = 1, z = 2}, + {x = -1, y = 0, z = 2}, {x = -1, y = 1, z = 2}, + {x = 0, y = 0, z = 2}, {x = 0, y = 1, z = 2}, + {x = 1, y = 0, z = 2}, {x = 1, y = 1, z = 2}, + {x = 2, y = 0, z = 2}, {x = 2, y = 1, z = 2}, + -- {x = -2, y = 0, z = -2}, {x = -2, y = 1, z = -2}, + {x = -2, y = 0, z = -1}, {x = -2, y = 1, z = -1}, + {x = -2, y = 0, z = 0}, {x = -2, y = 1, z = 0}, + {x = -2, y = 0, z = 1}, {x = -2, y = 1, z = 1}, + {x = -2, y = 0, z = 2}, {x = -2, y = 1, z = 2}, + {x = 2, y = 0, z = -2}, {x = 2, y = 1, z = -2}, + {x = 2, y = 0, z = -1}, {x = 2, y = 1, z = -1}, + {x = 2, y = 0, z = 0}, {x = 2, y = 1, z = 0}, + {x = 2, y = 0, z = 1}, {x = 2, y = 1, z = 1}, + -- {x = 2, y = 0, z = 2}, {x = 2, y = 1, z = 2}, + }, + air_positions = { + {x = -1, y = 0, z = -1}, {x = -1, y = 1, z = -1}, + {x = -1, y = 0, z = -1}, {x = -1, y = 1, z = -1}, + {x = 0, y = 0, z = -1}, {x = 0, y = 1, z = -1}, + {x = 1, y = 0, z = -1}, {x = 1, y = 1, z = -1}, + {x = 1, y = 0, z = -1}, {x = 1, y = 1, z = -1}, + {x = -1, y = 0, z = 1}, {x = -1, y = 1, z = 1}, + {x = -1, y = 0, z = 1}, {x = -1, y = 1, z = 1}, + {x = 0, y = 0, z = 1}, {x = 0, y = 1, z = 1}, + {x = 1, y = 0, z = 1}, {x = 1, y = 1, z = 1}, + {x = 1, y = 0, z = 1}, {x = 1, y = 1, z = 1}, + -- {x = -1, y = 0, z = -1}, {x = -1, y = 1, z = -1}, + {x = -1, y = 0, z = -1}, {x = -1, y = 1, z = -1}, + {x = -1, y = 0, z = 0}, {x = -1, y = 1, z = 0}, + {x = -1, y = 0, z = 1}, {x = -1, y = 1, z = 1}, + {x = -1, y = 0, z = 1}, {x = -1, y = 1, z = 1}, + {x = 1, y = 0, z = -1}, {x = 1, y = 1, z = -1}, + {x = 1, y = 0, z = -1}, {x = 1, y = 1, z = -1}, + {x = 1, y = 0, z = 0}, {x = 1, y = 1, z = 0}, + {x = 1, y = 0, z = 1}, {x = 1, y = 1, z = 1}, + -- {x = 1, y = 0, z = 1}, {x = 1, y = 1, z = 1}, + }, } dofile(modpath .. "/engine.lua") dofile(modpath .. "/enchantments.lua") -dofile(modpath .. "/command.lua") -dofile(modpath .. "/tt.lua") -dofile(modpath .. "/book.lua") --- dofile(modpath .. "/ui.lua") --- dofile(modpath .. "/fx.lua") --- dofile(modpath .. "/book.lua") --- dofile(modpath .. "/table.lua") + +minetest.register_chatcommand("enchant", { + description = "Enchant an item.", + params = " []", + privs = {give = true}, + func = function(_, param) + local sparam = param:split(" ") + local target_name = sparam[1] + local enchantment = sparam[2] + local level_str = sparam[3] + local level = tonumber(level_str or "1") + if not target_name or not enchantment then + return false, "Usage: /enchant []" + end + local target = minetest.get_player_by_name(target_name) + if not target then + return false, "Player '" .. target_name .. "' cannot be found" + end + local itemstack = target:get_wielded_item() + local can_enchant, errorstring, extra_info = mcl_enchanting.can_enchant(itemstack, enchantment, level) + if not can_enchant then + if errorstring == "enchantment invalid" then + return false, "There is no such enchantment '" .. enchantment .. "'" + elseif errorstring == "item missing" then + return false, "The target doesn't hold an item" + elseif errorstring == "item not supported" then + return false, "The selected enchantment can't be added to the target item" + elseif errorstring == "level invalid" then + return false, "'" .. level_str .. "' is not a valid number" + elseif errorstring == "level too high" then + return false, "The number you have entered (" .. level_str .. ") is too big, it must be at most " .. extra_info + elseif errorstring == "level too small" then + return false, "The number you have entered (" .. level_str .. ") is too small, it must be at least " .. extra_info + elseif errorstring == "incompatible" then + return false, mcl_enchanting.get_enchantment_description(enchantment, level) .. " can't be combined with " .. extra_info + end + else + target:set_wielded_item(mcl_enchanting.enchant(itemstack, enchantment, level)) + return true, "Enchanting succeded" + end + end +}) + +minetest.register_chatcommand("forceenchant", { + description = "Forcefully enchant an item.", + params = " []", + func = function(_, param) + local sparam = param:split(" ") + local target_name = sparam[1] + local enchantment = sparam[2] + local level_str = sparam[3] + local level = tonumber(level_str or "1") + if not target_name or not enchantment then + return false, "Usage: /forceenchant []" + end + local target = minetest.get_player_by_name(target_name) + if not target then + return false, "Player '" .. target_name .. "' cannot be found" + end + local itemstack = target:get_wielded_item() + local can_enchant, errorstring, extra_info = mcl_enchanting.can_enchant(itemstack, enchantment, level) + if errorstring == "enchantment invalid" then + return false, "There is no such enchantment '" .. enchantment .. "'" + elseif errorstring == "item missing" then + return false, "The target doesn't hold an item" + elseif errorstring == "item not supported" and not mcl_enchanting.is_enchantable(itemstack:get_name()) then + return false, "The target item is not enchantable" + elseif errorstring == "level invalid" then + return false, "'" .. level_str .. "' is not a valid number" + else + target:set_wielded_item(mcl_enchanting.enchant(itemstack, enchantment, level)) + return true, "Enchanting succeded" + end + end +}) + +minetest.register_craftitem("mcl_enchanting:book_enchanted", { + description = "Enchanted Book", + inventory_image = "mcl_enchanting_book_enchanted.png" .. mcl_enchanting.overlay, + groups = {enchanted = 1, not_in_creative_inventory = 1, enchantability = 1}, + _mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted", + stack_max = 1, +}) + +minetest.register_entity("mcl_enchanting:book", { + initial_properties = { + visual = "mesh", + mesh = "mcl_enchanting_book.b3d", + visual_size = {x = 12.5, y = 12.5}, + collisionbox = {0, 0, 0}, + physical = false, + textures = {"mcl_enchanting_book_entity.png"}, + }, + player_near = false, + on_activate = function(self) + self.object:set_armor_groups({immortal = 1}) + mcl_enchanting.set_book_animation(self, "close") + mcl_enchanting.check_book(vector.subtract(self.object:get_pos(), mcl_enchanting.book_offset)) + end, + on_step = function(self, dtime) + local old_player_near = self.player_near + local player_near = false + local player + for _, obj in ipairs(minetest.get_objects_inside_radius(vector.subtract(self.object:get_pos(), mcl_enchanting.book_offset), 2.5)) do + if obj:is_player() then + player_near = true + player = obj + end + end + if player_near and not old_player_near then + mcl_enchanting.set_book_animation(self, "opening") + mcl_enchanting.schedule_book_animation(self, "open") + elseif old_player_near and not player_near then + mcl_enchanting.set_book_animation(self, "closing") + mcl_enchanting.schedule_book_animation(self, "close") + end + if player then + mcl_enchanting.look_at(self, player:get_pos()) + end + self.player_near = player_near + mcl_enchanting.check_animation_schedule(self, dtime) + end, +}) + +minetest.register_node("mcl_enchanting:table", { + description = "Enchanting Table", + drawtype = "nodebox", + tiles = {"mcl_enchanting_table_top.png", "mcl_enchanting_table_bottom.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png"}, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0.25, 0.5}, + }, + sounds = mcl_sounds.node_sound_stone_defaults(), + groups = {pickaxey = 2}, + on_rotate = (rawget(_G, "screwdriver") or {}).rotate_simple, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local player_meta = clicker:get_meta() + local table_meta = minetest.get_meta(pos) + local num_bookshelves = table_meta:get_int("mcl_enchanting:num_bookshelves") + local table_name = table_meta:get_string("name") + if table_name == "" then + table_name = "Enchant" + end + player_meta:set_int("mcl_enchanting:num_bookshelves", num_bookshelves) + player_meta:set_string("mcl_enchanting:table_name", table_name) + mcl_enchanting.show_enchanting_formspec(clicker) + end, + on_construct = function(pos) + minetest.add_entity(vector.add(pos, mcl_enchanting.book_offset), "mcl_enchanting:book") + end, + on_destruct = function(pos) + local itemstack = ItemStack("mcl_enchanting:table") + local meta = minetest.get_meta(pos) + local itemmeta = itemstack:get_meta() + itemmeta:set_string("name", meta:get_string("name")) + itemmeta:set_string("description", meta:get_string("description")) + minetest.add_item(pos, itemstack) + end, + after_place_node = function(pos, placer, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + local itemmeta = itemstack:get_meta() + meta:set_string("name", itemmeta:get_string("name")) + meta:set_string("description", itemmeta:get_string("description")) + end, + after_destruct = mcl_enchanting.check_table, + drop = "", + _mcl_blast_resistance = 1200, + _mcl_hardness = 5, +}) + +minetest.register_craft({ + output = "mcl_enchanting:table", + recipe = { + {"", "mcl_books:book", ""}, + {"mcl_core:diamond", "mcl_core:obsidian", "mcl_core:diamond"}, + {"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"} + } +}) + +minetest.register_abm({ + name = "Enchanting table bookshelf particles", + interval = 1, + chance = 1, + nodenames = "mcl_enchanting:table", + action = function(pos) + mcl_enchanting.check_book(pos) + local absolute, relative = mcl_enchanting.get_bookshelves(pos) + for i, ap in ipairs(absolute) do + if math.random(10) == 1 then + local rp = relative[i] + minetest.add_particle({ + pos = ap, + velocity = vector.subtract(vector.new(0, 5, 0), rp), + acceleration = {x = 0, y = -9.81, z = 0}, + expirationtime = 2, + size = 2, + texture = "mcl_enchanting_glyph_" .. math.random(18) .. ".png" + }) + end + end + minetest.get_meta(pos):set_int("mcl_enchanting:num_bookshelves", math.min(15, #absolute)) + end +}) minetest.register_on_mods_loaded(mcl_enchanting.initialize) +minetest.register_on_joinplayer(mcl_enchanting.initialize_player) +minetest.register_on_player_receive_fields(mcl_enchanting.handle_formspec_fields) +table.insert(tt.registered_snippets, 1, mcl_enchanting.enchantments_snippet) diff --git a/mods/CORE/mcl_enchanting/mod.conf b/mods/CORE/mcl_enchanting/mod.conf index fef460ab12..ac4dad644b 100644 --- a/mods/CORE/mcl_enchanting/mod.conf +++ b/mods/CORE/mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting -description = The rewrite of the Enchanting mod for MineClone2 -depends = mcl_formspec, tt, mcl_books, walkover +description = Enchanting for MineClone2 +depends = tt, walkover, mcl_sounds optional_depends = screwdriver author = Fleckenstein diff --git a/mods/CORE/mcl_enchanting/table.lua b/mods/CORE/mcl_enchanting/table.lua deleted file mode 100644 index fde16f8482..0000000000 --- a/mods/CORE/mcl_enchanting/table.lua +++ /dev/null @@ -1,189 +0,0 @@ -local enchanting_table_formspec = "" - .. "size[9.07,8.6;]" - .. "formspec_version[3]" - .. "label[0,0;" .. minetest.formspec_escape(minetest.colorize("#313131", "Enchant")) .. "]" - .. mcl_formspec.get_itemslot_bg(1.1, 2.4, 1, 1) - .. "image[1.1,2.4;1,1;mcl_enchanting_lapis_background.png]" - .. "list[context;lapis;1.1,2.4;1,1;]" - .. mcl_formspec.get_itemslot_bg(0.2, 2.4, 1, 1) - .. "list[context;tool;0.2,2.4;1,1;]" - .. "label[0,4;" .. minetest.formspec_escape(minetest.colorize("#313131", "Inventory")) .. "]" - .. mcl_formspec.get_itemslot_bg(0,4.5,9,3) - .. mcl_formspec.get_itemslot_bg(0,7.74,9,1) - .. "list[current_player;main;0,4.5;9,3;9]" - .. "listring[]" - .. "list[current_player;main;0,7.74;9,1;]" - .. "real_coordinates[true]" - .. "image[3.15,0.6;7.6,4.1;mcl_enchanting_button_background.png]" - -local bookshelf_positions = {{x = 1}, {x = -1}, {z = 1}, {z = -1}} - -for _, p in pairs(bookshelf_positions) do - for _, d in pairs({"x", "y", "z"}) do - p[d] = p[d] or 0 - end -end - -minetest.register_abm({ - name = "Enchanting table bookshelf particles", - interval = 0.1, - chance = 1, - nodenames = "mcl_books:bookshelf", - action = function(pos) - for _, relative_pos in pairs(bookshelf_positions) do - if minetest.get_node(vector.add(pos, vector.multiply(relative_pos, 2))).name == "mcl_enchanting:table" and minetest.get_node(vector.add(pos, relative_pos, 2)).name == "air" then - minetest.add_particle({ - pos = pos, - velocity = vector.subtract(relative_pos, vector.new(0, -2, 0)), - acceleration = {x = 0, y = -2, z = 0}, - expirationtime = 2, - size = 2, - texture = "mcl_enchanting_glyph_" .. math.random(18) .. ".png" - }) - end - end - end -}) - - -function mcl_enchanting.update_formspec(pos) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - local full_tool_name = inv:get_stack("tool", 1):get_name() - local shortened_tool_name = mcl_enchanting.all_tools[full_tool_name] - local supported_enchantments = (shortened_tool_name and mcl_enchanting.tools[shortened_tool_name].enchantments or {}) - local sup_ench = false - local formspec = enchanting_table_formspec - local e_list = minetest.deserialize(meta:get_string("enchantments")) - local y = 0.65 - for i, e in pairs(e_list) do - local enchantment_supported = table.indexof(supported_enchantments, e.enchantment) ~= -1 - sup_ench = sup_ench or enchantment_supported - local enough_lapis = inv:contains_item("lapis", ItemStack(mcl_enchanting.lapis_itemstring .. " " .. e.cost)) - local ending = (enough_lapis and enchantment_supported and "" or "_off") - local hover_ending = (enough_lapis and enchantment_supported and "_hovered" or "_off") - formspec = formspec - .. "container[3.2," .. y .. "]" - .. (enchantment_supported and "tooltip[button_" .. i .. ";" .. C("#818181") .. mcl_enchanting.get_enchantment_description(e.enchantment, e.level) .. " " .. C("#FFFFFF") .. " . . . ?\n\n" .. C(enough_lapis and "#818181" or "#FC5454") .. e.cost .. " Lapis Lazuli" .. "]" or "") - .. "style[button_" .. i .. ";bgimg=mcl_enchanting_button" .. ending .. ".png;bgimg_hovered=mcl_enchanting_button" .. hover_ending .. ".png;bgimg_pressed=mcl_enchanting_button" .. hover_ending .. ".png]" - .. "button[0,0;7.5,1.3;button_" .. i .. ";]" - .. (enchantment_supported and "image[0,0;1.3,1.3;mcl_enchanting_number_" .. i .. ending .. ".png]" or "") - .. (enchantment_supported and e.glyphs or "") - .. "container_end[]" - y = y + 1.35 - end - formspec = formspec - .. "image[" .. (sup_ench and 0.58 or 1.15) .. ",1.2;" .. (sup_ench and 2 or 0.87) .. ",1.43;mcl_enchanting_book_" .. (sup_ench and "open" or "closed") .. ".png]" - meta:set_string("formspec", formspec) -end - -function mcl_enchanting.progress_formspec_input(pos, _, fields, player) - if fields.quit then - return - end - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - local e_list = minetest.deserialize(meta:get_string("enchantments")) - local button_pressed - for i = 1, 3 do - if fields["button_" .. i] then - button_pressed = i - end - end - if not button_pressed then return end - local e = e_list[button_pressed] - local lapis_cost = ItemStack(mcl_enchanting.lapis_itemstring .. " " .. e.cost) - if not inv:contains_item("lapis", lapis_cost) then return end - local tool_stack = inv:get_stack("tool", 1) - local full_tool_name = tool_stack:get_name() - local shortened_tool_name = mcl_enchanting.all_tools[full_tool_name] - if not shortened_tool_name then return end - if table.indexof(mcl_enchanting.tools[shortened_tool_name].enchantments, e.enchantment) == -1 then return end - local wear = tool_stack:get_wear() - inv:remove_item("lapis", lapis_cost) - local enchanted_tool_stack = ItemStack(full_tool_name .. "_enchanted_" .. e.enchantment .. "_" .. e.level) - enchanted_tool_stack:add_wear(tool_stack:get_wear()) - inv:set_stack("tool", 1, enchanted_tool_stack) - minetest.sound_play("mcl_enchanting_enchant", {to_player = player:get_player_name(), gain = 5.0}) - mcl_enchanting.add_enchantments(pos) -end - - -function mcl_enchanting.drop_inventory(pos) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - for _, listname in ipairs({"tool", "lapis"}) do - local stack = inv:get_stack(listname, 1) - if not stack:is_empty() then - minetest.add_item(vector.add(pos, {x = math.random(0, 10) / 10 - 0.5, y = 0, z = math.random(0, 10) / 10 - 0.5}), stack) - end - end -end - -function mcl_enchanting.init_table(pos) - local inv = minetest.get_meta(pos):get_inventory() - inv:set_size("tool", 1) - inv:set_size("lapis", 1) - mcl_enchanting.add_enchantments(pos) - minetest.add_entity(vector.add(pos, mcl_enchanting.book_offset), "mcl_enchanting:book") -end - -function mcl_enchanting.add_enchantments_to_table(pos) - local meta = minetest.get_meta(pos) - local e_list = {} - for i = 1, 3 do - local e = {} - e.cost = math.random(mcl_enchanting.max_cost) - e.enchantment = mcl_enchanting.enchantment_name_list[math.random(#mcl_enchanting.enchantment_name_list)] - local max_level = mcl_enchanting.enchantments[e.enchantment].max_level - e.level = max_level + 1 - math.ceil(math.pow(math.random(math.pow(max_level, mcl_enchanting.level_rarity_grade)), 1 / mcl_enchanting.level_rarity_grade)) - e.glyphs = "" - local x = 1.3 - for i = 1, 9 do - e.glyphs = e.glyphs .. "image[".. x .. ",0.1;0.5,0.5;mcl_enchanting_glyph_" .. math.random(18) .. ".png^[colorize:#675D49:255]" - x = x + 0.6 - end - e_list[i] = e - end - meta:set_string("enchantments", minetest.serialize(e_list)) - mcl_enchanting.update_formspec(pos) -end - -minetest.register_node("mcl_enchanting:table", { - description = "Enchanting Table", - drawtype = "nodebox", - tiles = {"mcl_enchanting_table_top.png", "mcl_enchanting_table_bottom.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png", "mcl_enchanting_table_side.png"}, - node_box = { - type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, 0.25, 0.5}, - }, - sounds = mcl_sounds.node_sound_stone_defaults(), - groups = {pickaxey = 2}, - _mcl_blast_resistance = 1200, - _mcl_hardness = 5, - on_rotate = (screwdriver or {}).rotate_simple, - on_construct = mcl_enchanting.init_table, - on_destruct = mcl_enchanting.drop_inventory, - after_destruct = mcl_enchanting.check_book, - on_receive_fields = mcl_enchanting.progress_formspec_input, - on_metadata_inventory_put = mcl_enchanting.update_formspec, - on_metadata_inventory_take = mcl_enchanting.update_formspec, - allow_metadata_inventory_put = function(_, listname, _, stack) - if listname == "lapis" then - return (stack:get_name() == mcl_enchanting.lapis_itemstring) and stack:get_count() or 0 - end - return 1 - end, - allow_metadata_inventory_move = function() - return 0 - end, -}) - -minetest.register_craft({ - output = "mcl_enchanting:table", - recipe = { - {"", "mcl_books:book", ""}, - {"mcl_core:diamond", "mcl_core:obsidian", "mcl_core:diamond"}, - {"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"} - } -}) diff --git a/mods/CORE/mcl_enchanting/table_book.lua b/mods/CORE/mcl_enchanting/table_book.lua deleted file mode 100644 index 132fb880b4..0000000000 --- a/mods/CORE/mcl_enchanting/table_book.lua +++ /dev/null @@ -1,87 +0,0 @@ -local book_animations = {["close"] = 1, ["opening"] = 2, ["open"] = 3, ["closing"] = 4} -local book_animation_steps = {0, 640, 680, 700, 740} -local book_animation_speed = 40 - -function mcl_enchanting.schedule_book_animation(self, anim) - self.scheduled_anim = {timer = self.anim_length, anim = anim} -end - -function mcl_enchanting.set_book_animation(self, anim) - local anim_index = book_animations[anim] - local start, stop = book_animation_steps[anim_index], book_animation_steps[anim_index + 1] - self.object:set_animation({x = start, y = stop}, book_animation_speed) - self.scheduled_anim = nil - self.anim_length = (stop - start) / 40 -end - -function mcl_enchanting.check_animation_schedule(self, dtime) - local schedanim = self.scheduled_anim - if schedanim then - schedanim.timer = schedanim.timer - dtime - if schedanim.timer <= 0 then - mcl_enchanting.set_book_animation(self, schedanim.anim)local pos1=self.object:get_pos() - end - end -end - -function mcl_enchanting.look_at(self, pos2) - local pos1 = self.object:get_pos() - local vec = vector.subtract(pos1, pos2) - local yaw = math.atan(vec.z / vec.x) - math.pi/2 - yaw = yaw + (pos1.x >= pos2.x and math.pi or 0) - self.object:set_yaw(yaw + math.pi) -end - -function mcl_enchanting.check_book(pos) - local obj_pos = vector.add(pos, mcl_enchanting.book_offset) - for _, obj in pairs(minetest.get_objects_inside_radius(obj_pos, 0.1)) do - local luaentity = obj:get_luaentity() - if luaentity and luaentity.name == "mcl_enchanting:book" then - if minetest.get_node(pos).name ~= "mcl_enchanting:table" then - obj:remove() - end - return - end - end - minetest.add_entity(obj_pos, "mcl_enchanting:book") -end - -minetest.register_entity("mcl_enchanting:book", { - initial_properties = { - visual = "mesh", - mesh = "mcl_enchanting_book.b3d", - visual_size = {x = 12.5, y = 12.5}, - collisionbox = {0, 0, 0}, - physical = false, - textures = {"mcl_enchanting_book_entity.png"}, - }, - player_near = false, - on_activate = function(self) - self.object:set_armor_groups({immortal = 1}) - mcl_enchanting.set_book_animation(self, "close") - mcl_enchanting.check_book(vector.subtract(self.object:get_pos(), mcl_enchanting.book_offset)) - end, - on_step = function(self, dtime) - local old_player_near = self.player_near - local player_near = false - local player - for _, obj in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 2.5)) do - if obj:is_player() then - player_near = true - player = obj - end - end - if player_near and not old_player_near then - mcl_enchanting.set_book_animation(self, "opening") - mcl_enchanting.schedule_book_animation(self, "open") - elseif old_player_near and not player_near then - mcl_enchanting.set_book_animation(self, "closing") - mcl_enchanting.schedule_book_animation(self, "close") - end - if player then - mcl_enchanting.look_at(self, player:get_pos()) - end - self.player_near = player_near - mcl_enchanting.check_animation_schedule(self, dtime) - end, -}) diff --git a/mods/CORE/mcl_enchanting/tt.lua b/mods/CORE/mcl_enchanting/tt.lua deleted file mode 100644 index e6529b0586..0000000000 --- a/mods/CORE/mcl_enchanting/tt.lua +++ /dev/null @@ -1,18 +0,0 @@ -function mcl_enchanting.enchantments_snippet(_, _, itemstack) - if not itemstack then - return - end - local enchantments = mcl_enchanting.get_enchantments(itemstack) - local text = "" - for enchantment, level in pairs(enchantments) do - text = text .. mcl_enchanting.get_colorized_enchantment_description(enchantment, level) .. "\n" - end - if text ~= "" then - if not itemstack:get_definition()._tt_original_description then - text = text:sub(1, text:len() - 1) - end - return text, false - end -end - -table.insert(tt.registered_snippets, 1, mcl_enchanting.enchantments_snippet) diff --git a/mods/HELP/tt/init.lua b/mods/HELP/tt/init.lua index aa42290bb3..f23778b6c4 100644 --- a/mods/HELP/tt/init.lua +++ b/mods/HELP/tt/init.lua @@ -14,22 +14,6 @@ dofile(minetest.get_modpath(minetest.get_current_modname()).."/snippets.lua") -- Apply item description updates -local function equals(t1, t2) - for k, v in pairs(t1) do - local equal - local v2 = rawget(t2, k) - if type(v) == "table" then - equal = equals(v, v2) - else - equal = (v == v2) - end - if not equal then - return false - end - end - return true -end - local function apply_snippets(desc, itemstring, toolcaps, itemstack) local first = true -- Apply snippets @@ -80,10 +64,9 @@ tt.reload_itemstack_description = function(itemstack) if def and def._mcl_generate_description then def._mcl_generate_description(itemstack) elseif should_change(itemstring, def) and meta:get_string("name") == "" then - local toolcaps = itemstack:get_tool_capabilities() - local hand_toolcaps = ItemStack(""):get_tool_capabilities() - if equals(toolcaps, hand_toolcaps) then - toolcaps = nil + local toolcaps + if def.tool_capabilities then + toolcaps = itemstack:get_tool_capabilities() end local orig_desc = def._tt_original_description or def.description local desc = apply_snippets(orig_desc, itemstring, toolcaps or def.tool_capabilities, itemstack) diff --git a/mods/HUD/mcl_inventory/depends.txt b/mods/HUD/mcl_inventory/depends.txt index cf04c75efd..27231e5dff 100644 --- a/mods/HUD/mcl_inventory/depends.txt +++ b/mods/HUD/mcl_inventory/depends.txt @@ -5,3 +5,4 @@ _mcl_autogroup? mcl_armor? mcl_brewing? mcl_potions? +mcl_enchanting diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index c358754f4d..a4bd0e167f 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -8,7 +8,7 @@ local mod_player = minetest.get_modpath("mcl_player") ~= nil local mod_craftguide = minetest.get_modpath("mcl_craftguide") ~= nil -- Returns a single itemstack in the given inventory to the main inventory, or drop it when there's no space left -local function return_item(itemstack, dropper, pos, inv) +function return_item(itemstack, dropper, pos, inv) if dropper:is_player() then -- Return to main inventory if inv:room_for_item("main", itemstack) then @@ -36,9 +36,11 @@ local function return_item(itemstack, dropper, pos, inv) end -- Return items in the given inventory list (name) to the main inventory, or drop them if there is no space left -local function return_fields(player, name) +function return_fields(player, name) local inv = player:get_inventory() - for i,stack in ipairs(inv:get_list(name)) do + local list = inv:get_list(name) + if not list then return end + for i,stack in ipairs(list) do return_item(stack, player, player:get_pos(), inv) stack:clear() inv:set_stack(name, i, stack) @@ -137,6 +139,9 @@ end minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.quit then return_fields(player,"craft") + return_fields(player,"enchanting_lapis") + return_fields(player,"enchanting_item") + mcl_enchanting.reload_inventory(player) if not minetest.is_creative_enabled(player:get_player_name()) and (formname == "" or formname == "main") then set_inventory(player) end @@ -152,6 +157,8 @@ end -- Drop crafting grid items on leaving minetest.register_on_leaveplayer(function(player) return_fields(player, "craft") + return_fields(player, "enchanting_lapis") + return_fields(player, "enchanting_item") end) minetest.register_on_joinplayer(function(player) @@ -189,6 +196,8 @@ minetest.register_on_joinplayer(function(player) when the server has been shutdown and the server didn't clean up the player inventories. ]] return_fields(player, "craft") + return_fields(player, "enchanting_item") + return_fields(player, "enchanting_lapis") end) if minetest.is_creative_enabled("") then diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index 0c57186b77..69801d010b 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -137,7 +137,7 @@ armor.set_player_armor = function(self, player) local level = def.groups["armor_"..k] if level then local texture = def.texture or item:gsub("%:", "_") - local enchanted_addition = (mcl_enchanting.is_enchanted_def(item) and "^[colorize:white:50^[colorize:purple:50" or "") + local enchanted_addition = (mcl_enchanting.is_enchanted(item) and mcl_enchanting.overlay or "") table.insert(textures, "("..texture..".png"..enchanted_addition..")") preview = "(player.png^[opacity:0^"..texture.."_preview.png"..enchanted_addition..")"..(preview and "^"..preview or "") armor_level = armor_level + level diff --git a/mods/ITEMS/mcl_armor/init.lua b/mods/ITEMS/mcl_armor/init.lua index 1eb03d32bc..c5502cf424 100644 --- a/mods/ITEMS/mcl_armor/init.lua +++ b/mods/ITEMS/mcl_armor/init.lua @@ -13,7 +13,7 @@ minetest.register_tool("mcl_armor:helmet_leather", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_helmet_leather.png", - groups = {armor_head=1, mcl_armor_points=1, mcl_armor_uses=56}, + groups = {armor_head=1, mcl_armor_points=1, mcl_armor_uses=56, enchantability=15}, _repair_material = "mcl_mobitems:leather", sounds = { _mcl_armor_equip = "mcl_armor_equip_leather", @@ -28,7 +28,7 @@ minetest.register_tool("mcl_armor:helmet_iron", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_helmet_iron.png", - groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=166}, + groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=166, enchantability=9 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -44,7 +44,7 @@ minetest.register_tool("mcl_armor:helmet_gold", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_helmet_gold.png", - groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=78}, + groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=78, enchantability=25 }, _repair_material = "mcl_core:gold_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -59,7 +59,7 @@ minetest.register_tool("mcl_armor:helmet_diamond",{ _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_helmet_diamond.png", - groups = {armor_head=1, mcl_armor_points=3, mcl_armor_uses=364, mcl_armor_toughness=2}, + groups = {armor_head=1, mcl_armor_points=3, mcl_armor_uses=364, mcl_armor_toughness=2, enchantability=10 }, _repair_material = "mcl_core:diamond", sounds = { _mcl_armor_equip = "mcl_armor_equip_diamond", @@ -74,7 +74,7 @@ minetest.register_tool("mcl_armor:helmet_chain", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_helmet_chain.png", - groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=166}, + groups = {armor_head=1, mcl_armor_points=2, mcl_armor_uses=166, enchantability=12 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_chainmail", @@ -91,7 +91,7 @@ minetest.register_tool("mcl_armor:chestplate_leather", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_chestplate_leather.png", - groups = {armor_torso=1, mcl_armor_points=3, mcl_armor_uses=81}, + groups = {armor_torso=1, mcl_armor_points=3, mcl_armor_uses=81, enchantability=15 }, _repair_material = "mcl_mobitems:leather", sounds = { _mcl_armor_equip = "mcl_armor_equip_leather", @@ -106,7 +106,7 @@ minetest.register_tool("mcl_armor:chestplate_iron", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_chestplate_iron.png", - groups = {armor_torso=1, mcl_armor_points=6, mcl_armor_uses=241}, + groups = {armor_torso=1, mcl_armor_points=6, mcl_armor_uses=241, enchantability=9 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -121,7 +121,7 @@ minetest.register_tool("mcl_armor:chestplate_gold", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_chestplate_gold.png", - groups = {armor_torso=1, mcl_armor_points=5, mcl_armor_uses=113}, + groups = {armor_torso=1, mcl_armor_points=5, mcl_armor_uses=113, enchantability=25 }, _repair_material = "mcl_core:gold_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -136,7 +136,7 @@ minetest.register_tool("mcl_armor:chestplate_diamond",{ _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_chestplate_diamond.png", - groups = {armor_torso=1, mcl_armor_points=8, mcl_armor_uses=529, mcl_armor_toughness=2}, + groups = {armor_torso=1, mcl_armor_points=8, mcl_armor_uses=529, mcl_armor_toughness=2, enchantability=10 }, _repair_material = "mcl_core:diamond", sounds = { _mcl_armor_equip = "mcl_armor_equip_diamond", @@ -151,7 +151,7 @@ minetest.register_tool("mcl_armor:chestplate_chain", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_chestplate_chain.png", - groups = {armor_torso=1, mcl_armor_points=5, mcl_armor_uses=241}, + groups = {armor_torso=1, mcl_armor_points=5, mcl_armor_uses=241, enchantability=12 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_chainmail", @@ -168,7 +168,7 @@ minetest.register_tool("mcl_armor:leggings_leather", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_leggings_leather.png", - groups = {armor_legs=1, mcl_armor_points=2, mcl_armor_uses=76}, + groups = {armor_legs=1, mcl_armor_points=2, mcl_armor_uses=76, enchantability=15 }, _repair_material = "mcl_mobitems:leather", sounds = { _mcl_armor_equip = "mcl_armor_equip_leather", @@ -183,7 +183,7 @@ minetest.register_tool("mcl_armor:leggings_iron", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_leggings_iron.png", - groups = {armor_legs=1, mcl_armor_points=5, mcl_armor_uses=226}, + groups = {armor_legs=1, mcl_armor_points=5, mcl_armor_uses=226, enchantability=9 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -198,7 +198,7 @@ minetest.register_tool("mcl_armor:leggings_gold", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_leggings_gold.png", - groups = {armor_legs=1, mcl_armor_points=3, mcl_armor_uses=106}, + groups = {armor_legs=1, mcl_armor_points=3, mcl_armor_uses=106, enchantability=25 }, _repair_material = "mcl_core:gold_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -213,7 +213,7 @@ minetest.register_tool("mcl_armor:leggings_diamond",{ _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_leggings_diamond.png", - groups = {armor_legs=1, mcl_armor_points=6, mcl_armor_uses=496, mcl_armor_toughness=2}, + groups = {armor_legs=1, mcl_armor_points=6, mcl_armor_uses=496, mcl_armor_toughness=2, enchantability=10 }, _repair_material = "mcl_core:diamond", sounds = { _mcl_armor_equip = "mcl_armor_equip_diamond", @@ -228,7 +228,7 @@ minetest.register_tool("mcl_armor:leggings_chain", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_leggings_chain.png", - groups = {armor_legs=1, mcl_armor_points=4, mcl_armor_uses=226}, + groups = {armor_legs=1, mcl_armor_points=4, mcl_armor_uses=226, enchantability=12 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_chainmail", @@ -244,7 +244,7 @@ minetest.register_tool("mcl_armor:boots_leather", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_boots_leather.png", - groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=66}, + groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=66, enchantability=15 }, _repair_material = "mcl_mobitems:leather", sounds = { _mcl_armor_equip = "mcl_armor_equip_leather", @@ -259,7 +259,7 @@ minetest.register_tool("mcl_armor:boots_iron", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_boots_iron.png", - groups = {armor_feet=1, mcl_armor_points=2, mcl_armor_uses=196}, + groups = {armor_feet=1, mcl_armor_points=2, mcl_armor_uses=196, enchantability=9 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -274,7 +274,7 @@ minetest.register_tool("mcl_armor:boots_gold", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_boots_gold.png", - groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=92}, + groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=92, enchantability=25 }, _repair_material = "mcl_core:gold_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_iron", @@ -289,7 +289,7 @@ minetest.register_tool("mcl_armor:boots_diamond",{ _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_boots_diamond.png", - groups = {armor_feet=1, mcl_armor_points=3, mcl_armor_uses=430, mcl_armor_toughness=2}, + groups = {armor_feet=1, mcl_armor_points=3, mcl_armor_uses=430, mcl_armor_toughness=2, enchantability=10 }, _repair_material = "mcl_core:diamond", sounds = { _mcl_armor_equip = "mcl_armor_equip_diamond", @@ -304,7 +304,7 @@ minetest.register_tool("mcl_armor:boots_chain", { _doc_items_longdesc = longdesc, _doc_items_usagehelp = usage, inventory_image = "mcl_armor_inv_boots_chain.png", - groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=196}, + groups = {armor_feet=1, mcl_armor_points=1, mcl_armor_uses=196, enchantability=12 }, _repair_material = "mcl_core:iron_ingot", sounds = { _mcl_armor_equip = "mcl_armor_equip_chainmail", diff --git a/mods/ITEMS/mcl_books/init.lua b/mods/ITEMS/mcl_books/init.lua index 0be575939b..45208c4132 100644 --- a/mods/ITEMS/mcl_books/init.lua +++ b/mods/ITEMS/mcl_books/init.lua @@ -15,7 +15,8 @@ minetest.register_craftitem("mcl_books:book", { _doc_items_longdesc = S("Books are used to make bookshelves and book and quills."), inventory_image = "default_book.png", stack_max = 64, - groups = { book=1, craftitem = 1 }, + groups = { book=1, craftitem = 1, enchantability = 1 }, + _mcl_enchanting_enchanted_tool = "mcl_enchanting:book_enchanted", }) if minetest.get_modpath("mcl_core") and minetest.get_modpath("mcl_mobitems") then diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index fa2c2c5304..6e41007cdb 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -133,7 +133,7 @@ S("The speed and damage of the arrow increases the longer you charge. The regula range = 1, -- Trick to disable digging as well on_use = function() end, - groups = {weapon=1,weapon_ranged=1,bow=1}, + groups = {weapon=1,weapon_ranged=1,bow=1,enchantability=1}, }) -- Iterates through player inventory and resets all the bows in "charging" state back to their original stage @@ -173,10 +173,10 @@ for level=0, 2 do wield_scale = { x = 1.8, y = 1.8, z = 1 }, stack_max = 1, range = 0, -- Pointing range to 0 to prevent punching with bow :D - groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1}, + groups = {not_in_creative_inventory=1, not_in_craft_guide=1, bow=1, enchantability=1}, on_drop = function(itemstack, dropper, pos) reset_bow_state(dropper) - if mcl_enchanting.is_enchanted(itemstack) then + if mcl_enchanting.is_enchanted(itemstack:get_name()) then itemstack:set_name("mcl_bows:bow_enchanted") else itemstack:set_name("mcl_bows:bow") @@ -201,7 +201,7 @@ controls.register_on_release(function(player, key, time) wielditem:get_name()=="mcl_bows:bow_0_enchanted" or wielditem:get_name()=="mcl_bows:bow_1_enchanted" or wielditem:get_name()=="mcl_bows:bow_2_enchanted") then local has_shot = false - local enchanted = mcl_enchanting.is_enchanted(wielditem) + local enchanted = mcl_enchanting.is_enchanted(wielditem:get_name()) local speed, damage local p_load = bow_load[player:get_player_name()] local charge @@ -269,7 +269,7 @@ controls.register_on_hold(function(player, key, time) local inv = minetest.get_inventory({type="player", name=name}) local wielditem = player:get_wielded_item() if bow_load[name] == nil and (wielditem:get_name()=="mcl_bows:bow" or wielditem:get_name()=="mcl_bows:bow_enchanted") and (creative or get_arrow(player)) then - local enchanted = mcl_enchanting.is_enchanted(wielditem) + local enchanted = mcl_enchanting.is_enchanted(wielditem:get_name()) if enchanted then wielditem:set_name("mcl_bows:bow_0_enchanted") else diff --git a/mods/ITEMS/mcl_compass/init.lua b/mods/ITEMS/mcl_compass/init.lua index 1b2810de69..66553dfc0b 100644 --- a/mods/ITEMS/mcl_compass/init.lua +++ b/mods/ITEMS/mcl_compass/init.lua @@ -57,7 +57,7 @@ minetest.register_globalstep(function(dtime) if minetest.get_item_group(stack:get_name(), "compass") ~= 0 and minetest.get_item_group(stack:get_name(), "compass")-1 ~= compass_image then local itemname = "mcl_compass:"..compass_image - if mcl_enchanting.is_enchanted(stack) then + if mcl_enchanting.is_enchanted(stack:get_name()) then itemname = itemname .. "_enchanted" end stack:set_name(itemname) @@ -98,7 +98,7 @@ for i,img in ipairs(images) do inventory_image = img, wield_image = img, stack_max = 64, - groups = {not_in_creative_inventory=inv, compass=i, tool=1, disable_repair=1} + groups = {not_in_creative_inventory=inv, compass=i, tool=1, disable_repair=1, enchantability=1 } }) -- Help aliases. Makes sure the lookup tool works correctly diff --git a/mods/ITEMS/mcl_farming/hoes.lua b/mods/ITEMS/mcl_farming/hoes.lua index a7caadb357..0a483f3043 100644 --- a/mods/ITEMS/mcl_farming/hoes.lua +++ b/mods/ITEMS/mcl_farming/hoes.lua @@ -70,7 +70,7 @@ minetest.register_tool("mcl_farming:hoe_wood", { inventory_image = "farming_tool_woodhoe.png", wield_scale = { x = 1.8, y = 1.8, z = 1 }, on_place = hoe_on_place_function(uses.wood), - groups = { tool=1, hoe=1 }, + groups = { tool=1, hoe=1, enchantability=15 }, tool_capabilities = { full_punch_interval = 1, damage_groups = { fleshy = 1, }, @@ -109,7 +109,7 @@ minetest.register_tool("mcl_farming:hoe_stone", { inventory_image = "farming_tool_stonehoe.png", wield_scale = { x = 1.8, y = 1.8, z = 1 }, on_place = hoe_on_place_function(uses.stone), - groups = { tool=1, hoe=1 }, + groups = { tool=1, hoe=1, enchantability=5 }, tool_capabilities = { full_punch_interval = 0.5, damage_groups = { fleshy = 1, }, @@ -143,7 +143,7 @@ minetest.register_tool("mcl_farming:hoe_iron", { inventory_image = "farming_tool_steelhoe.png", wield_scale = { x = 1.8, y = 1.8, z = 1 }, on_place = hoe_on_place_function(uses.iron), - groups = { tool=1, hoe=1 }, + groups = { tool=1, hoe=1, enchantability=14 }, tool_capabilities = { -- 1/3 full_punch_interval = 0.33333333, @@ -185,7 +185,7 @@ minetest.register_tool("mcl_farming:hoe_gold", { inventory_image = "farming_tool_goldhoe.png", wield_scale = { x = 1.8, y = 1.8, z = 1 }, on_place = hoe_on_place_function(uses.gold), - groups = { tool=1, hoe=1 }, + groups = { tool=1, hoe=1, enchantability=22 }, tool_capabilities = { full_punch_interval = 1, damage_groups = { fleshy = 1, }, @@ -228,7 +228,7 @@ minetest.register_tool("mcl_farming:hoe_diamond", { inventory_image = "farming_tool_diamondhoe.png", wield_scale = { x = 1.8, y = 1.8, z = 1 }, on_place = hoe_on_place_function(uses.diamond), - groups = { tool=1, hoe=1 }, + groups = { tool=1, hoe=1, enchantability=10 }, tool_capabilities = { full_punch_interval = 0.25, damage_groups = { fleshy = 1, }, diff --git a/mods/ITEMS/mcl_farming/pumpkin.lua b/mods/ITEMS/mcl_farming/pumpkin.lua index 72b4e54125..990da549d2 100644 --- a/mods/ITEMS/mcl_farming/pumpkin.lua +++ b/mods/ITEMS/mcl_farming/pumpkin.lua @@ -112,6 +112,7 @@ pumpkin_face_base_def._doc_items_longdesc = S("A pumpkin can be worn as a helmet pumpkin_face_base_def._doc_items_usagehelp = nil pumpkin_face_base_def.tiles = {"farming_pumpkin_top.png", "farming_pumpkin_top.png", "farming_pumpkin_side.png", "farming_pumpkin_side.png", "farming_pumpkin_side.png", "farming_pumpkin_face.png"} pumpkin_face_base_def.groups.armor_head=1 +pumpkin_face_base_def.groups.enchantability=1 pumpkin_face_base_def._mcl_armor_mob_range_factor = 0 pumpkin_face_base_def._mcl_armor_mob_range_mob = "mobs_mc:enderman" pumpkin_face_base_def.groups.non_combat_armor=1 diff --git a/mods/ITEMS/mcl_fire/flint_and_steel.lua b/mods/ITEMS/mcl_fire/flint_and_steel.lua index e0bfca288d..7b585f3481 100644 --- a/mods/ITEMS/mcl_fire/flint_and_steel.lua +++ b/mods/ITEMS/mcl_fire/flint_and_steel.lua @@ -9,7 +9,7 @@ minetest.register_tool("mcl_fire:flint_and_steel", { inventory_image = "mcl_fire_flint_and_steel.png", liquids_pointable = false, stack_max = 1, - groups = { tool = 1 }, + groups = { tool = 1, enchantability = 1 }, on_place = function(itemstack, user, pointed_thing) -- Use pointed node's on_rightclick function first, if present local node = minetest.get_node(pointed_thing.under) diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index ac64f07d99..3b7ba37c06 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -322,7 +322,7 @@ minetest.register_tool("mcl_fishing:fishing_rod", { _tt_help = S("Catches fish in water"), _doc_items_longdesc = S("Fishing rods can be used to catch fish."), _doc_items_usagehelp = S("Rightclick to launch the bobber. When it sinks right-click again to reel in an item. Who knows what you're going to catch?"), - groups = { tool=1, fishing_rod=1 }, + groups = { tool=1, fishing_rod=1, enchantability=1 }, inventory_image = "mcl_fishing_fishing_rod.png", wield_image = "mcl_fishing_fishing_rod.png^[transformR270", wield_scale = { x = 1.5, y = 1.5, z = 1 }, diff --git a/mods/ITEMS/mcl_heads/init.lua b/mods/ITEMS/mcl_heads/init.lua index cb83ed1fa2..7502bf1159 100644 --- a/mods/ITEMS/mcl_heads/init.lua +++ b/mods/ITEMS/mcl_heads/init.lua @@ -42,7 +42,7 @@ local function addhead(name, texture, desc, longdesc, rangemob, rangefactor) { -0.25, -0.5, -0.25, 0.25, 0.0, 0.25, }, }, }, - groups = {handy=1, armor_head=1,non_combat_armor=1, head=1, deco_block=1, dig_by_piston=1}, + groups = {handy=1, armor_head=1,non_combat_armor=1, head=1, deco_block=1, dig_by_piston=1, enchantability=1}, -- The head textures are based off the textures of an actual mob. tiles = { -- Note: bottom texture is overlaid over top texture to get rid of possible transparency. diff --git a/mods/ITEMS/mcl_tools/init.lua b/mods/ITEMS/mcl_tools/init.lua index f88ea8fa18..5df422f08d 100644 --- a/mods/ITEMS/mcl_tools/init.lua +++ b/mods/ITEMS/mcl_tools/init.lua @@ -81,7 +81,7 @@ minetest.register_tool("mcl_tools:pick_wood", { _doc_items_hidden = false, inventory_image = "default_tool_woodpick.png", wield_scale = wield_scale, - groups = { tool=1, pickaxe=1, dig_speed_class=2, }, + groups = { tool=1, pickaxe=1, dig_speed_class=2, enchantability=15 }, tool_capabilities = { -- 1/1.2 full_punch_interval = 0.83333333, @@ -100,7 +100,7 @@ minetest.register_tool("mcl_tools:pick_stone", { _doc_items_longdesc = pickaxe_longdesc, inventory_image = "default_tool_stonepick.png", wield_scale = wield_scale, - groups = { tool=1, pickaxe=1, dig_speed_class=3, }, + groups = { tool=1, pickaxe=1, dig_speed_class=3, enchantability=5 }, tool_capabilities = { -- 1/1.2 full_punch_interval = 0.83333333, @@ -119,7 +119,7 @@ minetest.register_tool("mcl_tools:pick_iron", { _doc_items_longdesc = pickaxe_longdesc, inventory_image = "default_tool_steelpick.png", wield_scale = wield_scale, - groups = { tool=1, pickaxe=1, dig_speed_class=4, }, + groups = { tool=1, pickaxe=1, dig_speed_class=4, enchantability=14 }, tool_capabilities = { -- 1/1.2 full_punch_interval = 0.83333333, @@ -138,7 +138,7 @@ minetest.register_tool("mcl_tools:pick_gold", { _doc_items_longdesc = pickaxe_longdesc, inventory_image = "default_tool_goldpick.png", wield_scale = wield_scale, - groups = { tool=1, pickaxe=1, dig_speed_class=6, }, + groups = { tool=1, pickaxe=1, dig_speed_class=6, enchantability=22 }, tool_capabilities = { -- 1/1.2 full_punch_interval = 0.83333333, @@ -157,7 +157,7 @@ minetest.register_tool("mcl_tools:pick_diamond", { _doc_items_longdesc = pickaxe_longdesc, inventory_image = "default_tool_diamondpick.png", wield_scale = wield_scale, - groups = { tool=1, pickaxe=1, dig_speed_class=5, }, + groups = { tool=1, pickaxe=1, dig_speed_class=5, enchantability=10 }, tool_capabilities = { -- 1/1.2 full_punch_interval = 0.83333333, @@ -277,7 +277,7 @@ minetest.register_tool("mcl_tools:shovel_wood", { inventory_image = "default_tool_woodshovel.png", wield_image = "default_tool_woodshovel.png^[transformR90", wield_scale = wield_scale, - groups = { tool=1, shovel=1, dig_speed_class=2, }, + groups = { tool=1, shovel=1, dig_speed_class=2, enchantability=15 }, tool_capabilities = { full_punch_interval = 1, max_drop_level=1, @@ -298,7 +298,7 @@ minetest.register_tool("mcl_tools:shovel_stone", { inventory_image = "default_tool_stoneshovel.png", wield_image = "default_tool_stoneshovel.png^[transformR90", wield_scale = wield_scale, - groups = { tool=1, shovel=1, dig_speed_class=3, }, + groups = { tool=1, shovel=1, dig_speed_class=3, enchantability=5 }, tool_capabilities = { full_punch_interval = 1, max_drop_level=3, @@ -319,7 +319,7 @@ minetest.register_tool("mcl_tools:shovel_iron", { inventory_image = "default_tool_steelshovel.png", wield_image = "default_tool_steelshovel.png^[transformR90", wield_scale = wield_scale, - groups = { tool=1, shovel=1, dig_speed_class=4, }, + groups = { tool=1, shovel=1, dig_speed_class=4, enchantability=14 }, tool_capabilities = { full_punch_interval = 1, max_drop_level=4, @@ -361,7 +361,7 @@ minetest.register_tool("mcl_tools:shovel_diamond", { inventory_image = "default_tool_diamondshovel.png", wield_image = "default_tool_diamondshovel.png^[transformR90", wield_scale = wield_scale, - groups = { tool=1, shovel=1, dig_speed_class=5, }, + groups = { tool=1, shovel=1, dig_speed_class=5, enchantability=10 }, tool_capabilities = { full_punch_interval = 1, max_drop_level=5, @@ -383,7 +383,7 @@ minetest.register_tool("mcl_tools:axe_wood", { _doc_items_hidden = false, inventory_image = "default_tool_woodaxe.png", wield_scale = wield_scale, - groups = { tool=1, axe=1, dig_speed_class=2, }, + groups = { tool=1, axe=1, dig_speed_class=2, enchantability=15 }, tool_capabilities = { full_punch_interval = 1.25, max_drop_level=1, @@ -401,7 +401,7 @@ minetest.register_tool("mcl_tools:axe_stone", { _doc_items_longdesc = axe_longdesc, inventory_image = "default_tool_stoneaxe.png", wield_scale = wield_scale, - groups = { tool=1, axe=1, dig_speed_class=3, }, + groups = { tool=1, axe=1, dig_speed_class=3, enchantability=5 }, tool_capabilities = { full_punch_interval = 1.25, max_drop_level=3, @@ -419,7 +419,7 @@ minetest.register_tool("mcl_tools:axe_iron", { _doc_items_longdesc = axe_longdesc, inventory_image = "default_tool_steelaxe.png", wield_scale = wield_scale, - groups = { tool=1, axe=1, dig_speed_class=4, }, + groups = { tool=1, axe=1, dig_speed_class=4, enchantability=14 }, tool_capabilities = { -- 1/0.9 full_punch_interval = 1.11111111, @@ -438,7 +438,7 @@ minetest.register_tool("mcl_tools:axe_gold", { _doc_items_longdesc = axe_longdesc, inventory_image = "default_tool_goldaxe.png", wield_scale = wield_scale, - groups = { tool=1, axe=1, dig_speed_class=6, }, + groups = { tool=1, axe=1, dig_speed_class=6, enchantability=22 }, tool_capabilities = { full_punch_interval = 1.0, max_drop_level=2, @@ -456,7 +456,7 @@ minetest.register_tool("mcl_tools:axe_diamond", { _doc_items_longdesc = axe_longdesc, inventory_image = "default_tool_diamondaxe.png", wield_scale = wield_scale, - groups = { tool=1, axe=1, dig_speed_class=5, }, + groups = { tool=1, axe=1, dig_speed_class=5, enchantability=10 }, tool_capabilities = { full_punch_interval = 1.0, max_drop_level=5, @@ -477,7 +477,7 @@ minetest.register_tool("mcl_tools:sword_wood", { _doc_items_hidden = false, inventory_image = "default_tool_woodsword.png", wield_scale = wield_scale, - groups = { weapon=1, sword=1, dig_speed_class=2, }, + groups = { weapon=1, sword=1, dig_speed_class=2, enchantability=15 }, tool_capabilities = { full_punch_interval = 0.625, max_drop_level=1, @@ -496,7 +496,7 @@ minetest.register_tool("mcl_tools:sword_stone", { _doc_items_longdesc = sword_longdesc, inventory_image = "default_tool_stonesword.png", wield_scale = wield_scale, - groups = { weapon=1, sword=1, dig_speed_class=3, }, + groups = { weapon=1, sword=1, dig_speed_class=3, enchantability=5 }, tool_capabilities = { full_punch_interval = 0.625, max_drop_level=3, @@ -515,7 +515,7 @@ minetest.register_tool("mcl_tools:sword_iron", { _doc_items_longdesc = sword_longdesc, inventory_image = "default_tool_steelsword.png", wield_scale = wield_scale, - groups = { weapon=1, sword=1, dig_speed_class=4, }, + groups = { weapon=1, sword=1, dig_speed_class=4, enchantability=14 }, tool_capabilities = { full_punch_interval = 0.625, max_drop_level=4, @@ -534,7 +534,7 @@ minetest.register_tool("mcl_tools:sword_gold", { _doc_items_longdesc = sword_longdesc, inventory_image = "default_tool_goldsword.png", wield_scale = wield_scale, - groups = { weapon=1, sword=1, dig_speed_class=6, }, + groups = { weapon=1, sword=1, dig_speed_class=6, enchantability=22 }, tool_capabilities = { full_punch_interval = 0.625, max_drop_level=2, @@ -553,7 +553,7 @@ minetest.register_tool("mcl_tools:sword_diamond", { _doc_items_longdesc = sword_longdesc, inventory_image = "default_tool_diamondsword.png", wield_scale = wield_scale, - groups = { weapon=1, sword=1, dig_speed_class=5, }, + groups = { weapon=1, sword=1, dig_speed_class=5, enchantability=10 }, tool_capabilities = { full_punch_interval = 0.625, max_drop_level=5, @@ -576,7 +576,7 @@ minetest.register_tool("mcl_tools:shears", { inventory_image = "default_tool_shears.png", wield_image = "default_tool_shears.png", stack_max = 1, - groups = { tool=1, shears=1, dig_speed_class=4, }, + groups = { tool=1, shears=1, dig_speed_class=4, enchantability=1 }, tool_capabilities = { full_punch_interval = 0.5, max_drop_level=1, diff --git a/mods/ITEMS/screwdriver/init.lua b/mods/ITEMS/screwdriver/init.lua index ec4f1a2adf..bf264a50c6 100644 --- a/mods/ITEMS/screwdriver/init.lua +++ b/mods/ITEMS/screwdriver/init.lua @@ -176,7 +176,7 @@ minetest.register_tool("screwdriver:screwdriver", { description = S("Screwdriver"), inventory_image = "screwdriver.png", wield_image = "screwdriver.png^[transformFX", - groups = { tool = 1, not_in_creative_inventory = 1 }, + groups = { tool = 1, not_in_creative_inventory = 1, enchantability = 1 }, on_use = function(itemstack, user, pointed_thing) screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200) return itemstack