--[[ Mobs Monster EXP System Copyright (C) 2021 Noodlemire 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 --]] mobs_exp = {} local data = minetest.get_mod_storage() minetest.register_on_dieplayer(function(player) local pname = player:get_player_name() local loss = math.floor(data:get_int(pname) * 0.2) local prev_lvl = mobs_exp.exp_to_level(data:get_int(pname)) local next_lvl = mobs_exp.exp_to_level(data:get_int(pname) - loss) data:set_int(pname, data:get_int(pname) - loss) minetest.chat_send_player(pname, "Upon death, you lost "..loss.." EXP!") if next_lvl < prev_lvl then minetest.chat_send_player(pname, "Level down! You are now Tier: "..mobs_exp.roman(next_lvl)) end end) function mobs_exp.exp_to_level(e) return 1 + math.floor((math.sqrt(.4 * e + 1) - 1) / 2) end function mobs_exp.level_to_exp(l) return 10 * l * (l + 1) end function mobs_exp.exp_per_level(l) return 20 * l end function mobs_exp.roman(n) local r = "" while n >= 100 do r = r.."C" n = n - 100 end if n >= 90 then r = r.."XC" n = n - 90 end if n >= 50 then r = r.."L" n = n - 50 end if n >= 40 then r = r.."XL" n = n - 40 end while n >= 10 do r = r.."X" n = n - 10 end if n >= 9 then r = r.."IX" n = n - 9 end if n >= 5 then r = r.."V" n = n - 5 end if n >= 4 then r = r.."IV" n = n - 4 end while n >= 1 do r = r.."I" n = n - 1 end return r end minetest.register_entity("mobs_exp:orb", { initial_properties = { physical = true, collide_with_objects = false, collisionbox = {-0.125, -0.125, -0.125, 0.125, 0.125, 0.125}, pointable = false, visual = "sprite", visual_size = {x = 0.125, y = 0.125}, textures = {"mobs_exp_orb.png"}, glow = -1, static_save = false, }, on_step = function(self) local objs = minetest.get_objects_inside_radius(self.object:get_pos(), 1.5) local players = {} for _, obj in ipairs(objs) do if obj:is_player() and obj:get_hp() > 0 then table.insert(players, obj:get_player_name()) end end if #players > 0 then local exp = self.exp or 0 local player = players[math.random(#players)] local prev_lvl = mobs_exp.exp_to_level(data:get_int(player)) local next_lvl = mobs_exp.exp_to_level(data:get_int(player) + exp) data:set_int(player, data:get_int(player) + exp) minetest.chat_send_player(player, "You gained "..exp.." EXP!") if next_lvl > prev_lvl then minetest.chat_send_player(player, "Level up! You are now Tier: "..mobs_exp.roman(next_lvl)) end self.object:remove() end end, }) minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage) if hitter:is_player() and player:get_hp() > 0 and player:get_hp() - damage <= 0 then local exp = mobs_exp.exp_to_level(data:get_int(player:get_player_name())) * 5 local p = player:get_pos() local ref = minetest.add_entity({x=p.x, y=p.y+1, z=p.z}, "mobs_exp:orb") if ref then ref:get_luaentity().exp = exp end end end) minetest.register_on_mods_loaded(function() for name, def in pairs(minetest.registered_entities) do if def.mod_origin == "mobs_monster" then local old_on_die = def.on_die rawset(def, "on_die", function(self, pos) local ref = minetest.add_entity(pos, "mobs_exp:orb") if ref then local armor = self.armor > 0 and self.armor or 1 ref:get_luaentity().exp = math.ceil(((self.hp_min + self.hp_max) / 2 + self.damage) * (100 / self.armor)) end if old_on_die then old_on_die(self, pos) end end) end end end)