NPC: Cleaned up debugging logs.

Standarized logs to have different levels.
Show by default only INFO, ERROR log messages.
Dialogues: Standarized function for NPC chat messages.
Removed trader.lua and trader_test.lua which are part of old 'mobs_npc' mod.
This commit is contained in:
Hector Franqui 2017-06-17 09:44:25 -04:00
parent bf0f643e3e
commit a91160ecc6
9 changed files with 111 additions and 715 deletions

View File

@ -141,8 +141,8 @@ end
-- and the NPC is allowed to roam freely. -- and the NPC is allowed to roam freely.
function npc.actions.freeze(self, args) function npc.actions.freeze(self, args)
local freeze_mobs_api = args.freeze local freeze_mobs_api = args.freeze
minetest.log("Received: "..dump(freeze_mobs_api)) --minetest.log("Received: "..dump(freeze_mobs_api))
minetest.log("Returning: "..dump(not(freeze_mobs_api))) --minetest.log("Returning: "..dump(not(freeze_mobs_api)))
return not(freeze_mobs_api) return not(freeze_mobs_api)
end end
@ -333,7 +333,7 @@ function npc.actions.take_item_from_external_inventory(self, args)
else else
inv = minetest.get_inventory({type="node", pos=pos}) inv = minetest.get_inventory({type="node", pos=pos})
end end
-- Create ItemSTack to take from external inventory -- Create ItemStack to take from external inventory
local item = ItemStack(item_name.." "..count) local item = ItemStack(item_name.." "..count)
-- Check if there is enough of the item to take -- Check if there is enough of the item to take
if inv:contains_item(inv_list, item) then if inv:contains_item(inv_list, item) then
@ -369,7 +369,7 @@ end
-- TODO: Refactor this function so that it uses a table to check -- TODO: Refactor this function so that it uses a table to check
-- for doors instead of having separate logic for each door type -- for doors instead of having separate logic for each door type
function npc.actions.get_openable_node_state(node, npc_dir) function npc.actions.get_openable_node_state(node, npc_dir)
minetest.log("Node name: "..dump(node.name)) --minetest.log("Node name: "..dump(node.name))
local state = npc.actions.const.doors.state.CLOSED local state = npc.actions.const.doors.state.CLOSED
-- Check for default doors and gates -- Check for default doors and gates
local a_i1, a_i2 = string.find(node.name, "_a") local a_i1, a_i2 = string.find(node.name, "_a")
@ -383,7 +383,7 @@ function npc.actions.get_openable_node_state(node, npc_dir)
if a_i1 == nil and open_i1 == nil and not half_door_is_closed then if a_i1 == nil and open_i1 == nil and not half_door_is_closed then
state = npc.actions.const.doors.state.OPEN state = npc.actions.const.doors.state.OPEN
end end
minetest.log("Door state: "..dump(state)) --minetest.log("Door state: "..dump(state))
return state return state
end end
@ -412,10 +412,10 @@ end
-- items from a chest, are provided here. -- items from a chest, are provided here.
local function get_pos_argument(self, pos) local function get_pos_argument(self, pos)
minetest.log("Type of pos: "..dump(type(pos))) --minetest.log("Type of pos: "..dump(type(pos)))
-- Check which type of position argument we received -- Check which type of position argument we received
if type(pos) == "table" then if type(pos) == "table" then
minetest.log("Received table pos: "..dump(pos)) --minetest.log("Received table pos: "..dump(pos))
-- Check if table is position -- Check if table is position
if pos.x ~= nil and pos.y ~= nil and pos.z ~= nil then if pos.x ~= nil and pos.y ~= nil and pos.z ~= nil then
-- Position received, return position -- Position received, return position
@ -468,7 +468,7 @@ end
function npc.actions.use_furnace(self, args) function npc.actions.use_furnace(self, args)
local pos = get_pos_argument(self, args.pos) local pos = get_pos_argument(self, args.pos)
if pos == nil then if pos == nil then
minetest.log("[advanced_npc] WARNING Got nil position in 'use_furnace' using args.pos: "..dump(args.pos)) npc.log("WARNING", "Got nil position in 'use_furnace' using args.pos: "..dump(args.pos))
return return
end end
@ -503,15 +503,15 @@ function npc.actions.use_furnace(self, args)
local fuel_time = local fuel_time =
minetest.get_craft_result({method="fuel", width=1, items={ItemStack(fuel_item.item_string)}}).time minetest.get_craft_result({method="fuel", width=1, items={ItemStack(fuel_item.item_string)}}).time
local total_fuel_time = fuel_time * npc.get_item_count(fuel_item.item_string) local total_fuel_time = fuel_time * npc.get_item_count(fuel_item.item_string)
minetest.log("Fuel time: "..dump(fuel_time)) npc.log("DEBUG", "Fuel time: "..dump(fuel_time))
-- Get item to cook's cooking time -- Get item to cook's cooking time
local cook_result = local cook_result =
minetest.get_craft_result({method="cooking", width=1, items={ItemStack(src_item.item_string)}}) minetest.get_craft_result({method="cooking", width=1, items={ItemStack(src_item.item_string)}})
local total_cook_time = cook_result.time * npc.get_item_count(item) local total_cook_time = cook_result.time * npc.get_item_count(item)
minetest.log("Cook: "..dump(cook_result)) npc.log("DEBUG", "Cook: "..dump(cook_result))
minetest.log("Total cook time: "..total_cook_time npc.log("DEBUG", "Total cook time: "..total_cook_time
..", total fuel burn time: "..dump(total_fuel_time)) ..", total fuel burn time: "..dump(total_fuel_time))
-- Check if there is enough fuel to cook all items -- Check if there is enough fuel to cook all items
@ -531,7 +531,7 @@ function npc.actions.use_furnace(self, args)
fuel_amount = 1 fuel_amount = 1
end end
minetest.log("Amount of fuel needed: "..fuel_amount) npc.log("DEBUG", "Amount of fuel needed: "..fuel_amount)
-- Put this item on the fuel inventory list of the furnace -- Put this item on the fuel inventory list of the furnace
local args = { local args = {
@ -554,7 +554,7 @@ function npc.actions.use_furnace(self, args)
npc.add_action(self, npc.actions.cmd.PUT_ITEM, args) npc.add_action(self, npc.actions.cmd.PUT_ITEM, args)
-- Now, set NPC to wait until furnace is done. -- Now, set NPC to wait until furnace is done.
minetest.log("Setting wait action for "..dump(total_cook_time)) npc.log("DEBUG", "Setting wait action for "..dump(total_cook_time))
npc.add_action(self, npc.actions.cmd.SET_INTERVAL, {interval=total_cook_time, freeze=freeze}) npc.add_action(self, npc.actions.cmd.SET_INTERVAL, {interval=total_cook_time, freeze=freeze})
-- Reset timer -- Reset timer
@ -563,7 +563,7 @@ function npc.actions.use_furnace(self, args)
-- If freeze is false, then we will have to find the way back to the furnace -- If freeze is false, then we will have to find the way back to the furnace
-- once cooking is done. -- once cooking is done.
if freeze == false then if freeze == false then
minetest.log("Adding walk to position to wandering: "..dump(pos)) npc.log("DEBUG", "Adding walk to position to wandering: "..dump(pos))
npc.add_task(self, npc.actions.cmd.WALK_TO_POS, {end_pos=pos, walkable={}}) npc.add_task(self, npc.actions.cmd.WALK_TO_POS, {end_pos=pos, walkable={}})
end end
@ -577,10 +577,10 @@ function npc.actions.use_furnace(self, args)
count = npc.get_item_count(item), count = npc.get_item_count(item),
is_furnace = false is_furnace = false
} }
minetest.log("Taking item back: "..minetest.pos_to_string(pos)) npc.log("DEBUG", "Taking item back: "..minetest.pos_to_string(pos))
npc.add_action(self, npc.actions.cmd.TAKE_ITEM, args) npc.add_action(self, npc.actions.cmd.TAKE_ITEM, args)
minetest.log("Inventory: "..dump(self.inventory)) npc.log("DEBUG", "Inventory: "..dump(self.inventory))
return true return true
end end
@ -594,7 +594,7 @@ end
function npc.actions.use_bed(self, args) function npc.actions.use_bed(self, args)
local pos = get_pos_argument(self, args.pos) local pos = get_pos_argument(self, args.pos)
if pos == nil then if pos == nil then
minetest.log("[advanced_npc] WARNING Got nil position in 'use_bed' using args.pos: "..dump(args.pos)) npc.log("WARNING", "Got nil position in 'use_bed' using args.pos: "..dump(args.pos))
return return
end end
local action = args.action local action = args.action
@ -654,7 +654,7 @@ end
function npc.actions.use_sittable(self, args) function npc.actions.use_sittable(self, args)
local pos = get_pos_argument(self, args.pos) local pos = get_pos_argument(self, args.pos)
if pos == nil then if pos == nil then
minetest.log("[advanced_npc] WARNING Got nil position in 'use_sittable' using args.pos: "..dump(args.pos)) npc.log("WARNING", "Got nil position in 'use_sittable' using args.pos: "..dump(args.pos))
return return
end end
local action = args.action local action = args.action
@ -727,7 +727,7 @@ function npc.actions.walk_to_pos(self, args)
-- Get arguments for this task -- Get arguments for this task
local end_pos = get_pos_argument(self, args.end_pos) local end_pos = get_pos_argument(self, args.end_pos)
if end_pos == nil then if end_pos == nil then
minetest.log("[advanced_npc] WARNING Got nil position in 'walk_to_pos' using args.pos: "..dump(args.end_pos)) npc.log("WARNING", "Got nil position in 'walk_to_pos' using args.pos: "..dump(args.end_pos))
return return
end end
local enforce_move = args.enforce_move or true local enforce_move = args.enforce_move or true
@ -737,8 +737,8 @@ function npc.actions.walk_to_pos(self, args)
local start_pos = vector.round(self.object:getpos()) local start_pos = vector.round(self.object:getpos())
-- Use y of end_pos (this can only be done assuming flat terrain) -- Use y of end_pos (this can only be done assuming flat terrain)
--start_pos.y = self.object:getpos().y --start_pos.y = self.object:getpos().y
minetest.log("[advanced_npc] INFO walk_to_pos: Start pos: "..minetest.pos_to_string(start_pos)) npc.log("DEBUG", "walk_to_pos: Start pos: "..minetest.pos_to_string(start_pos))
minetest.log("[advanced_npc] INFO walk_to_pos: End pos: "..minetest.pos_to_string(end_pos)) npc.log("DEBUG", "walk_to_pos: End pos: "..minetest.pos_to_string(end_pos))
-- Set walkable nodes to empty if the parameter hasn't been used -- Set walkable nodes to empty if the parameter hasn't been used
if walkable_nodes == nil then if walkable_nodes == nil then
@ -759,11 +759,8 @@ function npc.actions.walk_to_pos(self, args)
end end
path = path_detail path = path_detail
--minetest.log("Found path: "..dump(path)) npc.log("DEBUG", "Detailed path: "..dump(path))
npc.log("INFO", "walk_to_pos Found path to node: "..minetest.pos_to_string(end_pos))
--minetest.log("Path detail: "..dump(path_detail))
--minetest.log("New path: "..dump(path))
minetest.log("[advanced_npc] INFO walk_to_pos Found path to node: "..minetest.pos_to_string(end_pos))
-- Store path -- Store path
self.actions.walking.path = path self.actions.walking.path = path
@ -784,6 +781,8 @@ function npc.actions.walk_to_pos(self, args)
if (i+1) == #path then if (i+1) == #path then
-- Add direction to last node -- Add direction to last node
local dir = npc.actions.get_direction(path[i].pos, end_pos) local dir = npc.actions.get_direction(path[i].pos, end_pos)
-- Add the last step
npc.add_action(self, npc.actions.cmd.WALK_STEP, {dir = dir, speed = speed, target_pos = path[i+1].pos})
-- Add stand animation at end -- Add stand animation at end
npc.add_action(self, npc.actions.cmd.STAND, {dir = dir}) npc.add_action(self, npc.actions.cmd.STAND, {dir = dir})
break break
@ -823,7 +822,7 @@ function npc.actions.walk_to_pos(self, args)
-- end -- end
-- local pos_on_close = {x=path[i+1].pos.x + x_adj, y=path[i+1].pos.y + 1, z=path[i+1].pos.z + z_adj} -- local pos_on_close = {x=path[i+1].pos.x + x_adj, y=path[i+1].pos.y + 1, z=path[i+1].pos.z + z_adj}
-- Add extra walk step to ensure that one is standing at other side of openable node -- Add extra walk step to ensure that one is standing at other side of openable node
npc.add_action(self, npc.actions.cmd.WALK_STEP, {dir = dir, speed = speed, target_pos = path[i+2].pos}) -- npc.add_action(self, npc.actions.cmd.WALK_STEP, {dir = dir, speed = speed, target_pos = path[i+2].pos})
-- Stop to close the door -- Stop to close the door
npc.add_action(self, npc.actions.cmd.STAND, {dir=(dir + 2) % 4 })--, pos=pos_on_close}) npc.add_action(self, npc.actions.cmd.STAND, {dir=(dir + 2) % 4 })--, pos=pos_on_close})
-- Close door -- Close door
@ -840,7 +839,7 @@ function npc.actions.walk_to_pos(self, args)
else else
-- Unable to find path -- Unable to find path
minetest.log("[advanced_npc] INFO walk_to_pos Unable to find path. Teleporting to: "..minetest.pos_to_string(end_pos)) npc.log("WARNING", "walk_to_pos Unable to find path. Teleporting to: "..minetest.pos_to_string(end_pos))
-- Check if movement is enforced -- Check if movement is enforced
if enforce_move then if enforce_move then
-- Move to end pos -- Move to end pos

View File

@ -124,7 +124,7 @@ function npc.places.find_node_orthogonally(pos, nodes, y_adjustment)
local result = {} local result = {}
for _,point in pairs(points) do for _,point in pairs(points) do
local node = minetest.get_node(point) local node = minetest.get_node(point)
minetest.log("Found node: "..dump(node)..", at pos: "..dump(point)) --minetest.log("Found node: "..dump(node)..", at pos: "..dump(point))
for _,node_name in pairs(nodes) do for _,node_name in pairs(nodes) do
if node.name == node_name then if node.name == node_name then
table.insert(result, {name=node.name, pos=point, param2=node.param2}) table.insert(result, {name=node.name, pos=point, param2=node.param2})
@ -194,8 +194,8 @@ function npc.places.find_entrance_from_openable_nodes(all_openable_nodes, marker
--local path = pathfinder.find_path(start_pos, end_pos, 20, {}) --local path = pathfinder.find_path(start_pos, end_pos, 20, {})
local entity = {} local entity = {}
entity.collisionbox = {-0.20,-1.0,-0.20, 0.20,0.8,0.20} entity.collisionbox = {-0.20,-1.0,-0.20, 0.20,0.8,0.20}
minetest.log("Start pos: "..minetest.pos_to_string(start_pos)) --minetest.log("Start pos: "..minetest.pos_to_string(start_pos))
minetest.log("End pos: "..minetest.pos_to_string(end_pos)) --minetest.log("End pos: "..minetest.pos_to_string(end_pos))
local path = pathfinder.find_path(start_pos, end_pos, entity) local path = pathfinder.find_path(start_pos, end_pos, entity)
--minetest.log("Found path: "..dump(path)) --minetest.log("Found path: "..dump(path))
if path ~= nil then if path ~= nil then
@ -217,13 +217,13 @@ function npc.places.find_entrance_from_openable_nodes(all_openable_nodes, marker
-- Check if min-distance door is a cottages door -- Check if min-distance door is a cottages door
-- while we have a MTG door -- while we have a MTG door
if min_node_name == "cottages:half_door" and doors_st ~= nil then if min_node_name == "cottages:half_door" and doors_st ~= nil then
minetest.log("Assigned new door...") --minetest.log("Assigned new door...")
min = #path min = #path
result = openable_nodes[i] result = openable_nodes[i]
end end
end end
else else
minetest.log("Path not found to marker from "..minetest.pos_to_string(start_pos)) npc.log("ERROR", "Path not found to marker from "..minetest.pos_to_string(start_pos))
end end
end end
end end
@ -302,7 +302,7 @@ function npc.places.is_in_staircase(pos)
-- Get next node -- Get next node
local upper_node = minetest.get_node(upper_pos) local upper_node = minetest.get_node(upper_pos)
local lower_node = minetest.get_node(lower_pos) local lower_node = minetest.get_node(lower_pos)
minetest.log("Next node: "..dump(upper_pos)) --minetest.log("Next node: "..dump(upper_pos))
-- Check if next node is also a stairs node -- Check if next node is also a stairs node
local up_p1, up_p2 = string.find(upper_node.name, "stairs:") local up_p1, up_p2 = string.find(upper_node.name, "stairs:")
local lo_p1, lo_p2 = string.find(lower_node.name, "stairs:") local lo_p1, lo_p2 = string.find(lower_node.name, "stairs:")
@ -351,7 +351,7 @@ end
-- front of a door. Used to make NPCs exit buildings. -- front of a door. Used to make NPCs exit buildings.
function npc.places.find_node_in_front_of_door(door_pos) function npc.places.find_node_in_front_of_door(door_pos)
local door = minetest.get_node(door_pos) local door = minetest.get_node(door_pos)
minetest.log("Param2 of door: "..dump(door.param2)) --minetest.log("Param2 of door: "..dump(door.param2))
if door.param2 == 0 then if door.param2 == 0 then
-- Looking south -- Looking south
return {x=door_pos.x, y=door_pos.y, z=door_pos.z - 1} return {x=door_pos.x, y=door_pos.y, z=door_pos.z - 1}

View File

@ -296,7 +296,7 @@ function npc.dialogue.process_dialogue(self, dialogue, player_name)
-- Send dialogue line -- Send dialogue line
if dialogue.text then if dialogue.text then
minetest.chat_send_player(player_name, self.npc_name..": "..dialogue.text) npc.chat(self.npc_name, player_name, dialogue.text)
end end
-- Check if dialogue has responses. If it doesn't, unlock the actions -- Check if dialogue has responses. If it doesn't, unlock the actions

View File

@ -23,7 +23,6 @@ else
end end
mobs.intllib = S mobs.intllib = S
-- NPC
dofile(path .. "/npc.lua") dofile(path .. "/npc.lua")
dofile(path .. "/spawner.lua") dofile(path .. "/spawner.lua")
dofile(path .. "/relationships.lua") dofile(path .. "/relationships.lua")

46
npc.lua
View File

@ -42,9 +42,27 @@ npc.action_state = {
interrupted = 2 interrupted = 2
} }
npc.log_level = {
INFO = true,
WARNING = false,
ERROR = true,
DEBUG = false
}
--------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------
-- General functions -- General functions
--------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------
-- Logging
function npc.log(level, message)
if npc.log_level[level] then
minetest.log("[advanced_npc] "..type..": "..message)
end
end
-- NPC chat
function npc.chat(npc_name, player_name, message)
minetest.chat_send_player(player_name, npc_name..": "..message)
-- Gets name of player or NPC -- Gets name of player or NPC
function npc.get_entity_name(entity) function npc.get_entity_name(entity)
if entity:is_player() then if entity:is_player() then
@ -176,7 +194,7 @@ end
-- Spawn function. Initializes all variables that the -- Spawn function. Initializes all variables that the
-- NPC will have and choose random, starting values -- NPC will have and choose random, starting values
function npc.initialize(entity, pos, is_lua_entity, npc_stats) function npc.initialize(entity, pos, is_lua_entity, npc_stats)
minetest.log("[advanced_npc] INFO: Initializing NPC at "..minetest.pos_to_string(pos)) npc.log("INFO", "Initializing NPC at "..minetest.pos_to_string(pos))
-- Get variables -- Get variables
local ent = entity local ent = entity
@ -426,7 +444,7 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats)
table.insert(ent.trader_data.custom_trades, offer2) table.insert(ent.trader_data.custom_trades, offer2)
--minetest.log(dump(ent)) --minetest.log(dump(ent))
minetest.log("[advanced_npc] INFO Successfully initialized NPC with name "..dump(ent.npc_name)) npc.log("INFO", "Successfully initialized NPC with name "..dump(ent.npc_name))
-- Refreshes entity -- Refreshes entity
ent.object:set_properties(ent) ent.object:set_properties(ent)
end end
@ -596,7 +614,7 @@ end
function npc.execute_action(self) function npc.execute_action(self)
-- Check if an action was interrupted -- Check if an action was interrupted
if self.actions.current_action_state == npc.action_state.interrupted then if self.actions.current_action_state == npc.action_state.interrupted then
minetest.log("[advanced_npc] DEBUG Re-inserting interrupted action for NPC: '"..dump(self.npc_name).."': "..dump(self.actions.state_before_lock.interrupted_action)) npc.log("DEBUG", "Re-inserting interrupted action for NPC: '"..dump(self.npc_name).."': "..dump(self.actions.state_before_lock.interrupted_action))
-- Insert into queue the interrupted action -- Insert into queue the interrupted action
table.insert(self.actions.queue, 1, self.actions.state_before_lock.interrupted_action) table.insert(self.actions.queue, 1, self.actions.state_before_lock.interrupted_action)
-- Clear the action -- Clear the action
@ -618,7 +636,7 @@ function npc.execute_action(self)
-- If the entry is a task, then push all this new operations in -- If the entry is a task, then push all this new operations in
-- stack fashion -- stack fashion
if action_obj.is_task == true then if action_obj.is_task == true then
minetest.log("[advanced_npc] DEBUG Executing task for NPC '"..dump(self.npc_name).."': "..dump(action_obj)) npc.log("DEBUG", "Executing task for NPC '"..dump(self.npc_name).."': "..dump(action_obj))
-- Backup current queue -- Backup current queue
local backup_queue = self.actions.queue local backup_queue = self.actions.queue
-- Remove this "task" action from queue -- Remove this "task" action from queue
@ -634,7 +652,7 @@ function npc.execute_action(self)
table.insert(self.actions.queue, backup_queue[i]) table.insert(self.actions.queue, backup_queue[i])
end end
else else
minetest.log("[advanced_npc] DEBUG Executing action for NPC '"..dump(self.npc_name).."': "..dump(action_obj)) npc.log("DEBUG", "Executing action for NPC '"..dump(self.npc_name).."': "..dump(action_obj))
-- Store the action that is being executed -- Store the action that is being executed
self.actions.state_before_lock.interrupted_action = action_obj self.actions.state_before_lock.interrupted_action = action_obj
-- Store current position -- Store current position
@ -689,7 +707,7 @@ function npc.lock_actions(self)
-- Freeze mobs_redo API -- Freeze mobs_redo API
self.freeze = false self.freeze = false
minetest.log("Locking") npc.log("DEBUG", "Locking NPC "..dump(self.npc_id).." actions")
end end
function npc.unlock_actions(self) function npc.unlock_actions(self)
@ -703,7 +721,7 @@ function npc.unlock_actions(self)
self.freeze = true self.freeze = true
end end
minetest.log("Unlocked") npc.log("DEBUG", "Unlocked NPC "..dump(self.npc_id).." actions")
end end
--------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------
@ -863,7 +881,7 @@ mobs:register_mob("advanced_npc:npc", {
{"npc_female1.png"}, -- female by nuttmeg20 {"npc_female1.png"}, -- female by nuttmeg20
}, },
child_texture = { child_texture = {
{"npc_baby_male1.png"}, -- derpy baby by AmirDerAssassine {"npc_baby_male1.png"},
{"npc_baby_female1.png"}, {"npc_baby_female1.png"},
}, },
makes_footstep_sound = true, makes_footstep_sound = true,
@ -915,11 +933,7 @@ mobs:register_mob("advanced_npc:npc", {
--self.base_texture = "mobs_npc_child_male1.png" --self.base_texture = "mobs_npc_child_male1.png"
--self.object:set_properties(self) --self.object:set_properties(self)
minetest.log(dump(self)) npc.log("DEBUG", "Right-clicked NPC: "..dump(self))
minetest.log("Child: "..dump(self.is_child))
minetest.log("Sex: "..dump(self.sex))
minetest.log("Textures: "..dump(self.textures))
-- Receive gift or start chat. If player has no item in hand -- Receive gift or start chat. If player has no item in hand
-- then it is going to start chat directly -- then it is going to start chat directly
@ -952,7 +966,7 @@ mobs:register_mob("advanced_npc:npc", {
-- Initialize NPC if spawned using the spawn egg built in from -- Initialize NPC if spawned using the spawn egg built in from
-- mobs_redo. This functionality will be removed in the future in -- mobs_redo. This functionality will be removed in the future in
-- favor of a better manual spawning method with customization -- favor of a better manual spawning method with customization
minetest.log("[advanced_npc] WARNING: Initializing NPC from entity step. This message should only be appearing if an NPC is being spawned from inventory with egg!") npc.log("WARNING", "Initializing NPC from entity step. This message should only be appearing if an NPC is being spawned from inventory with egg!")
npc.initialize(self, self.object:getpos(), true) npc.initialize(self, self.object:getpos(), true)
else else
self.tamed = false self.tamed = false
@ -1049,7 +1063,7 @@ mobs:register_mob("advanced_npc:npc", {
-- to action queue. This is for jobs. -- to action queue. This is for jobs.
-- TODO: Need to implement -- TODO: Need to implement
else else
minetest.log("Adding actions to action queue") npc.log("DEBUG", "Adding actions to action queue")
-- Add to action queue all actions on schedule -- Add to action queue all actions on schedule
for i = 1, #schedule[time] do for i = 1, #schedule[time] do
if schedule[time][i].action == nil then if schedule[time][i].action == nil then
@ -1060,7 +1074,7 @@ mobs:register_mob("advanced_npc:npc", {
npc.add_action(self, schedule[time][i].action, schedule[time][i].args) npc.add_action(self, schedule[time][i].action, schedule[time][i].args)
end end
end end
minetest.log("New action queue: "..dump(self.actions)) npc.log("DEBUG", "New action queue: "..dump(self.actions))
end end
end end
end end

View File

@ -209,7 +209,7 @@ function spawner.assign_places(self, pos)
-- Find unowned bed -- Find unowned bed
for i = 1, #node_data.bed_type do for i = 1, #node_data.bed_type do
-- Check if bed has owner -- Check if bed has owner
minetest.log("Node: "..dump(node_data.bed_type[i])) --minetest.log("Node: "..dump(node_data.bed_type[i]))
if node_data.bed_type[i].owner == "" then if node_data.bed_type[i].owner == "" then
-- If bed has no owner, check if it is accessible -- If bed has no owner, check if it is accessible
local empty_nodes = npc.places.find_node_orthogonally( local empty_nodes = npc.places.find_node_orthogonally(
@ -223,7 +223,7 @@ function spawner.assign_places(self, pos)
npc.places.PLACE_TYPE.BED.PRIMARY, node_data.bed_type[i].node_pos, empty_nodes[1].pos) npc.places.PLACE_TYPE.BED.PRIMARY, node_data.bed_type[i].node_pos, empty_nodes[1].pos)
-- Store changes to node_data -- Store changes to node_data
meta:set_string("node_data", minetest.serialize(node_data)) meta:set_string("node_data", minetest.serialize(node_data))
minetest.log("Added bed at "..minetest.pos_to_string(node_data.bed_type[i].node_pos) npc.log("DEBUG", "Added bed at "..minetest.pos_to_string(node_data.bed_type[i].node_pos)
.." to NPC "..dump(self.npc_name)) .." to NPC "..dump(self.npc_name))
break break
end end
@ -233,7 +233,7 @@ function spawner.assign_places(self, pos)
--local plot_info = minetest.deserialize(meta:get_string("plot_info")) --local plot_info = minetest.deserialize(meta:get_string("plot_info"))
--minetest.log("Plot info:"..dump(plot_info)) --minetest.log("Plot info:"..dump(plot_info))
minetest.log("places: "..dump(self.places_map)) npc.log("DEBUG", "Places for NPC "..self.npc_name..": "..dump(self.places_map))
-- Make NPC go into their house -- Make NPC go into their house
npc.add_task(self, npc.add_task(self,
@ -274,9 +274,9 @@ function npc.spawner.spawn_npc(pos)
-- Check amount of NPCs that should be spawned -- Check amount of NPCs that should be spawned
local npc_count = meta:get_int("npc_count") local npc_count = meta:get_int("npc_count")
local spawned_npc_count = meta:get_int("spawned_npc_count") local spawned_npc_count = meta:get_int("spawned_npc_count")
minetest.log("[advanced_npc] INFO Currently spawned "..dump(spawned_npc_count).." of "..dump(npc_count).." NPCs") npc.log("INFO", "Currently spawned "..dump(spawned_npc_count).." of "..dump(npc_count).." NPCs")
if spawned_npc_count < npc_count then if spawned_npc_count < npc_count then
minetest.log("[advanced_npc] INFO Spawning NPC at "..minetest.pos_to_string(pos)) npc.log("INFO", "Spawning NPC at "..minetest.pos_to_string(pos))
-- Spawn a NPC -- Spawn a NPC
local ent = minetest.add_entity({x=pos.x, y=pos.y+1, z=pos.z}, "advanced_npc:npc") local ent = minetest.add_entity({x=pos.x, y=pos.y+1, z=pos.z}, "advanced_npc:npc")
if ent and ent:get_luaentity() then if ent and ent:get_luaentity() then
@ -324,21 +324,21 @@ function npc.spawner.spawn_npc(pos)
meta:set_string("npc_stats", minetest.serialize(npc_stats)) meta:set_string("npc_stats", minetest.serialize(npc_stats))
-- Temp -- Temp
--meta:set_string("infotext", meta:get_string("infotext")..", "..spawned_npc_count) --meta:set_string("infotext", meta:get_string("infotext")..", "..spawned_npc_count)
minetest.log("[advanced_npc] INFO Spawning successful!") npc.log("INFO", "Spawning successful!")
-- Check if there are more NPCs to spawn -- Check if there are more NPCs to spawn
if spawned_npc_count >= npc_count then if spawned_npc_count >= npc_count then
-- Stop timer -- Stop timer
minetest.log("[advanced_npc] INFO No more NPCs to spawn at this location") npc.log("INFO", "No more NPCs to spawn at this location")
timer:stop() timer:stop()
else else
-- Start another timer to spawn more NPC -- Start another timer to spawn more NPC
local new_delay = math.random(npc.spawner.spawn_delay) local new_delay = math.random(npc.spawner.spawn_delay)
minetest.log("[advanced_npc] INFO Spawning one more NPC in "..dump(npc.spawner.spawn_delay).."s") npc.log("INFO", "Spawning one more NPC in "..dump(npc.spawner.spawn_delay).."s")
timer:start(new_delay) timer:start(new_delay)
end end
return true return true
else else
minetest.log("[advanced_npc] Spawning failed!") npc.log("ERROR", "Spawning failed!")
ent:remove() ent:remove()
return false return false
end end
@ -358,13 +358,13 @@ function spawner.calculate_npc_spawning(pos)
-- Get nodes for this building -- Get nodes for this building
local node_data = minetest.deserialize(meta:get_string("node_data")) local node_data = minetest.deserialize(meta:get_string("node_data"))
if node_data == nil then if node_data == nil then
minetest.log("[advanced_npc] ERROR: Mis-configured advanced_npc:plotmarker_auto_spawner at position: "..minetest.pos_to_string(pos)) npc.log("ERROR", "Mis-configured advanced_npc:plotmarker_auto_spawner at position: "..minetest.pos_to_string(pos))
return return
end end
-- Check number of beds -- Check number of beds
local beds_count = #node_data.bed_type--#spawner.filter_first_floor_nodes(node_data.bed_type, pos) local beds_count = #node_data.bed_type--#spawner.filter_first_floor_nodes(node_data.bed_type, pos)
minetest.log("[advanced_npc] INFO: Found "..dump(beds_count).." beds in the building at "..minetest.pos_to_string(pos)) npc.log("DEBUG", "Found "..dump(beds_count).." beds in the building at "..minetest.pos_to_string(pos))
local npc_count = 0 local npc_count = 0
-- If number of beds is zero or beds/2 is less than one, spawn -- If number of beds is zero or beds/2 is less than one, spawn
-- a single NPC. -- a single NPC.
@ -375,7 +375,7 @@ function spawner.calculate_npc_spawning(pos)
-- Spawn (beds_count/2) NPCs -- Spawn (beds_count/2) NPCs
npc_count = ((beds_count / 2) - ((beds_count / 2) % 1)) npc_count = ((beds_count / 2) - ((beds_count / 2) % 1))
end end
minetest.log("[advanced_npc] INFO: Will spawn "..dump(npc_count).." NPCs at "..minetest.pos_to_string(pos)) npc.log("INFO", "Will spawn "..dump(npc_count).." NPCs at "..minetest.pos_to_string(pos))
-- Store amount of NPCs to spawn -- Store amount of NPCs to spawn
meta:set_int("npc_count", npc_count) meta:set_int("npc_count", npc_count)
-- Store amount of NPCs spawned -- Store amount of NPCs spawned
@ -435,14 +435,14 @@ function spawner.scan_mg_villages_building(pos, building_data)
--minetest.set_node({x=pos.x,y=pos.y,z=pos.z + (z_sign * z_size)}, {name = "wool:blue"}) --minetest.set_node({x=pos.x,y=pos.y,z=pos.z + (z_sign * z_size)}, {name = "wool:blue"})
--minetest.get_meta({x=pos.x,y=pos.y,z=pos.z + (z_sign * z_size)}):set_string("infotext", minetest.get_meta(pos):get_string("infotext")..", Axis: z, Sign: "..dump(z_sign)) --minetest.get_meta({x=pos.x,y=pos.y,z=pos.z + (z_sign * z_size)}):set_string("infotext", minetest.get_meta(pos):get_string("infotext")..", Axis: z, Sign: "..dump(z_sign))
minetest.log("Start pos: "..minetest.pos_to_string(start_pos)) npc.log("DEBUG", "Start pos: "..minetest.pos_to_string(start_pos))
minetest.log("Plot: "..dump(minetest.get_meta(start_pos):get_string("infotext"))) npc.log("DEBUG", "Plot: "..dump(minetest.get_meta(start_pos):get_string("infotext")))
minetest.log("Brotate: "..dump(brotate)) npc.log("DEBUG", "Brotate: "..dump(brotate))
minetest.log("X_sign: "..dump(x_sign)) npc.log("DEBUG", "X_sign: "..dump(x_sign))
minetest.log("X_adj: "..dump(x_sign*x_size)) npc.log("DEBUG", "X_adj: "..dump(x_sign*x_size))
minetest.log("Z_sign: "..dump(z_sign)) npc.log("DEBUG", "Z_sign: "..dump(z_sign))
minetest.log("Z_adj: "..dump(z_sign*z_size)) npc.log("DEBUG", "Z_adj: "..dump(z_sign*z_size))
local end_pos = {x=pos.x + (x_sign * x_size), y=pos.y + y_size, z=pos.z + (z_sign * z_size)} local end_pos = {x=pos.x + (x_sign * x_size), y=pos.y + y_size, z=pos.z + (z_sign * z_size)}
@ -451,7 +451,7 @@ function spawner.scan_mg_villages_building(pos, building_data)
--minetest.set_node(end_pos, {name="default:mese_block"}) --minetest.set_node(end_pos, {name="default:mese_block"})
--minetest.get_meta(end_pos):set_string("infotext", minetest.get_meta(start_pos):get_string("infotext")) --minetest.get_meta(end_pos):set_string("infotext", minetest.get_meta(start_pos):get_string("infotext"))
minetest.log("Calculated end pos: "..minetest.pos_to_string(end_pos)) npc.log("DEBUG", "Calculated end pos: "..minetest.pos_to_string(end_pos))
return spawner.scan_area(start_pos, end_pos) return spawner.scan_area(start_pos, end_pos)
end end
@ -477,7 +477,7 @@ function spawner.replace_mg_villages_plotmarker(pos)
if building_type == value then if building_type == value then
minetest.log("Replacing mg_villages:plotmarker at "..minetest.pos_to_string(pos)) npc.log("INFO", "Replacing mg_villages:plotmarker at "..minetest.pos_to_string(pos))
-- Replace the plotmarker for auto-spawner -- Replace the plotmarker for auto-spawner
minetest.set_node(pos, {name="advanced_npc:plotmarker_auto_spawner"}) minetest.set_node(pos, {name="advanced_npc:plotmarker_auto_spawner"})
-- Store old plotmarker metadata again -- Store old plotmarker metadata again
@ -498,9 +498,9 @@ function spawner.replace_mg_villages_plotmarker(pos)
--minetest.log("Found "..dump(#doors).." openable nodes") --minetest.log("Found "..dump(#doors).." openable nodes")
local entrance = npc.places.find_entrance_from_openable_nodes(doors, pos) local entrance = npc.places.find_entrance_from_openable_nodes(doors, pos)
if entrance then if entrance then
minetest.log("Found building entrance at: "..minetest.pos_to_string(entrance.node_pos)) npc.log("INFO", "Found building entrance at: "..minetest.pos_to_string(entrance.node_pos))
else else
minetest.log("Unable to find building entrance!") npc.log("ERROR", "Unable to find building entrance!")
end end
-- Store building entrance -- Store building entrance
meta:set_string("entrance", minetest.serialize(entrance)) meta:set_string("entrance", minetest.serialize(entrance))
@ -569,7 +569,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
-- end -- end
-- minetest.get_meta(pos):set_string("node_data", minetest.serialize(nodedata)) -- minetest.get_meta(pos):set_string("node_data", minetest.serialize(nodedata))
-- minetest.log("Cleared bed owners") -- minetest.log("Cleared bed owners")
minetest.log("NPC stats: "..dump(minetest.deserialize(minetest.get_meta(pos):get_string("npc_stats")))) --minetest.log("NPC stats: "..dump(minetest.deserialize(minetest.get_meta(pos):get_string("npc_stats"))))
return mg_villages.plotmarker_formspec( pos, nil, {}, clicker ) return mg_villages.plotmarker_formspec( pos, nil, {}, clicker )
end, end,
@ -610,7 +610,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
-- end -- end
-- }) -- })
-- ABM Registration... for when LBM fails. -- ABM Registration
minetest.register_abm({ minetest.register_abm({
label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners", label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners",
nodenames = {"mg_villages:plotmarker"}, nodenames = {"mg_villages:plotmarker"},

View File

@ -415,8 +415,8 @@ function npc.trade.get_dedicated_trade_offers(self)
-- If item found, create a buy offer for this item -- If item found, create a buy offer for this item
-- Again, offers are created for one item only. Buy offers should be removed -- Again, offers are created for one item only. Buy offers should be removed
-- after the NPC has bought a certain quantity, say, 5 items. -- after the NPC has bought a certain quantity, say, 5 items.
minetest.log("Item: "..item_name) --minetest.log("Item: "..item_name)
minetest.log("Trade info: "..dump(trade_info)) --minetest.log("Trade info: "..dump(trade_info))
--minetest.log("Logic: "..dump(trade_info.item_bought_count == nil --minetest.log("Logic: "..dump(trade_info.item_bought_count == nil
-- or (trade_info.item_bought_count ~= nil and trade_info.item_bought_count <= npc.trade.DEDICATED_MAX_BUY_AMOUNT))) -- or (trade_info.item_bought_count ~= nil and trade_info.item_bought_count <= npc.trade.DEDICATED_MAX_BUY_AMOUNT)))
if trade_info.item_bought_count == nil if trade_info.item_bought_count == nil
@ -537,16 +537,17 @@ function npc.trade.perform_trade(self, player_name, offer)
inv:add_item("main", price_stacks[j]) inv:add_item("main", price_stacks[j])
end end
-- Send message to player -- Send message to player
minetest.chat_send_player(player_name, "Thank you!") npc.chat(self.npc_name, player_name, "Thank you!")
return true return true
else else
minetest.chat_send_player(player_name, npc.chat(self.npc_name, player_name,
"Looks like you can't get what I'm giving you for payment!") "Looks like you can't get what I'm giving you for payment!")
return false return false
end end
end end
else else
minetest.chat_send_player(player_name, "Looks like you don't have what I want to buy...") npc.chat(self.npc_name, player_name,
"Looks like you don't have what I want to buy...")
return false return false
end end
else else
@ -570,14 +571,16 @@ function npc.trade.perform_trade(self, player_name, offer)
-- Add item items to player -- Add item items to player
inv:add_item("main", item_stack) inv:add_item("main", item_stack)
-- Send message to player -- Send message to player
minetest.chat_send_player(player_name, "Thank you!") npc.chat(self.npc_name, player_name, "Thank you!")
return true return true
else else
minetest.chat_send_player(player_name, "Looks like you can't carry anything else...") npc.chat(self.npc_name, player_name,
"Looks like you can't carry anything else...")
return false return false
end end
else else
minetest.chat_send_player(player_name, "Looks like you don't have what I'm asking for!") npc.chat(self.npc_name, player_name,
"Looks like you don't have what I'm asking for!")
return false return false
end end
end end
@ -624,8 +627,8 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
if player_response.offers_type == npc.trade.OFFER_BUY then if player_response.offers_type == npc.trade.OFFER_BUY then
-- Increase the item bought count -- Increase the item bought count
local offer_item_name = npc.get_item_name(trade_offers[i].item) local offer_item_name = npc.get_item_name(trade_offers[i].item)
minetest.log("Bought item name: "..dump(offer_item_name)) --minetest.log("Bought item name: "..dump(offer_item_name))
minetest.log(dump(player_response.npc.trader_data.trade_list.both[offer_item_name])) --minetest.log(dump(player_response.npc.trader_data.trade_list.both[offer_item_name]))
-- Check if this item has been bought before -- Check if this item has been bought before
if player_response.npc.trader_data.trade_list.both[offer_item_name].item_bought_count == nil then if player_response.npc.trader_data.trade_list.both[offer_item_name].item_bought_count == nil then
-- Set first count to 1 -- Set first count to 1

View File

@ -1,355 +0,0 @@
local S = mobs.intllib
mobs.human = {
items = {
--{item for sale, price, chance of appearing in trader's inventory}
{"default:apple 10", "default:gold_ingot 2", 10},
{"farming:bread 10", "default:gold_ingot 4", 5},
{"default:clay 10", "default:gold_ingot 2", 12},
{"default:brick 10", "default:gold_ingot 4", 17},
{"default:glass 10", "default:gold_ingot 4", 17},
{"default:obsidian 10", "default:gold_ingot 15", 50},
{"default:diamond 1", "default:gold_ingot 5", 40},
{"farming:wheat 10", "default:gold_ingot 2", 17},
{"default:tree 5", "default:gold_ingot 4", 20},
{"default:stone 10", "default:gold_ingot 8", 17},
{"default:desert_stone 10", "default:gold_ingot 8", 27},
{"default:sapling 1", "default:gold_ingot 1", 7},
{"default:pick_steel 1", "default:gold_ingot 2", 7},
{"default:sword_steel 1", "default:gold_ingot 2", 17},
{"default:shovel_steel 1", "default:gold_ingot 1", 17},
},
names = {
"Bob", "Duncan", "Bill", "Tom", "James", "Ian", "Lenny"
}
}
-- Trader ( same as NPC but with right-click shop )
mobs:register_mob("mobs_npc:trader", {
type = "npc",
passive = false,
damage = 3,
attack_type = "dogfight",
attacks_monsters = true,
pathfinding = false,
hp_min = 10,
hp_max = 20,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.8,0.35},
visual = "mesh",
mesh = "character.b3d",
textures = {
{"mobs_trader.png"}, -- by Frerin
},
makes_footstep_sound = true,
sounds = {},
walk_velocity = 2,
run_velocity = 3,
jump = false,
drops = {},
water_damage = 0,
lava_damage = 4,
light_damage = 0,
follow = {"default:diamond"},
view_range = 15,
owner = "",
order = "stand",
fear_height = 3,
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
mobs_trader(self, clicker, entity, mobs.human)
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
-------------------------------------------------------------------------------
function mobs.allow_move(inv, from_list, from_index, to_list, to_index, count, player)
if to_list ~= "selection"
or from_list == "price"
or from_list == "payment"
or from_list == "takeaway"
or from_list == "identifier" then
return 0
end
-- forbid moving split stacks
local old_stack = inv.get_stack(inv, from_list, from_index)
if count ~= old_stack.get_count(old_stack) then
return 0
end
return count
end
function mobs.allow_put(inv, listname, index, stack, player)
if listname == "payment" then
return 99
end
return 0
end
function mobs.allow_take(inv, listname, index, stack, player)
if listname == "takeaway"
or listname == "payment" then
return 99
else
return 0
end
end
function mobs.on_put(inv, listname, index, stack)
if listname == "payment" then
mobs.update_takeaway(inv)
end
end
function mobs.on_take(inv, listname, count, index, stack, player)
if listname == "takeaway" then
local amount = inv:get_stack("payment", 1):get_count()
local price = inv:get_stack("price", 1):get_count()
local thing = inv:get_stack("payment", 1):get_name()
inv.set_stack(inv,"selection", 1, nil)
inv.set_stack(inv,"price", 1, nil)
inv.set_stack(inv,"takeaway", 1, nil)
inv.set_stack(inv,"payment", 1, thing .. " " .. amount - price)
end
if listname == "payment" then
if mobs.check_pay(inv, false) then
local selection = inv.get_stack(inv, "selection", 1)
if selection ~= nil then
inv.set_stack(inv,"takeaway", 1, selection)
end
else
inv.set_stack(inv, "takeaway", 1, nil)
end
end
end
function mobs.update_takeaway(inv)
if mobs.check_pay(inv,false) then
local selection = inv.get_stack(inv,"selection", 1)
if selection ~= nil then
inv.set_stack(inv,"takeaway", 1, selection)
end
else
inv.set_stack(inv,"takeaway", 1, nil)
end
end
function mobs.check_pay(inv, paynow)
local now_at_pay = inv.get_stack(inv,"payment", 1)
local count = now_at_pay.get_count(now_at_pay)
local name = now_at_pay.get_name(now_at_pay)
local price = inv.get_stack(inv, "price", 1)
if price:get_name() == name then
local price = price:get_count()
if price > 0
and price <= count then
if paynow then
now_at_pay.take_item(now_at_pay, price)
inv.set_stack(inv,"payment", 1, now_at_pay)
return true
else
return true
end
else
if paynow then
inv.set_stack(inv, "payment", 1, nil)
end
end
end
return false
end
mobs.trader_inventories = {}
function mobs.add_goods(entity, race)
local goods_to_add = nil
for i = 1, 15 do
if math.random(0, 100) > race.items[i][3] then
mobs.trader_inventory.set_stack(mobs.trader_inventory,
"goods", i, race.items[i][1])
end
end
end
function mobs_trader(self, clicker, entity, race)
local player = clicker:get_player_name()
if not self.id then
self.id = (math.random(1, 1000) * math.random(1, 10000))
.. self.npc_name .. (math.random(1, 1000) ^ 2)
end
if not self.game_name then
self.game_name = tostring(race.names[math.random(1, #race.names)])
self.npc_nametag = S("Trader @1", self.game_name)
self.object:set_properties({
nametag = self.npc_nametag,
nametag_color = "#00FF00"
})
end
local unique_entity_id = self.id
local is_inventory = minetest.get_inventory({
type = "detached", name = unique_entity_id})
local move_put_take = {
allow_move = mobs.allow_move,
allow_put = mobs.allow_put,
allow_take = mobs.allow_take,
on_move = function(inventory, from_list, from_index, to_list, to_index, count, player)
if from_list == "goods"
and to_list == "selection" then
local inv = inventory
local moved = inv.get_stack(inv,to_list, to_index)
local goodname = moved.get_name(moved)
local elements = moved.get_count(moved)
if elements > count then
-- remove the surplus parts
inv.set_stack(inv,"selection", 1,
goodname .. " " .. tostring(count))
-- the slot we took from is now free
inv.set_stack(inv,"goods",from_index,
goodname .. " " .. tostring(elements - count))
-- update the real amount of items in the slot now
elements = count
end
local good = nil
for i = 1, #race.items, 1 do
local stackstring = goodname .." " .. count
if race.items[i][1] == stackstring then
good = race.items[i]
end
end
if good ~= nil then
inventory.set_stack(inventory,"price", 1, good[2])
else
inventory.set_stack(inventory,"price", 1, nil)
end
mobs.update_takeaway(inv)
end
end,
on_put = mobs.on_put,
on_take = mobs.on_take
}
if is_inventory == nil then
mobs.trader_inventory = minetest.create_detached_inventory(unique_entity_id, move_put_take)
mobs.trader_inventory.set_size(mobs.trader_inventory,"goods", 15)
mobs.trader_inventory.set_size(mobs.trader_inventory,"takeaway", 1)
mobs.trader_inventory.set_size(mobs.trader_inventory,"selection", 1)
mobs.trader_inventory.set_size(mobs.trader_inventory,"price", 1)
mobs.trader_inventory.set_size(mobs.trader_inventory,"payment", 1)
mobs.add_goods(entity, race)
end
minetest.chat_send_player(player, S("[NPC] <Trader @1 > Hello, @2, have a look at my wares.",
self.game_name, player))
minetest.show_formspec(player, "trade", "size[8,10;]"
.. default.gui_bg_img
.. default.gui_slots
.. "label[0,0;" .. S("Trader @1's stock:", self.game_name) .. "]"
.. "list[detached:" .. unique_entity_id .. ";goods;.5,.5;3,5;]"
.. "label[4.5,0.5;" .. S("Selection") .. "]"
.. "list[detached:" .. unique_entity_id .. ";selection;4.5,1;5.5,2;]"
.. "label[6,0.5;" .. S("Price") .. "]"
.. "list[detached:" .. unique_entity_id .. ";price;6,1;7,2;]"
.. "label[4.5,3.5;" .. S("Payment") .. "]"
.. "list[detached:" .. unique_entity_id .. ";payment;4.5,4;5.5,5;]"
.. "label[6,3.5;" .. S("Bought items") .. "]"
.. "list[detached:" .. unique_entity_id .. ";takeaway;6,4;7.5,5.5;]"
.. "list[current_player;main;0,6;8,4;]"
)
end
mobs:register_egg("mobs_npc:trader", S("Trader"), "default_sandstone.png", 1)
-- compatibility
mobs:alias_mob("mobs:trader", "mobs_npc:trader")

View File

@ -1,264 +0,0 @@
if not minetest.get_modpath("shop") then
minetest.register_alias("shop:coin", "default:gold_ingot")
end
local S = mobs.intllib
mobs.human = {
items = {
-- item, price, chance
{"default:apple 10", "shop:coin 2", 40},
{"farming:bread 10", "shop:coin 4", 50},
{"default:clay 10", "shop:coin 2", 14},
{"default:brick 10", "shop:coin 4", 17},
{"default:glass 10", "shop:coin 4", 17},
{"default:obsidian 10", "shop:coin 15", 50},
{"default:diamond 1", "default:goldblock 1", 7},
{"default:goldblock 1", "default:diamond 1", 7},
{"farming:wheat 10", "shop:coin 2", 17},
{"default:tree 5", "shop:coin 4", 20},
{"default:stone 10", "shop:coin 8", 17},
{"default:desert_stone 10", "shop:coin 8", 27},
{"default:sapling 1", "shop:coin 1", 7},
{"default:pick_steel 1", "shop:coin 2", 7},
{"default:sword_steel 1", "shop:coin 2", 17},
{"default:shovel_steel 1", "shop:coin 1", 17},
},
names = {
"Bob", "Duncan", "Bill", "Tom", "James", "Ian", "Lenny"
}
}
-- Trader ( same as NPC but with right-click shop )
mobs:register_mob("mobs_npc:trader", {
type = "npc",
passive = false,
damage = 3,
attack_type = "dogfight",
attacks_monsters = true,
pathfinding = false,
hp_min = 10,
hp_max = 20,
armor = 100,
collisionbox = {-0.35,-1.0,-0.35, 0.35,0.8,0.35},
visual = "mesh",
mesh = "character.b3d",
textures = {
{"mobs_trader.png"}, -- by Frerin
{"mobs_trader2.png"}, -- re-coloured by amhadinger
{"mobs_trader3.png"}, -- re-coloured by amhadinger
},
makes_footstep_sound = true,
sounds = {},
walk_velocity = 2,
run_velocity = 3,
jump = false,
drops = {},
water_damage = 0,
lava_damage = 4,
light_damage = 0,
follow = {"default:diamond"},
view_range = 15,
owner = "",
order = "stand",
fear_height = 3,
animation = {
speed_normal = 30,
speed_run = 30,
stand_start = 0,
stand_end = 79,
walk_start = 168,
walk_end = 187,
run_start = 168,
run_end = 187,
punch_start = 200,
punch_end = 219,
},
on_rightclick = function(self, clicker)
mobs_trader(self, clicker, mobs.human)
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
-------------------------------------------------------------------------------
-- Modifications Copyright 2016 by James Stevenson
local trader_inventory = {}
local function add_goods(race)
local goods_to_add = nil
for i = 1, 16 do
if math.random(0, 100) > race.items[i][3] then
trader_inventory.set_stack(trader_inventory,
"goods", i, race.items[i][1])
end
end
end
function mobs_trader(self, clicker, race)
local player = clicker:get_player_name()
if not self.id then
self.id = (math.random(1, 1000) * math.random(1, 10000))
.. self.npc_name .. (math.random(1, 1000) ^ 2)
end
if not self.game_name then
self.game_name = tostring(race.names[math.random(1, #race.names)])
self.npc_nametag = S("Trader @1", self.game_name)
self.object:set_properties({
nametag = self.npc_nametag,
nametag_color = "#00FF00"
})
end
local unique_entity_id = self.id
local is_inventory = minetest.get_inventory({
type = "detached", name = unique_entity_id})
local move_put_take = {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
if (from_list == "goods" and
to_list == "selection") or
(from_list == "selection" and
to_list == "goods") then
return count
else
return 0
end
end,
allow_put = function(inv, listname, index, stack, player)
return 0
end,
allow_take = function(inv, listname, index, stack, player)
return 0
end,
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
if from_list == "goods" and
to_list == "selection" then
local moved = inv.get_stack(inv, to_list, to_index)
local goodname = moved.get_name(moved)
local elements = moved.get_count(moved)
if elements > count then
-- Remove the surplus parts
inv.set_stack(inv, "selection", 1,
goodname .. " " .. tostring(count))
-- The slot we took from is now free.
inv.set_stack(inv, "goods", from_index,
goodname .. " " .. tostring(elements - count))
-- Update the real amount of items in the slot now.
elements = count
end
local good = nil
for i = 1, #race.items, 1 do
local stackstring = goodname .. " " .. count
if race.items[i][1] == stackstring then
good = race.items[i]
end
end
if good ~= nil then
inv.set_stack(inv, "price", 1, good[2])
else
inv.set_stack(inv, "price", 1, nil)
end
elseif from_list == "selection" and
to_list == "goods" then
inv.set_stack(inv, "price", 1, nil)
end
end,
on_put = function(inv, listname, index, stack, player)
end,
on_take = function(inv, listname, index, stack, player)
end,
}
if is_inventory == nil then
trader_inventory = minetest.create_detached_inventory(unique_entity_id, move_put_take)
trader_inventory.set_size(trader_inventory, "goods", 16)
trader_inventory.set_size(trader_inventory, "selection", 1)
trader_inventory.set_size(trader_inventory, "price", 1)
add_goods(race)
--print("added stuff")
end
minetest.chat_send_player(player, S("[NPC] <Trader @1> Hello, @2, have a look at my wares.",
self.game_name, player))
minetest.show_formspec(player, "mobs_npc:trader", "size[8,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[detached:" .. unique_entity_id .. ";goods;0,0;8,2]" ..
"label[0,3;Selection]" ..
"list[detached:" .. unique_entity_id .. ";selection;2,3;1,1]" ..
"label[4,3;Price]" ..
"list[detached:" .. unique_entity_id .. ";price;6,3;1,1]" ..
"button[4,4;2,1;purchase;Purchase]" ..
"list[current_player;main;0,5;8,1;]" ..
"list[current_player;main;0,6.25;8,3;8]" ..
default.get_hotbar_bg(0, 5))
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "mobs_npc:trader" then
return
end
--print(dump(trader_inventory:get_lists()))
local selection_name = trader_inventory:get_stack("selection", 1):get_name()
local selection_count = trader_inventory:get_stack("selection", 1):get_count()
local selection_string = selection_name .. " " .. tostring(selection_count)
local price_name = trader_inventory:get_stack("price", 1):get_name()
local price_count = trader_inventory:get_stack("price", 1):get_count()
local price_string = price_name .. " " .. tostring(price_count)
--print(selection_string .. "\nfor:\n" .. price_string)
if player:get_inventory():contains_item("main", price_string) then
--print("you got it!")
trader_inventory:set_stack("selection", 1, nil)
trader_inventory:set_stack("price", 1, nil)
player:get_inventory():remove_item("main", price_string)
local adder = player:get_inventory():add_item("main", selection_string)
if adder then
minetest.add_item(player:getpos(), adder)
end
else
minetest.chat_send_player(player:get_player_name(),
"Not enough credits!")
end
end)
mobs:register_egg("mobs_npc:trader", S("Trader"), "default_sandstone.png", 1)
-- compatibility
mobs:alias_mob("mobs:trader", "mobs_npc:trader")