make fly_in a map

This commit is contained in:
kno10 2025-01-08 00:26:34 +01:00
parent ac1333be94
commit a4fa9c1913
3 changed files with 47 additions and 45 deletions
mods/ENTITIES/mcl_mobs

View file

@ -127,6 +127,23 @@ function mcl_mobs.register_mob(name, def)
end
end
local fly_in = {}
if type(def.fly_in) == "string" then
fly_in[def.fly_in] = true
elseif def.fly_in then
for k,v in pairs(def.fly_in) do
if type(k) == "number" then
fly_in[v] = true
elseif v == true then
fly_in[k] = true
else
minetest.log("warning", "mob "..name.." fly_in not understood: "..dump(k).." "..dump(v))
end
end
else
fly_in["air"] = true
end
local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}
-- Workaround for <https://github.com/minetest/minetest/issues/5966>:
-- Increase upper Y limit to avoid mobs glitching through solid nodes.
@ -153,7 +170,7 @@ function mcl_mobs.register_mob(name, def)
attack_type = def.attack_type,
attack_frequency = def.attack_frequency,
fly = def.fly or false,
fly_in = (type(def.fly_in) == "string" and {def.fly_in}) or def.fly_in or {"air"},
fly_in = fly_in,
owner = def.owner or "",
order = def.order or "",
on_die = def.on_die,

View file

@ -291,22 +291,9 @@ end
-- are we flying in what we are suppose to? (taikedz)
function mob_class:flight_check()
local nod = self.standing_in
local def = minetest.registered_nodes[nod]
if not def then return false end -- nil check
for _,checknode in pairs(self.fly_in or {"air"}) do
if nod == checknode or nod == "ignore" then
return true
end
if checknode == "air" and def.drawtype == "airlike" then
return true
end
end
return false
if nod == "ignore" then return true end
return not not self.fly_in[nod] -- force boolean
end
-- check if mob is dead or only hurt

View file

@ -530,16 +530,11 @@ local function get_water_spawn(p)
end
end
local FLY_IN_AIR = { air = true }
local function has_room(self, pos)
local cb = self.spawnbox or self.collisionbox
local nodes = self.fly_in or { "air" }
local airlike = false
for i=1,#nodes do
if nodes[i] == "air" then
airlike = true
break
end
end
local fly_in = self.fly_in or FLY_IN_AIR
local fly_in_air = not not fly_in["air"]
-- Calculate area to check for room
local cb_height = cb[5] - cb[2]
@ -564,26 +559,29 @@ local function has_room(self, pos)
p.x = x
local node = get_node(p)
local nam = node.name
if nam == "ignore" then goto continue end
if nam == "air" and airlike then goto continue end
if airlike then
local n_def = registered_nodes[nam]
if not n_def then goto continue end
if not n_def.walkable and n_def.liquidtype == "none" then goto continue end
local n_def = registered_nodes[nam]
-- Fast-track common cases:
local continue = nam == "ignore" or (nam == "air" and fly_in_air) or not n_def
-- if fly_in "air", also include other non-walkable non-liquid nodes:
continue = continue or (fly_in_air and n_def and not n_def.walkable and n_def.liquidtype == "none")
-- other things we can fly in
continue = continue or not not fly_in[nam]
if not continue then
if not check_headroom then
return false
end
if n_def.node_box == "regular" then
return false
end
-- perform sub-node checks in top layer
local boxes = minetest.get_node_boxes("collision_box", p, node)
for i = 1,#boxes do
-- headroom is measured from the bottom, hence +0.5
if boxes[i][2] + 0.5 < headroom then
return false
end
end
end
for i = 1,#nodes do
-- todo: support groups, too?
if nam == nodes[i] then goto continue end
end
if not check_headroom then return false end
-- perform sub-node checks in top layer
local boxes = minetest.get_node_boxes("collision_box", p, node)
for i = 1,#boxes do
local box = boxes[i]
if box[2] + 0.5 < headroom then return false end
if box[5] + 0.5 < headroom then return false end
end
::continue::
end
end
end
@ -680,7 +678,7 @@ function mcl_mobs.spawn(pos,id)
if not def or not def.is_mob or (def.can_spawn and not def.can_spawn(pos)) then return false end
if not has_room(def, pos) then return false end
if math.round(pos.y) == pos.y then -- node spawn
pos.y = pos.y - 0.5 - def.collisionbox[2] -- spawn just above ground below
pos.y = pos.y - 0.495 - def.collisionbox[2] -- spawn just above ground below
end
local obj = minetest.add_entity(pos, def.name)
-- initialize head bone
@ -725,7 +723,7 @@ local S = minetest.get_translator("mcl_mobs")
minetest.register_chatcommand("spawn_mob",{
privs = { debug = true },
description=S("spawn_mob is a chatcommand that allows you to type in the name of a mob without 'typing mobs_mc:' all the time like so; 'spawn_mob spider'. however, there is more you can do with this special command, currently you can edit any number, boolean, and string variable you choose with this format: spawn_mob 'any_mob:var<mobs_variable=variable_value>:'. any_mob being your mob of choice, mobs_variable being the variable, and variable value being the value of the chosen variable. and example of this format: \n spawn_mob skeleton:var<passive=true>:\n this would spawn a skeleton that wouldn't attack you. REMEMBER-THIS> when changing a number value always prefix it with 'NUM', example: \n spawn_mob skeleton:var<jump_height=NUM10>:\n this setting the skelly's jump height to 10. if you want to make multiple changes to a mob, you can, example: \n spawn_mob skeleton:var<passive=true>::var<jump_height=NUM10>::var<fly_in=air>::var<fly=true>:\n etc."),
description=S("spawn_mob is a chatcommand that allows you to type in the name of a mob without 'typing mobs_mc:' all the time like so; 'spawn_mob spider'. however, there is more you can do with this special command, currently you can edit any number, boolean, and string variable you choose with this format: spawn_mob 'any_mob:var<mobs_variable=variable_value>:'. any_mob being your mob of choice, mobs_variable being the variable, and variable value being the value of the chosen variable. and example of this format: \n spawn_mob skeleton:var<passive=true>:\n this would spawn a skeleton that wouldn't attack you. REMEMBER-THIS> when changing a number value always prefix it with 'NUM', example: \n spawn_mob skeleton:var<jump_height=NUM10>:\n this setting the skelly's jump height to 10. if you want to make multiple changes to a mob, you can, example: \n spawn_mob skeleton:var<passive=true>::var<jump_height=NUM10>::var<fly=true>:\n etc."),
func = function(n,param)
local pos = minetest.get_player_by_name(n):get_pos()