Change creepers line of sight check to raycast and do it from eyes to targets feet and head

This commit is contained in:
ancientmarinerdev 2023-08-31 23:12:30 +01:00
parent a648e53699
commit 1749712318
3 changed files with 79 additions and 1 deletions

@ -853,7 +853,8 @@ function mob_class:do_states_attack (dtime)
return
end
local target_line_of_sight = self:line_of_sight(s, p, 2)
local target_line_of_sight = self:target_visible(s)
if not target_line_of_sight then
if self.target_time_lost then
local time_since_seen = os.time() - self.target_time_lost

@ -76,6 +76,82 @@ function mob_class:is_node_waterhazard(nodename)
return false
end
local function raycast_line_of_sight (origin, target)
local raycast = minetest.raycast(origin, target, false, true)
local los_blocked = false
for hitpoint in raycast do
if hitpoint.type == "node" then
--TODO type object could block vision, for example chests
--minetest.log(dump(hitpoint.type))
local node = minetest.get_node(minetest.get_pointed_thing_position(hitpoint))
--minetest.log("ray node:" .. node.name)
if node.name ~= "air" then
local nodef = minetest.registered_nodes[node.name]
if nodef and nodef.walkable then
--minetest.log("walkable:" .. tostring(nodef.walkable))
los_blocked = true
break
end
end
end
end
--minetest.log("los_blocked: " .. tostring(los_blocked))
--minetest.log("visible: " .. tostring(not los_blocked))
return not los_blocked
end
function mob_class:target_visible(origin)
if not origin then return end
if not self.attack then return end
local target_pos = self.attack:get_pos()
if not target_pos then return end
local origin_eye_pos = vector.offset(origin, 0, self.head_eye_height, 0)
--minetest.log("origin: " .. dump(origin))
--minetest.log("origin_eye_pos: " .. dump(origin_eye_pos))
local targ_head_height, targ_feet_height
if self.attack:is_player() then
local cbox = self.object:get_properties().collisionbox
targ_head_height = vector.offset(target_pos, 0, cbox[5], 0)
targ_feet_height = target_pos -- Cbox would put feet under ground which interferes with ray
else
targ_head_height = vector.offset(target_pos, 0, self.collisionbox[5], 0)
targ_feet_height = vector.offset(target_pos, 0, self.collisionbox[2], 0)
end
--local target_line_of_sight = self:line_of_sight(origin_eye_pos, targ_head_height, 2)
--local target_line_of_sight_feet = self:line_of_sight(origin_eye_pos, targ_feet_height, 2)
--minetest.log("target_line_of_sight: " .. tostring(target_line_of_sight))
--minetest.log("target_line_of_sight_feet: " .. tostring(target_line_of_sight_feet))
--minetest.log("start targ_head_height: " .. dump(targ_head_height))
if raycast_line_of_sight (origin_eye_pos, targ_head_height) then
return true
end
--minetest.log("Start targ_feet_height: " .. dump(targ_feet_height))
if raycast_line_of_sight (origin_eye_pos, targ_feet_height) then
return true
end
-- TODO mid way between feet and head
--minetest.log("target is not visible so return false")
return false
end
-- check line of sight (BrunoMine)
function mob_class:line_of_sight(pos1, pos2, stepsize)

@ -24,6 +24,7 @@ mcl_mobs.register_mob("mobs_mc:creeper", {
mesh = "mobs_mc_creeper.b3d",
head_swivel = "Head_Control",
bone_eye_height = 2.35,
head_eye_height = 1.8;
curiosity = 2,
textures = {
{"mobs_mc_creeper.png",