Merge pull request 'Villager tries to get closest bed and jobsite. Villager will wait if failed to path recently' (#2898) from feature/villagers_pt4 into master
Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/2898 Reviewed-by: cora <cora@noreply.git.minetest.land>
This commit is contained in:
commit
d18f55aa48
|
@ -2607,8 +2607,9 @@ local function check_gowp(self,dtime)
|
|||
-- 0.1 is optimal.
|
||||
--less frequently = villager will get sent back after passing a point.
|
||||
--more frequently = villager will fail points they shouldn't they just didn't get there yet
|
||||
if gowp_etime < 0.1 then return end
|
||||
gowp_etime = 0
|
||||
|
||||
--if gowp_etime < 0.05 then return end
|
||||
--gowp_etime = 0
|
||||
local p = self.object:get_pos()
|
||||
|
||||
-- no destination
|
||||
|
@ -2663,6 +2664,7 @@ local function check_gowp(self,dtime)
|
|||
self.current_target = nil
|
||||
self.waypoints = nil
|
||||
self._target = nil
|
||||
self._pf_last_failed = os.time()
|
||||
self.object:set_velocity({x = 0, y = 0, z = 0})
|
||||
self.object:set_acceleration({x = 0, y = 0, z = 0})
|
||||
return
|
||||
|
@ -3408,6 +3410,7 @@ local function calculate_path_through_door (p, t, target)
|
|||
if not wp then
|
||||
mcl_log("No direct path. Path through door")
|
||||
|
||||
-- This could improve. There could be multiple doors. Check you can path from door to target first.
|
||||
local cur_door_pos = minetest.find_node_near(target,16,{"group:door"})
|
||||
if cur_door_pos then
|
||||
mcl_log("Found a door near: " .. minetest.pos_to_string(cur_door_pos))
|
||||
|
@ -3457,21 +3460,29 @@ local gopath_last = os.time()
|
|||
function mcl_mobs:gopath(self,target,callback_arrived)
|
||||
if self.state == PATHFINDING then mcl_log("Already pathfinding, don't set another until done.") return end
|
||||
|
||||
if os.time() - gopath_last < 5 then
|
||||
mcl_log("Not ready to path yet")
|
||||
if self._pf_last_failed and (os.time() - self._pf_last_failed) < 30 then
|
||||
mcl_log("We are not ready to path as last fail is less than threshold: " .. (os.time() - self._pf_last_failed))
|
||||
return
|
||||
else
|
||||
mcl_log("We are ready to pathfind, no previous fail or we are past threshold")
|
||||
end
|
||||
gopath_last = os.time()
|
||||
|
||||
--if os.time() - gopath_last < 5 then
|
||||
-- mcl_log("Not ready to path yet")
|
||||
-- return
|
||||
--end
|
||||
--gopath_last = os.time()
|
||||
|
||||
self.order = nil
|
||||
|
||||
--mcl_log("gowp target: " .. minetest.pos_to_string(target))
|
||||
local p = self.object:get_pos()
|
||||
local t = vector.offset(target,0,1,0)
|
||||
|
||||
local wp = calculate_path_through_door(p, t, target)
|
||||
if not wp then
|
||||
mcl_log("Could not calculate path")
|
||||
self._pf_last_failed = os.time()
|
||||
-- Cover for a flaw in pathfind where it chooses the wrong door and gets stuck. Take a break, allow others.
|
||||
end
|
||||
--output_table(wp)
|
||||
|
||||
|
@ -3484,12 +3495,6 @@ function mcl_mobs:gopath(self,target,callback_arrived)
|
|||
else
|
||||
mcl_log("Nil pos")
|
||||
end
|
||||
--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.waypoints = wp
|
||||
self.state = PATHFINDING
|
||||
|
|
|
@ -578,10 +578,9 @@ function get_activity(tod)
|
|||
end
|
||||
tod = ( tod * 24000 ) % 24000
|
||||
|
||||
|
||||
local lunch_start = 12000
|
||||
local lunch_start = 11000
|
||||
local lunch_end = 13500
|
||||
local work_start = 8500
|
||||
local work_start = 7000
|
||||
local work_end = 16500
|
||||
|
||||
local activity = nil
|
||||
|
@ -602,6 +601,31 @@ function get_activity(tod)
|
|||
|
||||
end
|
||||
|
||||
local function find_closest_unclaimed_block (p, requested_block_types)
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), requested_block_types)
|
||||
|
||||
local distance_to_closest_block = nil
|
||||
local closest_block = nil
|
||||
|
||||
for i,n in pairs(nn) do
|
||||
local m = minetest.get_meta(n)
|
||||
|
||||
if m:get_string("villager") == "" then
|
||||
mcl_log("Block: " .. minetest.pos_to_string(n).. ", owner: ".. m:get_string("villager"))
|
||||
|
||||
local distance_to_block = vector.distance(p, n)
|
||||
mcl_log("Distance to block ".. i .. ": ".. distance_to_block)
|
||||
|
||||
if not distance_to_closest_block or distance_to_closest_block > distance_to_block then
|
||||
mcl_log("This block is closer than the last.")
|
||||
closest_block = n
|
||||
distance_to_closest_block = distance_to_block
|
||||
end
|
||||
end
|
||||
end
|
||||
return closest_block
|
||||
end
|
||||
|
||||
local function check_bed (entity)
|
||||
local b = entity._bed
|
||||
if not b then
|
||||
|
@ -677,16 +701,15 @@ local function take_bed (entity)
|
|||
if not entity then return end
|
||||
|
||||
local p = entity.object:get_pos()
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48), vector.offset(p,48,48,48), spawnable_bed)
|
||||
|
||||
for _,n in pairs(nn) do
|
||||
local m=minetest.get_meta(n)
|
||||
--mcl_log("Bed owner: ".. m:get_string("villager"))
|
||||
if m:get_string("villager") == "" and not (entity.state == PATHFINDING) then
|
||||
mcl_log("Can we path to bed: "..minetest.pos_to_string(n) )
|
||||
local gp = mcl_mobs:gopath(entity,n,function(self)
|
||||
local closest_block = find_closest_unclaimed_block (p, spawnable_bed)
|
||||
|
||||
if closest_block then
|
||||
local m = minetest.get_meta(closest_block)
|
||||
mcl_log("Can we path to bed: "..minetest.pos_to_string(closest_block) )
|
||||
local gp = mcl_mobs:gopath(entity, closest_block,function(self)
|
||||
if self then
|
||||
self.order = "sleep"
|
||||
self.order = SLEEP
|
||||
mcl_log("Sleepy time" )
|
||||
else
|
||||
mcl_log("Can't sleep, no self in the callback" )
|
||||
|
@ -695,15 +718,12 @@ local function take_bed (entity)
|
|||
if gp then
|
||||
mcl_log("Nice bed. I'll defintely take it as I can path")
|
||||
m:set_string("villager", entity._id)
|
||||
entity._bed = n
|
||||
break
|
||||
entity._bed = closest_block
|
||||
else
|
||||
mcl_log("Awww. I can't find my bed.")
|
||||
end
|
||||
else
|
||||
mcl_log("Currently gowp, or it's taken: ".. m:get_string("villager"))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function has_golem(pos)
|
||||
|
@ -847,43 +867,32 @@ end
|
|||
local function look_for_job(self, requested_jobsites)
|
||||
mcl_log("Looking for jobs")
|
||||
|
||||
local looking_for_type = jobsites
|
||||
if requested_jobsites then
|
||||
--mcl_log("Looking for jobs of my type: " .. tostring(requested_jobsites))
|
||||
looking_for_type = requested_jobsites
|
||||
else
|
||||
mcl_log("Looking for any job type")
|
||||
end
|
||||
|
||||
local p = self.object:get_pos()
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48), looking_for_type)
|
||||
|
||||
--Ideally should check for closest available. It'll make pathing easier.
|
||||
for _,n in pairs(nn) do
|
||||
local m = minetest.get_meta(n)
|
||||
--mcl_log("Job owner: ".. m:get_string("villager"))
|
||||
local closest_block = find_closest_unclaimed_block(p, requested_jobsites)
|
||||
|
||||
if m:get_string("villager") == "" then
|
||||
mcl_log("It's a free job for me (".. minetest.pos_to_string(p) .. ")! I might be interested: "..minetest.pos_to_string(n) )
|
||||
if closest_block then
|
||||
mcl_log("It's a free job for me (" .. minetest.pos_to_string(p) .. ")! I might be interested: ".. minetest.pos_to_string(closest_block) )
|
||||
|
||||
local gp = mcl_mobs:gopath(self,n,function(self)
|
||||
local gp = mcl_mobs:gopath(self, closest_block,function(self)
|
||||
mcl_log("Arrived at block callback")
|
||||
if self and self.state == "stand" then
|
||||
self.order = WORK
|
||||
else
|
||||
mcl_log("no self. passing param to callback failed")
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
if gp then
|
||||
if n then
|
||||
mcl_log("We can path to this block.. " .. tostring(n))
|
||||
if closest_block then
|
||||
mcl_log("We can path to this block.. " .. tostring(closest_block))
|
||||
end
|
||||
return n
|
||||
return closest_block
|
||||
else
|
||||
mcl_log("We could not path to block or it's not ready to path yet.")
|
||||
end
|
||||
end
|
||||
else
|
||||
mcl_log("We don't have a job block to path to")
|
||||
end
|
||||
|
||||
return nil
|
||||
|
@ -1052,7 +1061,7 @@ end
|
|||
local function do_activity (self)
|
||||
-- Maybe just check we're pathfinding first?
|
||||
|
||||
if not self._bed then
|
||||
if not self._bed and self.state ~= PATHFINDING then
|
||||
--mcl_log("Villager has no bed. Currently at location: "..minetest.pos_to_string(self.object:get_pos()))
|
||||
take_bed (self)
|
||||
end
|
||||
|
@ -1063,7 +1072,6 @@ local function do_activity (self)
|
|||
wandered_too_far = ( self.state ~= PATHFINDING ) and (vector.distance(self.object:get_pos(),self._bed) > 50 )
|
||||
end
|
||||
|
||||
|
||||
if wandered_too_far then
|
||||
--mcl_log("Wandered too far! Return home ")
|
||||
go_home(self, false)
|
||||
|
@ -1074,7 +1082,6 @@ local function do_activity (self)
|
|||
elseif get_activity() == GATHERING then
|
||||
go_to_town_bell(self)
|
||||
else
|
||||
-- gossip at town bell or stroll around
|
||||
mcl_log("No order, so remove it.")
|
||||
self.order = nil
|
||||
end
|
||||
|
@ -1769,12 +1776,12 @@ mcl_mobs:register_mob("mobs_mc:villager", {
|
|||
self._trading_players[name] = true
|
||||
|
||||
if self._trades == nil or self._trades == false then
|
||||
minetest.log("Trades is nil so init")
|
||||
--minetest.log("Trades is nil so init")
|
||||
init_trades(self)
|
||||
end
|
||||
update_max_tradenum(self)
|
||||
if self._trades == false then
|
||||
minetest.log("Trades is false. no right click op")
|
||||
--minetest.log("Trades is false. no right click op")
|
||||
-- Villager has no trades, rightclick is a no-op
|
||||
return
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user