Fix multiple warnings, Add shallow walkable node check, Improve get_wander_pos

This commit is contained in:
ElCeejo 2022-02-20 11:37:39 -08:00
parent 43c124db15
commit 8273f25207
2 changed files with 116 additions and 140 deletions

View file

@ -58,54 +58,90 @@ local function fast_ray_sight(pos1, pos2)
return true return true
end end
local step_tick = 0.15
-- Local Utilities -- -- Local Utilities --
local default_node_def = {walkable = true} -- both ignore and unknown nodes are walkable local default_node_def = {walkable = true} -- both ignore and unknown nodes are walkable
local function get_node_def(name)
return minetest.registered_nodes[name] or default_node_def local function get_node_height(name)
local def = minetest.registered_nodes[name]
if not def then return 0.5 end
if def.walkable then
if def.drawtype == "nodebox" then
if def.node_box
and def.node_box.type == "fixed" then
if type(def.node_box.fixed[1]) == "number" then
return 0.5 + def.node_box.fixed[5]
elseif type(def.node_box.fixed[1]) == "table" then
return 0.5 + def.node_box.fixed[1][5]
else
return 1
end
else
return 1
end
else
return 1
end
else
return 1
end
end end
local function get_ground_level(pos2, max_height) local function get_node_def(name)
local def = minetest.registered_nodes[name] or default_node_def
if def.walkable
and get_node_height(name) < 0.26 then
def.walkable = false -- workaround for nodes like snow
end
return def
end
local function get_ground_level(pos2, max_diff)
local node = minetest.get_node(pos2) local node = minetest.get_node(pos2)
local node_under = minetest.get_node({ local node_under = minetest.get_node({
x = pos2.x, x = pos2.x,
y = pos2.y - 1, y = pos2.y - 1,
z = pos2.z z = pos2.z
}) })
local height = 0 local walkable = get_node_def(node_under.name) and not get_node_def(node.name)
local walkable = get_node_def(node_under).walkable and not get_node_def(node).walkable
if walkable then if walkable then
return pos2 return pos2
elseif not walkable then
if not get_node_def(node_under).walkable then
while not get_node_def(node_under).walkable
and height < max_height do
pos2.y = pos2.y - 1
node_under = minetest.get_node({
x = pos2.x,
y = pos2.y - 1,
z = pos2.z
})
height = height + 1
end
else
while get_node_def(node).walkable
and height < max_height do
pos2.y = pos2.y + 1
node = minetest.get_node(pos2)
height = height + 1
end
end
return pos2
end end
local diff = 0
if not get_node_def(node_under.name) then
for i = 1, max_diff do
pos2.y = pos2.y - 1
node = minetest.get_node(pos2)
node_under = minetest.get_node({
x = pos2.x,
y = pos2.y - 1,
z = pos2.z
})
walkable = get_node_def(node_under.name) and not get_node_def(node.name)
if walkable then break end
end
else
for i = 1, max_diff do
pos2.y = pos2.y + 1
node = minetest.get_node(pos2)
node_under = minetest.get_node({
x = pos2.x,
y = pos2.y - 1,
z = pos2.z
})
walkable = get_node_def(node_under.name) and not get_node_def(node.name)
if walkable then break end
end
end
return pos2
end end
------------------------- -------------------------
-- Physics/Vitals Tick -- -- Physics/Vitals Tick --
------------------------- -------------------------
local step_tick = 0.15
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
if step_tick <= 0 then if step_tick <= 0 then
step_tick = 0.15 step_tick = 0.15
@ -325,21 +361,56 @@ end
-- Terrain Navigation -- -- Terrain Navigation --
function mob:get_wander_pos(min_range, max_range, max_vert) function mob:get_wander_pos(min_range, max_range, dir)
local pos = vec_center(self.object:get_pos())
pos.y = floor(pos.y + 0.5)
local node = minetest.get_node(pos)
local us = minetest.get_us_time()
if get_node_def(node.name).walkable then -- Occurs if small mob is touching a fence
local offset = vector.add(pos, vec_multi(vec_dir(pos, self.object:get_pos()), 1.5))
pos.x = floor(offset.x + 0.5)
pos.z = floor(offset.z + 0.5)
pos = get_ground_level(pos, 1)
end
local width = self.width
local outset = random(min_range, max_range) local outset = random(min_range, max_range)
local move_dir = { if width < 0.6 then width = 0.6 end
local move_dir = vec_normal({
x = random(-10, 10) * 0.1, x = random(-10, 10) * 0.1,
z = 0, y = 0,
y = random(-10, 10) * 0.1 z = random(-10, 10) * 0.1
} })
local pos2 = get_ground_level(vec_add(pos, vec_multi(vec_normal(move_dir), outset)), max_vert or min_range) local pos2 = vec_add(pos, vec_multi(move_dir, width))
for i = 2, outset do if get_node_def(minetest.get_node(pos2).name).walkable
local out_pos = vec_add(pos, vec_multi(vec_normal(move_dir), i)) and not dir then
if get_node_def(minetest.get_node(out_pos).name).walkable for i = 1, 3 do
or not get_node_def(minetest.get_node(vec_raise(pos2, -1)).name).walkable then move_dir = {
x = move_dir.z,
y = 0,
z = move_dir.x * -1
}
pos2 = vec_add(pos, vec_multi(move_dir, width))
if not get_node_def(minetest.get_node(pos2).name).walkable then
break
end
end
elseif dir then
move_dir = dir
end
for i = 1, outset do
local a_pos = vec_add(pos2, vec_multi(move_dir, i))
local a_node = minetest.get_node(a_pos)
local b_pos = {x = a_pos.x, y = a_pos.y - 1, z = a_pos.z}
local b_node = minetest.get_node(b_pos)
if get_node_def(a_node.name).walkable
or not get_node_def(b_node.name).walkable then
a_pos = get_ground_level(a_pos, floor(self.stepheight or 1))
end
if not get_node_def(a_node.name).walkable then
pos2 = a_pos
else
break break
end end
pos2 = out_pos
end end
return pos2 return pos2
end end
@ -355,7 +426,7 @@ function mob:get_wander_pos_3d(min_range, max_range)
local pos2 = vec_add(pos, vec_multi(vec_normal(move_dir), 1)) local pos2 = vec_add(pos, vec_multi(vec_normal(move_dir), 1))
local fail_safe = 0 local fail_safe = 0
while fail_safe < 4 while fail_safe < 4
and get_node_def(minetest.get_node(pos2).name).walkable do and minetest.registered_nodes[minetest.get_node(pos2).name].walkable do
move_dir = { move_dir = {
x = random(-10, 10) * 0.1, x = random(-10, 10) * 0.1,
z = random(-10, 10) * 0.1, z = random(-10, 10) * 0.1,
@ -365,7 +436,7 @@ function mob:get_wander_pos_3d(min_range, max_range)
end end
for i = 2, outset do for i = 2, outset do
local out_pos = vec_add(pos, vec_multi(vec_normal(move_dir), i)) local out_pos = vec_add(pos, vec_multi(vec_normal(move_dir), i))
if get_node_def(minetest.get_node(out_pos).name).walkable then if minetest.registered_nodes[minetest.get_node(out_pos).name].walkable then
break break
end end
pos2 = out_pos pos2 = out_pos
@ -591,30 +662,6 @@ function mob:clear_action()
self._action = {} self._action = {}
end end
function mob:force_behavior(func)
self._bh_tree_data = {
active_task = #self.bh_tree + 1,
func = func,
current_selection = 1
}
end
function mob:set_behavior(func)
self._bh_tree_data = {
active_task = #self.bh_tree + 1,
func = func,
current_selection = 1
}
end
function mob:clear_behavior(func)
self._bh_tree_data = {
active_task = 0,
func = nil,
current_selection = 0
}
end
function mob:set_utility(func) function mob:set_utility(func)
self._utility_data.func = func self._utility_data.func = func
end end
@ -743,15 +790,6 @@ function mob:staticdata()
return minetest.serialize(data) return minetest.serialize(data)
end end
local function average(t)
local sum = 0
for _,v in pairs(t) do -- Get the sum of all numbers in t
sum = sum + v
end
return sum / #t
end
function mob:on_step(dtime, moveresult) function mob:on_step(dtime, moveresult)
--local us_time = minetest.get_us_time() --local us_time = minetest.get_us_time()
if not self.hp then return end if not self.hp then return end
@ -778,16 +816,10 @@ function mob:on_step(dtime, moveresult)
if self._move then if self._move then
self:_move() self:_move()
end end
-- Execute Mobkit-like Logic
self:_execute_logic()
-- Execute Task Tree
if self.bh_tree
and self._execute_bh_tree then
self:_execute_bh_tree()
end
if self.utility_stack if self.utility_stack
and self._execute_utilities then and self._execute_utilities then
self:_execute_utilities() self:_execute_utilities()
self:_execute_actions()
end end
-- Die -- Die
if self.hp <= 0 if self.hp <= 0
@ -1005,9 +1037,9 @@ function mob:_move()
end end
end end
-- Execute Tasks and Actions -- Execute Actions
function mob:_execute_logic() function mob:_execute_actions()
if not self.object then return end if not self.object then return end
local task = self._task local task = self._task
if #self._task > 0 then if #self._task > 0 then
@ -1027,62 +1059,6 @@ function mob:_execute_logic()
end end
end end
function mob:_execute_bh_tree(immediate)
if not self._bh_tree_data then
self._bh_tree_data = {
active_task = 0,
func = nil,
current_selection = 0
}
end
if (self:timer(self.task_timer or 1)
or immediate
or self._bh_tree_data.func == nil) then
for i = #self.bh_tree, 1, -1 do
local active_task_no = self._bh_tree_data.active_task
if i >= active_task_no then
local selector = self.bh_tree[i].selector
local selection, args = selector(self)
if selection
and (args
or selection < 1) then
if selection < 1
and i == active_task_no then
self._bh_tree_data = {
active_task = 0,
func = nil,
current_selection = 0
}
self:clear_action()
elseif selection > 0
and ((i > active_task_no
or selection ~= self._bh_tree_data.current_selection)
or active_task_no == 0) then
self._bh_tree_data.active_task = i
self._bh_tree_data.current_selection = selection
self:clear_action()
local func = self.bh_tree[i][selection]
if not self.object:get_pos() then return end
func(unpack(args))
break
end
end
end
end
end
if self._bh_tree_data.func then
local func = self._bh_tree_data.func
if func(self) then
self._bh_tree_data = {
active_task = 0,
func = nil,
current_selection = 0
}
self:clear_action()
end
end
end
local function tbl_equals(tbl1, tbl2) local function tbl_equals(tbl1, tbl2)
local match = true local match = true
for k, v in pairs(tbl1) do for k, v in pairs(tbl1) do

View file

@ -309,7 +309,7 @@ function creatura.find_path(self, start, goal, obj_width, obj_height, max_open,
gScore = 0, gScore = 0,
fScore = 0 fScore = 0
} }
temp_gScore = current.gScore + get_distance_to_neighbor(current.pos, neighbor.pos) local temp_gScore = current.gScore + get_distance_to_neighbor(current.pos, neighbor.pos)
local new_gScore = 0 local new_gScore = 0
if openSet[minetest.hash_node_position(neighbor.pos)] then if openSet[minetest.hash_node_position(neighbor.pos)] then
new_gScore = openSet[minetest.hash_node_position(neighbor.pos)].gScore new_gScore = openSet[minetest.hash_node_position(neighbor.pos)].gScore