movement improvements, door opening

This commit is contained in:
kno10 2024-10-27 19:23:00 +01:00
parent d32d64250b
commit 8ad5d16ccc
4 changed files with 71 additions and 100 deletions

View File

@ -413,11 +413,7 @@ local function on_step_work(self, dtime, moveresult)
self:check_water_flow()
if not self._jumping_cliff then
self._can_jump_cliff = self:can_jump_cliff()
else
self._can_jump_cliff = false
end
self._can_jump_cliff = not self._jumping_cliff and self:can_jump_cliff()
self:flop()
@ -503,26 +499,24 @@ end
-- main mob function
function mob_class:on_step(dtime, moveresult)
if not DEVELOPMENT then
-- Removed as bundled Lua (5.1 doesn't support xpcall)
--local status, retVal = xpcall(on_step_work, on_step_error_handler, self, dtime)
local status, retVal = pcall(on_step_work, self, dtime, moveresult)
if status then
return retVal
else
warn_user_error ()
local pos = self.object:get_pos()
if pos then
local node = minetest.get_node(pos)
if node and node.name == "ignore" then
minetest.log("warning", "Pos is ignored: " .. dump(pos))
end
end
log_error (dump(retVal), dump(pos), dump(self))
end
else
return on_step_work (self, dtime, moveresult)
if DEVELOPMENT then
return on_step_work(self, dtime, moveresult)
end
-- Removed as bundled Lua (5.1 doesn't support xpcall)
--local status, retVal = xpcall(on_step_work, on_step_error_handler, self, dtime)
local status, retVal = pcall(on_step_work, self, dtime, moveresult)
if status then
return retVal
end
warn_user_error ()
local pos = self.object:get_pos()
if pos then
local node = minetest.get_node(pos)
if node and node.name == "ignore" then
minetest.log("warning", "Pos is ignored: " .. dump(pos))
end
end
log_error (dump(retVal), dump(pos), dump(self))
end
local timer = 0

View File

@ -755,8 +755,9 @@ function mob_class:go_to_pos(b)
if not b then return end
local s = self.object:get_pos()
if vector.distance(b,s) < .5 then return true end
if b.y > s.y then self:do_jump() end
self:turn_in_direction(b.x - s.x, b.z - s.z, 2)
self:set_velocity(self.follow_velocity)
self:set_velocity(self.walk_velocity)
self:set_animation("walk")
end
@ -909,10 +910,10 @@ function mob_class:do_states_walk()
-- otherwise randomly turn
elseif random() <= 0.3 then
local home = self._home or self._bed
if home and random() < 0.3 then
if home and random() < 0.1 then
self:turn_in_direction(home.x - s.x, home.z - s.z, 8)
else
self:turn_by(PIHALF * (random() - 0.5), 10)
self:turn_by(PIQUARTER * (random() - 0.5), 10)
end
end
self:set_velocity(self.walk_velocity)

View File

@ -42,8 +42,8 @@ function append_paths (wp1, wp2)
mcl_log("Cannot append wp's")
return
end
output_table(wp1)
output_table(wp2)
--output_table(wp1)
--output_table(wp2)
for _,a in pairs (wp2) do
table.insert(wp1, a)
end
@ -51,18 +51,13 @@ function append_paths (wp1, wp2)
end
local function output_enriched (wp_out)
mcl_log("Output enriched path")
--mcl_log("Output enriched path")
local i = 0
for _,outy in pairs (wp_out) do
i = i + 1
mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"]))
local action = outy["action"]
if action then
--mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"]))
mcl_log("type: " .. action["type"])
mcl_log("action: " .. action["action"])
mcl_log("target: " .. minetest.pos_to_string(action["target"]))
mcl_log("Pos ".. i ..":" .. minetest.pos_to_string(outy["pos"])..", type: " .. action["type"]..", action: " .. action["action"]..", target: " .. minetest.pos_to_string(action["target"]))
end
--mcl_log("failed attempts: " .. outy["failed_attempts"])
end
@ -113,17 +108,17 @@ end
local last_pathing_time = os.time()
function mob_class:ready_to_path(prioritised)
mcl_log("Check ready to path")
-- mcl_log("Check ready to path")
if self._pf_last_failed and (os.time() - self._pf_last_failed) < PATHFINDING_FAIL_WAIT then
mcl_log("Not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed))
-- mcl_log("Not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed))
return false
else
local time_since_path_start = os.time() - last_pathing_time
mcl_log("time_since_path_start: " .. tostring(time_since_path_start))
if prioritised or (time_since_path_start) > PATHING_START_DELAY then
mcl_log("We are ready to pathfind, no previous fail or we are past threshold")
mcl_log("We are ready to pathfind, no previous fail or we are past threshold: "..tostring(time_since_path_start))
return true
end
mcl_log("time_since_path_start: " .. tostring(time_since_path_start))
end
end
@ -272,13 +267,7 @@ function mob_class:gopath(target, callback_arrived, prioritised)
--output_table(wp)
self._target = t
self.callback_arrived = callback_arrived
local current_location = table.remove(wp,1)
if current_location and current_location["pos"] then
mcl_log("Removing first co-ord? " .. tostring(current_location["pos"]))
else
mcl_log("Nil pos")
end
self.current_target = current_location
self.current_target = table.remove(wp,1)
self.waypoints = wp
self.state = PATHFINDING
return true
@ -300,19 +289,17 @@ function mob_class:interact_with_door(action, target)
local n = minetest.get_node(target)
if n.name:find("_b_") or n.name:find("_t_") then
mcl_log("Door")
local def = minetest.registered_nodes[n.name]
local closed = n.name:find("_b_1") or n.name:find("_t_1")
--if self.state == PATHFINDING then
if closed and action == "open" and def.on_rightclick then
mcl_log("Open door")
def.on_rightclick(target,n,self)
end
if not closed and action == "close" and def.on_rightclick then
mcl_log("Close door")
def.on_rightclick(target,n,self)
end
--else
local meta = minetest.get_meta(target)
local closed = meta:get_int("is_open") == 0
if closed and action == "open" and def.on_rightclick then
mcl_log("Open door")
def.on_rightclick(target,n,self)
end
if not closed and action == "close" and def.on_rightclick then
mcl_log("Close door")
def.on_rightclick(target,n,self)
end
else
mcl_log("Not door")
end
@ -333,6 +320,7 @@ function mob_class:do_pathfind_action(action)
end
if type and type == "door" then
mcl_log("Type is door")
self.object:set_velocity(vector.zero())
self:interact_with_door(action_val, target)
end
end
@ -343,8 +331,7 @@ function mob_class:check_gowp(dtime)
-- no destination
if not p or not self._target then
mcl_log("p: ".. tostring(p))
mcl_log("self._target: ".. tostring(self._target))
mcl_log("p: ".. tostring(p)..", self._target: ".. tostring(self._target))
return
end
@ -374,11 +361,12 @@ function mob_class:check_gowp(dtime)
--distance_to_current_target = vector.distance(p,self.current_target["pos"])
end
-- also check next target, maybe we were too fast
local next_target = #self.waypoints > 0 and self.waypoints[1]
if next_target and next_target["pos"] and distance_to_current_target < 2 then
local next_target = #self.waypoints > 1 and self.waypoints[1]
if not self.current_target["action"] and next_target and next_target["pos"] and distance_to_current_target < 1.5 then
local dx, dy, dz = next_target["pos"].x-p.x, next_target["pos"].y-p.y, next_target["pos"].z-p.z
local distance_to_next_target = (dx*dx+dy*dy*0.25+dz*dz)^0.5 -- reduced weight on y
if distance_to_next_target < distance_to_current_target then
mcl_log("Skipped one waypoint.")
self.current_target = table.remove(self.waypoints, 1) -- pop waypoint already
distance_to_current_target = distance_to_next_target
end
@ -387,7 +375,8 @@ function mob_class:check_gowp(dtime)
-- 0.6 is working but too sensitive. sends villager back too frequently. 0.7 is quite good, but not with heights
-- 0.8 is optimal for 0.025 frequency checks and also 1... Actually. 0.8 is winning
-- 0.9 and 1.0 is also good. Stick with unless door open or closing issues
if self.waypoints and #self.waypoints > 0 and ( not self.current_target or not self.current_target["pos"] or distance_to_current_target < 0.8 ) then
local threshold = self.current_target["action"] and 0.8 or 1.2
if self.waypoints and #self.waypoints > 0 and ( not self.current_target or not self.current_target["pos"] or distance_to_current_target < threshold ) then
-- We have waypoints, and are at current_target or have no current target. We need a new current_target.
self:do_pathfind_action (self.current_target["action"])
@ -396,11 +385,15 @@ function mob_class:check_gowp(dtime)
self.current_target = table.remove(self.waypoints, 1)
-- use smoothing
if #self.waypoints > 0 then
--[[if #self.waypoints > 0 and not self.current_target["action"] then
local curwp, nextwp = self.current_target["pos"], self.waypoints[1]["pos"]
self:go_to_pos(vector.new(curwp.x*0.5+nextwp.x*0.5,curwp.y*0.5+nextwp.y*0.5,curwp.z*0.5+nextwp.z*0.5))
end
self:go_to_pos(vector.new(curwp.x*0.7+nextwp.x*0.3,curwp.y,curwp.z*0.7+nextwp.z*0.3))
return
end]]--
self:go_to_pos(self.current_target["pos"])
if self.current_target["action"] then
self:set_velocity(self.walk_velocity * 0.25)
end
return
elseif self.current_target and self.current_target["pos"] then
-- No waypoints left, but have current target and not close enough. Potentially last waypoint to go to.
@ -408,7 +401,7 @@ function mob_class:check_gowp(dtime)
self.current_target["failed_attempts"] = self.current_target["failed_attempts"] + 1
local failed_attempts = self.current_target["failed_attempts"]
if failed_attempts >= PATHFINDING_FAIL_THRESHOLD then
mcl_log("Failed to reach position (" .. minetest.pos_to_string(self.current_target["pos"]) .. ") too many times. Abandon route. Times tried: " .. failed_attempts)
mcl_log("Failed to reach position " .. minetest.pos_to_string(self.current_target["pos"]) .. " too many times. At: "..minetest.pos_to_string(p).." Abandon route. Times tried: " .. failed_attempts .. " current distance "..distance_to_current_target)
self.state = "stand"
self.current_target = nil
self.waypoints = nil
@ -421,7 +414,7 @@ function mob_class:check_gowp(dtime)
--mcl_log("Not at pos with failed attempts ".. failed_attempts ..": ".. minetest.pos_to_string(p) .. "self.current_target: ".. minetest.pos_to_string(self.current_target["pos"]) .. ". Distance: ".. distance_to_current_target)
self:go_to_pos(self.current_target["pos"])
self:turn_by(2 * (math.random() - 0.5), 2) -- but try turning left or right
self:turn_by((math.random() - 0.5), 2) -- but try turning left or right
-- Do i just delete current_target, and return so we can find final path.
else
-- Not at target, no current waypoints or current_target. Through the door and should be able to path to target.
@ -462,7 +455,7 @@ function mob_class:check_gowp(dtime)
mcl_log("Current p: ".. minetest.pos_to_string(updated_p))
-- 1.6 is good. is 1.9 better? It could fail less, but will it path to door when it isn't after door
if distance_to_cur_targ > 1.9 then
if distance_to_cur_targ > 1.6 then
mcl_log("not close to current target: ".. minetest.pos_to_string(self.current_target["pos"]))
self:go_to_pos(self._current_target)
else

View File

@ -59,9 +59,7 @@ end
-- Return true if object is in view_range
function mob_class:object_in_range(object)
if not object then
return false
end
if not object then return false end
local factor
-- Apply view range reduction for special player armor
if object:is_player() then
@ -141,12 +139,7 @@ function mob_class:item_drop(cooked, looting_level)
end
if obj and obj:get_luaentity() then
obj:set_velocity({
x = math.random(-10, 10) / 9,
y = 6,
z = math.random(-10, 10) / 9,
})
obj:set_velocity(vector.new((math.random() - 0.5) * 1.5, 6, (math.random() - 0.5) * 1.5))
elseif obj then
obj:remove() -- item does not exist
end
@ -862,10 +855,7 @@ end
-- falling and fall damage
-- returns true if mob died
function mob_class:falling(pos, moveresult)
if self.fly and self.state ~= "die" then
return
end
if self.fly and self.state ~= "die" then return end
if not self.fall_speed then self.fall_speed = DEFAULT_FALL_SPEED end
if mcl_portals ~= nil then
@ -878,10 +868,10 @@ function mob_class:falling(pos, moveresult)
local v = self.object:get_velocity()
if v then
local new_acceleration
if v.y > 0 then
-- apply gravity when moving up
new_acceleration = vector.new(0, DEFAULT_FALL_SPEED, 0)
elseif v.y <= 0 and v.y > self.fall_speed then
if v.y > 0 and v.y < -0.5 * DEFAULT_FALL_SPEED then
-- when moving up, always use gravity
new_acceleration = vector.new(0, 0.5 * DEFAULT_FALL_SPEED, 0)
elseif v.y <= 0 and v.y > 0.5 * self.fall_speed then
-- fall downwards at set speed
if moveresult and moveresult.touching_ground then
-- when touching ground, retain a minimal gravity to keep the touching_ground flag
@ -894,7 +884,6 @@ function mob_class:falling(pos, moveresult)
-- stop accelerating once max fall speed hit
new_acceleration = vector.zero()
end
self.object:set_acceleration(new_acceleration)
end
@ -904,14 +893,14 @@ function mob_class:falling(pos, moveresult)
if registered_node.groups.lava then
if acc and self.floats_on_lava == 1 then
self.object:set_acceleration(vector.new(0, -self.fall_speed / (math.max(1, v.y) ^ 2), 0))
self.object:set_acceleration(vector.new(0, -self.fall_speed / math.max(1, v.y^2), 0))
end
end
-- in water then float up
if registered_node.groups.water then
if acc and self.floats == 1 and minetest.registered_nodes[node_ok(vector.offset(pos,0,self.collisionbox[5] -0.25,0)).name].groups.water then
self.object:set_acceleration(vector.new(0, -self.fall_speed / (math.max(1, v.y) ^ 2), 0))
self.object:set_acceleration(vector.new(0, -self.fall_speed / math.max(1, v.y^2), 0))
end
else
-- fall damage onto solid ground
@ -935,13 +924,9 @@ end
function mob_class:check_water_flow()
-- Add water flowing for mobs from mcl_item_entity
local p, node, nn, def
p = self.object:get_pos()
node = minetest.get_node_or_nil(p)
if node then
nn = node.name
def = minetest.registered_nodes[nn]
end
local p = self.object:get_pos()
local node = minetest.get_node_or_nil(p)
local def = node and minetest.registered_nodes[node.name]
-- Move item around on flowing liquids
if def and def.liquidtype == "flowing" then
@ -961,9 +946,7 @@ function mob_class:check_water_flow()
self.physical_state = true
self._flowing = true
self.object:set_properties({
physical = true
})
self.object:set_properties({ physical = true })
return
end
elseif self._flowing == true then