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:
		@@ -141,8 +141,8 @@ end
 | 
			
		||||
-- and the NPC is allowed to roam freely.
 | 
			
		||||
function npc.actions.freeze(self, args)
 | 
			
		||||
	local freeze_mobs_api = args.freeze
 | 
			
		||||
	minetest.log("Received: "..dump(freeze_mobs_api))
 | 
			
		||||
	minetest.log("Returning: "..dump(not(freeze_mobs_api)))
 | 
			
		||||
	--minetest.log("Received: "..dump(freeze_mobs_api))
 | 
			
		||||
	--minetest.log("Returning: "..dump(not(freeze_mobs_api)))
 | 
			
		||||
	return not(freeze_mobs_api)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -333,7 +333,7 @@ function npc.actions.take_item_from_external_inventory(self, args)
 | 
			
		||||
	else
 | 
			
		||||
		inv = minetest.get_inventory({type="node", pos=pos})
 | 
			
		||||
	end
 | 
			
		||||
	-- Create ItemSTack to take from external inventory
 | 
			
		||||
	-- Create ItemStack to take from external inventory
 | 
			
		||||
	local item = ItemStack(item_name.." "..count)
 | 
			
		||||
	-- Check if there is enough of the item to take
 | 
			
		||||
	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
 | 
			
		||||
-- for doors instead of having separate logic for each door type
 | 
			
		||||
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
 | 
			
		||||
	-- Check for default doors and gates
 | 
			
		||||
	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
 | 
			
		||||
		state = npc.actions.const.doors.state.OPEN
 | 
			
		||||
	end
 | 
			
		||||
	minetest.log("Door state: "..dump(state))
 | 
			
		||||
	--minetest.log("Door state: "..dump(state))
 | 
			
		||||
	return state
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -412,10 +412,10 @@ end
 | 
			
		||||
-- items from a chest, are provided here.
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	if type(pos) == "table" then
 | 
			
		||||
		minetest.log("Received table pos: "..dump(pos))
 | 
			
		||||
		--minetest.log("Received table pos: "..dump(pos))
 | 
			
		||||
		-- Check if table is position
 | 
			
		||||
		if pos.x ~= nil and pos.y ~= nil and pos.z ~= nil then
 | 
			
		||||
			-- Position received, return position
 | 
			
		||||
@@ -468,7 +468,7 @@ end
 | 
			
		||||
function npc.actions.use_furnace(self, args)
 | 
			
		||||
	local pos = get_pos_argument(self, args.pos)
 | 
			
		||||
	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
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
@@ -478,14 +478,14 @@ function npc.actions.use_furnace(self, args)
 | 
			
		||||
	-- will mainly use this as fuels to avoid getting useful
 | 
			
		||||
	-- items (such as coal lumps) for burning
 | 
			
		||||
	local fuels = {"default:leaves", 
 | 
			
		||||
								 "default:pine_needles",
 | 
			
		||||
								 "default:tree",
 | 
			
		||||
								 "default:acacia_tree",
 | 
			
		||||
								 "default:aspen_tree",
 | 
			
		||||
								 "default:jungletree",
 | 
			
		||||
								 "default:pine_tree",
 | 
			
		||||
								 "default:coalblock",
 | 
			
		||||
								 "farming:straw"}
 | 
			
		||||
					"default:pine_needles",
 | 
			
		||||
					"default:tree",
 | 
			
		||||
					"default:acacia_tree",
 | 
			
		||||
					"default:aspen_tree",
 | 
			
		||||
					"default:jungletree",
 | 
			
		||||
					"default:pine_tree",
 | 
			
		||||
					"default:coalblock",
 | 
			
		||||
					"farming:straw"}
 | 
			
		||||
 | 
			
		||||
	-- Check if NPC has item to cook
 | 
			
		||||
	local src_item = npc.inventory_contains(self, npc.get_item_name(item))
 | 
			
		||||
@@ -503,15 +503,15 @@ function npc.actions.use_furnace(self, args)
 | 
			
		||||
			local fuel_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)
 | 
			
		||||
			minetest.log("Fuel time: "..dump(fuel_time))
 | 
			
		||||
			npc.log("DEBUG", "Fuel time: "..dump(fuel_time))
 | 
			
		||||
 | 
			
		||||
			-- Get item to cook's cooking time
 | 
			
		||||
			local cook_result = 
 | 
			
		||||
			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)
 | 
			
		||||
			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))
 | 
			
		||||
 | 
			
		||||
			-- Check if there is enough fuel to cook all items
 | 
			
		||||
@@ -531,7 +531,7 @@ function npc.actions.use_furnace(self, args)
 | 
			
		||||
				fuel_amount = 1
 | 
			
		||||
			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
 | 
			
		||||
			local args = {
 | 
			
		||||
@@ -554,7 +554,7 @@ function npc.actions.use_furnace(self, args)
 | 
			
		||||
			npc.add_action(self, npc.actions.cmd.PUT_ITEM, args)
 | 
			
		||||
 | 
			
		||||
			-- 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})
 | 
			
		||||
 | 
			
		||||
			-- 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
 | 
			
		||||
			-- once cooking is done.
 | 
			
		||||
			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={}})
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
@@ -577,10 +577,10 @@ function npc.actions.use_furnace(self, args)
 | 
			
		||||
				 count = npc.get_item_count(item),
 | 
			
		||||
				 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)
 | 
			
		||||
 | 
			
		||||
			minetest.log("Inventory: "..dump(self.inventory))
 | 
			
		||||
			npc.log("DEBUG", "Inventory: "..dump(self.inventory))
 | 
			
		||||
 | 
			
		||||
			return true
 | 
			
		||||
		end
 | 
			
		||||
@@ -594,7 +594,7 @@ end
 | 
			
		||||
function npc.actions.use_bed(self, args)
 | 
			
		||||
	local pos = get_pos_argument(self, args.pos)
 | 
			
		||||
	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
 | 
			
		||||
	end
 | 
			
		||||
	local action = args.action
 | 
			
		||||
@@ -654,7 +654,7 @@ end
 | 
			
		||||
function npc.actions.use_sittable(self, args)
 | 
			
		||||
	local pos = get_pos_argument(self, args.pos)
 | 
			
		||||
	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
 | 
			
		||||
	end
 | 
			
		||||
	local action = args.action
 | 
			
		||||
@@ -727,7 +727,7 @@ function npc.actions.walk_to_pos(self, args)
 | 
			
		||||
	-- Get arguments for this task 
 | 
			
		||||
	local end_pos = get_pos_argument(self, args.end_pos)
 | 
			
		||||
	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
 | 
			
		||||
	end
 | 
			
		||||
	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())
 | 
			
		||||
	-- Use y of end_pos (this can only be done assuming flat terrain)
 | 
			
		||||
	--start_pos.y = self.object:getpos().y
 | 
			
		||||
	minetest.log("[advanced_npc] INFO 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: Start pos: "..minetest.pos_to_string(start_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
 | 
			
		||||
	if walkable_nodes == nil then
 | 
			
		||||
@@ -759,11 +759,8 @@ function npc.actions.walk_to_pos(self, args)
 | 
			
		||||
		end
 | 
			
		||||
		path = path_detail
 | 
			
		||||
 | 
			
		||||
		--minetest.log("Found path: "..dump(path))
 | 
			
		||||
 | 
			
		||||
		--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))
 | 
			
		||||
		npc.log("DEBUG", "Detailed path: "..dump(path))
 | 
			
		||||
		npc.log("INFO", "walk_to_pos Found path to node: "..minetest.pos_to_string(end_pos))
 | 
			
		||||
		-- Store path
 | 
			
		||||
		self.actions.walking.path = path
 | 
			
		||||
 | 
			
		||||
@@ -784,6 +781,8 @@ function npc.actions.walk_to_pos(self, args)
 | 
			
		||||
			if (i+1) == #path then
 | 
			
		||||
				-- Add direction to last node
 | 
			
		||||
				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
 | 
			
		||||
				npc.add_action(self, npc.actions.cmd.STAND, {dir = dir})
 | 
			
		||||
				break
 | 
			
		||||
@@ -823,7 +822,7 @@ function npc.actions.walk_to_pos(self, args)
 | 
			
		||||
				-- 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}
 | 
			
		||||
				-- 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
 | 
			
		||||
				npc.add_action(self, npc.actions.cmd.STAND, {dir=(dir + 2) % 4 })--, pos=pos_on_close})
 | 
			
		||||
				-- Close door
 | 
			
		||||
@@ -840,7 +839,7 @@ function npc.actions.walk_to_pos(self, args)
 | 
			
		||||
 | 
			
		||||
	else
 | 
			
		||||
		-- 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
 | 
			
		||||
		if enforce_move then
 | 
			
		||||
			-- Move to end pos
 | 
			
		||||
 
 | 
			
		||||
@@ -124,7 +124,7 @@ function npc.places.find_node_orthogonally(pos, nodes, y_adjustment)
 | 
			
		||||
  local result = {}
 | 
			
		||||
  for _,point in pairs(points) do
 | 
			
		||||
    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
 | 
			
		||||
      if node.name == node_name then
 | 
			
		||||
        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 entity = {}
 | 
			
		||||
      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("End pos: "..minetest.pos_to_string(end_pos))
 | 
			
		||||
      --minetest.log("Start pos: "..minetest.pos_to_string(start_pos))
 | 
			
		||||
      --minetest.log("End pos: "..minetest.pos_to_string(end_pos))
 | 
			
		||||
      local path = pathfinder.find_path(start_pos, end_pos, entity)
 | 
			
		||||
      --minetest.log("Found path: "..dump(path))
 | 
			
		||||
      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
 | 
			
		||||
          -- while we have a MTG door
 | 
			
		||||
          if min_node_name == "cottages:half_door" and doors_st ~= nil then
 | 
			
		||||
            minetest.log("Assigned new door...")
 | 
			
		||||
            --minetest.log("Assigned new door...")
 | 
			
		||||
            min = #path
 | 
			
		||||
            result = openable_nodes[i]
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      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
 | 
			
		||||
@@ -302,7 +302,7 @@ function npc.places.is_in_staircase(pos)
 | 
			
		||||
    -- Get next node
 | 
			
		||||
    local upper_node = minetest.get_node(upper_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
 | 
			
		||||
    local up_p1, up_p2 = string.find(upper_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.
 | 
			
		||||
function npc.places.find_node_in_front_of_door(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
 | 
			
		||||
    -- Looking south
 | 
			
		||||
    return {x=door_pos.x, y=door_pos.y, z=door_pos.z - 1}
 | 
			
		||||
 
 | 
			
		||||
@@ -296,7 +296,7 @@ function npc.dialogue.process_dialogue(self, dialogue, player_name)
 | 
			
		||||
 | 
			
		||||
	-- Send dialogue line
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
  -- Check if dialogue has responses. If it doesn't, unlock the actions
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								init.lua
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								init.lua
									
									
									
									
									
								
							@@ -23,7 +23,6 @@ else
 | 
			
		||||
end
 | 
			
		||||
mobs.intllib = S
 | 
			
		||||
 | 
			
		||||
-- NPC
 | 
			
		||||
dofile(path .. "/npc.lua")
 | 
			
		||||
dofile(path .. "/spawner.lua")
 | 
			
		||||
dofile(path .. "/relationships.lua")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								npc.lua
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								npc.lua
									
									
									
									
									
								
							@@ -42,9 +42,27 @@ npc.action_state = {
 | 
			
		||||
  interrupted = 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
npc.log_level = {
 | 
			
		||||
  INFO = true,
 | 
			
		||||
  WARNING = false,
 | 
			
		||||
  ERROR = true,
 | 
			
		||||
  DEBUG = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
---------------------------------------------------------------------------------------
 | 
			
		||||
-- 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
 | 
			
		||||
function npc.get_entity_name(entity)
 | 
			
		||||
  if entity:is_player() then
 | 
			
		||||
@@ -176,7 +194,7 @@ end
 | 
			
		||||
-- Spawn function. Initializes all variables that the
 | 
			
		||||
-- NPC will have and choose random, starting values
 | 
			
		||||
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
 | 
			
		||||
  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)
 | 
			
		||||
 | 
			
		||||
  --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
 | 
			
		||||
  ent.object:set_properties(ent)
 | 
			
		||||
end
 | 
			
		||||
@@ -596,7 +614,7 @@ end
 | 
			
		||||
function npc.execute_action(self)
 | 
			
		||||
  -- Check if an action was interrupted
 | 
			
		||||
  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
 | 
			
		||||
    table.insert(self.actions.queue, 1, self.actions.state_before_lock.interrupted_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
 | 
			
		||||
  -- stack fashion
 | 
			
		||||
  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
 | 
			
		||||
    local backup_queue = self.actions.queue
 | 
			
		||||
    -- Remove this "task" action from queue
 | 
			
		||||
@@ -634,7 +652,7 @@ function npc.execute_action(self)
 | 
			
		||||
      table.insert(self.actions.queue, backup_queue[i])
 | 
			
		||||
    end
 | 
			
		||||
  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
 | 
			
		||||
    self.actions.state_before_lock.interrupted_action = action_obj
 | 
			
		||||
    -- Store current position
 | 
			
		||||
@@ -689,7 +707,7 @@ function npc.lock_actions(self)
 | 
			
		||||
  -- Freeze mobs_redo API
 | 
			
		||||
  self.freeze = false
 | 
			
		||||
 | 
			
		||||
  minetest.log("Locking")
 | 
			
		||||
  npc.log("DEBUG", "Locking NPC "..dump(self.npc_id).." actions")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function npc.unlock_actions(self)
 | 
			
		||||
@@ -703,7 +721,7 @@ function npc.unlock_actions(self)
 | 
			
		||||
    self.freeze = true
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  minetest.log("Unlocked")
 | 
			
		||||
  npc.log("DEBUG", "Unlocked NPC "..dump(self.npc_id).." actions")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---------------------------------------------------------------------------------------
 | 
			
		||||
@@ -863,7 +881,7 @@ mobs:register_mob("advanced_npc:npc", {
 | 
			
		||||
		{"npc_female1.png"}, -- female by nuttmeg20
 | 
			
		||||
	},
 | 
			
		||||
	child_texture = {
 | 
			
		||||
		{"npc_baby_male1.png"}, -- derpy baby by AmirDerAssassine
 | 
			
		||||
		{"npc_baby_male1.png"},
 | 
			
		||||
	  {"npc_baby_female1.png"},
 | 
			
		||||
  },
 | 
			
		||||
	makes_footstep_sound = true,
 | 
			
		||||
@@ -915,12 +933,8 @@ mobs:register_mob("advanced_npc:npc", {
 | 
			
		||||
    --self.base_texture = "mobs_npc_child_male1.png"
 | 
			
		||||
    --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
 | 
			
		||||
    -- then it is going to start chat directly
 | 
			
		||||
    if self.can_have_relationship and item:to_table() ~= nil then
 | 
			
		||||
@@ -952,7 +966,7 @@ mobs:register_mob("advanced_npc:npc", {
 | 
			
		||||
      -- Initialize NPC if spawned using the spawn egg built in from
 | 
			
		||||
      -- mobs_redo. This functionality will be removed in the future in
 | 
			
		||||
      -- 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)
 | 
			
		||||
    else
 | 
			
		||||
      self.tamed = false
 | 
			
		||||
@@ -1049,7 +1063,7 @@ mobs:register_mob("advanced_npc:npc", {
 | 
			
		||||
                -- to action queue. This is for jobs.
 | 
			
		||||
                -- TODO: Need to implement
 | 
			
		||||
              else
 | 
			
		||||
                minetest.log("Adding actions to action queue")
 | 
			
		||||
                npc.log("DEBUG", "Adding actions to action queue")
 | 
			
		||||
                -- Add to action queue all actions on schedule
 | 
			
		||||
                for i = 1, #schedule[time] do
 | 
			
		||||
                  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)
 | 
			
		||||
                  end
 | 
			
		||||
                end
 | 
			
		||||
                minetest.log("New action queue: "..dump(self.actions))
 | 
			
		||||
                npc.log("DEBUG", "New action queue: "..dump(self.actions))
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								spawner.lua
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								spawner.lua
									
									
									
									
									
								
							@@ -209,7 +209,7 @@ function spawner.assign_places(self, pos)
 | 
			
		||||
  	-- Find unowned bed
 | 
			
		||||
  	for i = 1, #node_data.bed_type do
 | 
			
		||||
  		-- 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 bed has no owner, check if it is accessible
 | 
			
		||||
  			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)
 | 
			
		||||
  				-- Store changes to 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))
 | 
			
		||||
  				break
 | 
			
		||||
  			end
 | 
			
		||||
@@ -233,7 +233,7 @@ function spawner.assign_places(self, pos)
 | 
			
		||||
 | 
			
		||||
  --local plot_info = minetest.deserialize(meta:get_string("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
 | 
			
		||||
	npc.add_task(self, 
 | 
			
		||||
@@ -274,9 +274,9 @@ function npc.spawner.spawn_npc(pos)
 | 
			
		||||
  -- Check amount of NPCs that should be spawned
 | 
			
		||||
  local npc_count = meta:get_int("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
 | 
			
		||||
    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
 | 
			
		||||
    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
 | 
			
		||||
@@ -324,21 +324,21 @@ function npc.spawner.spawn_npc(pos)
 | 
			
		||||
      meta:set_string("npc_stats", minetest.serialize(npc_stats))
 | 
			
		||||
      -- Temp
 | 
			
		||||
      --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
 | 
			
		||||
      if spawned_npc_count >= npc_count then
 | 
			
		||||
        -- 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()
 | 
			
		||||
      else
 | 
			
		||||
        -- Start another timer to spawn more NPC
 | 
			
		||||
        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)
 | 
			
		||||
      end
 | 
			
		||||
      return true
 | 
			
		||||
    else
 | 
			
		||||
        minetest.log("[advanced_npc] Spawning failed!")
 | 
			
		||||
        npc.log("ERROR", "Spawning failed!")
 | 
			
		||||
        ent:remove()
 | 
			
		||||
      return false
 | 
			
		||||
    end
 | 
			
		||||
@@ -358,13 +358,13 @@ function spawner.calculate_npc_spawning(pos)
 | 
			
		||||
  -- Get nodes for this building
 | 
			
		||||
  local node_data = minetest.deserialize(meta:get_string("node_data"))
 | 
			
		||||
  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
 | 
			
		||||
  end
 | 
			
		||||
  -- Check number of beds
 | 
			
		||||
  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
 | 
			
		||||
  -- If number of beds is zero or beds/2 is less than one, spawn
 | 
			
		||||
  -- a single NPC.
 | 
			
		||||
@@ -375,7 +375,7 @@ function spawner.calculate_npc_spawning(pos)
 | 
			
		||||
    -- Spawn (beds_count/2) NPCs
 | 
			
		||||
    npc_count = ((beds_count / 2) - ((beds_count / 2) % 1))
 | 
			
		||||
  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
 | 
			
		||||
  meta:set_int("npc_count", npc_count)
 | 
			
		||||
  -- 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.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))
 | 
			
		||||
  minetest.log("Plot: "..dump(minetest.get_meta(start_pos):get_string("infotext")))
 | 
			
		||||
  npc.log("DEBUG", "Start pos: "..minetest.pos_to_string(start_pos))
 | 
			
		||||
  npc.log("DEBUG", "Plot: "..dump(minetest.get_meta(start_pos):get_string("infotext")))
 | 
			
		||||
 | 
			
		||||
  minetest.log("Brotate: "..dump(brotate))
 | 
			
		||||
  minetest.log("X_sign: "..dump(x_sign))
 | 
			
		||||
  minetest.log("X_adj: "..dump(x_sign*x_size))
 | 
			
		||||
  minetest.log("Z_sign: "..dump(z_sign))
 | 
			
		||||
  minetest.log("Z_adj: "..dump(z_sign*z_size))
 | 
			
		||||
  npc.log("DEBUG", "Brotate: "..dump(brotate))
 | 
			
		||||
  npc.log("DEBUG", "X_sign: "..dump(x_sign))
 | 
			
		||||
  npc.log("DEBUG", "X_adj: "..dump(x_sign*x_size))
 | 
			
		||||
  npc.log("DEBUG", "Z_sign: "..dump(z_sign))
 | 
			
		||||
  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)}
 | 
			
		||||
 | 
			
		||||
@@ -451,7 +451,7 @@ function spawner.scan_mg_villages_building(pos, building_data)
 | 
			
		||||
  --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.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)
 | 
			
		||||
end
 | 
			
		||||
@@ -477,7 +477,7 @@ function spawner.replace_mg_villages_plotmarker(pos)
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
      minetest.set_node(pos, {name="advanced_npc:plotmarker_auto_spawner"})
 | 
			
		||||
      -- Store old plotmarker metadata again
 | 
			
		||||
@@ -498,9 +498,9 @@ function spawner.replace_mg_villages_plotmarker(pos)
 | 
			
		||||
      --minetest.log("Found "..dump(#doors).." openable nodes")
 | 
			
		||||
      local entrance = npc.places.find_entrance_from_openable_nodes(doors, pos)
 | 
			
		||||
      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
 | 
			
		||||
        minetest.log("Unable to find building entrance!")
 | 
			
		||||
        npc.log("ERROR", "Unable to find building entrance!")
 | 
			
		||||
      end
 | 
			
		||||
      -- Store building entrance
 | 
			
		||||
      meta:set_string("entrance", minetest.serialize(entrance))
 | 
			
		||||
@@ -569,7 +569,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
 | 
			
		||||
      -- end
 | 
			
		||||
      -- minetest.get_meta(pos):set_string("node_data", minetest.serialize(nodedata))
 | 
			
		||||
      -- 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 )
 | 
			
		||||
    end,
 | 
			
		||||
@@ -610,7 +610,7 @@ if minetest.get_modpath("mg_villages") ~= nil then
 | 
			
		||||
  --   end
 | 
			
		||||
  -- })
 | 
			
		||||
 | 
			
		||||
  -- ABM Registration... for when LBM fails.
 | 
			
		||||
  -- ABM Registration
 | 
			
		||||
  minetest.register_abm({
 | 
			
		||||
    label = "Replace mg_villages:plotmarker with Advanced NPC auto spawners",
 | 
			
		||||
    nodenames = {"mg_villages:plotmarker"},
 | 
			
		||||
 
 | 
			
		||||
@@ -415,8 +415,8 @@ function npc.trade.get_dedicated_trade_offers(self)
 | 
			
		||||
              -- If item found, create a buy offer for this item
 | 
			
		||||
              -- Again, offers are created for one item only. Buy offers should be removed
 | 
			
		||||
              -- after the NPC has bought a certain quantity, say, 5 items.
 | 
			
		||||
              minetest.log("Item: "..item_name)
 | 
			
		||||
              minetest.log("Trade info: "..dump(trade_info))
 | 
			
		||||
              --minetest.log("Item: "..item_name)
 | 
			
		||||
              --minetest.log("Trade info: "..dump(trade_info))
 | 
			
		||||
              --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)))
 | 
			
		||||
              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])
 | 
			
		||||
          end
 | 
			
		||||
          -- Send message to player
 | 
			
		||||
          minetest.chat_send_player(player_name, "Thank you!")
 | 
			
		||||
          npc.chat(self.npc_name, player_name, "Thank you!")
 | 
			
		||||
          return true
 | 
			
		||||
        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!")
 | 
			
		||||
          return false
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    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
 | 
			
		||||
    end
 | 
			
		||||
  else
 | 
			
		||||
@@ -570,14 +571,16 @@ function npc.trade.perform_trade(self, player_name, offer)
 | 
			
		||||
          -- Add item items to player
 | 
			
		||||
          inv:add_item("main", item_stack)
 | 
			
		||||
          -- Send message to player
 | 
			
		||||
          minetest.chat_send_player(player_name, "Thank you!")
 | 
			
		||||
          npc.chat(self.npc_name, player_name, "Thank you!")
 | 
			
		||||
          return true
 | 
			
		||||
        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
 | 
			
		||||
        end
 | 
			
		||||
      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
 | 
			
		||||
      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
 | 
			
		||||
              -- Increase the item bought count
 | 
			
		||||
              local offer_item_name = npc.get_item_name(trade_offers[i].item)
 | 
			
		||||
              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("Bought item name: "..dump(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
 | 
			
		||||
              if player_response.npc.trader_data.trade_list.both[offer_item_name].item_bought_count == nil then
 | 
			
		||||
                -- Set first count to 1
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										355
									
								
								trader.lua
									
									
									
									
									
								
							
							
						
						
									
										355
									
								
								trader.lua
									
									
									
									
									
								
							@@ -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")
 | 
			
		||||
							
								
								
									
										264
									
								
								trader_test.lua
									
									
									
									
									
								
							
							
						
						
									
										264
									
								
								trader_test.lua
									
									
									
									
									
								
							@@ -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")
 | 
			
		||||
		Reference in New Issue
	
	Block a user