add support for smart_dialogs mod to npc only

This commit is contained in:
tenplus1 2022-06-07 08:06:53 +01:00
parent 7d10806bda
commit da5c5ce9be
3 changed files with 186 additions and 26 deletions

View File

@ -2,3 +2,4 @@ mobs
default?
lucky_block?
intllib?
smart_dialogs?

View File

@ -1,4 +1,4 @@
name = mobs_npc
depends = mobs
optional_depends = default, lucky_block, intllib
optional_depends = default, lucky_block, intllib, simple_dialogs
description = Adds simple NPC and Trader.

209
npc.lua
View File

@ -1,6 +1,64 @@
local S = mobs.intllib_npc
-- check for simple_dialogs mod and setup
local context = {}
local useDialogs = "N"
minetest.register_on_leaveplayer(function(player)
context[player:get_player_name()] = nil
end)
if minetest.get_modpath("simple_dialogs") then
useDialogs = "Y"
simple_dialogs.register_varloader(function(npcself,playername)
simple_dialogs.save_dialog_var(npcself, "NPCNAME", npcself.nametag, playername)
simple_dialogs.save_dialog_var(npcself, "STATE", npcself.state, playername)
simple_dialogs.save_dialog_var(npcself, "FOOD", npcself.food, playername)
simple_dialogs.save_dialog_var(npcself, "HEALTH", npcself.health, playername)
simple_dialogs.save_dialog_var(npcself, "owner", npcself.owner, playername)
end)
simple_dialogs.register_hook(function(npcself,playername,hook)
if hook.func == "TELEPORT" then
if npcself.owner then
--check to see if the player has 'bring' teleport privliges
local player_privs = minetest.get_player_privs(npcself.owner)
if player_privs["bring"] then
--validate x,y,z coords
if hook.parm and hook.parmcount and hook.parmcount > 2 then
local pos = {
x = tonumber(hook.parm[1]),
y = tonumber(hook.parm[2]),
z = tonumber(hook.parm[3])
}
if pos.x and pos.y and pos.z
and pos.x > -31500 and pos.x < 31500
and pos.y > -31500 and pos.y < 31500
and pos.z > -31500 and pos.z < 31500 then
local player = minetest.get_player_by_name(playername)
if player then
player:set_pos(pos) end
end
end
end
end
return "EXIT"
end
end)
end
-- Npc by TenPlus1
mobs.npc_drops = {
@ -70,6 +128,8 @@ mobs:register_mob("mobs_npc:npc", {
on_rightclick = function(self, clicker)
self.id = set_npc_id(self)
-- feed to heal npc
if mobs:feed_tame(self, clicker, 8, true, true) then return end
@ -110,41 +170,22 @@ mobs:register_mob("mobs_npc:npc", {
obj:set_velocity({x = -dir.x, y = 1.5, z = -dir.z})
--minetest.chat_send_player(name, S("NPC dropped you an item for gold!"))
return
end
-- by right-clicking owner can switch npc between follow, wander and stand
if self.owner and self.owner == name then
if self.order == "follow" then
minetest.show_formspec(name, "mobs_npc:controls",
get_npc_controls_formspec(name, self))
self.order = "wander"
minetest.chat_send_player(name, S("NPC will wander."))
elseif self.order == "wander" then
self.order = "stand"
self.state = "stand"
self.attack = nil
self:set_animation("stand")
self:set_velocity(0)
minetest.chat_send_player(name, S("NPC stands still."))
elseif self.order == "stand" then
self.order = "follow"
minetest.chat_send_player(name, S("NPC will follow you."))
end
elseif useDialogs == "Y" then
simple_dialogs.show_dialog_formspec(name, self)
end
end
})
if not mobs.custom_spawn_npc then
mobs:spawn({
name = "mobs_npc:npc",
@ -158,7 +199,125 @@ mobs:spawn({
})
end
mobs:register_egg("mobs_npc:npc", S("Npc"), "default_brick.png", 1)
-- compatibility
mobs:alias_mob("mobs:npc", "mobs_npc:npc")
-- Kilarin's formspec functions
function get_npc_controls_formspec(name,self)
local currentordermode = self.order
local npcId = self.id
local orderArray = {"wander", "stand", "follow"}
local currentorderidx = 1
for i = 1, 3 do --this seems like a clumsy way to do this
if orderArray[i] == currentordermode then
currentorderidx = i
break
end
end
-- Make npc controls formspec
local text = "NPC Controls"
local size = useDialogs == "Y" and "size[15,10]" or "size[3.85,2.8]"
local formspec = {
size,
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
"dropdown[0.375,1.25; 3,0.6;ordermode;wander,stand,follow;", currentorderidx, "]",
"button[0.375,2;3,0.8;exit;Exit]"
}
if useDialogs == "Y" then
simple_dialogs.add_dialog_control_to_formspec(name, self, formspec, 0.375, 3.4)
end
table.concat(formspec, "")
--store npc id in local context so we can use it when the form is returned
context[name] = npcId
return table.concat(formspec, "")
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local pname = player:get_player_name()
if formname ~= "mobs_npc:controls" then
if context[pname] then context[pname] = nil end
return
end
local npcId = context[pname] or nil --get the npc id from local context
local npcself = get_npcself_from_id(npcId)
if npcself ~= nil then
if fields["exit"] then
minetest.close_formspec(pname, "mobs_npc:controls")
elseif fields["ordermode"] then
-- minetest.chat_send_all("received ordermode")
local pname = player:get_player_name()
npcself.order = fields["ordermode"]
if npcself.order == "wander" then
minetest.chat_send_player(pname, S("NPC will wander."))
elseif npcself.order == "stand" then
npcself.state = "stand"
npcself.attack = nil
npcself:set_animation("stand")
npcself:set_velocity(0)
minetest.chat_send_player(pname, S("NPC stands still."))
elseif npcself.order == "follow" then
minetest.chat_send_player(pname, S("NPC will follow you."))
end
end
if useDialogs == "Y" then
simple_dialogs.process_simple_dialog_control_fields(pname, npcself, fields)
end
end
end)
-- check if npc has id set otherwise create one
function set_npc_id(npcself)
if not npcself.id then
npcself.id = (math.random(1, 1000) * math.random(1, 10000))
.. npcself.name .. (math.random(1, 1000) ^ 2)
end
return npcself.id
end
--this function finds an npcself in the luaentities list given an npcId
function get_npcself_from_id(npcId)
if npcId == nil then return nil end
for k, v in pairs(minetest.luaentities) do
if v.object and v.id and v.id == npcId then
return v
end
end
end