diff --git a/mods/HUD/awards/LICENSE.txt b/mods/HUD/awards/LICENSE.txt new file mode 100644 index 0000000000..4362b49151 --- /dev/null +++ b/mods/HUD/awards/LICENSE.txt @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/mods/HUD/awards/api.lua b/mods/HUD/awards/api.lua new file mode 100644 index 0000000000..f53ee0d74a --- /dev/null +++ b/mods/HUD/awards/api.lua @@ -0,0 +1,521 @@ +-- AWARDS +-- +-- Copyright (C) 2013-2015 rubenwardy +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- This 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 Lesser General Public License for more details. +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-- + +-- The global award namespace +awards = { + show_mode = "hud" +} +dofile(minetest.get_modpath("awards").."/api_helpers.lua") + +-- Table Save Load Functions +function awards.save() + local file = io.open(minetest.get_worldpath().."/awards.txt", "w") + if file then + file:write(minetest.serialize(awards.players)) + file:close() + end +end + +local S = function(s) return s end +function awards.set_intllib(locale) + S = locale +end + +function awards.init() + awards.players = awards.load() + awards.def = {} + awards.trigger_types = {} + awards.on = {} + awards.on_unlock = {} +end + +function awards.load() + local file = io.open(minetest.get_worldpath().."/awards.txt", "r") + if file then + local table = minetest.deserialize(file:read("*all")) + if type(table) == "table" then + return table + end + end + return {} +end + +function awards.register_trigger(name, func) + awards.trigger_types[name] = func + awards.on[name] = {} + awards['register_on_'..name] = function(func) + table.insert(awards.on[name], func) + end +end + +function awards.run_trigger_callbacks(player, data, trigger, table_func) + for i = 1, #awards.on[trigger] do + local res = nil + local entry = awards.on[trigger][i] + if type(entry) == "function" then + res = entry(player, data) + elseif type(entry) == "table" and entry.award then + res = table_func(entry) + end + + if res then + awards.unlock(player:get_player_name(), res) + end + end +end + +function awards.increment_item_counter(data, field, itemname, count) + local name_split = string.split(itemname, ":") + if #name_split ~= 2 then + return false + end + local mod = name_split[1] + local item = name_split[2] + + if data and field and mod and item then + awards.assertPlayer(data) + awards.tbv(data, field) + awards.tbv(data[field], mod) + awards.tbv(data[field][mod], item, 0) + + data[field][mod][item] = data[field][mod][item] + (count or 1) + return true + else + return false + end +end + +function awards.get_item_count(data, field, itemname) + local name_split = string.split(itemname, ":") + if #name_split ~= 2 then + return false + end + local mod = name_split[1] + local item = name_split[2] + + if data and field and mod and item then + awards.assertPlayer(data) + awards.tbv(data, field) + awards.tbv(data[field], mod) + awards.tbv(data[field][mod], item, 0) + return data[field][mod][item] + end +end + +function awards.get_total_item_count(data, field) + local i = 0 + if data and field then + awards.assertPlayer(data) + awards.tbv(data, field) + for mod,_ in pairs(data[field]) do + awards.tbv(data[field], mod) + for item,_ in pairs(data[field][mod]) do + awards.tbv(data[field][mod], item, 0) + i = i + data[field][mod][item] + end + end + end + return i +end + +function awards.register_on_unlock(func) + table.insert(awards.on_unlock, func) +end + +-- API Functions +function awards._additional_triggers(name, def) + -- Depreciated! +end + +function awards.register_achievement(name, def) + def.name = name + + -- Add Triggers + if def.trigger and def.trigger.type then + local func = awards.trigger_types[def.trigger.type] + + if func then + func(def) + else + awards._additional_triggers(name, def) + end + end + + -- Add Award + awards.def[name] = def + + local tdef = awards.def[name] + if def.description == nil and tdef.getDefaultDescription then + def.description = tdef:getDefaultDescription() + end +end + +function awards.enable(name) + local data = awards.player(name) + if data then + data.disabled = nil + end +end + +function awards.disable(name) + local data = awards.player(name) + if data then + data.disabled = true + end +end + +function awards.clear_player(name) + awards.players[name] = {} +end + +-- This function is called whenever a target condition is met. +-- It checks if a player already has that achievement, and if they do not, +-- it gives it to them +---------------------------------------------- +--awards.unlock(name, award) +-- name - the name of the player +-- award - the name of the award to give +function awards.unlock(name, award) + -- Access Player Data + local data = awards.players[name] + local awdef = awards.def[award] + + -- Perform checks + if not data then + return + end + if not awdef then + return + end + if data.disabled then + return + end + awards.tbv(data,"unlocked") + + -- Don't give the achievement if it has already been given + if data.unlocked[award] and data.unlocked[award] == award then + return + end + + -- Unlock Award + minetest.log("action", name.." has unlocked award "..name) + data.unlocked[award] = award + awards.save() + + -- Give Prizes + if awdef and awdef.prizes then + for i = 1, #awdef.prizes do + local itemstack = ItemStack(awdef.prizes[i]) + if not itemstack:is_empty() then + local receiverref = minetest.get_player_by_name(name) + if receiverref then + receiverref:get_inventory():add_item("main", itemstack) + end + end + end + end + + -- Run callbacks + if awdef.on_unlock and awdef.on_unlock(name, awdef) then + return + end + for _, callback in pairs(awards.on_unlock) do + if callback(name, awdef) then + return + end + end + + -- Get Notification Settings + local title = awdef.title or award + local desc = awdef.description or "" + local background = awdef.background or "awards_bg_default.png" + local icon = awdef.icon or "awards_unknown.png" + local sound = awdef.sound + if sound == nil then + -- Explicit check for nil because sound could be `false` to disable it + sound = {name="awards_got_generic", gain=0.25} + end + local custom_announce = awdef.custom_announce + if not custom_announce then + if awdef.secret then + custom_announce = S("Secret Achievement Unlocked:") + else + custom_announce = S("Achievement Unlocked:") + end + end + + -- Do Notification + if sound then + -- Enforce sound delay to prevent sound spamming + local lastsound = awards.players[name].lastsound + if lastsound == nil or os.difftime(os.time(), lastsound) >= 1 then + minetest.sound_play(sound, {to_player=name}) + awards.players[name].lastsound = os.time() + end + end + + if awards.show_mode == "formspec" then + -- use a formspec to send it + minetest.show_formspec(name, "achievements:unlocked", "size[4,2]".. + "image_button_exit[0,0;4,2;"..background..";close1; ]".. + "image_button_exit[0.2,0.8;1,1;"..icon..";close2; ]".. + "label[1.1,1;"..title.."]".. + "label[0.3,0.1;"..custom_announce.."]") + elseif awards.show_mode == "chat" then + local chat_announce + if awdef.secret == true then + chat_announce = S("Secret Achievement Unlocked: %s") + else + chat_announce = S("Achievement Unlocked: %s") + end + -- use the chat console to send it + minetest.chat_send_player(name, string.format(chat_announce, title)) + if desc~="" then + minetest.chat_send_player(name, desc) + end + else + local player = minetest.get_player_by_name(name) + local one = player:hud_add({ + hud_elem_type = "image", + name = "award_bg", + scale = {x = 1, y = 1}, + text = background, + position = {x = 0.5, y = 0}, + offset = {x = 0, y = 138}, + alignment = {x = 0, y = -1} + }) + local hud_announce + if awdef.secret == true then + hud_announce = S("Secret Achievement Unlocked!") + else + hud_announce = S("Achievement Unlocked!") + end + local two = player:hud_add({ + hud_elem_type = "text", + name = "award_au", + number = 0xFFFFFF, + scale = {x = 100, y = 20}, + text = hud_announce, + position = {x = 0.5, y = 0}, + offset = {x = 0, y = 40}, + alignment = {x = 0, y = -1} + }) + local three = player:hud_add({ + hud_elem_type = "text", + name = "award_title", + number = 0xFFFFFF, + scale = {x = 100, y = 20}, + text = title, + position = {x = 0.5, y = 0}, + offset = {x = 30, y = 100}, + alignment = {x = 0, y = -1} + }) + local four = player:hud_add({ + hud_elem_type = "image", + name = "award_icon", + scale = {x = 4, y = 4}, + text = icon, + position = {x = 0.5, y = 0}, + offset = {x = -81.5, y = 126}, + alignment = {x = 0, y = -1} + }) + minetest.after(3, function() + player:hud_remove(one) + player:hud_remove(two) + player:hud_remove(three) + player:hud_remove(four) + end) + end +end + +-- Backwards compatibility +awards.give_achievement = awards.unlock + +--[[minetest.register_chatcommand("gawd", { + params = "award name", + description = "gawd: give award to self", + func = function(name, param) + awards.unlock(name,param) + end +})]]-- + +function awards.getFormspec(name, to, sid) + local formspec = "" + local listofawards = awards._order_awards(name) + local playerdata = awards.players[name] + + if #listofawards == 0 then + formspec = formspec .. "label[3.9,1.5;"..minetest.formspec_escape(S("Error: No awards available.")).."]" + formspec = formspec .. "button_exit[4.2,2.3;3,1;close;"..minetest.formspec_escape(S("OK")).."]" + return formspec + end + + -- Sidebar + if sid then + local item = listofawards[sid+0] + local def = awards.def[item.name] + + if def and def.secret and not item.got then + formspec = formspec .. "label[1,2.75;"..minetest.formspec_escape(S("(Secret Award)")).."]".. + "image[1,0;3,3;awards_unknown.png]" + if def and def.description then + formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..minetest.formspec_escape(S("Unlock this award to find out what it is."))..";]" + end + else + local title = item.name + if def and def.title then + title = def.title + end + local status = "%s" + if item.got then + status = S("%s (got)") + end + formspec = formspec .. "label[1,2.75;" .. + string.format(status, minetest.formspec_escape(title)) .. + "]" + if def and def.icon then + formspec = formspec .. "image[1,0;3,3;" .. def.icon .. "]" + end + local barwidth = 4.6 + local perc = nil + local label = nil + if def.getProgress and playerdata then + local res = def:getProgress(playerdata) + perc = res.perc + label = res.label + end + if perc then + if perc > 1 then + perc = 1 + end + formspec = formspec .. "background[0,4.80;" .. barwidth ..",0.25;awards_progress_gray.png;false]" + formspec = formspec .. "background[0,4.80;" .. (barwidth * perc) ..",0.25;awards_progress_green.png;false]" + if label then + formspec = formspec .. "label[1.75,4.63;" .. minetest.formspec_escape(label) .. "]" + end + end + if def and def.description then + formspec = formspec .. "textarea[0.25,3.25;4.8,1.7;;"..minetest.formspec_escape(def.description)..";]" + end + end + end + + -- Create list box + formspec = formspec .. "textlist[4.75,0;6,5;awards;" + local first = true + for _,award in pairs(listofawards) do + local def = awards.def[award.name] + if def then + if not first then + formspec = formspec .. "," + end + first = false + + if def.secret and not award.got then + formspec = formspec .. "#707070"..minetest.formspec_escape(S("(Secret Award)")) + else + local title = award.name + if def and def.title then + title = def.title + end + if award.got then + formspec = formspec .. minetest.formspec_escape(title) + else + formspec = formspec .. "#ACACAC".. minetest.formspec_escape(title) + end + end + end + end + return formspec .. ";"..sid.."]" +end + +function awards.show_to(name, to, sid, text) + if name == "" or name == nil then + name = to + end + if name == to and awards.player(to).disabled then + minetest.chat_send_player(S("You've disabled awards. Type /awards enable to reenable.")) + return + end + if text then + local listofawards = awards._order_awards(name) + if #listofawards == 0 then + minetest.chat_send_player(to, S("Error: No awards available.")) + return + elseif not awards.players[name] or not awards.players[name].unlocked then + minetest.chat_send_player(to, S("You have not unlocked any awards.")) + return + end + minetest.chat_send_player(to, string.format(S("%s’s awards:"), name)) + + for _, str in pairs(awards.players[name].unlocked) do + local def = awards.def[str] + if def then + if def.title then + if def.description then + minetest.chat_send_player(to, string.format(S("%s: %s"), def.title, def.description)) + else + minetest.chat_send_player(to, def.title) + end + else + minetest.chat_send_player(to, str) + end + end + end + else + if sid == nil or sid < 1 then + sid = 1 + end + local deco = "" + if minetest.global_exists("default") then + deco = default.gui_bg .. default.gui_bg_img + end + -- Show formspec to user + minetest.show_formspec(to,"awards:awards", + "size[11,5]" .. deco .. + awards.getFormspec(name, to, sid)) + end +end +awards.showto = awards.show_to + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "awards:awards" then + return false + end + if fields.quit then + return true + end + local name = player:get_player_name() + if fields.awards then + local event = minetest.explode_textlist_event(fields.awards) + if event.type == "CHG" then + awards.show_to(name, name, event.index, false) + end + end + + return true +end) + +awards.init() + +minetest.register_on_newplayer(function(player) + local playern = player:get_player_name() + awards.assertPlayer(playern) +end) + +minetest.register_on_shutdown(function() + awards.save() +end) diff --git a/mods/HUD/awards/api_helpers.lua b/mods/HUD/awards/api_helpers.lua new file mode 100644 index 0000000000..cd499ab423 --- /dev/null +++ b/mods/HUD/awards/api_helpers.lua @@ -0,0 +1,58 @@ +function awards.tbv(tb,value,default) + if not default then + default = {} + end + if not tb or type(tb) ~= "table" then + if not value then + value = "[NULL]" + end + minetest.log("error", "awards.tbv - table "..dump(value).." is null, or not a table! Dump: "..dump(tb)) + return + end + if not value then + error("[ERROR] awards.tbv was not used correctly!\n".. + "Value: '"..dump(value).."'\n".. + "Dump:"..dump(tb)) + return + end + if not tb[value] then + tb[value] = default + end +end + +function awards.assertPlayer(playern) + awards.tbv(awards.players, playern) + awards.tbv(awards.players[playern], "name", playern) + awards.tbv(awards.players[playern], "unlocked") + awards.tbv(awards.players[playern], "place") + awards.tbv(awards.players[playern], "count") + awards.tbv(awards.players[playern], "craft") + awards.tbv(awards.players[playern], "eat") + awards.tbv(awards.players[playern], "deaths", 0) + awards.tbv(awards.players[playern], "joins", 0) + awards.tbv(awards.players[playern], "chats", 0) +end + +function awards.player(name) + return awards.players[name] +end + +function awards._order_awards(name) + local done = {} + local retval = {} + local player = awards.player(name) + if player and player.unlocked then + for _,got in pairs(player.unlocked) do + if awards.def[got] then + done[got] = true + table.insert(retval,{name=got,got=true}) + end + end + end + for _,def in pairs(awards.def) do + if not done[def.name] then + table.insert(retval,{name=def.name,got=false}) + end + end + return retval +end diff --git a/mods/HUD/awards/chat_commands.lua b/mods/HUD/awards/chat_commands.lua new file mode 100644 index 0000000000..c386c19cb5 --- /dev/null +++ b/mods/HUD/awards/chat_commands.lua @@ -0,0 +1,73 @@ +-- AWARDS +-- +-- Copyright (C) 2013-2015 rubenwardy +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- This 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 Lesser General Public License for more details. +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-- + +local S +if minetest.get_modpath("intllib") then + S = intllib.Getter() +else + S = function ( s ) return s end +end + +minetest.register_chatcommand("awards", { + params = S("[c|clear|disable|enable]"), + description = S("Show, clear, disable or enable your achievements"), + func = function(name, param) + if param == "clear" then + awards.clear_player(name) + minetest.chat_send_player(name, + S("All your awards and statistics have been cleared. You can now start again.")) + elseif param == "disable" then + awards.disable(name) + minetest.chat_send_player(name, S("You have disabled your achievements.")) + elseif param == "enable" then + awards.enable(name) + minetest.chat_send_player(name, S("You have enabled your achievements.")) + elseif param == "c" then + awards.show_to(name, name, nil, true) + else + awards.show_to(name, name, nil, false) + end + end +}) + +minetest.register_chatcommand("awd", { + params = S(""), + description = S("Show details of an achievement"), + func = function(name, param) + local def = awards.def[param] + if def then + minetest.chat_send_player(name, string.format(S("%s: %s"), def.title, def.description)) + else + minetest.chat_send_player(name, S("Achievement not found.")) + end + end +}) + +minetest.register_chatcommand("awpl", { + privs = { + server = true + }, + params = S(""), + description = S("Get the achievements statistics for the given player or yourself"), + func = function(name, param) + if not param or param == "" then + param = name + end + minetest.chat_send_player(name, param) + local player = awards.player(param) + minetest.chat_send_player(name, dump(player)) + end +}) diff --git a/mods/HUD/awards/depends.txt b/mods/HUD/awards/depends.txt new file mode 100644 index 0000000000..c0de3afd3f --- /dev/null +++ b/mods/HUD/awards/depends.txt @@ -0,0 +1,13 @@ +intllib? +sfinv? +unified_inventory? +default? +stairs? +farming? +dye? +beds? +wool? +vessels? +moreblocks? +fire? +flowers? diff --git a/mods/HUD/awards/description.txt b/mods/HUD/awards/description.txt new file mode 100644 index 0000000000..f2b9944c7e --- /dev/null +++ b/mods/HUD/awards/description.txt @@ -0,0 +1 @@ +Adds achievements to Minetest, and an API to register new ones. diff --git a/mods/HUD/awards/init.lua b/mods/HUD/awards/init.lua new file mode 100644 index 0000000000..e841603d4e --- /dev/null +++ b/mods/HUD/awards/init.lua @@ -0,0 +1,936 @@ +-- AWARDS +-- +-- Copyright (C) 2013-2015 rubenwardy +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- This 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 Lesser General Public License for more details. +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-- + + +local S +if minetest.get_modpath("intllib") then + S = intllib.Getter() +else + S = function ( s ) return s end +end + +dofile(minetest.get_modpath("awards").."/api.lua") +dofile(minetest.get_modpath("awards").."/chat_commands.lua") +dofile(minetest.get_modpath("awards").."/sfinv.lua") +dofile(minetest.get_modpath("awards").."/unified_inventory.lua") +dofile(minetest.get_modpath("awards").."/triggers.lua") +awards.set_intllib(S) + +-- Saint-Maclou +if minetest.get_modpath("moreblocks") then + awards.register_achievement("award_saint_maclou",{ + title = S("Saint-Maclou"), + description = S("Place 20 coal checkers."), + icon = "awards_novicebuilder.png", + trigger = { + type = "place", + node = "moreblocks:coal_checker", + target = 20 + } + }) + + -- Castorama + awards.register_achievement("award_castorama",{ + title = S("Castorama"), + description = S("Place 20 iron checkers."), + icon = "awards_novicebuilder.png", + trigger = { + type = "place", + node = "moreblocks:iron_checker", + target = 20 + } + }) + + -- Sam the Trapper + awards.register_achievement("award_sam_the_trapper",{ + title = S("Sam the Trapper"), + description = S("Place 2 trap stones."), + icon = "awards_novicebuilder.png", + trigger = { + type = "place", + node = "moreblocks:trap_stone", + target = 2 + } + }) +end + +-- This award can't be part of Unified Inventory, it would make a circular dependency +if minetest.get_modpath("unified_inventory") then + if minetest.get_all_craft_recipes("unified_inventory:bag_large") ~= nil then + awards.register_achievement("awards_ui_bags", { + title = S("Backpacker"), + description = S("Craft 4 large bags."), + icon = "awards_ui_bags.png", + trigger = { + type = "craft", + item = "unified_inventory:bag_large", + target = 4 + } + }) + end +end + +if minetest.get_modpath("fire") then + awards.register_achievement("awards_pyro", { + title = S("Pyromaniac"), + description = S("Craft 8 times flint and steel."), + icon = "fire_flint_steel.png", + trigger = { + type = "craft", + item = "fire:flint_and_steel", + target = 8 + } + }) + if minetest.setting_getbool("disable_fire") ~= true then + awards.register_achievement("awards_firefighter", { + title = S("Firefighter"), + description = S("Put out 1000 fires."), + icon = "awards_firefighter.png", + trigger = { + type = "dig", + node = "fire:basic_flame", + target = 1000 + } + }) + end +end + +if minetest.get_modpath("default") then + -- Light it up + awards.register_achievement("award_lightitup",{ + title = S("Light It Up"), + description = S("Place 100 torches."), + icon = "awards_novicebuilder.png^awards_level1.png", + trigger = { + type = "place", + node = "default:torch", + target = 100 + } + }) + + -- Light ALL the things! + awards.register_achievement("award_well_lit",{ + title = S("Well Lit"), + description = S("Place 1,000 torches."), + icon = "awards_novicebuilder.png^awards_level2.png", + trigger = { + type = "place", + node = "default:torch", + target = 1000 + } + }) + + awards.register_achievement("award_meselamp",{ + title = S("Really Well Lit"), + description = S("Craft 10 mese lamps."), + icon = "default_meselamp.png", + trigger = { + type = "craft", + item = "default:meselamp", + target = 10 + } + }) + + awards.register_achievement("awards_stonebrick", { + title = S("Outpost"), + description = S("Craft 200 stone bricks."), + icon = "default_stone_brick.png^awards_level1.png", + trigger = { + type = "craft", + item = "default:stonebrick", + target = 200 + } + }) + + awards.register_achievement("awards_stonebrick2", { + title = S("Watchtower"), + description = S("Craft 800 stone bricks."), + icon = "default_stone_brick.png^awards_level2.png", + trigger = { + type = "craft", + item = "default:stonebrick", + target = 800 + } + }) + + awards.register_achievement("awards_stonebrick3", { + title = S("Fortress"), + description = S("Craft 3,200 stone bricks."), + icon = "default_stone_brick.png^awards_level3.png", + trigger = { + type = "craft", + item = "default:stonebrick", + target = 3200 + } + }) + + awards.register_achievement("awards_desert_stonebrick", { + title = S("Desert Dweller"), + description = S("Craft 400 desert stone bricks."), + icon = "default_desert_stone_brick.png", + trigger = { + type = "craft", + item = "default:desert_stonebrick", + target = 400 + } + }) + + awards.register_achievement("awards_desertstonebrick", { + title = S("Pharaoh"), + description = S("Craft 100 sandstone bricks."), + icon = "default_sandstone_brick.png", + trigger = { + type = "craft", + item = "default:sandstonebrick", + target = 100 + } + }) + + awards.register_achievement("awards_bookshelf", { + title = S("Little Library"), + description = S("Craft 7 bookshelves."), + icon = "default_bookshelf.png", + trigger = { + type = "craft", + item = "default:bookshelf", + target = 7 + } + }) + + awards.register_achievement("awards_obsidian", { + title = S("Lava and Water"), + description = S("Mine your first obsidian."), + icon = "default_obsidian.png^awards_level1.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:obsidian", + target = 1 + } + }) + + -- Obsessed with Obsidian + awards.register_achievement("award_obsessed_with_obsidian",{ + title = S("Obsessed with Obsidian"), + description = S("Mine 50 obsidian."), + icon = "default_obsidian.png^awards_level2.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:obsidian", + target = 50 + } + }) + + -- Proof that player has found lava + awards.register_achievement("award_lavaminer",{ + title = S("Lava Miner"), + description = S("Mine any block while being very close to lava."), + background = "awards_bg_mining.png", + icon = "default_lava.png", + }) + awards.register_on_dig(function(player,data) + local pos = player:getpos() + if pos and (minetest.find_node_near(pos, 1, "default:lava_source") ~= nil or + minetest.find_node_near(pos, 1, "default:lava_flowing") ~= nil) then + return "award_lavaminer" + end + return nil + end) + + -- On the way + awards.register_achievement("award_on_the_way", { + title = S("On The Way"), + description = S("Place 100 rails."), + icon = "default_rail.png", + trigger = { + type = "place", + node = "default:rail", + target = 100 + } + }) + + awards.register_achievement("award_lumberjack_firstday", { + title = S("First Day in the Woods"), + description = S("Dig 6 tree blocks."), + icon = "default_tree.png^awards_level1.png", + trigger = { + type = "dig", + node = "default:tree", + target = 6 + } + }) + + -- Lumberjack + awards.register_achievement("award_lumberjack", { + title = S("Lumberjack"), + description = S("Dig 36 tree blocks."), + icon = "default_tree.png^awards_level2.png", + trigger = { + type = "dig", + node = "default:tree", + target = 36 + } + }) + + -- Semi-pro Lumberjack + awards.register_achievement("award_lumberjack_semipro", { + title = S("Semi-pro Lumberjack"), + description = S("Dig 216 tree blocks."), + icon = "default_tree.png^awards_level3.png", + trigger = { + type = "dig", + node = "default:tree", + target = 216 + } + }) + + -- Professional Lumberjack + awards.register_achievement("award_lumberjack_professional", { + title = S("Professional Lumberjack"), + description = S("Dig 1,296 tree blocks."), + icon = "default_tree.png^awards_level4.png", + trigger = { + type = "dig", + node = "default:tree", + target = 1296 + } + }) + + -- Junglebaby + awards.register_achievement("award_junglebaby", { + title = S("Junglebaby"), + description = S("Dig 100 jungle tree blocks."), + icon = "default_jungletree.png^awards_level1.png", + trigger = { + type = "dig", + node = "default:jungletree", + target = 100 + } + }) + + -- Jungleman + awards.register_achievement("award_jungleman", { + title = S("Jungleman"), + description = S("Dig 1,000 jungle tree blocks."), + icon = "default_jungletree.png^awards_level2.png", + trigger = { + type = "dig", + node = "default:jungletree", + target = 1000 + } + }) + + -- Found some Mese! + awards.register_achievement("award_mesefind", { + title = S("First Mese Find"), + description = S("Mine your first mese ore."), + icon = "default_stone.png^default_mineral_mese.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone_with_mese", + target = 1 + } + }) + + -- Mese Block + awards.register_achievement("award_meseblock", { + secret = true, + title = S("Mese Mastery"), + description = S("Mine a mese block."), + icon = "default_mese_block.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:mese", + target = 1 + } + }) + + -- You're a copper + awards.register_achievement("award_youre_a_copper", { + title = S("You’re a copper"), + description = S("Dig 1,000 copper ores."), + icon = "default_stone.png^default_mineral_copper.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone_with_copper", + target = 1000 + } + }) + + -- Found a Nyan cat! + awards.register_achievement("award_nyanfind", { + secret = true, + title = S("A Cat in a Pop-Tart?!"), + description = S("Mine a nyan cat."), + icon = "nyancat_front.png", + trigger = { + type = "dig", + node = "default:nyancat", + target = 1 + } + }) + + -- Mini Miner + awards.register_achievement("award_mine2", { + title = S("Mini Miner"), + description = S("Dig 100 stone blocks."), + icon = "awards_miniminer.png^awards_level1.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone", + target = 100 + } + }) + + -- Hardened Miner + awards.register_achievement("award_mine3", { + title = S("Hardened Miner"), + description = S("Dig 1,000 stone blocks."), + icon = "awards_miniminer.png^awards_level2.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone", + target = 1000 + } + }) + + -- Master Miner + awards.register_achievement("award_mine4", { + title = S("Master Miner"), + description = S("Dig 10,000 stone blocks."), + icon = "awards_miniminer.png^awards_level3.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone", + target = 10000 + } + }) + + -- Marchand de sable + awards.register_achievement("award_marchand_de_sable", { + title = S("Marchand De Sable"), + description = S("Dig 1,000 sand."), + icon = "default_sand.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:sand", + target = 1000 + } + }) + + awards.register_achievement("awards_crafter_of_sticks", { + title = S("Crafter of Sticks"), + description = S("Craft 100 sticks."), + icon = "default_stick.png", + trigger = { + type = "craft", + item = "default:stick", + target = 100 + } + }) + + awards.register_achievement("awards_junglegrass", { + title = S("Jungle Discoverer"), + description = S("Mine your first jungle grass."), + icon = "default_junglegrass.png", + trigger = { + type = "dig", + node = "default:junglegrass", + target = 1 + } + }) + + awards.register_achievement("awards_grass", { + title = S("Grasslands Discoverer"), + description = S("Mine some grass."), + icon = "default_grass_3.png", + trigger = { + type = "dig", + node = "default:grass_1", + target = 1 + } + }) + + awards.register_achievement("awards_dry_grass", { + title = S("Savannah Discoverer"), + description = S("Mine some dry grass."), + icon = "default_dry_grass_3.png", + trigger = { + type = "dig", + node = "default:dry_grass_3", + target = 1 + } + }) + + awards.register_achievement("awards_cactus", { + title = S("Desert Discoverer"), + description = S("Mine your first cactus."), + icon = "default_cactus_side.png", + trigger = { + type = "dig", + node = "default:cactus", + target = 1 + } + }) + + awards.register_achievement("awards_dry_shrub", { + title = S("Far Lands"), + description = S("Mine your first dry shrub."), + icon = "default_dry_shrub.png", + trigger = { + type = "dig", + node = "default:dry_shrub", + target = 1 + } + }) + + awards.register_achievement("awards_ice", { + title = S("Glacier Discoverer"), + description = S("Mine your first ice."), + icon = "default_ice.png", + trigger = { + type = "dig", + node = "default:ice", + target = 1 + } + }) + + -- Proof that player visited snowy lands + awards.register_achievement("awards_snowblock", { + title = S("Very Simple Snow Man"), + description = S("Place two snow blocks."), + icon = "default_snow.png", + trigger = { + type = "place", + node = "default:snowblock", + target = 2 + } + }) + + awards.register_achievement("awards_gold_ore", { + title = S("First Gold Find"), + description = S("Mine your first gold ore."), + icon = "default_stone.png^default_mineral_gold.png^awards_level1.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone_with_gold", + target = 1 + } + }) + + awards.register_achievement("awards_gold_rush", { + title = S("Gold Rush"), + description = S("Mine 45 gold ores."), + icon = "default_stone.png^default_mineral_gold.png^awards_level2.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone_with_gold", + target = 45 + } + }) + + awards.register_achievement("awards_diamond_ore", { + title = S("Wow, I am Diamonds!"), + description = S("Mine your first diamond ore."), + icon = "default_stone.png^default_mineral_diamond.png^awards_level1.png", + trigger = { + type = "dig", + node = "default:stone_with_diamond", + target = 1 + } + }) + + awards.register_achievement("awards_diamond_rush", { + title = S("Girl's Best Friend"), + description = S("Mine 18 diamond ores."), + icon = "default_stone.png^default_mineral_diamond.png^awards_level2.png", + background = "awards_bg_mining.png", + trigger = { + type = "dig", + node = "default:stone_with_diamond", + target = 18 + } + }) + + awards.register_achievement("awards_diamondblock", { + title = S("Hardest Block on Earth"), + description = S("Craft a diamond block."), + icon = "default_diamond_block.png", + trigger = { + type = "craft", + item = "default:diamondblock", + target = 1 + } + }) + + awards.register_achievement("awards_mossycobble", { + title = S("In the Dungeon"), + description = S("Mine a mossy cobblestone."), + icon = "default_mossycobble.png", + trigger = { + type = "dig", + node = "default:mossycobble", + target = 1 + } + }) + + awards.register_achievement("award_furnace", { + title = S("Smelter"), + description = S("Craft 10 furnaces."), + icon = "default_furnace_front.png", + trigger = { + type = "craft", + item= "default:furnace", + target = 10 + } + }) + + awards.register_achievement("award_chest", { + title = S("Treasurer"), + description = S("Craft 15 chests."), + icon = "default_chest_front.png", + trigger = { + type = "craft", + item= "default:chest", + target = 15 + } + }) + + awards.register_achievement("award_chest2", { + title = S("Bankier"), + description = S("Craft 30 locked chests."), + icon = "default_chest_lock.png", + trigger = { + type = "craft", + item= "default:chest_locked", + target = 30 + } + }) + + awards.register_achievement("award_brick", { + title = S("Bricker"), + description = S("Craft 200 brick blocks."), + icon = "default_brick.png", + trigger = { + type = "craft", + item= "default:brick", + target = 200 + } + }) + + awards.register_achievement("award_obsidianbrick", { + title = S("House of Obsidian"), + description = S("Craft 100 obsidian bricks."), + icon = "default_obsidian_brick.png", + trigger = { + type = "craft", + item= "default:obsidianbrick", + target = 100 + } + }) + + awards.register_achievement("award_placestone", { + title = S("Build a Cave"), + description = S("Place 100 stone."), + icon = "default_stone.png", + trigger = { + type = "place", + node = "default:stone", + target = 100 + } + }) + + awards.register_achievement("award_woodladder", { + title = S("Long Ladder"), + description = S("Place 400 wooden ladders."), + icon = "default_ladder_wood.png", + trigger = { + type = "place", + node = "default:ladder_wood", + target = 400 + } + }) + + awards.register_achievement("award_steelladder", { + title = S("Industrial Age"), + description = S("Place 40 steel ladders."), + icon = "default_ladder_steel.png", + trigger = { + type = "place", + node = "default:ladder_steel", + target = 40 + } + }) + + awards.register_achievement("award_apples", { + title = S("Yummy!"), + description = S("Eat 80 apples."), + icon = "default_apple.png", + trigger = { + type = "eat", + item = "default:apple", + target = 80 + } + }) +end + +if minetest.get_modpath("vessels") then + awards.register_achievement("award_vessels_shelf", { + title = S("Glasser"), + icon = "vessels_shelf.png", + description = S("Craft 14 vessels shelves."), + trigger = { + type = "craft", + item= "vessels:shelf", + target = 14 + } + }) +end + +if minetest.get_modpath("farming") then + awards.register_achievement("awards_farmer", { + title = S("Farming Skills Aquired"), + description = S("Harvest a fully grown wheat plant."), + icon = "farming_wheat_8.png^awards_level1.png", + trigger = { + type = "dig", + node = "farming:wheat_8", + target = 1 + } + }) + awards.register_achievement("awards_farmer2", { + title = S("Field Worker"), + description = S("Harvest 25 fully grown wheat plants."), + icon = "farming_wheat_8.png^awards_level2.png", + trigger = { + type = "dig", + node = "farming:wheat_8", + target = 25 + } + }) + + awards.register_achievement("awards_farmer3", { + title = S("Aspiring Farmer"), + description = S("Harvest 125 fully grown wheat plants."), + icon = "farming_wheat_8.png^awards_level3.png", + trigger = { + type = "dig", + node = "farming:wheat_8", + target = 125 + } + }) + + awards.register_achievement("awards_farmer4", { + title = S("Wheat Magnate"), + description = S("Harvest 625 fully grown wheat plants."), + icon = "farming_wheat_8.png^awards_level4.png", + trigger = { + type = "dig", + node = "farming:wheat_8", + target = 625 + } + }) + + awards.register_achievement("award_bread", { + title = S("Baker"), + description = S("Eat 10 loaves of bread."), + icon = "farming_bread.png", + trigger = { + type = "eat", + item = "farming:bread", + target = 10 + } + }) + +end + +if minetest.get_modpath("wool") and minetest.get_modpath("farming") then + awards.register_achievement("awards_wool", { + title = S("Wool Over Your Eyes"), + description = S("Craft 250 white wool."), + icon = "wool_white.png", + trigger = { + type = "craft", + item = "wool:white", + target = 250 + } + }) +end + +if minetest.get_modpath("beds") then + awards.register_achievement("award_bed", { + title = S("Hotelier"), + description = S("Craft 15 fancy beds."), + icon = "beds_bed_fancy.png", + trigger = { + type = "craft", + item= "beds:fancy_bed_bottom", + target = 15 + } + }) +end + +if minetest.get_modpath("stairs") then + awards.register_achievement("award_stairs_goldblock", { + title = S("Filthy Rich"), + description = S("Craft 24 gold block stairs."), + icon = "default_gold_block.png", + trigger = { + type = "craft", + item= "stairs:stair_goldblock", + target = 24 + } + }) +end + +if minetest.get_modpath("dye") then + awards.register_achievement("awards_dye_red", { + title = S("Roses Are Red"), + description = S("Craft 400 red dyes."), + icon = "dye_red.png", + trigger = { + type = "craft", + item = "dye:red", + target = 400 + } + }) + + awards.register_achievement("awards_dye_yellow", { + title = S("Dandelions are Yellow"), + description = S("Craft 400 yellow dyes."), + icon = "dye_yellow.png", + trigger = { + type = "craft", + item = "dye:yellow", + target = 400 + } + }) + + awards.register_achievement("awards_dye_blue", { + title = S("Geraniums are Blue"), + description = S("Craft 400 blue dyes."), + icon = "dye_blue.png", + trigger = { + type = "craft", + item= "dye:blue", + target = 400 + } + }) + + awards.register_achievement("awards_dye_white", { + title = S("White Color Stock"), + description = S("Craft 100 white dyes."), + icon = "dye_white.png", + trigger = { + type = "craft", + item= "dye:white", + target = 100 + } + }) +end + +if minetest.get_modpath("flowers") then + awards.register_achievement("awards_brown_mushroom1", { + title = S("Tasty Mushrooms"), + description = S("Eat 3 brown mushrooms."), + icon = "flowers_mushroom_brown.png^awards_level1.png", + trigger = { + type = "eat", + item= "flowers:mushroom_brown", + target = 3, + } + }) + awards.register_achievement("awards_brown_mushroom2", { + title = S("Mushroom Lover"), + description = S("Eat 33 brown mushrooms."), + icon = "flowers_mushroom_brown.png^awards_level2.png", + trigger = { + type = "eat", + item= "flowers:mushroom_brown", + target = 33, + } + }) + awards.register_achievement("awards_brown_mushroom3", { + title = S("Underground Mushroom Farmer"), + description = S("Eat 333 brown mushrooms."), + icon = "flowers_mushroom_brown.png^awards_level3.png", + trigger = { + type = "eat", + item= "flowers:mushroom_brown", + target = 333, + } + }) +end + +-- This ensures the following code is executed after all items have been registered +minetest.after(0, function() + -- Check whether there is at least one node which can be built by the player + local building_is_possible = false + for _, def in pairs(minetest.registered_nodes) do + if (def.description and def.pointable ~= false and not def.groups.not_in_creative_inventory) then + building_is_possible = true + break + end + end + + -- The following awards require at least one node which can be built + if not building_is_possible then + return + end + + awards.register_achievement("awards_builder1", { + title = S("Builder"), + icon = "awards_house.png^awards_level1.png", + trigger = { + type = "place", + target = 1000, + }, + }) + awards.register_achievement("awards_builder2", { + title = S("Constructor"), + icon = "awards_house.png^awards_level2.png", + trigger = { + type = "place", + target = 5000, + }, + }) + awards.register_achievement("awards_builder3", { + title = S("Architect"), + icon = "awards_house.png^awards_level3.png", + trigger = { + type = "place", + target = 10000, + }, + }) + awards.register_achievement("awards_builder4", { + title = S("Master Architect"), + icon = "awards_house.png^awards_level4.png", + trigger = { + type = "place", + target = 25000, + }, + }) +end) diff --git a/mods/HUD/awards/locale/de.txt b/mods/HUD/awards/locale/de.txt new file mode 100644 index 0000000000..6564eff6be --- /dev/null +++ b/mods/HUD/awards/locale/de.txt @@ -0,0 +1,198 @@ +A Cat in a Pop-Tart?! = Eine Katze im Pop-Tart?! +Aspiring Farmer = Aufstrebender Bauer +Backpacker = Rucksacktourist +Bankier = Bankier +Bricker = Ziegler +Build a Cave = Höhlenbauer +Castorama = Gießmeister +Craft 10 furnaces. = Fertigen Sie 10 Öfen. +Craft 10 mese lamps. = Fertigen Sie 10 Meselampen. +Craft 100 obsidian bricks. = Fertigen Sie 100 Obsidianziegel. +Craft 100 sandstone bricks. = Fertigen Sie 100 Sandsteinziegel. +Craft 100 sticks. = Fertigen Sie 100 Stöcke. +Craft 100 white dyes. = Fertigen Sie 100 weiße Farbstoffe. +Craft 14 vessels shelves. = Fertigen Sie 14 Gefäßregale. +Craft 15 chests. = Fertigen Sie 15 Truhen. +Craft 15 fancy beds. = Fertigen Sie 15 schicke Betten. +Craft 200 brick blocks. = Fertigen Sie 200 Ziegelblöcke. +Craft 200 stone bricks. = Fertigen Sie 200 Steinziegel. +Craft 24 gold block stairs. = Fertigen Sie 24 Goldblockstufen. +Craft 250 white wool. = Fertigen Sie 250 weiße Wolle. +Craft 3,200 stone bricks. = Fertigen Sie 3200 Steinziegel. +Craft 30 locked chests. = Fertigen Sie 30 abgeschlossene Truhen. +Craft 4 large bags. = Fertigen Sie 4 große Taschen. +Craft 400 blue dyes. = Fertigen Sie 400 blaue Farbstoffe. +Craft 400 desert stone bricks. = Fertigen Sie 400 Wüstensteinziegel. +Craft 400 red dyes. = Fertigen Sie 400 rote Farbstoffe. +Craft 400 yellow dyes. = Fertigen Sie 400 gelbe Farbstoffe. +Craft 7 bookshelves. = Fertigen Sie 7 Bücherregale. +Craft 8 times flint and steel. = Fertigen Sie 8 mal einen Feuerstein und Stahl an. +Craft 800 stone bricks. = Fertigen Sie 800 Steinziegel an. +Craft a diamond block. = Fertigen Sie einen Diamantblock an. +Crafter of Sticks = Stockmacher +Dandelions are Yellow = Löwenzahn ist gelb +Desert Discoverer = Wüstenerkunder +Desert Dweller = Wüstenbewohner +Dig 1,000 copper ores. = Bauen Sie 1000 Kupfererze ab. +Dig 1,000 jungle tree blocks. = Bauen Sie 1000 Dschungelbaumblöcke ab. +Dig 1,000 sand. = Bauen Sie 1000 Sand ab. +Dig 1,000 stone blocks. = Bauen Sie 1000 Steine ab. +Dig 1,296 tree blocks. = Bauen Sie 1296 Baumblöcke ab. +Dig 10,000 stone blocks. = Bauen Sie 10000 Steine ab. +Dig 100 jungle tree blocks. = Bauen Sie 100 Dschungelbaumblöcke ab. +Dig 100 stone blocks. = Bauen Sie 100 Steinblöcke ab. +Dig 216 tree blocks. = Bauen Sie 216 Baumblöcke ab. +Dig 36 tree blocks. = Bauen Sie 36 Baumblöcke ab. +Dig 6 tree blocks. = Bauen Sie 6 Baumblöcke ab. +Far Lands = Ferne Lande +Farming Skills Aquired = Landwirtschaft erlernt +Field Worker = Feldarbeiter +Filthy Rich = Stinkreich +Firefighter = Feuerwehr +First Day in the Woods = Erster Tag im Wald +First Gold Find = Erster Goldfund +First Mese Find = Erster Mesefund +Fortress = Burg +Geraniums are Blue = Geranien sind blau +Girl's Best Friend = Bester Freund der Mädchen +Glacier Discoverer = Gletschererkunder +Glasser = Glasmacher +Gold Rush = Goldrausch +Grasslands Discoverer = Prärieerkunder +Hardened Miner = Abhehärteter Bergarbeiter +Hardest Block on Earth = Härtester Block der Welt +Harvest 125 fully grown wheat plants. = Ernten Sie 125 voll ausgewachsene Getreidepflanzen. +Harvest 25 fully grown wheat plants. = Ernten Sie 25 voll ausgewachsene Getreidepflanzen. +Harvest 625 fully grown wheat plants. = Ernten Sie 625 voll ausgewachsene Getreidepflanzen. +Harvest a fully grown wheat plant. = Ernten Sie eine voll ausgewachsene Getreidepflanze. +Hotelier = Hotelier +House of Obsidian = Haus aus Obsidian +In the Dungeon = Im Verlies +Industrial Age = Industriezeitalter +Jungle Discoverer = Dschungelerkunder +Junglebaby = Dschungelbaby +Jungleman = Dschungelmann +Lava Miner = Lavagräber +Lava and Water = Lava und Wasser +Light It Up = Licht an! +Little Library = Kleine Bücherei +Long Ladder = Lange Leiter +Lumberjack = Holzfäller +Marchand De Sable = +Master Miner = Profibergarbeiter +Mese Mastery = Mesemeister +Mine 18 diamond ores. = Bauen Sie 18 Diamanterze ab. +Mine 45 gold ores. = Bauen Sie 18 Diamanterze ab. +Mine 50 obsidian. = Bauen Sie 50 Obsidian ab. +Mine a mese block. = Bauen Sie einen Meseblock ab. +Mine a mossy cobblestone. = Bauen Sie ein bemoostes Kopfsteinpflaster ab. +Mine a nyan cat. = Bauen Sie eine Nyan Cat ab. +Mine any block while being very close to lava. = Bauen Sie einen beliebigen Block ab, während Sie sehr nahe an der Lava stehen. +Mine some dry grass. = Bauen Sie etwas trockenes Gras ab. +Mine some grass. = Bauen Sie etwas Gras ab. +Mine your first cactus. = Bauen Sie Ihren ersten Kaktus ab. +Mine your first diamond ore. = Bauen Sie Ihr erstes Diamanterz ab. +Mine your first dry shrub. = Bauen Sie Ihren ersten vertrockneten Strauch ab. +Mine your first gold ore. = Bauen Sie Ihr erstes Golderz ab. +Mine your first ice. = Bauen Sie Ihr erstes Eis ab. +Mine your first jungle grass. = Bauen Sie Ihr erstes Dschungelgras ab. +Mine your first mese ore. = Bauen Sie Ihr erstes Meseerz ab. +Mine your first obsidian. = Bauen Sie Ihr erstes Obsidian ab. +Mini Miner = Berganfänger +Obsessed with Obsidian = Von Obsidian besessen +On The Way = Auf dem Weg +Outpost = Außenposten +Pharaoh = Pharao +Place 1,000 torches. = Platzieren Sie 1000 Fackeln. +Place 100 rails. = Platzieren Sie 100 Gleise. +Place 100 stone. = Platzieren Sie 100 Steine. +Place 100 torches. = Platzieren Sie 100 Fackeln. +Place 2 trap stones. = Platzieren Sie 2 Fallensteine. +Place 20 coal checkers. = Platzieren Sie 20 Kohlenschachbrettmuster. +Place 20 iron checkers. = Platzieren Sie 20 Eisenschachbrettmuster. +Place 40 steel ladders. = Platzieren Sie 40 Stahlleitern. +Place 400 wooden ladders. = Platzieren Sie 400 Holzleitern. +Place two snow blocks. = Platzieren Sie zwei Schneeblöcke. +Professional Lumberjack = Profiholzfäller +Put out 1000 fires. = Löschen Sie 1000 Flammen. +Pyromaniac = Pyromane +Really Well Lit = Sehr gute Beleuchtung +Roses Are Red = Rosen sind rot +Saint-Maclou = Saint-Maclou +Sam the Trapper = Sam der Fallensteller +Savannah Discoverer = Savannenerkunder +Semi-pro Lumberjack = Fortgeschrittener Holzfäller +Smelter = Schmelzer +Treasurer = Schatzmeister +Very Simple Snow Man = Sehr simpler Schneemann +Watchtower = Wachturm +Well Lit = Gut ausgeleuchtet +Wheat Magnate = Getreidemagnat +White Color Stock = Weißer Farbstoffvorrat +Wool Over Your Eyes = Wollige Augen +Wow, I am Diamonds! = Wow, ich bin Diamanten! +You’re a copper = Du Kupfer! +%s: %s = %s: %s +%s (got) = %s (erhalten) +%s’s awards: = %ss Auszeichnungen: +(Secret Award) = (Geheime Auszeichnung) +Achievement Unlocked! = Auszeichnung erhalten! +Achievement Unlocked: = Auszeichnung erhalten: +Achievement Unlocked: %s = Auszeichnung erhalten: %s +Secret Achievement Unlocked! = Geheime Auszeichnung erhalten! +Secret Achievement Unlocked: = Geheime Auszeichnung erhalten: +Secret Achievement Unlocked: %s = Geheime Auszeichnung erhalten: %s +Unlock this award to find out what it is. = Verdienen Sie sich diese Auszeichnung, um herauszufinden, was sie ist. +You have not unlocked any awards. = Sie haben noch keine Auszeichnungen. +You've disabled awards. Type /awards enable to reenable. = Sie haben die Auszeichnungen deaktiviert. Geben Sie »/awards enable« ein, um sie wieder zu aktivieren. + = + = +Achievement not found. = Auszeichnung nicht gefunden. +All your awards and statistics have been cleared. You can now start again. = All Ihre Auszeichnugen und Statistiken wurden zurückgesetzt. Sie können nun von vorne anfangen. +Get the achievements statistics for the given player or yourself = Die Statistik der Auszeichnungen eines Spielers zeigen +List awards in chat (deprecated) = Auszeichnungen im Chat anzeigen (veraltet) +Show, clear, disable or enable your achievements = Zeigen, löschen, deaktivieren oder aktivieren Sie Ihre Auszeichnungen +You have disabled your achievements. = Sie haben Ihre Auszeichnungen deaktiviert. +You have enabled your achievements. = Sie haben Ihre Auszeichnungen aktiviert. +[c|clear|disable|enable] = [c|clear|disable|enable] +Awards = Auszeichnungen +%d/%d crafted = %d/%d gefertigt +%d/%d deaths = %d/%d Tode +%d/%d dug = %d/%d abgebaut +%d/%d game joins = %d/%d Spielen beigetreten +%d/%d lines of chat = %d/%d Chatzeilen +%d/%d placed = %d/%d platziert +Die %d times. = Sterben Sie %d mal. +Die. = Sterben Sie. +Craft: %d×%s = Fertigen Sie an: %d×%s +Craft: %s = Fertigen Sie an: %s +Mine a block: %s = Bauen Sie einen Block ab: %s +Mine blocks: %d×%s = Bauen Sie Blöcke ab: %d×%s +Place a block: %s = Platzieren Sie einen Block: %s +Place blocks: %d×%s = Platzieren Sie Blöcke: %d×%s +Join the game. = Treten Sie dem Spiel bei. +Join the game %d times. = Treten Sie dem Spiel %d mal bei. +Show details of an achievement = Details einer Auszeichnung anzeigen +OK = OK +Error: No awards available. = Fehler: Keine Auszeichnungen vorhanden. +Eat: %d×%s = Essen Sie: %d×%s +Eat: %s = Essen Sie: %s +%d/%d eaten = %d/%d gegessen +Yummy! = Lecker! +Baker = Bäcker +Eat 10 loaves of bread. = Essen Sie 10 Brote. +Eat 80 apples. = Essen Sie 80 Äpfel. +Tasty Mushrooms = Leckere Pilze +Mushroom Lover = Pilzfreund +Underground Mushroom Farmer = Unterirdischer Pilzbauer +Eat 3 brown mushrooms. = Essen Sie 3 braune Pilze. +Eat 33 brown mushrooms. = Essen Sie 33 braune Pilze. +Eat 333 brown mushrooms. = Essen Sie 333 braune Pilze. +Builder = Bauarbeiter +Constructor = Konstrukteur +Architect = Architekt +Master Architect = Meisterarchitekt +Place %d block(s). = Platzieren Sie %d Blöcke. +Dig %d block(s). = Bauen Sie %d Blöcke ab. +Eat %d item(s). = Essen Sie %d Dinge. +Craft %d item(s). = Fertigen Sie %d Gegenstände. diff --git a/mods/HUD/awards/locale/template.txt b/mods/HUD/awards/locale/template.txt new file mode 100644 index 0000000000..454f153a65 --- /dev/null +++ b/mods/HUD/awards/locale/template.txt @@ -0,0 +1,196 @@ +%d/%d chat messages = +%d/%d crafted = +%d/%d deaths = +%d/%d dug = +%d/%d game joins = +%d/%d placed = +%s (got) = +%s: %s = +%s’s awards: = +(Secret Award) = + = + = +A Cat in a Pop-Tart?! = +Achievement Unlocked! = +Achievement Unlocked: = +Achievement Unlocked: %s = +Achievement not found. = +All your awards and statistics have been cleared. You can now start again. = +Aspiring Farmer = +Awards = +Backpacker = +Bankier = +Bricker = +Build a Cave = +Castorama = +Craft 10 furnaces. = +Craft 10 mese lamps. = +Craft 100 obsidian bricks. = +Craft 100 sandstone bricks. = +Craft 100 sticks. = +Craft 100 white dyes. = +Craft 14 vessels shelves. = +Craft 15 chests. = +Craft 15 fancy beds. = +Craft 200 brick blocks. = +Craft 200 stone bricks. = +Craft 24 gold block stairs. = +Craft 250 white wool. = +Craft 3,200 stone bricks. = +Craft 30 locked chests. = +Craft 4 large bags. = +Craft 400 blue dyes. = +Craft 400 desert stone bricks. = +Craft 400 red dyes. = +Craft 400 yellow dyes. = +Craft 7 bookshelves. = +Craft 8 times flint and steel. = +Craft 800 stone bricks. = +Craft a diamond block. = +Craft: %d×%s = +Craft: %s = +Crafter of Sticks = +Dandelions are Yellow = +Desert Discoverer = +Desert Dweller = +Die %d times. = +Die. = +Dig 1,000 copper ores. = +Dig 1,000 jungle tree blocks. = +Dig 1,000 sand. = +Dig 1,000 stone blocks. = +Dig 1,296 tree blocks. = +Dig 10,000 stone blocks. = +Dig 100 jungle tree blocks. = +Dig 100 stone blocks. = +Dig 216 tree blocks. = +Dig 36 tree blocks. = +Dig 6 tree blocks. = +Far Lands = +Farming Skills Aquired = +Field Worker = +Filthy Rich = +Firefighter = +First Day in the Woods = +First Gold Find = +First Mese Find = +Fortress = +Geraniums are Blue = +Get the achievements statistics for the given player or yourself = +Girl's Best Friend = +Glacier Discoverer = +Glasser = +Gold Rush = +Grasslands Discoverer = +Hardened Miner = +Hardest Block on Earth = +Harvest 125 fully grown wheat plants. = +Harvest 25 fully grown wheat plants. = +Harvest 625 fully grown wheat plants. = +Harvest a fully grown wheat plant. = +Hotelier = +House of Obsidian = +In the Dungeon = +Industrial Age = +Join the game %d times. = +Join the game. = +Jungle Discoverer = +Junglebaby = +Jungleman = +Lava Miner = +Lava and Water = +Light It Up = +List awards in chat (deprecated) = +Little Library = +Long Ladder = +Lumberjack = +Marchand De Sable = +Master Miner = +Mese Mastery = +Mine 18 diamond ores. = +Mine 45 gold ores. = +Mine 50 obsidian. = +Mine a block: %s = +Mine a mese block. = +Mine a mossy cobblestone. = +Mine a nyan cat. = +Mine any block while being very close to lava. = +Mine blocks: %d×%s = +Mine some dry grass. = +Mine some grass. = +Mine your first cactus. = +Mine your first diamond ore. = +Mine your first dry shrub. = +Mine your first gold ore. = +Mine your first ice. = +Mine your first jungle grass. = +Mine your first mese ore. = +Mine your first obsidian. = +Mini Miner = +Obsessed with Obsidian = +On The Way = +Outpost = +Pharaoh = +Place 1,000 torches. = +Place 100 rails. = +Place 100 stone. = +Place 100 torches. = +Place 2 trap stones. = +Place 20 coal checkers. = +Place 20 iron checkers. = +Place 40 steel ladders. = +Place 400 wooden ladders. = +Place a block: %s = +Place blocks: %d×%s = +Place two snow blocks. = +Professional Lumberjack = +Put out 1000 fires. = +Pyromaniac = +Really Well Lit = +Roses Are Red = +Saint-Maclou = +Sam the Trapper = +Savannah Discoverer = +Secret Achievement Unlocked! = +Secret Achievement Unlocked: = +Secret Achievement Unlocked: %s = +Semi-pro Lumberjack = +Show details of an achievement = +Show, clear, disable or enable your achievements = +Smelter = +Treasurer = +Unlock this award to find out what it is. = +Very Simple Snow Man = +Watchtower = +Well Lit = +Wheat Magnate = +White Color Stock = +Wool Over Your Eyes = +Wow, I am Diamonds! = +Write %d chat messages. = +Write something in chat. = +You have disabled your achievements. = +You have enabled your achievements. = +You have not unlocked any awards. = +You've disabled awards. Type /awards enable to reenable. = +You’re a copper = +[c|clear|disable|enable] = +OK = +Error: No awards available. = +Eat: %d×%s = +Eat: %s = +%d/%d eaten = +Place %d block(s). = +Dig %d block(s). = +Eat %d item(s). = +Craft %d item(s). = +Yummy! = +Baker = +Eat 10 loaves of bread. = +Eat 80 apples. = +Tasty Mushrooms = +Mushroom Lover = +Underground Mushroom Farmer = +Eat 3 brown mushrooms. = +Eat 33 brown mushrooms. = +Eat 333 brown mushrooms. = diff --git a/mods/HUD/awards/mod.conf b/mods/HUD/awards/mod.conf new file mode 100644 index 0000000000..24042f2678 --- /dev/null +++ b/mods/HUD/awards/mod.conf @@ -0,0 +1,7 @@ +name = awards +title = Achievements +author = rubenwardy +description = Adds achievements to Minetest, and an API to register new ones. +license = LGPL 2.1 or later +forum = https://forum.minetest.net/viewtopic.php?t=4870 +version = 2.3.0 diff --git a/mods/HUD/awards/readme.md b/mods/HUD/awards/readme.md new file mode 100644 index 0000000000..83235130ab --- /dev/null +++ b/mods/HUD/awards/readme.md @@ -0,0 +1,162 @@ +# Awards + +by Andrew "Rubenwardy" Ward, LGPL 2.1 or later. + +This mod adds achievements to Minetest. + +Majority of awards are back ported from Calinou's +old fork in Carbone, under same license. + + +# Basic API + +* awards.register_achievement(name, def) + * name + * desciption + * sound [optional] - set a custom sound (SimpleSoundSpec) or `false` to play no sound. + If not specified, a default sound is played + * image [optional] - texture name, eg: award_one.png + * background [optional] - texture name, eg: award_one.png + * trigger [optional] [table] + * type - "dig", "place", "craft", "death", "chat", "join" or "eat" + * dig type: Dig a node. + * node: the dug node type. If nil, all dug nodes are counted + * place type: Place a node. + * node: the placed node type. If nil, all placed nodes are counted + * eat type: Eat an item. + * item: the eaten item type. If nil, all eaten items are counted + * craft type: Craft something. + * item: the crafted item type. If nil, all crafted items are counted + * death type: Die. + * chat type: Write a chat message. + * join type: Join the server. + * (for all types) target - how many times to dig/place/craft/etc. + * See Triggers + * secret [optional] - if true, then player needs to unlock to find out what it is. + * on_unlock [optional] - func(name, def) + * name is player name + * return true to cancel register_on_unlock callbacks and HUD +* awards.register_trigger(name, func(awardname, def)) + * Note: awards.on[name] is automatically created for triggers +* awards.run_trigger_callbacks(player, data, trigger, table_func(entry)) + * Goes through and checks all triggers registered to a trigger type, + unlocking the award if conditions are met. + * data is the player's award data, ie: awards.players[player_name] + * trigger is the name of the trigger type. Ie: awards.on[trigger] + * table_func is called if the trigger is a table - simply return an + award name to unlock it + * See triggers.lua for examples +* awards.increment_item_counter(data, field, itemname) + * add to an item's statistic count + * for example, (data, "place", "default:stone") will add 1 to the number of + times default:stone has been placed. + * data is the player's award data, ie: awards.players[player_name] + * returns true on success, false on failure (eg: cannot get modname and item from itemname) +* awards.register_on_unlock(func(name, def)) + * name is the player name + * def is the award def. + * return true to cancel HUD +* awards.unlock(name, award) + * gives an award to a player + * name is the player name + +# Included in the Mod + +The API, above, allows you to register awards +and triggers (things that look for events and unlock awards, they need +to be registered in order to get details from award_def.trigger). + +However, all awards and triggers are separate from the API. +They can be found in init.lua and triggers.lua + +## Triggers + +Callbacks (register a function to be run) + +### dig + + trigger = { + type = "dig", + node = "default:dirt", + target = 50 + } + +### place + + trigger = { + type = "place", + node = "default:dirt", + target = 50 + } + +### death + + trigger = { + type = "death", + target = 5 + } + +### chat + + trigger = { + type = "chat", + target = 100 + } + +### join + + trigger = { + type = "join", + target = 100 + } + +### eat + + trigger = { + type = "eat", + item = "default:apple", + target = 100 + } + +## Callbacks relating to triggers + +* awards.register_on_dig(func(player, data)) + * data is player data (see below) + * return award name or null +* awards.register_on_place(func(player, data)) + * data is player data (see below) + * return award name or null +* awards.register_on_eat(func(player, data)) + * data is player data (see below) + * return award name or null +* awards.register_on_death(func(player, data)) + * data is player data (see below) + * return award name or null +* awards.register_on_chat(func(player, data)) + * data is player data (see below) + * return award name or null +* awards.register_on_join(func(player, data) + * data is player data (see below) + * return award name or null + + +# Player Data + +A list of data referenced/hashed by the player's name. +* player name + * name [string] + * count [table] - dig counter + * modname [table] + * itemname [int] + * place [table] - place counter + * modname [table] + * itemname [int] + * craft [table] - craft counter + * modname [table] + * itemname [int] + * eat [table] - eat counter + * modname [table] + * itemname [int] + * deaths + * chats + * joins diff --git a/mods/HUD/awards/screenshot.png b/mods/HUD/awards/screenshot.png new file mode 100644 index 0000000000..ab9e19e567 Binary files /dev/null and b/mods/HUD/awards/screenshot.png differ diff --git a/mods/HUD/awards/sfinv.lua b/mods/HUD/awards/sfinv.lua new file mode 100644 index 0000000000..de85998c39 --- /dev/null +++ b/mods/HUD/awards/sfinv.lua @@ -0,0 +1,30 @@ +if minetest.get_modpath("sfinv") then + local S + if minetest.get_modpath("intllib") then + S = intllib.Getter() + else + S = function ( s ) return s end + end + + sfinv.register_page("awards:awards", { + title = S("Awards"), + on_enter = function(self, player, context) + context.awards_idx = 1 + end, + get = function(self, player, context) + local name = player:get_player_name() + return sfinv.make_formspec(player, context, + awards.getFormspec(name, name, context.awards_idx or 1), + false, "size[11,5]") + end, + on_player_receive_fields = function(self, player, context, fields) + if fields.awards then + local event = minetest.explode_textlist_event(fields.awards) + if event.type == "CHG" then + context.awards_idx = event.index + sfinv.set_player_inventory_formspec(player, context) + end + end + end + }) +end diff --git a/mods/HUD/awards/sounds/awards_got_generic.ogg b/mods/HUD/awards/sounds/awards_got_generic.ogg new file mode 100644 index 0000000000..3ae982b3a8 Binary files /dev/null and b/mods/HUD/awards/sounds/awards_got_generic.ogg differ diff --git a/mods/HUD/awards/textures/awards_bg_default.png b/mods/HUD/awards/textures/awards_bg_default.png new file mode 100644 index 0000000000..a6f57d3220 Binary files /dev/null and b/mods/HUD/awards/textures/awards_bg_default.png differ diff --git a/mods/HUD/awards/textures/awards_bg_mining.png b/mods/HUD/awards/textures/awards_bg_mining.png new file mode 100644 index 0000000000..a6987794f0 Binary files /dev/null and b/mods/HUD/awards/textures/awards_bg_mining.png differ diff --git a/mods/HUD/awards/textures/awards_firefighter.png b/mods/HUD/awards/textures/awards_firefighter.png new file mode 100644 index 0000000000..7c2236bb43 Binary files /dev/null and b/mods/HUD/awards/textures/awards_firefighter.png differ diff --git a/mods/HUD/awards/textures/awards_house.png b/mods/HUD/awards/textures/awards_house.png new file mode 100644 index 0000000000..e23e30d4ad Binary files /dev/null and b/mods/HUD/awards/textures/awards_house.png differ diff --git a/mods/HUD/awards/textures/awards_level1.png b/mods/HUD/awards/textures/awards_level1.png new file mode 100644 index 0000000000..8f628f3386 Binary files /dev/null and b/mods/HUD/awards/textures/awards_level1.png differ diff --git a/mods/HUD/awards/textures/awards_level2.png b/mods/HUD/awards/textures/awards_level2.png new file mode 100644 index 0000000000..9f9564facd Binary files /dev/null and b/mods/HUD/awards/textures/awards_level2.png differ diff --git a/mods/HUD/awards/textures/awards_level3.png b/mods/HUD/awards/textures/awards_level3.png new file mode 100644 index 0000000000..8931454ad3 Binary files /dev/null and b/mods/HUD/awards/textures/awards_level3.png differ diff --git a/mods/HUD/awards/textures/awards_level4.png b/mods/HUD/awards/textures/awards_level4.png new file mode 100644 index 0000000000..68e393f045 Binary files /dev/null and b/mods/HUD/awards/textures/awards_level4.png differ diff --git a/mods/HUD/awards/textures/awards_level5.png b/mods/HUD/awards/textures/awards_level5.png new file mode 100644 index 0000000000..d0a05bcc9a Binary files /dev/null and b/mods/HUD/awards/textures/awards_level5.png differ diff --git a/mods/HUD/awards/textures/awards_level6.png b/mods/HUD/awards/textures/awards_level6.png new file mode 100644 index 0000000000..5c6482fdf9 Binary files /dev/null and b/mods/HUD/awards/textures/awards_level6.png differ diff --git a/mods/HUD/awards/textures/awards_level7.png b/mods/HUD/awards/textures/awards_level7.png new file mode 100644 index 0000000000..5e318d81f1 Binary files /dev/null and b/mods/HUD/awards/textures/awards_level7.png differ diff --git a/mods/HUD/awards/textures/awards_mese.png b/mods/HUD/awards/textures/awards_mese.png new file mode 100644 index 0000000000..3fc800ec30 Binary files /dev/null and b/mods/HUD/awards/textures/awards_mese.png differ diff --git a/mods/HUD/awards/textures/awards_miniminer.png b/mods/HUD/awards/textures/awards_miniminer.png new file mode 100644 index 0000000000..45c72384e9 Binary files /dev/null and b/mods/HUD/awards/textures/awards_miniminer.png differ diff --git a/mods/HUD/awards/textures/awards_novicebuilder.png b/mods/HUD/awards/textures/awards_novicebuilder.png new file mode 100644 index 0000000000..f24d843ca4 Binary files /dev/null and b/mods/HUD/awards/textures/awards_novicebuilder.png differ diff --git a/mods/HUD/awards/textures/awards_progress_gray.png b/mods/HUD/awards/textures/awards_progress_gray.png new file mode 100644 index 0000000000..a5fc6cb35b Binary files /dev/null and b/mods/HUD/awards/textures/awards_progress_gray.png differ diff --git a/mods/HUD/awards/textures/awards_progress_green.png b/mods/HUD/awards/textures/awards_progress_green.png new file mode 100644 index 0000000000..54b4e5d5a4 Binary files /dev/null and b/mods/HUD/awards/textures/awards_progress_green.png differ diff --git a/mods/HUD/awards/textures/awards_template.png b/mods/HUD/awards/textures/awards_template.png new file mode 100644 index 0000000000..b290454803 Binary files /dev/null and b/mods/HUD/awards/textures/awards_template.png differ diff --git a/mods/HUD/awards/textures/awards_ui_bags.png b/mods/HUD/awards/textures/awards_ui_bags.png new file mode 100644 index 0000000000..4d6eb57117 Binary files /dev/null and b/mods/HUD/awards/textures/awards_ui_bags.png differ diff --git a/mods/HUD/awards/textures/awards_ui_icon.png b/mods/HUD/awards/textures/awards_ui_icon.png new file mode 100644 index 0000000000..239ad71ec9 Binary files /dev/null and b/mods/HUD/awards/textures/awards_ui_icon.png differ diff --git a/mods/HUD/awards/textures/awards_unknown.png b/mods/HUD/awards/textures/awards_unknown.png new file mode 100644 index 0000000000..b290454803 Binary files /dev/null and b/mods/HUD/awards/textures/awards_unknown.png differ diff --git a/mods/HUD/awards/triggers.lua b/mods/HUD/awards/triggers.lua new file mode 100644 index 0000000000..88a952fdfc --- /dev/null +++ b/mods/HUD/awards/triggers.lua @@ -0,0 +1,416 @@ +-- AWARDS +-- +-- Copyright (C) 2013-2015 rubenwardy +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU Lesser General Public License as published by +-- the Free Software Foundation; either version 2.1 of the License, or +-- (at your option) any later version. +-- This 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 Lesser General Public License for more details. +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +-- + +local S +if minetest.get_modpath("intllib") then + S = intllib.Getter() +else + S = function ( s ) return s end +end + +awards.register_trigger("dig", function(def) + local tmp = { + award = def.name, + node = def.trigger.node, + target = def.trigger.target, + } + table.insert(awards.on.dig, tmp) + def.getProgress = function(self, data) + local itemcount + if tmp.node then + itemcount = awards.get_item_count(data, "count", tmp.node) or 0 + else + itemcount = awards.get_total_item_count(data, "count") + end + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d dug"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.node then + local nname = minetest.registered_nodes[self.trigger.node].description + if nname == nil then + nname = self.trigger.node + end + if self.trigger.target ~= 1 then + return string.format(S("Mine blocks: %d×%s"), self.trigger.target, nname) + else + return string.format(S("Mine a block: %s"), nname) + end + else + return string.format(S("Mine %d block(s)."), self.trigger.target) + end + end +end) + +awards.register_trigger("place", function(def) + local tmp = { + award = def.name, + node = def.trigger.node, + target = def.trigger.target, + } + table.insert(awards.on.place, tmp) + def.getProgress = function(self, data) + local itemcount + if tmp.node then + itemcount = awards.get_item_count(data, "place", tmp.node) or 0 + else + itemcount = awards.get_total_item_count(data, "place") + end + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d placed"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.node then + local nname = minetest.registered_nodes[self.trigger.node].description + if nname == nil then + nname = self.trigger.node + end + if self.trigger.target ~= 1 then + return string.format(S("Place blocks: %d×%s"), self.trigger.target, nname) + else + return string.format(S("Place a block: %s"), nname) + end + else + return string.format(S("Place %d block(s)."), self.trigger.target) + end + end +end) + +awards.register_trigger("eat", function(def) + local tmp = { + award = def.name, + item = def.trigger.item, + target = def.trigger.target, + } + table.insert(awards.on.eat, tmp) + def.getProgress = function(self, data) + local itemcount + if tmp.item then + itemcount = awards.get_item_count(data, "eat", tmp.item) or 0 + else + itemcount = awards.get_total_item_count(data, "eat") + end + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d eaten"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.item then + local iname = minetest.registered_items[self.trigger.item].description + if iname == nil then + iname = self.trigger.iode + end + if self.trigger.target ~= 1 then + return string.format(S("Eat: %d×%s"), self.trigger.target, iname) + else + return string.format(S("Eat: %s"), iname) + end + else + return string.format(S("Eat %d item(s)."), self.trigger.target) + end + end +end) + +awards.register_trigger("death", function(def) + local tmp = { + award = def.name, + target = def.trigger.target, + } + table.insert(awards.on.death, tmp) + def.getProgress = function(self, data) + local itemcount = data.deaths or 0 + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d deaths"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.target ~= 1 then + return string.format(S("Die %d times."), self.trigger.target) + else + return S("Die.") + end + end +end) + +awards.register_trigger("chat", function(def) + local tmp = { + award = def.name, + target = def.trigger.target, + } + table.insert(awards.on.chat, tmp) + def.getProgress = function(self, data) + local itemcount = data.chats or 0 + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d chat messages"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.target ~= 1 then + return string.format(S("Write %d chat messages."), self.trigger.target) + else + return S("Write something in chat.") + end + end +end) + +awards.register_trigger("join", function(def) + local tmp = { + award = def.name, + target = def.trigger.target, + } + table.insert(awards.on.join, tmp) + def.getProgress = function(self, data) + local itemcount = data.joins or 0 + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d game joins"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.target ~= 1 then + return string.format(S("Join the game %d times."), self.trigger.target) + else + return S("Join the game.") + end + end +end) + +awards.register_trigger("craft", function(def) + local tmp = { + award = def.name, + item = def.trigger.item, + target = def.trigger.target, + } + table.insert(awards.on.craft, tmp) + def.getProgress = function(self, data) + local itemcount + if tmp.item then + itemcount = awards.get_item_count(data, "craft", tmp.item) or 0 + else + itemcount = awards.get_total_item_count(data, "craft") + end + return { + perc = itemcount / tmp.target, + label = string.format(S("%d/%d crafted"), itemcount, tmp.target) + } + end + def.getDefaultDescription = function(self) + if self.trigger.item then + local iname = minetest.registered_items[self.trigger.item].description + if iname == nil then + iname = self.trigger.item + end + if self.trigger.target ~= 1 then + return string.format(S("Craft: %d×%s"), self.trigger.target, iname) + else + return string.format(S("Craft: %s"), iname) + end + else + return string.format(S("Craft %d item(s)."), self.trigger.target) + end + end +end) + +-- Backwards compatibility +awards.register_onDig = awards.register_on_dig +awards.register_onPlace = awards.register_on_place +awards.register_onDeath = awards.register_on_death +awards.register_onChat = awards.register_on_chat +awards.register_onJoin = awards.register_on_join +awards.register_onCraft = awards.register_on_craft + +-- Trigger Handles +minetest.register_on_dignode(function(pos, oldnode, digger) + if not digger or not pos or not oldnode then + return + end + + local data = awards.players[digger:get_player_name()] + if not awards.increment_item_counter(data, "count", oldnode.name) then + return + end + awards.run_trigger_callbacks(digger, data, "dig", function(entry) + if entry.target then + if entry.node then + local tnodedug = string.split(entry.node, ":") + local tmod = tnodedug[1] + local titem = tnodedug[2] + if not tmod or not titem or not data.count[tmod] or not data.count[tmod][titem] then + -- table running failed! + elseif data.count[tmod][titem] > entry.target-1 then + return entry.award + end + elseif awards.get_total_item_count(data, "count") > entry.target-1 then + return entry.award + end + end + end) +end) + +minetest.register_on_placenode(function(pos, node, digger) + if not digger or not pos or not node or not digger:get_player_name() or digger:get_player_name()=="" then + return + end + local data = awards.players[digger:get_player_name()] + if not awards.increment_item_counter(data, "place", node.name) then + return + end + + awards.run_trigger_callbacks(digger, data, "place", function(entry) + if entry.target then + if entry.node then + local tnodedug = string.split(entry.node, ":") + local tmod = tnodedug[1] + local titem = tnodedug[2] + if not tmod or not titem or not data.place[tmod] or not data.place[tmod][titem] then + -- table running failed! + elseif data.place[tmod][titem] > entry.target-1 then + return entry.award + end + elseif awards.get_total_item_count(data, "place") > entry.target-1 then + return entry.award + end + end + end) +end) + +minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing) + if not user or not itemstack or not user:get_player_name() or user:get_player_name()=="" then + return + end + local data = awards.players[user:get_player_name()] + if not awards.increment_item_counter(data, "eat", itemstack:get_name()) then + return + end + awards.run_trigger_callbacks(user, data, "eat", function(entry) + if entry.target then + if entry.item then + local titemstring = string.split(entry.item, ":") + local tmod = titemstring[1] + local titem = titemstring[2] + if not tmod or not titem or not data.eat[tmod] or not data.eat[tmod][titem] then + -- table running failed! + elseif data.eat[tmod][titem] > entry.target-1 then + return entry.award + end + elseif awards.get_total_item_count(data, "eat") > entry.target-1 then + return entry.award + end + end + end) +end) + +minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) + if not player or not itemstack then + return + end + + local data = awards.players[player:get_player_name()] + if not awards.increment_item_counter(data, "craft", itemstack:get_name(), itemstack:get_count()) then + return + end + + awards.run_trigger_callbacks(player, data, "craft", function(entry) + if entry.target then + if entry.item then + local titemcrafted = string.split(entry.item, ":") + local tmod = titemcrafted[1] + local titem = titemcrafted[2] + if not tmod or not titem or not data.craft[tmod] or not data.craft[tmod][titem] then + -- table running failed! + elseif data.craft[tmod][titem] > entry.target-1 then + return entry.award + end + elseif awards.get_total_item_count(data, "craft") > entry.target-1 then + return entry.award + end + end + end) +end) + +minetest.register_on_dieplayer(function(player) + -- Run checks + local name = player:get_player_name() + if not player or not name or name=="" then + return + end + + -- Get player + awards.assertPlayer(name) + local data = awards.players[name] + + -- Increment counter + data.deaths = data.deaths + 1 + + awards.run_trigger_callbacks(player, data, "death", function(entry) + if entry.target and entry.award and data.deaths and + data.deaths >= entry.target then + return entry.award + end + end) +end) + +minetest.register_on_joinplayer(function(player) + -- Run checks + local name = player:get_player_name() + if not player or not name or name=="" then + return + end + + -- Get player + awards.assertPlayer(name) + local data = awards.players[name] + + -- Increment counter + data.joins = data.joins + 1 + + awards.run_trigger_callbacks(player, data, "join", function(entry) + if entry.target and entry.award and data.joins and + data.joins >= entry.target then + return entry.award + end + end) +end) + +minetest.register_on_chat_message(function(name, message) + -- Run checks + local idx = string.find(message,"/") + if not name or (idx ~= nil and idx <= 1) then + return + end + + -- Get player + awards.assertPlayer(name) + local data = awards.players[name] + local player = minetest.get_player_by_name(name) + + -- Increment counter + data.chats = data.chats + 1 + + awards.run_trigger_callbacks(player, data, "chat", function(entry) + if entry.target and entry.award and data.chats and + data.chats >= entry.target then + return entry.award + end + end) +end) diff --git a/mods/HUD/awards/unified_inventory.lua b/mods/HUD/awards/unified_inventory.lua new file mode 100644 index 0000000000..a4bb02dc3e --- /dev/null +++ b/mods/HUD/awards/unified_inventory.lua @@ -0,0 +1,18 @@ +if minetest.get_modpath("unified_inventory") ~= nil then + local S + if minetest.get_modpath("intllib") then + S = intllib.Getter() + else + S = function ( s ) return s end + end + + unified_inventory.register_button("awards", { + type = "image", + image = "awards_ui_icon.png", + tooltip = S("Awards"), + action = function(player) + local name = player:get_player_name() + awards.show_to(name, name, nil, false) + end, + }) +end