diff --git a/CHANGELOG.md b/CHANGELOG.md index 6439776..a1244dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Water freezes in cold biomes if not neighbouring heat emiting nodes - New lily pad texture - Add Time Device, it is not craftable in Survival mode and is only for Creative mode. +- Improve death messages ## [Oct 19th 2024] Bugfix Update diff --git a/mods/CORE/pyutest/sounds/pyutest-entity-hurt.ogg b/mods/CORE/pyutest/sounds/pyutest-entity-hurt.ogg new file mode 100644 index 0000000..37d1a67 Binary files /dev/null and b/mods/CORE/pyutest/sounds/pyutest-entity-hurt.ogg differ diff --git a/mods/ENTITIES/pyutest_entities/api.lua b/mods/ENTITIES/pyutest_entities/api.lua index 1bd3557..14f1501 100644 --- a/mods/ENTITIES/pyutest_entities/api.lua +++ b/mods/ENTITIES/pyutest_entities/api.lua @@ -1,6 +1,7 @@ -local PATH_FIND_ALGORITHM = "Dijkstra" --- local PATH_FIND_ALGORITHM = "A*_noprefetch" --- local PATH_FIND_ALGORITHM = "A*" +local PATH_FIND_ALGORITHM +PATH_FIND_ALGORITHM = "Dijkstra" +-- PATH_FIND_ALGORITHM = "A*_noprefetch" +-- PATH_FIND_ALGORITHM = "A*" PyuTest.ENTITY_BLOOD_AMOUNT = 6 PyuTest.HUMAN_LIKE_CBOX = {-0.25, -1, -0.25, 0.25, 1, 0.25} @@ -28,6 +29,94 @@ PyuTest.get_nearest_entity = function (self, pos, range, only_player) return nearest end +PyuTest.register_entity_spawn = function (name, entity, def) + if def == nil then + error("Table expected for options!") + end + + minetest.register_node(name, { + description = "Entity Spawner", + groups = { + not_in_creative_inventory = 1, + }, + drawtype = "airlike", + walkable = false, + pointable = false + }) + + minetest.register_decoration({ + sidelen = 80, + decoration = name, + deco_type = "simple", + place_on = def.place_on, + spawn_by = def.spawn_by, + num_spawn_by = def.num_spawn_by, + fill_ratio = def.fill_ratio or 0.0008, + y_max = def.y_max or 31000, + y_min = def.y_min or -31000, + biomes = {} + }) + + minetest.register_lbm({ + name = name.."_spawn", + run_at_every_load = true, + nodenames = {name}, + action = function (pos) + minetest.remove_node(pos) + + local min = def.min or 1 + local max = def.max or 3 + + for _ = min, math.random(min, max) do + minetest.add_entity(pos, entity) + end + end + }) +end + +local function do_physics(luaentity, cfg, moveresult) + local obj = luaentity.object + local data = luaentity.data + local pos = obj:get_pos() + + + if cfg.gravity then + if not moveresult.touching_ground then + + end + end +end + +local function path_find_nearest_entity(luaentity, cfg, dtime, player) + local obj = luaentity.object + local data = luaentity.data + local pos = obj:get_pos() + + if data.target.path == nil then + data.target.object = PyuTest.get_nearest_entity(obj, pos, cfg.sight_range, player) + + if data.target.object == nil then + return + end + + data.target.position = data.target.object:get_pos() + data.target.path = minetest.find_path(pos, data.target.position, cfg.view_range, cfg.max_jump, cfg.max_drop, PATH_FIND_ALGORITHM) + data.target.pathindex = 1 + else + if data.target.pathindex == #data.target.path then + data.target.path = nil + data.target.object = nil + data.target.position = nil + data.target.pathindex = nil + else + local p = data.target.path[data.target.pathindex] + obj:set_velocity(p * dtime) + obj:set_yaw(vector.angle(data.target.object:get_pos(), obj:get_pos())) + data.target.pathindex = data.target.pathindex + 1 + end + end +end + PyuTest.make_mob = function (name, properties, options) local default_options = { ai = "dummy", @@ -37,7 +126,13 @@ PyuTest.make_mob = function (name, properties, options) view_range = 3, sight_range = 10, gravity = true, - gravity_multiplier = 1 + gravity_multiplier = 1, + health_regen = true, + + sounds = { + hurt = "pyutest-entity-hurt" + }, + drops = {} } local cfg = {} @@ -55,12 +150,14 @@ PyuTest.make_mob = function (name, properties, options) minetest.register_entity(name, { initial_properties = PyuTest.util.tableconcat(properties, { + hp_max = properties.hp_max or 20, physical = true, collide_with_objects = true, stepheight = properties.stepheight or 1.1, collisionbox = collisionbox, selectionbox = properties.selectionbox or collisionbox, - show_on_minimap = properties.show_on_minimap or true + show_on_minimap = properties.show_on_minimap or true, + infotext = "", }), options = cfg, data = { @@ -73,39 +170,62 @@ PyuTest.make_mob = function (name, properties, options) }, on_step = function (self, dtime, moveresult) - local obj = self.object - local pos = obj:get_pos() local ai = self.options.ai - local data = self.data + local obj = self.object + local p = obj:get_properties() + + local hp = obj:get_hp() + if cfg.health_regen and not (hp >= p.hp_max) then + obj:set_hp(hp + 0.5) + end + + if obj:get_hp() > p.hp_max then + obj:set_hp(p.hp_max) + end + + p.infotext = string.format("Mob Health: %d/%d", obj:get_hp(), p.hp_max) + obj:set_properties(p) if ai == nil or ai == "dummy" then return end + do_physics(self, cfg, moveresult) + if ai == "follownearest" then - if data.target.path == nil then - data.target.object = PyuTest.get_nearest_entity(obj, pos, cfg.sight_range, true) + path_find_nearest_entity(self, cfg, dtime, true) + end + end, - if data.target.object == nil then - return - end + on_punch = function (self) + local pos = self.object:get_pos() + minetest.sound_play(cfg.sounds.hurt, {pos = pos}) - data.target.position = data.target.object:get_pos() - data.target.path = minetest.find_path(pos, data.target.position, cfg.view_range, cfg.max_jump, cfg.max_drop, PATH_FIND_ALGORITHM) - data.target.pathindex = 1 - else - if data.target.pathindex == #data.target.path then - data.target.path = nil - data.target.object = nil - data.target.position = nil - data.target.pathindex = nil - else - local p = data.target.path[data.target.pathindex] - obj:move_to(p) - obj:set_yaw(vector.angle(data.target.object:get_pos(), obj:get_pos())) - data.target.pathindex = data.target.pathindex + 1 - end - end + minetest.add_particlespawner({ + amount = 8, + time = 0.4, + minexptime = 0.4, + maxexptime = 0.8, + minsize = 1.5, + maxsize = 1.62, + vertical = false, + glow = minetest.LIGHT_MAX, + + collisiondetection = false, + texture = "pyutest-blood.png", + + minpos = pos, + maxpos = pos, + minvel = vector.new(-1, -1, 1), + maxvel = vector.new(1, 1, 1), + }) + end, + + on_death = function (self) + local pos = self.object:get_pos() + + for _, v in pairs(cfg.drops) do + minetest.add_item(pos, v) end end }) diff --git a/mods/ENTITIES/pyutest_entities/init.lua b/mods/ENTITIES/pyutest_entities/init.lua index 41c4802..f1d1568 100644 --- a/mods/ENTITIES/pyutest_entities/init.lua +++ b/mods/ENTITIES/pyutest_entities/init.lua @@ -2,16 +2,38 @@ local modpath = minetest.get_modpath("pyutest_entities") dofile(modpath .. "/api.lua") PyuTest.make_mob("pyutest_entities:test_follower", { - hp_max = 2, + visual = "upright_sprite", + visual_size = {x = 1, y = 2}, + makes_footstep_sound = true, + textures = { + "pyutest-monster.png", "pyutest-monster_back.png" + }, + nametag = "Test Follower", +}, { + ai = "follownearest", + max_jump = 1, + view_range = 3, + + drops = { + "pyutest_tools:apple 5" + } +}) + +PyuTest.make_mob("pyutest_entities:dummy", { visual = "upright_sprite", visual_size = {x = 1, y = 2}, makes_footstep_sound = true, textures = { "player.png", "player_back.png" }, - nametag = "Test Follower" -}, { - ai = "follownearest", - max_jump = 1, - view_range = 3, + nametag = "Dummy", +}, {}) + +PyuTest.register_entity_spawn("pyutest_entities:dummy_spawner", "pyutest_entities:dummy", { + min = 1, + max = 5, + + place_on = {"group:ground"}, + y_max = PyuTest.OVERWORLD_TOP, + y_min = PyuTest.OVERWORLD_SURFACE_BOTTOM }) diff --git a/mods/ITEMS/pyutest_blocks/basic.lua b/mods/ITEMS/pyutest_blocks/basic.lua index dc3861d..6999513 100644 --- a/mods/ITEMS/pyutest_blocks/basic.lua +++ b/mods/ITEMS/pyutest_blocks/basic.lua @@ -15,7 +15,7 @@ PyuTest.make_building_blocks("pyutest_blocks:podzol", "Podzol", { "pyutest-dirt. }) PyuTest.make_building_blocks("pyutest_blocks:snow", "Snow", { "pyutest-snow.png" }, nil, { -ground = 1, + ground = 1, acid_vulnerable = 1, crumbly = PyuTest.BLOCK_FAST }) diff --git a/mods/PLAYER/pyutest_player/init.lua b/mods/PLAYER/pyutest_player/init.lua index 0dbd7f9..38235af 100644 --- a/mods/PLAYER/pyutest_player/init.lua +++ b/mods/PLAYER/pyutest_player/init.lua @@ -49,7 +49,11 @@ end) -- player hand minetest.register_item(":", { type = "none", - wield_image = "pyutest-hand.png" + description = "Hands", + wield_image = "pyutest-hand.png", + groups = { + not_in_creative_inventory = 1 + } }) if minetest.is_creative_enabled("") then @@ -139,18 +143,25 @@ end) minetest.register_on_dieplayer(function(player, reason) local playername = player:get_player_name() - if reason.object ~= nil then - local le = reason.object:get_luaentity() + local message = string.format("%s died", playername) + if reason.type == "fall" then + message = string.format("%s fell from a high place", playername) + elseif reason.type == "drown" then + message = string.format("%s drowned", playername) + elseif reason.type == "respawn" then + return + elseif reason.type == "punch" then + local entity = reason.object:get_luaentity() - if le == nil then - minetest.chat_send_all(string.format("%s was slain by %s", - playername, reason.object:get_player_name())) + if entity ~= nil then + local name = reason.object:get_properties().nametag or entity.name or "an unnamed monster!" + message = string.format("%s was slain by %s", playername, name) else - local split = string.split(le.name, ":") - local name = split[#split] - name = name:gsub("_", " ") - name = string.upper(name:sub(1, 1))..name:sub(2, name:len()) - minetest.chat_send_all(string.format("%s was slain by %s", playername, name)) + local name = reason.object:get_player_name() + local itemname = reason.object:get_wielded_item():get_short_description() + message = string.format("%s was slain by %s using %s", playername, name, itemname) end end + + minetest.chat_send_all(message) end) diff --git a/mods/WORLD/pyutest_mapgen/api.lua b/mods/WORLD/pyutest_mapgen/api.lua index 1f0de96..5e92f8c 100644 --- a/mods/WORLD/pyutest_mapgen/api.lua +++ b/mods/WORLD/pyutest_mapgen/api.lua @@ -1,39 +1,39 @@ -- This function is used for structures because it will update the lighting when placed. PyuTest.register_structure = function (name, schematic, def) - local id = "pyutest_mapgen:structure_block_"..name + local id = minetest.get_current_modname()..":structure_block_"..name minetest.register_node(id, { - description = string.format("Structure Block (%s)", name), - groups = { - not_in_creative_inventory = 1 - }, - drawtype = "airlike", - walkable = false, - pointable = false, + description = string.format("Structure Block (%s)", name), + groups = { + not_in_creative_inventory = 1 + }, + drawtype = "airlike", + walkable = false, + pointable = false, }) minetest.register_decoration({ - sidelen = 80, - decoration = id, - deco_type = "simple", - place_on = def.place_on, - spawn_by = def.spawn_by, - num_spawn_by = def.num_spawn_by, - fill_ratio = def.fill_ratio, - noise_params = def.noise_params, - flags = def.flags or "place_center_x, place_center_y, force_placement", - biomes = def.biomes, - y_max = def.y_max, - y_min = def.y_min + sidelen = 80, + decoration = id, + deco_type = "simple", + place_on = def.place_on, + spawn_by = def.spawn_by, + num_spawn_by = def.num_spawn_by, + fill_ratio = def.fill_ratio, + noise_params = def.noise_params, + flags = def.flags or "place_center_x, place_center_y, force_placement", + biomes = def.biomes, + y_max = def.y_max, + y_min = def.y_min }) minetest.register_lbm({ - name = "pyutest_mapgen:spawn_"..name, - run_at_every_load = true, - nodenames = {id}, - action = function (pos, node) - minetest.remove_node(pos) - minetest.place_schematic(pos, PyuTest.get_schem_path(schematic), def.rotation or "random", def.replacements or {}, def.force_placement or true, def.flags or "place_center_x, place_center_z") - end + name = minetest.get_current_modname()..":spawn_"..name, + run_at_every_load = true, + nodenames = {id}, + action = function (pos, node) + minetest.remove_node(pos) + minetest.place_schematic(pos, PyuTest.get_schem_path(schematic), def.rotation or "random", def.replacements or {}, def.force_placement or true, def.flags or "place_center_x, place_center_z") + end }) end diff --git a/textures/pyutest-blood.png b/textures/pyutest-blood.png new file mode 100644 index 0000000..74fb491 Binary files /dev/null and b/textures/pyutest-blood.png differ