Places: Allow finding alternative nodes when nodes are being used.
Add owned and used properties to each owned/shared node. Actions: Allow to find alternative sittable/bed/furnace node if currently being used. Default occupation: Add alternative sitting finding. NPC: Log cleanup.
This commit is contained in:
parent
d92b729e19
commit
8a5e80e2cb
@ -664,19 +664,42 @@ local function get_pos_argument(self, pos, use_access_node)
|
||||
return pos
|
||||
elseif pos.place_type ~= nil then
|
||||
-- Received table in the following format:
|
||||
-- {place_type = "", index = 1, use_access_node = false}
|
||||
-- {
|
||||
-- place_category = "",
|
||||
-- place_type = "",
|
||||
-- index = 1,
|
||||
-- use_access_node = false|true,
|
||||
-- try_alternative_if_used = true|false
|
||||
-- }
|
||||
local index = pos.index or 1
|
||||
local use_access_node = pos.use_access_node or false
|
||||
local try_alternative_if_used = pos.try_alternative_if_used or false
|
||||
local places = npc.places.get_by_type(self, pos.place_type)
|
||||
--minetest.log("Place type: "..dump(pos.place_type))
|
||||
--minetest.log("Places: "..dump(places))
|
||||
-- Check index is valid on the places map
|
||||
if #places >= index then
|
||||
local place = places[index]
|
||||
-- Check if place is used, and if it is, find alternative if required
|
||||
if try_alternative_if_used == true then
|
||||
place = npc.places.find_unused_place(self, pos.place_category, pos.place_type, place)
|
||||
|
||||
--minetest.log("Mark as used? "..dump(pos.mark_target_as_used))
|
||||
if pos.mark_target_as_used == true then
|
||||
--minetest.log("Marking as used: "..minetest.pos_to_string(place.pos))
|
||||
npc.places.mark_place_used(place.pos, npc.places.USE_STATE.USED)
|
||||
end
|
||||
|
||||
npc.places.add_shared_accessible_place(
|
||||
self, {owner="", node_pos=place.pos}, npc.places.PLACE_TYPE.CALCULATED.TARGET, true, {})
|
||||
end
|
||||
-- Check if access node is desired
|
||||
if use_access_node == true then
|
||||
-- Return actual node pos
|
||||
return places[index].access_node, places[index].pos
|
||||
return place.access_node, place.pos
|
||||
else
|
||||
-- Return node pos that allows access to node
|
||||
return places[index].pos
|
||||
return place.pos
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -722,6 +745,7 @@ function npc.actions.use_furnace(self, args)
|
||||
return
|
||||
end
|
||||
|
||||
local enable_usage_marking = args.enable_usage_marking or true
|
||||
local item = args.item
|
||||
local freeze = args.freeze
|
||||
-- Define which items are usable as fuels. The NPC
|
||||
@ -775,6 +799,12 @@ function npc.actions.use_furnace(self, args)
|
||||
return cook_result.time - fuel_time
|
||||
end
|
||||
|
||||
-- Set furnace as used if flag is enabled
|
||||
if enable_usage_marking then
|
||||
-- Set place as used
|
||||
npc.places.mark_place_used(pos, npc.places.USE_STATE.USED)
|
||||
end
|
||||
|
||||
-- Calculate how much fuel is needed
|
||||
local fuel_amount = total_cook_time / fuel_time
|
||||
if fuel_amount < 1 then
|
||||
@ -832,6 +862,12 @@ function npc.actions.use_furnace(self, args)
|
||||
|
||||
npc.log("DEBUG", "Inventory: "..dump(self.inventory))
|
||||
|
||||
-- Set furnace as unused if flag is enabled
|
||||
if enable_usage_marking then
|
||||
-- Set place as used
|
||||
npc.places.mark_place_used(pos, npc.places.USE_STATE.NOT_USED)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -848,6 +884,7 @@ function npc.actions.use_bed(self, args)
|
||||
return
|
||||
end
|
||||
local action = args.action
|
||||
local enable_usage_marking = args.enable_usage_marking or true
|
||||
local node = minetest.get_node(pos)
|
||||
--minetest.log(dump(node))
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
@ -863,6 +900,10 @@ function npc.actions.use_bed(self, args)
|
||||
npc.add_action(self, npc.actions.cmd.SIT, {pos=bed_pos, dir=(node.param2 + 2) % 4})
|
||||
-- Lay down
|
||||
npc.add_action(self, npc.actions.cmd.LAY, {})
|
||||
if enable_usage_marking then
|
||||
-- Set place as used
|
||||
npc.places.mark_place_used(pos, npc.places.USE_STATE.USED)
|
||||
end
|
||||
else
|
||||
-- Calculate position to get up
|
||||
-- Error here due to ignore. Need to come up with better solution
|
||||
@ -906,9 +947,12 @@ function npc.actions.use_bed(self, args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Stand out of bed
|
||||
npc.add_action(self, npc.actions.cmd.STAND, {pos=pos_out_of_bed, dir=dir})
|
||||
if enable_usage_marking then
|
||||
-- Set place as unused
|
||||
npc.places.mark_place_used(pos, npc.places.USE_STATE.NOT_USED)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -921,6 +965,7 @@ function npc.actions.use_sittable(self, args)
|
||||
return
|
||||
end
|
||||
local action = args.action
|
||||
local enable_usage_marking = args.enable_usage_marking or true
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
if action == npc.actions.const.sittable.SIT then
|
||||
@ -932,6 +977,10 @@ function npc.actions.use_sittable(self, args)
|
||||
local sit_pos = npc.actions.nodes.sittable[node.name].get_sit_pos(pos, node.param2)
|
||||
-- Sit down on bench/chair/stairs
|
||||
npc.add_action(self, npc.actions.cmd.SIT, {pos=sit_pos, dir=(node.param2 + 2) % 4})
|
||||
if enable_usage_marking then
|
||||
-- Set place as used
|
||||
npc.places.mark_place_used(pos, npc.places.USE_STATE.USED)
|
||||
end
|
||||
else
|
||||
-- Find empty areas around chair
|
||||
local dir = node.param2 + 2 % 4
|
||||
@ -951,6 +1000,11 @@ function npc.actions.use_sittable(self, args)
|
||||
end
|
||||
-- Stand
|
||||
npc.add_action(self, npc.actions.cmd.STAND, {pos=pos_out_of_sittable, dir=dir})
|
||||
minetest.log("Setting sittable at "..minetest.pos_to_string(pos).." as not used")
|
||||
if enable_usage_marking then
|
||||
-- Set place as unused
|
||||
npc.places.mark_place_used(pos, npc.places.USE_STATE.NOT_USED)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,6 +63,17 @@ npc.places.nodes = {
|
||||
|
||||
|
||||
npc.places.PLACE_TYPE = {
|
||||
CATEGORIES = {
|
||||
BED = "BED",
|
||||
SITTABLE = "SITTABLE",
|
||||
FURNACE = "FURNACE",
|
||||
STORAGE = "STORAGE",
|
||||
OPENABLE = "OPENABLE",
|
||||
SCHEDULE = "SCHEDULE",
|
||||
CALCULATED = "CALCULATED",
|
||||
WORKPLACE = "WORKPLACE",
|
||||
OTHER = "OTHER"
|
||||
},
|
||||
BED = {
|
||||
PRIMARY = "bed_primary"
|
||||
},
|
||||
@ -84,6 +95,9 @@ npc.places.PLACE_TYPE = {
|
||||
SCHEDULE = {
|
||||
TARGET = "schedule_target_pos"
|
||||
},
|
||||
CALCULATED = {
|
||||
TARGET = "calculated_target_pos"
|
||||
},
|
||||
WORKPLACE = {
|
||||
PRIMARY = "workplace_primary",
|
||||
TOOL = "workplace_tool"
|
||||
@ -92,14 +106,60 @@ npc.places.PLACE_TYPE = {
|
||||
HOME_PLOTMARKER = "home_plotmarker",
|
||||
HOME_INSIDE = "home_inside",
|
||||
HOME_OUTSIDE = "home_outside"
|
||||
}
|
||||
},
|
||||
is_primary = function(place_type)
|
||||
local p1,p2 = string.find(place_type, "primary")
|
||||
return p1 ~= nil
|
||||
end,
|
||||
-- Only works for place types where there is a "primary" and a "shared"
|
||||
get_alternative = function(place_category, place_type)
|
||||
local result = {}
|
||||
local place_types = npc.places.PLACE_TYPE[place_category]
|
||||
-- Determine search type
|
||||
local search_shared = false
|
||||
if npc.places.PLACE_TYPE.is_primary(place_type) then
|
||||
search_shared = true
|
||||
end
|
||||
for key,place_type in pairs(place_types) do
|
||||
if search_shared == true then
|
||||
if npc.places.PLACE_TYPE.is_primary(place_type) == false then
|
||||
return place_type
|
||||
end
|
||||
else
|
||||
if npc.places.PLACE_TYPE.is_primary(place_type) == true then
|
||||
return place_type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
npc.places.USE_STATE = {
|
||||
USED = "true",
|
||||
NOT_USED = "false"
|
||||
}
|
||||
|
||||
function npc.places.add_shared(self, place_name, place_type, pos, access_node)
|
||||
-- Set metadata of node
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not meta:get_string("advanced_npc:used") then
|
||||
meta:set_string("advanced_npc:used", npc.places.USE_STATE.NOT_USED)
|
||||
end
|
||||
meta:set_string("advanced_npc:owner", "")
|
||||
-- This avoid lags
|
||||
meta:mark_as_private({"advanced_npc:used", "advanced_npc:owner"})
|
||||
self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="shared"}
|
||||
end
|
||||
|
||||
function npc.places.add_owned(self, place_name, place_type, pos, access_node)
|
||||
-- Set metadata of node
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not meta:get_string("advanced_npc:used") then
|
||||
meta:set_string("advanced_npc:used", npc.places.USE_STATE.NOT_USED)
|
||||
end
|
||||
meta:set_string("advanced_npc:owner", self.npc_id)
|
||||
-- This avoid lags
|
||||
meta:mark_as_private({"advanced_npc:used", "advanced_npc:owner"})
|
||||
self.places_map[place_name] = {type=place_type, pos=pos, access_node=access_node or pos, status="owned"}
|
||||
end
|
||||
|
||||
@ -161,6 +221,48 @@ function npc.places.add_shared_accessible_place(self, nodes, place_type, overrid
|
||||
end
|
||||
end
|
||||
|
||||
function npc.places.mark_place_used(pos, value)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local used = meta:get_string("advanced_npc:used")
|
||||
if value == used then
|
||||
npc.log("WARNING", "Attempted to set 'used' property of node at "
|
||||
..minetest.pos_to_string(pos).." to the same value: '"..dump(value).."'")
|
||||
return false
|
||||
else
|
||||
meta:set_string("advanced_npc:used", value)
|
||||
npc.log("DEBUG", "'Used' value at pos "..minetest.pos_to_string(pos)..": "..dump(meta:get_string("advanced_npc:used")))
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- This function is to find an alternative place if the original is
|
||||
-- not usable. If the original place is a "primary" place, it will
|
||||
-- try to find a "shared" place. If it is a "shared" place, it will try
|
||||
-- to find a "primary" place. If none is found, it retuns the given type.
|
||||
function npc.places.find_unused_place(self, place_category, place_type, original_place)
|
||||
local result = {}
|
||||
-- Check if node is being used
|
||||
local meta = minetest.get_meta(original_place.pos)
|
||||
local used = meta:get_string("advanced_npc:used")
|
||||
if used == npc.places.USE_STATE.USED then
|
||||
-- Node is being used, try to find alternative
|
||||
local alternative_place_type = npc.places.PLACE_TYPE.get_alternative(place_category, place_type)
|
||||
--minetest.log("Alternative place type: "..dump(alternative_place_type))
|
||||
local alternative_places = npc.places.get_by_type(self, alternative_place_type)
|
||||
--minetest.log("Alternatives: "..dump(alternative_places))
|
||||
for i = 1, #alternative_places do
|
||||
meta = minetest.get_meta(alternative_places[i].pos)
|
||||
local used = meta:get_string("advanced_npc:used")
|
||||
if used == npc.places.USE_STATE.NOT_USED then
|
||||
return alternative_places[i]
|
||||
end
|
||||
end
|
||||
else
|
||||
result = original_place
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function npc.places.get_by_type(self, place_type, exact_match)
|
||||
local result = {}
|
||||
for _, place_entry in pairs(self.places_map) do
|
||||
|
@ -55,17 +55,25 @@ local basic_def = {
|
||||
-- Schedule entry for 12 midday
|
||||
[12] = {
|
||||
-- Walk to a sittable node
|
||||
[1] = {task = npc.actions.cmd.WALK_TO_POS, args = {
|
||||
end_pos = {place_type=npc.places.PLACE_TYPE.SITTABLE.PRIMARY, use_access_node=true},
|
||||
walkable = {"cottages:bench"}
|
||||
},
|
||||
[1] = {task = npc.actions.cmd.WALK_TO_POS,
|
||||
args = {
|
||||
end_pos = {
|
||||
place_category=npc.places.PLACE_TYPE.CATEGORIES.SITTABLE,
|
||||
place_type=npc.places.PLACE_TYPE.SITTABLE.PRIMARY,
|
||||
use_access_node=true,
|
||||
try_alternative_if_used=true,
|
||||
mark_target_as_used = true
|
||||
},
|
||||
walkable = {"cottages:bench"}
|
||||
},
|
||||
chance = 75
|
||||
},
|
||||
-- Sit on the node
|
||||
[2] = {task = npc.actions.cmd.USE_SITTABLE, args = {
|
||||
pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY,
|
||||
action = npc.actions.const.sittable.SIT
|
||||
},
|
||||
[2] = {task = npc.actions.cmd.USE_SITTABLE,
|
||||
args = {
|
||||
pos = npc.places.PLACE_TYPE.CALCULATED.TARGET,
|
||||
action = npc.actions.const.sittable.SIT
|
||||
},
|
||||
depends = {1}
|
||||
},
|
||||
-- Stay put into place
|
||||
@ -83,10 +91,10 @@ local basic_def = {
|
||||
},
|
||||
-- Get up from sit
|
||||
[5] = {action = npc.actions.cmd.USE_SITTABLE, args = {
|
||||
pos = npc.places.PLACE_TYPE.SITTABLE.PRIMARY,
|
||||
pos = npc.places.PLACE_TYPE.CALCULATED.TARGET,
|
||||
action = npc.actions.const.sittable.GET_UP
|
||||
},
|
||||
depends = {4}
|
||||
--depends = {4}
|
||||
}
|
||||
},
|
||||
-- Schedule entry for 1 in the afternoon
|
||||
@ -142,10 +150,11 @@ local basic_def = {
|
||||
}
|
||||
},
|
||||
-- Use bed
|
||||
[2] = {task = npc.actions.cmd.USE_BED, args = {
|
||||
pos = npc.places.PLACE_TYPE.BED.PRIMARY,
|
||||
action = npc.actions.const.beds.LAY
|
||||
}
|
||||
[2] = {task = npc.actions.cmd.USE_BED,
|
||||
args = {
|
||||
pos = npc.places.PLACE_TYPE.BED.PRIMARY,
|
||||
action = npc.actions.const.beds.LAY
|
||||
}
|
||||
},
|
||||
-- Stay put on bed
|
||||
[3] = {action = npc.actions.cmd.FREEZE, args = {freeze = true}}
|
||||
|
2
npc.lua
2
npc.lua
@ -564,7 +564,7 @@ function npc.generate_trade_list_from_inventory(self)
|
||||
end
|
||||
|
||||
function npc.set_trading_status(self, status)
|
||||
minetest.log("Trader_data: "..dump(self.trader_data))
|
||||
--minetest.log("Trader_data: "..dump(self.trader_data))
|
||||
-- Set status
|
||||
self.trader_data.trader_status = status
|
||||
-- Re-generate trade offers
|
||||
|
Loading…
Reference in New Issue
Block a user