Progress on the entity system and improve death messages

This commit is contained in:
IamPyu 2024-10-22 19:44:01 -06:00
parent 33eb16544b
commit ca753d2803
8 changed files with 228 additions and 74 deletions

View File

@ -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

Binary file not shown.

View File

@ -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
})

View File

@ -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
})

View File

@ -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
})

View File

@ -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)

View File

@ -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

BIN
textures/pyutest-blood.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B