Progress on the entity system and improve death messages
This commit is contained in:
parent
33eb16544b
commit
ca753d2803
@ -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
|
||||
|
||||
|
BIN
mods/CORE/pyutest/sounds/pyutest-entity-hurt.ogg
Normal file
BIN
mods/CORE/pyutest/sounds/pyutest-entity-hurt.ogg
Normal file
Binary file not shown.
@ -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
|
||||
})
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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)
|
||||
|
@ -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
BIN
textures/pyutest-blood.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 180 B |
Loading…
x
Reference in New Issue
Block a user