allow NPC to use tools when punching and right-clicking blocks
This commit is contained in:
parent
1323f3d8fc
commit
b9bebe82bd
@ -159,6 +159,8 @@ yl_speak_up.blacklist_effect_on_block_right_click = {}
|
||||
-- taking something out of the inventory of a block or putting something in
|
||||
yl_speak_up.blacklist_effect_on_block_put = {}
|
||||
yl_speak_up.blacklist_effect_on_block_take = {}
|
||||
-- tools the NPC shall not be able to use (covers both punching and right-click):
|
||||
yl_speak_up.blacklist_effect_tool_use = {}
|
||||
|
||||
-- If some items are for some reasons not at all acceptable as quest items,
|
||||
-- blacklist them here. The data structure is the same as for the tables above.
|
||||
|
@ -19,7 +19,11 @@ yl_speak_up.dropdown_values_deal_with_offered_item = {
|
||||
-- how how to interact with the node
|
||||
-- node_name the node to place
|
||||
-- node_there the node that can currently be found at that position
|
||||
yl_speak_up.check_blacklisted = function(how, node_name, node_there)
|
||||
-- tool_name the name of the tool the NPC wants to use (punch or right-click with)
|
||||
yl_speak_up.check_blacklisted = function(how, node_name, node_there, tool_name)
|
||||
if(tool_name) then
|
||||
return yl_speak_up.blacklist_effect_tool_use[ tool_name ]
|
||||
end
|
||||
return yl_speak_up.blacklist_effect_on_block_interact[ node_name ]
|
||||
or yl_speak_up.blacklist_effect_on_block_interact[ node_there ]
|
||||
or (how == "place" and yl_speak_up.blacklist_effect_on_block_place[ node_name ])
|
||||
@ -31,6 +35,79 @@ yl_speak_up.check_blacklisted = function(how, node_name, node_there)
|
||||
end
|
||||
|
||||
|
||||
-- create fake playerdata so that the NPC can interact with inventories, punch and right-click blocks
|
||||
yl_speak_up.get_fake_player = function(owner_name, wielded_item)
|
||||
return {
|
||||
get_player_name = function()
|
||||
return owner_name
|
||||
end,
|
||||
is_player = function()
|
||||
return true
|
||||
end,
|
||||
is_fake_player = true,
|
||||
get_wielded_item = function(self, item)
|
||||
return ItemStack(wielded_item)
|
||||
end,
|
||||
get_player_control = function()
|
||||
-- NPC is not sneaking
|
||||
return {}
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
-- shall the NPC wield and use a tool? if so that tools' on_use or on_place
|
||||
-- function takes precedence over the block it's used on
|
||||
yl_speak_up.use_tool_on_block = function(r, fun_name, player, n_id, o_id)
|
||||
if(not(r.r_wielded) or r.r_wielded == "") then
|
||||
return false
|
||||
end
|
||||
-- we need the owner_name for creating the fake player
|
||||
local owner_name = yl_speak_up.npc_owner[ n_id ]
|
||||
if(not(owner_name) or owner_name == "") then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
r.r_type..": NPC does not have an owner. Aborting.")
|
||||
return false
|
||||
end
|
||||
local npc_inv = minetest.get_inventory({type="detached", name="yl_speak_up_npc_"..tostring(n_id)})
|
||||
-- can the tool be used?
|
||||
local tool_err_msg = nil
|
||||
if(not(minetest.registered_items[r.r_wielded])) then
|
||||
tool_err_msg = "Tool not defined"
|
||||
elseif(not(minetest.registered_items[r.r_wielded][fun_name])) then
|
||||
tool_err_msg = "Tool does not support "..tostring(r.r_value).."ing"
|
||||
-- do not use forbidden tools
|
||||
elseif(yl_speak_up.check_blacklisted(nil, nil, nil, r.r_wielded)) then
|
||||
tool_err_msg = "NPC are not allowed to use this tool"
|
||||
-- does the NPC have the item he's supposed to wield?
|
||||
elseif(not(npc_inv:contains_item("npc_main", r.r_wielded, false))) then
|
||||
tool_err_msg = "NPC lacks tool"
|
||||
end
|
||||
if(tool_err_msg) then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id)..
|
||||
" block: "..tostring(r.r_value).." - "..tool_err_msg.. ": \""..tostring(r.r_wielded).."\".")
|
||||
return false
|
||||
end
|
||||
-- act in the name of the owner when accessing inventories
|
||||
local fake_player = yl_speak_up.get_fake_player(owner_name, r.r_wielded)
|
||||
local itemstack = fake_player:get_wielded_item()
|
||||
local pointed_thing = {
|
||||
type = "node",
|
||||
under = r.r_pos,
|
||||
above = {x=r.r_pos.x, y=r.r_pos.y+1, z=r.r_pos.z}
|
||||
}
|
||||
local new_itemstack = minetest.registered_items[r.r_wielded][fun_name](
|
||||
itemstack, fake_player, pointed_thing)
|
||||
minetest.chat_send_player("singleplayer", "Did the rightclicking. Result: "..new_itemstack:get_name().." fun_name: "..tostring(fun_name))
|
||||
if(new_itemstack) then
|
||||
-- apply any itemstack changes
|
||||
npc_inv:remove_item("npc_main", itemstack)
|
||||
npc_inv:add_item("npc_main", new_itemstack)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- called by yl_speak_up.input_talk(..)
|
||||
-- and also by yl_speak_up.get_fs_trade_list(..)
|
||||
--
|
||||
@ -318,7 +395,8 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
|
||||
return false
|
||||
end
|
||||
-- do not interact with nodes on the blacklist
|
||||
if(yl_speak_up.check_blacklisted(how_to_interact, node.name, node.name)) then
|
||||
-- (this here is inventory interaction, so no need to check for tools)
|
||||
if(yl_speak_up.check_blacklisted(how_to_interact, node.name, node.name, nil)) then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
r.r_type..": Blocks of type \""..tostring(node.name).."\" do not allow "..
|
||||
"interaction of type \""..tostring(r.r_value).."\" for NPC.")
|
||||
@ -332,18 +410,7 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
|
||||
return false
|
||||
end
|
||||
-- act in the name of the owner when accessing inventories
|
||||
local fake_player = {
|
||||
get_player_name = function() return owner_name end,
|
||||
is_player = function() return true end,
|
||||
is_fake_player = true,
|
||||
get_wielded_item = function(self, item)
|
||||
if(self._inventory and def.wield_list) then
|
||||
return self._inventory:get_stack(def.wield_list, self._wield_index)
|
||||
end
|
||||
return ItemStack(self._wielded_item)
|
||||
end,
|
||||
}
|
||||
-- TODO: get the fake player from pipeworks?
|
||||
local fake_player = yl_speak_up.get_fake_player(owner_name, "")
|
||||
local def = minetest.registered_nodes[ node.name ]
|
||||
if(def and def[ "allow_metadata_inventory_"..how_to_interact ]) then
|
||||
local res = def[ "allow_metadata_inventory_"..how_to_interact ](
|
||||
@ -618,7 +685,7 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
|
||||
return false
|
||||
end
|
||||
-- do not interact with nodes on the blacklist
|
||||
if(yl_speak_up.check_blacklisted(r.r_value, r.r_node, node.name)) then
|
||||
if(yl_speak_up.check_blacklisted(r.r_value, r.r_node, node.name, nil)) then
|
||||
-- construct the right text for the error message
|
||||
local nname = node.name
|
||||
if(r.r_value == "place") then
|
||||
@ -640,6 +707,14 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
|
||||
" and thus cannot interact with it.")
|
||||
return false
|
||||
end
|
||||
-- create a fake player and a suitable itemstack
|
||||
local owner_name = yl_speak_up.npc_owner[ n_id ]
|
||||
if(not(owner_name) or owner_name == "") then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
r.r_type..": NPC does not have an owner. Aborting.")
|
||||
return false
|
||||
end
|
||||
|
||||
-- "If there is air: Place a block so that it looks like now.", -- 2
|
||||
if(r.r_value and r.r_value == "place") then
|
||||
if(is_protected) then
|
||||
@ -710,11 +785,22 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
|
||||
return true
|
||||
-- "Punch the block.", -- 4
|
||||
elseif(r.r_value and r.r_value == "punch") then
|
||||
-- shall the NPC wield and use an item? if so that items' on_use function takes
|
||||
-- precedence
|
||||
if(r.r_wielded and r.r_wielded ~= "") then
|
||||
return yl_speak_up.use_tool_on_block(r, "on_use", player, n_id, o_id)
|
||||
end
|
||||
-- even air can be punched - even if that is pretty pointless
|
||||
minetest.punch_node(r.r_pos)
|
||||
minetest.punch_node(r.r_pos, nil)
|
||||
return true
|
||||
-- "Right-click the block.", -- 5
|
||||
elseif(r.r_value and r.r_value == "right-click") then
|
||||
-- shall the NPC wield and use an item? if so that items' on_use function takes
|
||||
-- precedence
|
||||
if(r.r_wielded and r.r_wielded ~= "") then
|
||||
return yl_speak_up.use_tool_on_block(r, "on_place", player, n_id, o_id)
|
||||
end
|
||||
-- with a tool, clicking on air might make sense; without a tool it doesn't
|
||||
if(not(node) or not(node.name) or not(minetest.registered_nodes[node.name])) then
|
||||
return false
|
||||
end
|
||||
@ -748,14 +834,18 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
"block: Opened/closed trapdoor at "..pos_str..".")
|
||||
elseif(minetest.registered_nodes[node.name]
|
||||
and minetest.registered_nodes[node.name].on_rightclick
|
||||
and minetest.registered_nodes[node.name].on_rightclick(r.r_pos, node, nil)) then
|
||||
minetest.registered_nodes[node.name].on_rightclick(r.r_pos, node, nil)
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
"block: right-clicked at at pos "..pos_str..".")
|
||||
else
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
"block: right-click at at pos "..pos_str.." had no effect.")
|
||||
and minetest.registered_nodes[node.name].on_rightclick) then
|
||||
local fake_player = yl_speak_up.get_fake_player(owner_name, "")
|
||||
local itemstack = ItemStack("")
|
||||
local pointed_thing = nil -- TODO
|
||||
if(minetest.registered_nodes[node.name].on_rightclick(
|
||||
r.r_pos, node, fake_player, itemstack, pointed_thing)) then
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
"block: right-clicked at at pos "..pos_str..".")
|
||||
else
|
||||
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
|
||||
"block: right-click at at pos "..pos_str.." had no effect.")
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
|
@ -728,6 +728,12 @@ contain all the blocks which do not allow the NPCs this kind of interaction.
|
||||
<br>You may i.e. set the `put` and `take` tables for blocks that do extensive
|
||||
checks on the player object which the NPC simply can't provide.
|
||||
|
||||
|
||||
```
|
||||
yl_speak_up.blacklist_effect_tool_use
|
||||
```
|
||||
is a similar table. Please let it contain a list of all the tool item names that NPC are _not_ allowed to u se.
|
||||
|
||||
_Note_: The best way to deal with local adjustments may be to create your
|
||||
own mod, i.e. `yl_speak_up_addons`, and let that mod depend on this
|
||||
one, `yl_speak_up`, and do the necessary calls. This is very useful
|
||||
|
Loading…
Reference in New Issue
Block a user