810 lines
23 KiB
Lua
Executable File
810 lines
23 KiB
Lua
Executable File
-- Configurable NPC
|
|
-- This is a configurable NPC
|
|
--
|
|
|
|
-- Translator
|
|
local S = mobs.translator
|
|
|
|
local vlog = mobs.vlog or "action" --"info"
|
|
local vlog = "action" --"info"
|
|
-- Mod related infos
|
|
local modname = minetest.get_current_modname()
|
|
local modpath = minetest.get_modpath(modname)
|
|
|
|
local mob_name = "npc_idler"
|
|
local icprefix=modname..'_icon_'
|
|
|
|
local mod_storage = minetest.get_mod_storage()
|
|
|
|
local serialized_mob_data = mod_storage:get_string('mob_data')
|
|
mobs.npcs.mob_data = minetest.deserialize(serialized_mob_data) or {}
|
|
|
|
-- ------------------
|
|
--
|
|
-- helper function
|
|
--
|
|
|
|
|
|
local function find_in_array(needle,stack)
|
|
if needle and stack then
|
|
for k,v in ipairs(stack) do
|
|
if v == needle then
|
|
return k
|
|
end
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
|
|
data_values = {
|
|
"nametag_color",
|
|
"nametag",
|
|
"infotext",
|
|
"textures",
|
|
"infotext",
|
|
"wield_item",
|
|
"visual_size",
|
|
"action",
|
|
}
|
|
data_serialize = {
|
|
textures = true,
|
|
action = true,
|
|
}
|
|
|
|
local function save_node_meta(pos,data)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
for _,v in ipairs(data_values) do
|
|
if data_serialize[v] then
|
|
local szv = minetest.serialize(data[v])
|
|
meta:set_string(v,szv)
|
|
else
|
|
meta:set_string(v,data[v])
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
local function get_data_from_node_meta(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
local data = {}
|
|
|
|
for _,v in ipairs(data_values) do
|
|
if data_serialize[v] then
|
|
data[v] = minetest.deserialize(meta:get_string(v))
|
|
else
|
|
data[v] = meta:get_string(v)
|
|
end
|
|
end
|
|
return data
|
|
end
|
|
|
|
local function get_mob_data(pos)
|
|
local key = minetest.pos_to_string(pos)
|
|
return mobs.npcs.mob_data[key] or get_data_from_node_meta(pos)
|
|
end
|
|
|
|
local function set_mob_data(pos,data)
|
|
local key = minetest.pos_to_string(pos)
|
|
mobs.npcs.mob_data[key] = data
|
|
save_node_meta(pos,data)
|
|
-- local sz = minetest.serialize(mobs.npcs.mob_data)
|
|
-- mod_storage:set_string('mob_data',sz)
|
|
end
|
|
|
|
|
|
|
|
-- ------------------
|
|
--
|
|
-- helper function
|
|
--
|
|
|
|
-- ------------------
|
|
--
|
|
-- helper function
|
|
--
|
|
|
|
|
|
mobs.npcs.interactions = {
|
|
default = {
|
|
icon = icprefix..'chat_random.png',
|
|
desc = S("Say one of the default random chat message strings"),
|
|
on_rightclick = mobs.npcs.random_message_on_rightclick
|
|
},
|
|
say = {
|
|
icon = icprefix..'chat.png',
|
|
desc = S("Say one of the lines below as a chat message"),
|
|
formfields = {
|
|
{'textarea','message','',4},
|
|
},
|
|
on_rightclick = mobs.npcs.message_on_rightclick,
|
|
},
|
|
-- DONE: Set a timeout between heals with a different message too
|
|
-- TODO: Or set a limit per player per days
|
|
heal = {
|
|
icon = icprefix..'healer.png',
|
|
desc = S("Heal the player"),
|
|
formfields = {
|
|
{'label','Say one of theses sentences while healing',0.5},
|
|
{'textarea','message_heal','',3},
|
|
{'label','Say one of theses sentences during cooldown',0.5},
|
|
{'textarea','message_cooldown','',2},
|
|
},
|
|
message_heal = S("There you go... good as new !")
|
|
.. "\n" .. S("Oh you look bad, let fix you...")
|
|
.. "\n" .. S("Not what I was expecting but... good for you !")
|
|
.. '',
|
|
message_cooldown = S("I'm tired.")
|
|
.. "\n" .. S("I'm resting for a bit...")
|
|
.. "\n" .. S("I can't help you now.")
|
|
.. "\n" .. S("Come back later.")
|
|
.. '',
|
|
on_rightclick = mobs.npcs.heal_on_rightclick,
|
|
},
|
|
-- Following actions are planned but do not exist at the moment
|
|
--
|
|
dialog = {
|
|
icon = icprefix..'dialog.png',
|
|
desc = S("Open a dialog menu with a text and a choice of answers"),
|
|
disabled = true,
|
|
},
|
|
ai = {
|
|
icon = icprefix..'ai.png',
|
|
desc = S("Try to mimic an intercation with the player"),
|
|
disabled = true,
|
|
},
|
|
craft = {
|
|
icon = icprefix..'crafter.png',
|
|
desc = S("Open a special inventory where the player can give item and received some transformed output"),
|
|
disabled = true,
|
|
},
|
|
give = {
|
|
icon = icprefix..'giver.png',
|
|
desc = S("Give something to the player"),
|
|
disabled = true,
|
|
},
|
|
alert_owner = {
|
|
icon = icprefix..'giver.png',
|
|
desc = S("Send an alert to the owner (allowing)"),
|
|
hidden = true,
|
|
},
|
|
}
|
|
|
|
--
|
|
-- Specific mob informations
|
|
--
|
|
|
|
local mob_id = modname..':'..mob_name
|
|
local spawner_id = modname..':'..mob_name..'_spawner'
|
|
|
|
|
|
-- Get base defintion
|
|
local mob_def = mobs.npcs.base_def
|
|
mob_def._spawner_pos = nil
|
|
local textures_string
|
|
|
|
-- Get textures
|
|
-- local textures = mobs.npcs.get_textures_array("character_lambda_",modname)
|
|
-- if textures then
|
|
-- mob_def.textures = textures
|
|
-- end
|
|
|
|
|
|
|
|
|
|
--
|
|
-- Register Spawn condition and egg
|
|
--
|
|
|
|
|
|
-- More usable texture array
|
|
local ta = {}
|
|
for k,v in ipairs(mob_def.textures) do
|
|
ta[k] = v[1]
|
|
end
|
|
|
|
|
|
local function get_npc_formspec(pos,n)
|
|
|
|
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
|
|
local ww=8 -- window width
|
|
local wh=9 -- window height
|
|
local fw=5 -- field_width
|
|
local iy=0.5 -- index y
|
|
|
|
-- Texture list as a sring
|
|
local ts = table.concat(ta,',')
|
|
|
|
local data = get_mob_data(pos) or {}
|
|
|
|
if data.last_tab then n = data.last_tab end
|
|
if not n then n = 1 end
|
|
|
|
local n = tonumber(n)
|
|
minetest.log(vlog, '['..modname..'] '..'Showing formspec '..n)
|
|
|
|
-- print(dump(data))
|
|
|
|
local ti = 1
|
|
-- Get texture index
|
|
if data.textures then ti = find_in_array(data.textures[1],ta) or 1 end
|
|
|
|
|
|
|
|
local forms = {}
|
|
-- Not empty data values
|
|
local dv = {
|
|
nametag = data.nametag or '',
|
|
nametag_color = data.nametag_color or '',
|
|
infotext = data.infotext or '',
|
|
texture = ts or '',
|
|
wield_item = data.wield_item or '',
|
|
nametag = data.nametag or '',
|
|
}
|
|
forms[1] =
|
|
-- 'label[0,'.. iy - 0.5 ..';'..S('-- Menu de configuration --')..']' ..
|
|
-- 'container[0,0]'..
|
|
-- tooltip[<gui_element_name>;<tooltip_text>;<bgcolor>;<fontcolor>]
|
|
'field[0.3,'.. iy+1 ..';'..fw..',0.3;nametag;'..S('Nom')..';'..dv.nametag..']' ..
|
|
|
|
-- 'textarea[0.3,'.. iy+1.6 ..';'..fw..',1.6;infotext;'..S('InfoText')..';'..dv.infotext..']'..
|
|
-- 'field[0.3,'.. iy+2.5 ..';'..fw..',0.5;nametag_color;'..S('Nametag Color')..';#61ff0170]' ..
|
|
-- 'label[0,'.. iy+1.5 ..';'..S('Nametag Color')..']' ..
|
|
-- 'dropdown[0,'.. iy+2 ..';'..fw..';nametag_color;<item 1>,<item 2>,<item n>;1]' ..
|
|
|
|
'label[0,'.. iy+3 ..';'..S('Texture')..']' ..
|
|
'dropdown[0,'.. iy+3.5 ..';'..fw..';texture;'..dv.texture..';'..ti..']' ..
|
|
|
|
-- 'field[0.3,'.. iy+5 ..';'..fw..',0.3;wield_item;'..S('wield_item')..';'..dv.wield_item..']' ..
|
|
--~ 'button[0.1,2;2,1;form01;'..S('Look')..']' ..
|
|
--~ 'button[0.1,3;2,1;form01;'..S('Actions')..']' ..
|
|
-- 'button[0,'.. iy+5 ..';'..fw..',0.5;action;'..S('configurer les interactions')..']' ..
|
|
'button_exit['.. ww - 1 ..','.. wh - 1 ..';1,1;ok;ok]'..
|
|
''
|
|
|
|
forms[2] =
|
|
default.gui_slots ..
|
|
"list[nodemeta:" .. spos .. ";main;0,0.3;8,4;]" ..
|
|
"list[current_player;main;0,4.85;8,1;]" ..
|
|
"list[current_player;main;0,6.08;8,3;8]" ..
|
|
"listring[nodemeta:" .. spos .. ";main]" ..
|
|
"listring[current_player;main]" ..
|
|
default.get_hotbar_bg(0,4.85) ..
|
|
''
|
|
|
|
|
|
-- local action_buttons=''
|
|
-- local l = 0.1
|
|
-- for k,v in pairs(mobs.npcs.interactions) do
|
|
-- action_buttons = action_buttons..'image_button['..l..',0;1,1;'..v.icon..';'..k..';]'
|
|
-- l = l + 1
|
|
-- end
|
|
local acts={}
|
|
for k,v in pairs(mobs.npcs.interactions) do
|
|
if not ( v.disabled or v.hidden ) then
|
|
acts[#acts+1] = k
|
|
end
|
|
end
|
|
|
|
local action = data.action or {}
|
|
if not data.action then data.action = {} end
|
|
action.id = data.action.id or "default"
|
|
action.desc = mobs.npcs.interactions[action.id].desc
|
|
|
|
local actstr=table.concat(acts,',')
|
|
local ai = find_in_array(action.id,acts) or 1
|
|
local actionf = ''
|
|
local ayi = iy+2
|
|
local action_arr = mobs.npcs.interactions[action.id]
|
|
if action_arr and action_arr.formfields then
|
|
for _,v in ipairs(action_arr.formfields) do
|
|
if v[1] == 'label' then
|
|
actionf = actionf .. 'label[0,'.. ayi ..';'..v[2]..']'
|
|
ayi = ayi + 0.5
|
|
elseif v[1] == 'textarea' then
|
|
-- {'textarea','message_cooldown','',2},
|
|
local aname = v[2]
|
|
local dstr = action_arr[aname] or S("Hello").."\n"..S("Hi").."\n"..S("Hey")
|
|
actionf = actionf .. 'textarea[0.3,'.. ayi ..';'..fw..','..v[4]..';action_'..v[2]..';'..v[3]..';'..dstr..']'
|
|
-- print(dump(actionf))
|
|
ayi = ayi + v[4] + 0.1
|
|
end
|
|
end
|
|
end
|
|
forms[3] =
|
|
'label[0,'.. iy-0.5 ..';'..S('When a player interact with this character :')..']' ..
|
|
'dropdown[0,'.. iy+0.5 ..';'..fw..';action_id;'..actstr..';'..ai..']' ..
|
|
'label[0,'.. iy+1.5 ..';'..action.desc..']' ..
|
|
actionf..
|
|
-- textlist[<X>,<Y>;<W>,<H>;<name>;<listelem 1>,<listelem 2>,...,<listelem n>;<selected idx>;<transparent>]
|
|
-- 'textlist[0,0;'..ww - 3*(ww/4)..','.. wh-1 ..';stagelist;action_1,stage_2,stage_3;1;false]'..
|
|
-- 'container['..ww - 3*(ww/4)..',0]'..
|
|
-- image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
|
|
-- 'image_button[0.1,0;1,1;'..icprefix..'chat.png^'..icprefix..'selected.png'..';act1;]'..
|
|
-- action_buttons ..
|
|
|
|
|
|
-- 'container_end[]'..
|
|
-- 'button[0,'.. wh-1 ..';1,1;add_stage;+]'..
|
|
-- 'button[1,'.. wh-1 ..';1,1;help_stage;?]'..
|
|
'button_exit['.. ww - 1 ..','.. wh - 1 ..';1,1;ok;ok]'..
|
|
''
|
|
|
|
forms[4] =
|
|
'textarea[0.3,'.. iy+1.6 ..';'..fw..',1.6;infotext;'..S('InfoText')..';'..dv.infotext..']'..
|
|
'button_exit['.. ww - 1 ..','.. wh - 1 ..';1,1;ok;ok]'..
|
|
''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local content = forms[n] or ''
|
|
|
|
|
|
local formspec =
|
|
'size['..ww..','..wh..']' ..
|
|
-- default.gui_bg ..
|
|
-- default.gui_bg_img ..
|
|
'field[-1,-1;0,0.5;key;;'..minetest.pos_to_string(pos)..']' ..
|
|
'tabheader[0,'.. iy - 0.5 ..';tab;Apparence,Inventaire,Action,Misc;'.. n..';false;false]'..
|
|
content..
|
|
-- tabheader[<X>,<Y>;<name>;<caption 1>,<caption 2>,...,<caption n>;<current_tab>;<transparent>;<draw_border>]
|
|
|
|
|
|
--~ default.get_hotbar_bg(0,4.85)
|
|
--~ button[<X>,<Y>;<W>,<H>;<name>;<label>]
|
|
--~ field[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
|
|
--~ textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]
|
|
--~ label[<X>,<Y>;<label>]
|
|
--~ dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]
|
|
|
|
-- 'button_exit['.. ww - 1 ..',0;1,1;close;x]'..
|
|
''
|
|
return formspec
|
|
end
|
|
|
|
|
|
|
|
-- Function to initialize spawner : add entity and update metadata
|
|
-- Called after place node and on rightclick
|
|
|
|
|
|
|
|
mobs.npcs.update_cmob_properties = function(pos, player, mob)
|
|
|
|
minetest.log(vlog, '['..modname..'] '..'Updating mob properties from data at '..minetest.pos_to_string(pos))
|
|
local data = get_mob_data(pos) or {}
|
|
|
|
if data.obj and not mob then mob = data.obj end
|
|
|
|
--- -- FIXEME: Seem to return true even when entity isn't there
|
|
--- -- Probably because it's there just before being removed by the do_custom funtion
|
|
local self
|
|
if mob then self = mob:get_luaentity() end
|
|
if not self then return false end
|
|
|
|
-- mob:set_pos({ x= pos.x, y= pos.y + 1, z= pos.z, })
|
|
minetest.log(vlog, '['..modname..'] '..'Mob entity exist')
|
|
|
|
|
|
-- print(dump(data))
|
|
|
|
-- Set owner
|
|
-- TODO: check that node is the correct node
|
|
local player_name
|
|
if not player then
|
|
player_name = data.owner
|
|
else
|
|
player_name = player:get_player_name()
|
|
end
|
|
-- Set node meta
|
|
local meta = minetest.get_meta(pos)
|
|
local owner_name = data.owner or player_name
|
|
meta:set_string("owner", owner_name)
|
|
|
|
-- Set mob properties
|
|
-- print(dump(self))
|
|
|
|
if data.nametag then
|
|
mob:set_nametag_attributes({
|
|
color = data.nametag_color or 'green',
|
|
text = data.nametag,
|
|
})
|
|
end
|
|
|
|
mob:set_properties({
|
|
infotext = data.infotext or nil,
|
|
owner = owner_name,
|
|
textures = data.textures or self.textures,
|
|
infotext = data.infotext or self.infotext,
|
|
wield_item = data.wield_item or self.wield_item,
|
|
visual_size = data.visual_size or self.visual_size,
|
|
})
|
|
-- self = mob:get_luaentity()
|
|
self._mobname = data.nametag or nil
|
|
self._owner = owner_name
|
|
self._spawner_pos = pos
|
|
|
|
data.obj = mob
|
|
-- Register to global table
|
|
set_mob_data(pos,data)
|
|
|
|
-- print(dump(self))
|
|
|
|
end
|
|
|
|
mobs.npcs.update_cmob_data = function(pos)
|
|
|
|
minetest.log(vlog, '['..modname..'] '..'Updating mob data from current properties at '..minetest.pos_to_string(pos))
|
|
|
|
local data = get_mob_data(pos)
|
|
|
|
if data and data.obj then
|
|
minetest.log(vlog, '['..modname..'] '..'Mob data exist')
|
|
|
|
local self = data.obj:get_luaentity()
|
|
-- If self is nil, the mob isn't there anymore...
|
|
if not self then return false end
|
|
minetest.log(vlog, '['..modname..'] '..'Mob entity too')
|
|
|
|
local prop = data.obj:get_properties() or {}
|
|
-- print(dump(prop))
|
|
|
|
data.nametag = prop.nametag or nil
|
|
data.nametag_color = prop.nametag_color or 'green'
|
|
data.owner = prop.owner
|
|
data.textures = prop.textures or self.textures
|
|
data.infotext = prop.infotext or nil
|
|
data.spawner_pos = pos
|
|
data.wield_item = prop.wield_item or nil
|
|
data.visual_size = prop.visual_size or nil
|
|
|
|
end
|
|
|
|
set_mob_data(pos,data)
|
|
return data
|
|
end
|
|
|
|
mobs.npcs.add_cmob = function(pos, player, _)
|
|
|
|
minetest.log(vlog, '['..modname..'] '..'Adding new mob at :'..minetest.pos_to_string(pos))
|
|
|
|
-- Place mob
|
|
local above = { x=pos.x, y=pos.y+1, z=pos.z }
|
|
local mob = minetest.add_entity(above, modname..':'..mob_name,minetest.write_json({_spawner_pos = pos}))
|
|
|
|
mobs.npcs.update_cmob_properties(pos, player, mob)
|
|
mobs.npcs.update_cmob_data(pos)
|
|
-- Get Data
|
|
--~ local data = {}
|
|
--~ data.nametag = meta:get_string('npc_nametag')
|
|
--~ data.nametag_color = meta:get_string('npc_nametag_color')
|
|
|
|
-- Apply it to the mob
|
|
--~ local self = mob:get_luaentity()
|
|
--~ mob:set_properties({
|
|
--~ owner = owner,
|
|
--~ _spawner_pos = pos,
|
|
--~ })
|
|
--~ if data.nametag then
|
|
--~ if not data.nametag_color then data.nametag_color = 'green' end
|
|
--~ mob:set_nametag_attributes({
|
|
--~ color = data.nametag_color,
|
|
--~ text = data.nametag,
|
|
--~ })
|
|
--~ end
|
|
|
|
end
|
|
|
|
|
|
local function cmob_data_update(pos,player,itemstack,mob,playername)
|
|
|
|
-- Update mob properties
|
|
mobs.npcs.update_cmob_properties(pos, player, mob)
|
|
local data = mobs.npcs.update_cmob_data(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
local owner = meta:get_string('owner')
|
|
|
|
-- Re-call the after_place_node function if needed
|
|
if not ( data and data.obj ) then
|
|
|
|
-- Get infos about the owner
|
|
local powner = minetest.get_player_by_name(owner)
|
|
if player and (not powner) then
|
|
powner = player
|
|
end
|
|
|
|
|
|
-- Call the function
|
|
--~ local spw_init = minetest.registered_nodes[node.name].after_place_node
|
|
--~ if spw_init and player then
|
|
--~ spw_init(pos, player, itemstack)
|
|
--~ end
|
|
for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
|
if obj:get_luaentity().name == mob_id then
|
|
obj:remove()
|
|
end
|
|
end
|
|
mobs.npcs.add_cmob(pos, powner, itemstack)
|
|
end
|
|
|
|
return data
|
|
end
|
|
|
|
local function cmob_show_formspec(pos,player,data)
|
|
local tab = 1
|
|
if data and data.last_tab then
|
|
tab = data.last_tab
|
|
end
|
|
minetest.after(0.2,
|
|
minetest.show_formspec,
|
|
player:get_player_name(),
|
|
modname..':'..mob_name..'_form0'..tab,
|
|
get_npc_formspec(pos,tab))
|
|
end
|
|
--
|
|
-- Register Npc
|
|
--
|
|
|
|
mob_def.walk_chance = 0
|
|
mob_def.jump = false
|
|
local dtstep = 15
|
|
local dt = 0
|
|
mob_def.do_custom = function(self, dtime)
|
|
|
|
-- Save memory by runing only 1/dtstep times
|
|
if dt < dtstep then
|
|
dt = dt + 1
|
|
return false
|
|
else
|
|
dt = 0
|
|
end
|
|
|
|
|
|
-- Make sure that cooldown is a number
|
|
if type(self._cooldown) ~= 'number'
|
|
or self._cooldown <= 0
|
|
then
|
|
self._cooldown = 0
|
|
-- Cooldown if needed
|
|
else
|
|
self._cooldown = self._cooldown - ( dtstep * dtime )
|
|
-- print('Cooldown : '..dump(self._cooldown))
|
|
end
|
|
|
|
--- Get mob pos
|
|
local pos = self.object:get_pos()
|
|
local spawner_pos = self._spawner_pos
|
|
|
|
--- Look for reasons to remove the mob:
|
|
--- Spawner pos is not set...
|
|
--- ... try to find it
|
|
-- if not spawner_pos then
|
|
-- for i=-1,1 do
|
|
-- local spos = { x= pos.x, y= pos.y + i, z= pos.z, }
|
|
-- if ( minetest.get_node(spos).name == spawner_id ) then
|
|
-- spawner_pos = spos
|
|
-- break
|
|
-- end
|
|
-- end
|
|
-- end
|
|
|
|
--- Spawner pos is not set...
|
|
if ( not spawner_pos )
|
|
--- Or mob is away from spawner
|
|
or ( vector.distance(pos, spawner_pos) > 1 )
|
|
--- Or spawner has been removed
|
|
or ( minetest.get_node(spawner_pos).name ~= spawner_id )
|
|
then
|
|
self.object:remove()
|
|
return false
|
|
end
|
|
|
|
-- local meta = minetest.get_meta(spawner_pos)
|
|
local data = get_mob_data(spawner_pos)
|
|
if not data.obj then
|
|
self.object:remove()
|
|
mobs.npcs.add_cmob(spawner_pos, data.owner)
|
|
end
|
|
-- set_mob_data(spawner_pos,data)
|
|
-- mobs.npcs.update_cmob_properties(spawner_pos, nil, self.obj)
|
|
|
|
-- Make sure that it is still on the spawner (or at least 'in' it, or 'above' it)
|
|
-- for i=-1,1 do
|
|
-- local spos = { x= pos.x, y= pos.y + i, z= pos.z, }
|
|
-- if ( minetest.get_node(spos).name == spawner_id ) then
|
|
-- --- Stop function when spawner is found
|
|
-- mobs.npcs.update_cmob_properties(pos, nil, self.obj)
|
|
-- return false
|
|
-- end
|
|
-- end
|
|
|
|
-- Remove mob if it is away from spawner
|
|
-- self.object:remove()
|
|
return false
|
|
end
|
|
|
|
-- Set on_right_click interaction
|
|
mob_def.on_rightclick = function(self, clicker)
|
|
|
|
-- Look at the player
|
|
mobs.npcs.turn_to_player(self, clicker)
|
|
|
|
-- Find spawner
|
|
local spawner_pos = self._spawner_pos
|
|
|
|
-- Edit and update
|
|
local edit_key = 'sneak'
|
|
if spawner_pos and clicker:get_player_control()[edit_key] then
|
|
data = cmob_data_update(spawner_pos,clicker,nil,self.object)
|
|
cmob_show_formspec(spawner_pos,clicker,data)
|
|
return
|
|
end
|
|
|
|
if spawner_pos then
|
|
-- Do custom action
|
|
local data = get_mob_data(spawner_pos) or {}
|
|
if data.action and data.action.id then
|
|
local id = data.action.id
|
|
local ref = mobs.npcs.interactions
|
|
if ref[id] and ref[id].on_rightclick then
|
|
return ref[id].on_rightclick(self, clicker, data)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Or at least say something
|
|
local mobname = mobs.npcs.get_mobname(self)
|
|
local clickername = clicker:get_player_name()
|
|
local msg = mobs.npcs.messages.get_random()
|
|
mobs.npcs.send_chat_message(clickername,msg,mobname)
|
|
|
|
end
|
|
|
|
|
|
mob_def.after_activate = function(self, staticdata, def, dtime)
|
|
-- Update mob after activate
|
|
local pos = self._spawner_pos
|
|
if pos then
|
|
local playername, player
|
|
if self._owner then
|
|
playername = self._owner
|
|
player = minetest.get_player_by_name(playername)
|
|
end
|
|
local mob = self.object
|
|
cmob_data_update(pos,player,nil,mob)
|
|
end
|
|
end
|
|
|
|
mobs:register_mob(mob_id, mob_def)
|
|
|
|
-- This one doesn't spawn naturally, instead it spawn
|
|
minetest.register_node(spawner_id, {
|
|
description = 'Place this to spawn a configurable npc',
|
|
drawtype = "nodebox",
|
|
tiles = {"default_stone_block.png"},
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
is_ground_content = false,
|
|
groups = {oddly_breakable_by_hand = 2},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {-0.5, -0.48, -0.5, 0.5, -0.5, 0.5},
|
|
},
|
|
on_construct = function(pos)
|
|
-- minetest.get_node_timer(pos):start(20)
|
|
local meta = minetest.get_meta(pos)
|
|
-- meta:set_string("infotext", "Chest")
|
|
local inv = meta:get_inventory()
|
|
inv:set_size("main", 8*3)
|
|
end,
|
|
|
|
after_place_node = mobs.npcs.add_cmob,
|
|
|
|
--~ after_dig_node = function(pos, node, metadata, digger)
|
|
--~ mobs.npcs.remove_custom_mob(pos, placer)
|
|
--~ end,
|
|
can_dig = function(pos,player)
|
|
local meta = minetest.get_meta(pos);
|
|
local inv = meta:get_inventory()
|
|
return inv:is_empty("main") and default.can_interact_with_node(player, pos)
|
|
end,
|
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
|
|
|
-- --
|
|
-- Check that the npc is still there
|
|
-- --
|
|
local data = cmob_data_update(pos, clicker, itemstack)
|
|
|
|
-- --
|
|
-- Stop there if not allowed to interact
|
|
-- --
|
|
if not default.can_interact_with_node(clicker, pos) then
|
|
return itemstack
|
|
end
|
|
|
|
-- Show customisation form
|
|
cmob_show_formspec(pos,clicker,data)
|
|
end,
|
|
|
|
-- on_receive_fields = function(pos, formname, fields, sender)
|
|
-- end
|
|
})
|
|
|
|
|
|
-- Register egg
|
|
-- mobs:register_egg(mob_id, "npc", "character_lambda_inv.png", 0)
|
|
--~ mobs:doc_identifier_compat(mob_id, longdesc, usagehelp)
|
|
|
|
mobs:alias_mob("mobs:"..mob_name, mob_id) -- compatibility
|
|
|
|
local on_receive_fields = function(player, formname, fields)
|
|
|
|
local playername = player:get_player_name()
|
|
|
|
if not string.match(formname, modname..':'..mob_name..'_form0%d') then
|
|
return false
|
|
end
|
|
-- print('-------- FIELDS ------------')
|
|
-- print(dump(fields))
|
|
|
|
local pos
|
|
if fields.key then
|
|
pos = minetest.string_to_pos(fields.key)
|
|
end
|
|
|
|
if not pos then return false end
|
|
local data = get_mob_data(pos) or {}
|
|
|
|
-- Update data without overiding it
|
|
if fields.texture then data.textures = { fields.texture } end
|
|
if fields.action_id then
|
|
-- if fields.action_id and (( not data.action ) or ( fields.action_id ~= data.action.id )) then
|
|
data.action = data.action or {}
|
|
-- data.action.id = fields.action_id
|
|
-- data.action.message = fields.action_message or data.action.message
|
|
-- data.action = mobs.npcs.interactions[fields.action_id]
|
|
for k,v in pairs(fields) do
|
|
for l in string.gmatch(k,"action_([A-Za-z0-9_]+)") do
|
|
-- print('action '..dump(l)..' : '..dump(v))
|
|
data.action[l] = v or data.action[l]
|
|
end
|
|
end
|
|
end
|
|
local fk = {
|
|
'nametag','nametag_color','allowed','infotext','wield_item',
|
|
}
|
|
for _,v in ipairs(fk) do
|
|
if fields[v] then data[v] = fields[v] end
|
|
end
|
|
data.last_tab = fields.tab or data.last_tab
|
|
|
|
-- data.visual_size = {x = 1, y = 1.1}
|
|
|
|
-- print('-------- DATA ------------')
|
|
-- print(dump(data))
|
|
|
|
set_mob_data(pos,data)
|
|
mobs.npcs.update_cmob_properties(pos,player,data.obj)
|
|
|
|
local tb = data.last_tab
|
|
if ( fields.tab or fields.action_id ) and not fields.quit then
|
|
minetest.after(0.2,
|
|
minetest.show_formspec,
|
|
playername,
|
|
modname..':'..mob_name..'_form0'..tb,
|
|
get_npc_formspec(pos,tb))
|
|
|
|
end
|
|
|
|
|
|
end
|
|
|
|
minetest.register_on_player_receive_fields(on_receive_fields)
|