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 000000000..9cecc1d46 --- /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 000000000..4d1d5af9d --- /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 000000000..132fb880b --- /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 000000000..28b0cadc1 --- /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 000000000..e9fa523f2 --- /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 000000000..04783a679 --- /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 000000000..793ff85f5 --- /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 000000000..8489ff2d4 --- /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 000000000..2ec29e526 --- /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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 Y5>@_n;>MN@eV+agR>oO>TWdl82dXn-ZvX%Q 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 zcmV-x1C;!UP)<{98gxZibW?9;ba!ELWdKlNX>N2bPDNB8 zb~7$DE-^7j^FlWO00QSpL_t(&L+zEZ$`nBmg!eTBW6@MoBgNQ2FcD2vL{QK-5HZn2 zF)o1#FHi32d@!g2FyzP8IVNtvog=#Dt zAm4J%db}wbXWIY?h(aVl>k=Tk82u)Oc+GhNj7Moe-}gJQ3JQw?MBXlIq8boCf-Vl? zuLkf0$iQ7x>3zblD}qT&q@@x|_LKpgRl{}hn;S>6Cnhhj^y2$fi)Xkz=_4iTus52%UOfV*}^JZ5TrN?qXAIGvla!YL7cQ= zBjt;qa$-}Q^5$~Z;BvOG3Ks-btcr{c;KWN&n;M`e5Syr5flZCb<$nz)sFjn#Z4fy%+#anwG7jJV8r=qwQ^W1i%1Plih@2X3kFi_?oUpN6 z1e~z3Tm+o3v0MzCxG`K5oIufGlYNgp_9)PGe*lZF2uPWc9`FDF002ovPDHLkV1jbD BfUf`m 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 000000000..f40c65406 --- /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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 ZXnZAq`WlF`LsD5B&~uwZ@1afr{s-nWo!|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 000000000..fde16f848 --- /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 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 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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 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?H=O_6ICX z!V)sP$!uW^3=ATkE{-7_*OPx7K5(F*;b22!dm|%*pb6to`M90B3=9kmp00i_>zopr E02>}99{>OV 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!lF`v>+b3?Ffa&sx;Tb#TumdKI;Vst09XH=O_6ICX z!lEpz7d`-)An57h7{YNqIf0=`N`Wsifq{V~hvDM6i=TclFfcH9y85}Sb4q9e0HBg1 A%K!iX 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!Xhf2S3VwLU|`_)ba4#fxSpJlAi&^cz{$Yq!{GSi!%I;H1_lOCS3j3^P6H=O_6ICX z!g4yb4<^hp0@PqjX4+DDxqw5Q)%aa%w7#KWV{an^LB{Ts5 D@{%P8 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-AH3#U=Z?jaSY+Oo*a;nz>vhu#>mFVz+A&HQA;_2(k{(yx^Sc>n=8__uo3=F!SE{-7_*OLo={(bvYlo`bS3#z^QZ3Hrl!PC{xWt~$(69CFK BFuec( 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!ia0y~yU|<7b4iNd^%zF;_2(k{(yx^SXzb8=Pfq_1B0=ri(?4K_0sNxoD2#AhZpVm zpLb7amut;S=e-UKmuy+#;;_2(k{(yx^SlYVT<-tD&1_n7#7sn8e>&ZX<|F=K<|NnnU ny||ix@-x$t4luq@WMr^?C(QqA;_2(k{(yx^SXQFE(hOvzo~Mgr2*>r>GaCgN3^)!u9Q=3M z(Dj&r?=F@*D}GonUKCWi$5pjb{X^@F2F`D**_`b}1k6)r{$^lcVDNPHb6Mw<&;$T& CC@x|E 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!V;{R9P6erFfa&tx;Tb#Tu&BANJvH=O_6ICX z!r}%yl*_6Z7#M^+T^vI=t|wnec#v>`!HJcPmw}~(;bhzKQ@%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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!csbtJs}kg3=ATkE{-7_*OLPh0ulrg9wa0ru3%(fUc+!RW$$MJ1_lNOPgg&ebxsLQ E009mpWB>pF 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!V(7dyR)`3Ffa&tx;Tb#Tu)9&2w-qxW@BVyWMH;om?-`!cQ*qA1B0ilpUXO@geCxt C4IxSZ 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!g8WYPbEtj7#IXRT^vI=t|w1O2uKWIILyMpGK1kSbFIEM0|Nttr>mdKI;Vst09Y9z AbpQYW 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!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-ADs*lDyqr7&=&GJs21mI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_6ICX z!eVNnZ$4!)Ffa&ux;Tb#Tu&BAU~uGSV`JlHVCG?1sB`ed4F(1V22WQ%mvv4FO#pY= BA#(r# literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_glyph_9.png new file mode 100644 index 0000000000000000000000000000000000000000..4b3e366d97b6dfae280e7fd05f2a269855300305 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0y~yU|<7bMrH;EhFeUv+#pVXPlzi61H;9O&-)WoeHj=S z7)yfuf*Bm1-AH3#VBqs~aSY+Op8O%9py3b~1LqvZgI=FL&1Ya>VDNPHb6Mw<&;$TB CjT$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!ia0y~yU=RRd4rT@h1`S>QUE-){-YwglFKhSK z?{!rTKj+B|F5AT8u^u+_%w(VJ;eOYm?%5)IFw8~ufo9VA;^*tmwm*rD=HK}__4dmL%eR|VOm2)wvN*tRn zJWz?8CCogTD~riEK6#;OUfknQqn4au z(2OU~gyR^TlAni!*M%3Bzdm-qQB>f{)U?Aa-S&Q+&M&uZODPolv6BDX{OIPO+e{vU z$HG{gnV9S*X}Essv=mhAXR~9SxS7Syp&?}FMCk1 zZy$45!4SsL^>uPnBCn_@uV3h5HPf?Ei;f7G9-HyVX0g{Kkx9#D1Z|oUY`8HY>*A!D zsoFC)Kj645Q(Sbj=-kqT3rsJY?y<@(m8m%)$Y=X#BA@lAK&@&1yrJ1^Rz{uOYLa(p z!{6wflcw1_r~1iyuWVmu`|Zlw=W%S;ZcPwu>$AADVWRuapxYt$gBG(F%@1Den=8b9 zTL12fgL5vqHa#m`G+DBvP(i?dGJ}|jf7(3_mU&OqjORv^2;c})|cw-%eeyvmNqKkAd!dAd@g zOyzg#@%_T`tc5Tt+w2suhqUb<_q(W z1>e}KHn01__QyYKWNSVDIcL2OsTX{DdgWh^zr9XP_BuEJ@*D5kVVNY~dyRpCnIXU@ z#Fc@8!N%I!*U>7{&pj?OJUbyWH!rKaq_|I2X`Yqt?84|h!LECzl=Ss<%$qa)!s_1p z2Nu1)w3%TPjDleSOnGl7FfcGMmIV0)GdMiEkp|)21sKVcW(GE;Bbd9#>-fkD>O#W6(Ua&p1~!v`*pix+bn6a=U+ fq!kqu1f1N-pdG~!7v$H>0}3-wS3j3^P6QU^X_+~x z3MG{VsS2qTnQ06R6}R3_51jN^gQxAjP;}{@)7f4;XM} z?TjnF|4+2+?~8=Y+x_X)8;W255UbM2cbutgEOq<*_6Z+Sm;aSJ^)CGK@~3a2-M8G$ zj9vf!q(INI3&MPNT2&ssyzIDc_aieKPop^;+qAUy>3phvbLegj=e@gCov~|f>z!Z7 zVVK|kM`&@b`d_;;Z72OJa?19#2}S%LRm+l10vmx-+ES87 z3$$--^KvZI`N*=7Z5I0}$rS?1x0;1aSDCC>|7(eGu+N>F0mk!nPCrYE`7xza;jB}$ zZ`T$EF&*_4oM&pzw_e+k+FL#;`H9>`tZmgMbY zjw_hLyt@8ud~#ypszsVBvciI|FEaJ^i!44j?YU&Aug=UUGvn<^SC39!oo-&PAIB|z zP;i;5IQLO+&8sMY}X4bj%X}bKC z1hZ<73pRcwM$CqOERW1M6&6++b^B?4R571<^w15FQw!Xz9-7QL;$TpkBwMoix59Vt zJjcuXA04w-7FXM4@2KZfGW$+=-u-~=(%Qu*m`uta_GC_JZ06;=t6e?!zUThf_WxQR z#HzUWw%&8fU%353^o#$>CLbO%)|(!-zfd~SK6S+<69xumh5(-sR|WFdh=gk6BkiZ5p$pD?&Oad8ZhxSX6I!Fqy$fl+{g@y+zdRiH5PboFyt=akR{0M3P& AWdHyG 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!ia0y~yU=RRd4rT@h1`S>QUdK1=90W1ie@y1!IN8s${IoP2V?_Z+(~a{PeWbrvohH zw>$0WzBp~NUEkfV3$j~hKNr`3mHMjm&9RKkp1O7GS~@&jw~LoXpUQIl=%A6x+pW(vFikkEtCEKWZyfw=AaZ*o>9lPcDmUpXpA2l_)j& zPK^_{L&lpKue#oAy^Fl}BRzqYrL@&DvGJ(<@=oWMn%h$f#a^uBKQ}+Rc}*@ehhUAi znllrV-6RdyPsegxI+B^@H_hD4V&~8hvU8$zg7OW{W1Y+Mdkmv?t*PlM+``b}bwtfm zA%sDj#r0o=$BBiD79Cuf6>@n=r1unwMaLv`&l#_p5n-@3Bkkm-sVbT(zJ`%rn#(6y za`zdWHJp7~^LY%{9I+XC60r*cPaSNRd3Zrtu55|2{8FXbtQAqoTW4jhTUt1|?d|;} zSN_rZ&ObA`CQ&(B-o zm{Vr#_}Sv(NuDDX0v)$i8d{#6JfqIlsJ`>$ne=1J0@zG1aW228!q&7<`1OMByTUum zcUtn+AML%b^jvM%dxhs}yL{i7ZfCy|6}fz#jzh8dxfxZG7B?1L2!0sytp3vS?C+t> z_HA`MwX+u{K1u8DpS3jnzH?-L6o-h2{h$BOBOiM!Jz2M@G!;!d$M2HRsD>xJ$tYy zyIVEQ>O;TKwM%>UFZ>tu_r!#$kA3E?tIXJW%#co5XTlq=f zGxn~(`hU)YcikuSl-@ae+>5&yx?6h^e|!C&vilDIj$g3PJHcj`v+1`y&&?+F>j`hR zF)%PQ1o(uwGB7aMSX=u#T1EP~$3=!`Cq(AvWtEo{_o*t)v(lYi7`-Rhb;hbtqG!KNv0-3f(Dih243W5;oUlOi!LtVs zTm%_DSzHiZ$X&3Avp`AmAmbEgL!l)znwy)Oz4+J|g6=VF&OcV_4hln0S3j3^P6QU^X_+~x z3MG{VsS2qTnQ06R6}R3_51jN^gQxAj zaq8==^Kau5ulMs!+xE9&8+&&2@$DC!E4fd}%)EG`ZeMGQzV+Mh0cHDV+3BX=w_5bp z?{!tJe_KLH>%4*o!5&Ik^ZAPIif&)1cCtX}#;O$-S<~c?=-oLx{lVR}({CKz_4boY zm%!(;6Z(d?$}YW6-mdh;>8;_X%j|031>%#;-M$;1%PuudbuhQRA-$ zy`Fj3J}?PLSufl5Xt&poDdr!ABN!cH6U%fq9D6*;Vv1dnw^(}P{9_`Iwwj*!CFam! zur0|*MM1#0GiX`H8MhV-s~;g}=BR#TWLk1+?jZ*0gMJ2O^O6_$U;LE%^mNZ+R)r9w zZN1F_tZSx-{7gPM(K*yLIN<7w`E<5jaFjJD>a5cT&W-lY=#yrCzpN&JR#Nl=pT50|NtNNswPKgTu2MX&_FLx4R2N2dk_H0|NtRfk$L90|Vba5N3SkwDAA~ z0|R@Br>`sf6LtYEE751SkN*ePCoYa55|@(`Bv?-{Ffa-*Fus}oxC#_Tp00i_>zopr E0DgR?kN^Mx literal 0 HcmV?d00001 diff --git a/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png b/mods/CORE/mcl_enchanting/textures/mcl_enchanting_number_3.png new file mode 100644 index 0000000000000000000000000000000000000000..8dd37a8b93c0a5a17d32d25a80e7510087789ceb GIT binary patch literal 1922 zcmeIu>sJzX0LJm3$&?J#DDO9xc}v7gq?nrb07)TXIp!>dq%@-t&MBQ#>NIrXOg)le zYNAMP(uKKyO$XS07FGK^=oc?${FP8%u~#?j8r5y>vSqI^=ujwfU_?ag^A@0?yy1) ztrulLfGRV6ge_xA)cJEh?7j1iq^q^(s#_Rz!wBf0TgUWT=y|jER_J&3-;#;GeRJ#r zdq1n~<)M<@ZcZbdg!T5f$TJCskvpHvwmp{Xx6EWOC8wx=#7R3JEH<8;V`kY^2KtFR z^w0cv=BUzsPn!A=v)WO^TX=gfsC_}|2pc$V@?B49SJ~O%=hU(l^iOb7In*VujgKxW zmcP5&RZJS_iXq8YQq{A+Sq${Go7d&snQfHt?g#%Jwdns>WaRV-K1psTZt`7|K0xdU zwwOFTbkd_0(rb9Da@cE!4J&%=kP5$<*oGVlTM26^_4Ad5xRb>Z`D-fAVH?TBSlRA` zDiN2A8$bn%l%$VIzwr2WpA6bA)T0C3P#vq&7`FQ)gJ^jyw{}gtF5UCw zg+H)L$>=?b4^!X}P57zH0_eE|T8a;+N?{Bw+ZB*$m;nh=VwdghcqLV6&pNuj7r2JF zO+Y{`6ei(YLoE^X8_60-bIZZl3Z~aVI^ULY2mAB}ovs{esCH2wDsL>q^d9wSs)^B| zusxW*40Ll1$HV%Lf*ZcHNf2+kZw7kNak<0U;U9O4mz2n1+ty(!$4el>WPGv|NvpnL zHBoTx`oX(>tPuT#I;;(DlQPGDwBI(X@`o4K*YJYcC%jmJ|6KwK71Bk?AAQ5j)3F;W zZ1`-X`F#Q~=&z_IZQn%7tf+ok5_=7n-ncDJOn^Zm-A2N#x`L$M(m?pbUV-KkXWJyH zjI(Xh^?mjDmh|?vfMQe_$11Ka+Xg#YKS+5=)dkIuOaGM^eY9R<%=N+G&H==nAyoI8 zqbfb^OEP)=ZSM8HUD5V$z8cV7+idq(QoD-4a$eU#H2qhF`(MK@?tBw-^TR}z^Y@p$ z^+(dBb(i}kaKiIN%UfcM?9-t|EoKJWJq|r)Ci_!mwtSueC2FwjQ3pLD^y&1Jn&+8u z7&g7{-b1HTxJglc=foA!rRI>?T;Y^ykEXv}+dW_9&>yLebz~%th~oniBRorlMk%t+ zE3JFfX6@*#B+GSSx^QHCqC2g=w6~5azI&PVDu)%)ul99Xe>JjcX`xH9;78-?;XfBX z^l3)R#eu=AD&8Zh_eyBt$E8Bpk10S^G!d>T*V0AMQL$l#BN+X?`HF_#bQU^X_+~x z3MG{VsS2qTnQ06R6}R3_51jN^gQxAj?rP?PbSxyC0cdQIYgxi53-gKl|wZalJcdr$4y6cKVH@yWW11 z=@R%{c0%9qR@tTZ$=j8_IK4IebeUc4yFh%Bx!Y&MUt4$0GE$m)IPOZa=4#gC%nPSn z)m#b*>^S_vp#89q+DU-m=p9T=ur8w`(mg#c9`~@>ch??D9oRocn8TJao5w)%nHp^2&6(w_i5T*;+Wc z?d|=d%@_7e4YMv?667CS{qEY{>2d5uxhFiF-Q~<`rUd3^&3D9+<(Km9 z57&!UaPMus=aj#2`-SKix?lbaO8xlQuz%J=c@>w5uExeaH4F^Q3;{kNt_%zeHrCd@ zj#iO=?s1Xf*$I)kd0FKp#eJ$u^Q?4d7e?<1cHJ|jq_3xA-kj+dR`=dNu;}%r%?zVp z6buVs%6mJ3fq{XsB*-tA!Qt7BG!Q4r+uensgH_gpfq{Xuz$3Dlfq`!y2s6HN+IWD0 zfq}im)7O>#3A+H7mCSth`e<-{;^G)0aXC3bg7pLg1ET-~FVdQ&MBb@ E00f4mga7~l 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 zcmV+_0oDGAP)N2bPDNB8 zb~7$DE-^4L^m3s9005>*L_t(IPnD7}4#O}AMRS*Q>*%dZmK>oSdjE@*=%Jr)>?o>) zA_IPW3|XG*<1bs{_N%qRM8wUr3GCbU{k&zk`o$vz;h=61z=pk0aD#q!&lTtjDp5>w4|x2v8z3%g6{?1 w2jx{dK#6gEL|90+q^8Rfa5aw!aQmzO07Xoqhl^ym1poj507*qoM6N<$f-6pLg#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 zcmV-B0mS}^P)N2bPDNB8 zb~7$DE-^4L^m3s9006g1L_t(IPwkR13&KDQh4Wu@bF7mnU8IwvEeLK7I*OB<;O4K6 zyo0Z#;Rd0rg~uiDaxclFX8+G#&zpbVj|n12tTWdtx5IYr5kt2tIVX3SS1#D4?;PB( zX9tm2oO$KqZM9hX929{~)A+t^3lI|ra)VeqP9RbbRIK>a9}6f(oSfR~3VKKZ-D!~d zafLW00!*Ph#Wk;r0OO(li@;=syjL_6lbN9EL3TVE#~KJ!J(%+!d;wSfM&2;Rzrp|j N002ovPDHLkV1l66c=-ST 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 zcmV-a0jvIrP)N2bPDNB8 zb~7$DE-^4L^m3s9007WQL_t(IPlb^o4#GeXMSB-;$U0074vEDVNg4zWQpXjL1jAiW zoP`7M$lFX8C~fkxo!S1kvxVZY-^i(L{t+1{=(qJcCx305uWy0JY%(3C6R7CtWeFB0 z+*wo=da?T<}B50T+XiJ0boDU*xdqRjHG}L*Waekyhw_)?VQkVw|1? mp?6@cIqak>3C#d0&^9kpS_4zR`qH=n0000 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 28b0cadc1..e93a3979c 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 e9fa523f2..52cbe53b3 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 04783a679..13e09928b 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 793ff85f5..f12abe097 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 8489ff2d4..4d693f952 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 2ec29e526..237db4118 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 8231c8ed6..0368a4215 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 52cbe53b3..38a5e1767 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 4d693f952..80b171db1 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 237db4118..8dfe4e94f 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 000000000..41ceb6249 --- /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 376f00f2c..a3470b5c1 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 a510553ce..37f34d335 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 a79bf27b5..d1bb6d6b8 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 0368a4215..dc7334f31 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 13e09928b..4aab62f68 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 dc7334f31..21b55c31b 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 4aab62f68..000000000 --- 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 f12abe097..000000000 --- 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 38a5e1767..a64613499 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 000000000..dfe5559cb --- /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 80b171db1..5921d77d3 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 41ceb6249..f9b8e34c1 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 d1bb6d6b8..a2b747ce8 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 98a3e017e..c17e5a0b2 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 ce74a10d9..fbc1c9d03 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 21b55c31b..53776df3b 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 130c4acea..a797e7184 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 2bbf820fd..4c2d1c21f 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 54672a5db..adad4b1e7 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 dfe5559cb..ee007b91d 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 f9b8e34c1..e6529b058 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 a2b747ce8..aa42290bb 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 53261d53c..0389d3050 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 7a23cc50d..1b2810de6 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 adad4b1e7..4e0fa6e62 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 a64613499..907fb63dd 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 c17e5a0b2..89b87aa2d 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 fbc1c9d03..bf912c7a0 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 907fb63dd..158122562 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 132fb880b..7b0ee5080 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 ee007b91d..b5452f96e 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 5921d77d3..1611557ce 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 8dfe4e94f..3680b4fa9 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 000000000..132fb880b --- /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 zcmV-|0e$|7P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0002-Nkl4;g^gmc zu!=U;f}n+@6>GuDD%jZtdqJ?U6Z{WB|7Z0M+;x(T;3IHIGBfAyCL{)jwf1KUi$$!b zkq7GD;HUf@KnjZ>Y6N!NE(!Ub#w$>o^=b~>@0!(TJ39;91y|G}q)XV$kPi|u8MW-9 zUw6C{xd6`aBmg&)Zbd>Q{kF7+RoO`p5UO{kLozQ5(*4+x0E&b&m_Kjk!u7O$JqsG# zI(I~o5(I#2%%E=uVZ((0J}U 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 16fa14c5f..509542353 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 b5452f96e..63316b8d8 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 158122562..349e8882a 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 1611557ce..2181ef978 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 4e0fa6e62..56e6ea522 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 63316b8d8..07d302e3a 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 cf7efb623..efa3caeb5 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 c49c556e0..12e5a198d 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 569dbe686..6e2803502 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 b9aa1b271..5387aa701 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 e57f69dfb..067cf61b1 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 07d302e3a..e48e84572 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 349e8882a..ae04e3ed6 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 2181ef978..2398dc8b4 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 5387aa701..6f95baa72 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 e48e84572..dd505e960 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 833dded52..b7e1ba73a 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 dd505e960..2ceaf3b45 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 ae04e3ed6..f77e3dff9 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 2ceaf3b45..b1ac63561 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 f77e3dff9..40c600dbd 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 ca0f0433f..f80274858 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 0481b5340..8d451f9b0 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 6f95baa72..ee0f95cef 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 cf4daf0ba..0be575939 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 d1966e190..3d5fbbca3 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 978dde648..b8ddabf97 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 87e9a7863..83d2c1065 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 8955ff645..732eb2e43 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 43ff7b0f8..587b8a6e5 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 6f962b27f..12b00db8c 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 aac92839a..f026b6dbe 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 f04a02316..f3de5968e 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 5840d59ce..77d4f8e34 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 b98d65e38..4ecac8c6e 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 b1ac63561..f6a37f482 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 ee0f95cef..d00348b13 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 f6a37f482..b70cb19cf 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 b70cb19cf..f232f11d1 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 efa3caeb5..4942d81a8 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 f232f11d1..01b1bd9a4 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 2398dc8b4..1d4a9f7c3 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 3680b4fa9..fef460ab1 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 1e2749ff5..6bbd505d2 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 01b1bd9a4..c143044a0 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 8d451f9b0..641348132 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 b8ddabf97..f9ac0e01e 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 732eb2e43..3a8aef8d0 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 587b8a6e5..38b4c713c 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 5b630d562..42deede2f 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 f026b6dbe..71221cc5c 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 354fa6139..681abe094 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 77d4f8e34..647e87fe1 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 c143044a0..1da48f795 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 89f3405f3..0f603015e 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 4942d81a8..fa2c2c530 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 1da48f795..7ef5f7fe9 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 6bbe4cbdb..7a259f8c1 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 74d87c6c9..f18e6adfc 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 509542353..aabfa5906 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 7ef5f7fe9..4301c5642 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 40c600dbd..fa809cfac 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 1d4a9f7c3..f0f7a9513 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 3fb0c1ebf..256ad4963 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 fd4926d2f..95cba7aca 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 ca4573445..d4ae7ca33 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 3192a6c01..104ee4f57 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 f2bf2abbc..c9e087db3 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 5c92657af..f4206d2ac 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 66af8f227..6f7e3e5aa 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 6af50efff..e3604f947 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 416be8a3a..94b441bfe 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 577a49afc..3a3364560 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 a3470b5c1..8242f2c19 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 93ef0bf52..bbc3c6ad8 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 b7e1ba73a..ac64f07d9 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 4301c5642..a90088cd4 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 d00348b13..a4b7974d5 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 a4b7974d5..331a18b35 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 a90088cd4..c03cf9988 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 fdf1d6ad1..293fdba83 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 cbba537dd..d281a59ed 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 27998d170..2b39b5937 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 331a18b35..0c57186b7 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 0f603015e..1bc17354c 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 4d1d5af9d..000000000 --- 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 7b0ee5080..000000000 --- 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 e93a3979c..000000000 --- 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 c03cf9988..4ed94a0b3 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 fa809cfac..1202ec70d 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 f0f7a9513..d1f351b62 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 fef460ab1..ac4dad644 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 fde16f848..000000000 --- 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 132fb880b..000000000 --- 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 e6529b058..000000000 --- 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 aa42290bb..f23778b6c 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 cf04c75ef..27231e5df 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 c358754f4..a4bd0e167 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 0c57186b7..69801d010 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 1eb03d32b..c5502cf42 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 0be575939..45208c413 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 fa2c2c530..6e41007cd 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 1b2810de6..66553dfc0 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 a7caadb35..0a483f304 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 72b4e5412..990da549d 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 e0bfca288..7b585f348 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 ac64f07d9..3b7ba37c0 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 cb83ed1fa..7502bf115 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 f88ea8fa1..5df422f08 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 ec4f1a2ad..bf264a50c 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