123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- local S = mobs_npc.S
- -- show random message from list
- mobs_npc.npc_talk = function(self, player, message_list)
- local name = player:get_player_name() or ""
- local messages = message_list or self.messages or {"??"}
- if messages then
- local msg = messages[math.random(#messages)]
- minetest.chat_send_player(name, "<" .. (self.nametag or "") .. "> " .. msg)
- end
- end
- -- drop random item from list
- mobs_npc.drop_trade = function(self, player, item, item_list)
- local w_inv = player:get_wielded_item()
- if item ~= w_inv:get_name() then return end
- local name = player:get_player_name()
- if not mobs.is_creative(name) then
- w_inv:take_item()
- player:set_wielded_item(w_inv)
- end
- local pos = self.object:get_pos()
- local drops = item_list
- local drop = drops[math.random(#drops)]
- local chance = 1
- if type(drop) == "table" then
- chance = drop[2] or 1
- drop = drop[1]
- end
- if not minetest.registered_items[drop]
- or math.random(chance) > 1 then
- drop = "default:clay_lump"
- end
- local obj = minetest.add_item(pos, {name = drop})
- local dir = player:get_look_dir()
- obj:set_velocity({x = -dir.x, y = 1.5, z = -dir.z})
- return true
- end
- -- check for simple_dialogs mod and setup
- local context = {}
- mobs_npc.useDialogs = "N"
- minetest.register_on_leaveplayer(function(player)
- context[player:get_player_name()] = nil
- end)
- if minetest.get_modpath("simple_dialogs") then
- mobs_npc.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
- -- Kilarin's formspec functions
- function mobs_npc.get_controls_formspec(name, self)
- self.id = set_npc_id(self) -- make sure id is set
- 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 = mobs_npc.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 mobs_npc.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
- -- receive and do orders given through form
- 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
- 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 mobs_npc.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
- --This code comes almost exclusively from the trader and inventory of mobf, by Sapier.
- --The copyright notice below is from mobf:
- -------------------------------------------------------------------------------
- -- Mob Framework Mod by Sapier
- --
- -- You may copy, use, modify or do nearly anything except removing this
- -- copyright notice.
- -- And of course you are NOT allow to pretend you have written it.
- --
- --! @file inventory.lua
- --! @brief component containing mob inventory related functions
- --! @copyright Sapier
- --! @author Sapier
- --! @date 2013-01-02
- --
- --! @defgroup Inventory Inventory subcomponent
- --! @brief Component handling mob inventory
- --! @ingroup framework_int
- --! @{
- --
- -- Contact sapier a t gmx net
- -------------------------------------------------------------------------------
- -- This code has been heavily modified by isaiah658.
- -- Trades are saved in entity metadata so they always stay the same after
- -- initially being chosen. Also the formspec uses item image buttons instead of
- -- inventory slots.
- local function add_goods(self, race)
- local trade_index = 1
- local trades_already_added = {}
- local trader_pool_size = 10
- local item_pool_size = #race.items -- get number of items on list
- self.trades = {}
- if item_pool_size < trader_pool_size then
- trader_pool_size = item_pool_size
- end
- for i = 1, trader_pool_size do
- -- If there are more trades than the amount being added, they are
- -- randomly selected. If they are equal, there is no reason to randomly
- -- select them
- local random_trade = nil
- if item_pool_size == trader_pool_size then
- random_trade = i
- else
- while random_trade == nil do
- local num = math.random(item_pool_size)
- if trades_already_added[num] == nil then
- trades_already_added[num] = true
- random_trade = num
- end
- end
- end
- if math.random(0, 100) > race.items[random_trade][3] then
- self.trades[trade_index] = {
- race.items[random_trade][1],
- race.items[random_trade][2]
- }
- trade_index = trade_index + 1
- end
- end
- end
- function mobs_npc.shop_trade(self, clicker, race)
- self.id = set_npc_id(self) -- make sure id is set
- if not self.game_name then
- self.game_name = tostring(race.names[math.random(1, #race.names)])
- self.nametag = S("Trader @1", self.game_name)
- self.object:set_properties({
- nametag = self.nametag,
- nametag_color = "#00FF00"
- })
- end
- if self.trades == nil then
- add_goods(self, race)
- end
- local player = clicker:get_player_name() or ""
- minetest.chat_send_player(player,
- S("[NPC] <Trader @1> Hello, @2, have a look at my wares.",
- self.game_name, player))
- -- Make formspec trade list
- local formspec_trade_list = ""
- local x, y
- for i = 1, 10 do
- if self.trades[i] and self.trades[i] ~= "" then
- if i < 6 then
- x = 0.5
- y = i - 0.5
- else
- x = 4.5
- y = i - 5.5
- end
- formspec_trade_list = formspec_trade_list
- .. "item_image_button[".. x ..",".. y ..";1,1;"
- .. self.trades[i][2] .. ";prices#".. i .."#".. self.id ..";]"
- .. "item_image_button[".. x + 2 ..",".. y ..";1,1;"
- .. self.trades[i][1] .. ";goods#".. i .."#".. self.id ..";]"
- .. "image[".. x + 1 ..",".. y ..";1,1;gui_arrow_blank.png]"
- end
- end
- minetest.show_formspec(player, "mobs_npc:trade", "size[8,10]"
- .. default.gui_bg_img
- .. default.gui_slots
- .. "label[0.5,-0.1;" .. S("Trader @1's stock:", self.game_name) .. "]"
- .. formspec_trade_list
- .. "list[current_player;main;0,6;8,4;]"
- )
- end
- minetest.register_on_player_receive_fields(function(player, formname, fields)
- if formname ~= "mobs_npc:trade" then return end
- if fields then
- local trade = ""
- for k, v in pairs(fields) do
- trade = tostring(k)
- end
- local id = trade:split("#")[3]
- local self = nil
- if id ~= nil then
- for k, v in pairs(minetest.luaentities) do
- if v.object and v.id and v.id == id then
- self = v
- break
- end
- end
- end
- if self ~= nil then
- local trade_number = tonumber(trade:split("#")[2])
- if trade_number ~= nil and self.trades[trade_number] ~= nil then
- local price = self.trades[trade_number][2]
- local goods = self.trades[trade_number][1]
- local inv = player:get_inventory()
- if inv:contains_item("main", price) then
- inv:remove_item("main", price)
- local leftover = inv:add_item("main", goods)
- if leftover:get_count() > 0 then
- -- drop item(s) in front of player
- local droppos = player:get_pos()
- local dir = player:get_look_dir()
- droppos.x = droppos.x + dir.x
- droppos.z = droppos.z + dir.z
- minetest.add_item(droppos, leftover)
- end
- end
- end
- end
- end
- end)
|