Compare commits

..

5 Commits

Author SHA1 Message Date
Hector Franqui
5b9c072c03 Removed .idea folder 2018-01-13 10:20:35 -05:00
Hector Franqui
18f07ce50f Actions: Added description.
Fully implement helper methods for validating and evaluating expressions.
Full implementation of declarative commands.
2018-01-13 10:12:17 -05:00
Hector Franqui
ff82f83c0b NPC: Add execution environment
Actions: Rename 'actions' to 'command'
Add skeleton method for declarative and control commands
2018-01-09 20:04:20 -05:00
Hector Franqui
9125aa334a Actions: Replace "action" for "command".
Add declarative and control commands comments and function signature (no implementation yet).
2018-01-09 19:04:51 -05:00
Hector Franqui
221cfa3105 NPC: Add execution context. 2018-01-09 18:43:33 -05:00
16 changed files with 1642 additions and 1126 deletions

0
.idea/.gitignore generated vendored
View File

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/advanced_npc.iml" filepath="$PROJECT_DIR$/.idea/advanced_npc.iml" />
</modules>
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PreferredVcsStorage">
<preferredVcsName>ApexVCS</preferredVcsName>
</component>
</project>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

File diff suppressed because it is too large Load Diff

View File

@ -67,7 +67,7 @@ function pathfinder.get_decorated_path(path)
type=pathfinder.is_good_node(node, {})})
end
--npc.log("DEBUG", "Detailed path: "..dump(path_detail))
npc.log("DEBUG", "Detailed path: "..dump(path_detail))
return path_detail
end

View File

@ -179,8 +179,8 @@ function npc.places.add_owned_accessible_place(self, nodes, place_type, walkable
-- Assign node to NPC
npc.places.add_owned(self, place_type, place_type,
nodes[i].node_pos, empty_nodes[1].pos)
-- npc.log("DEBUG", "Added node at "..minetest.pos_to_string(nodes[i].node_pos)
-- .." to NPC "..dump(self.npc_name))
npc.log("DEBUG", "Added node at "..minetest.pos_to_string(nodes[i].node_pos)
.." to NPC "..dump(self.npc_name))
break
end
end
@ -227,12 +227,12 @@ function npc.places.mark_place_used(pos, value)
local meta = minetest.get_meta(pos)
local used = meta:get_string("advanced_npc:used")
if value == used then
-- npc.log("WARNING", "Attempted to set 'used' property of node at "
-- ..minetest.pos_to_string(pos).." to the same value: '"..dump(value).."'")
npc.log("WARNING", "Attempted to set 'used' property of node at "
..minetest.pos_to_string(pos).." to the same value: '"..dump(value).."'")
return false
else
meta:set_string("advanced_npc:used", value)
-- npc.log("DEBUG", "'Used' value at pos "..minetest.pos_to_string(pos)..": "..dump(meta:get_string("advanced_npc:used")))
npc.log("DEBUG", "'Used' value at pos "..minetest.pos_to_string(pos)..": "..dump(meta:get_string("advanced_npc:used")))
return true
end
end
@ -259,10 +259,9 @@ function npc.places.find_unused_place(self, place_category, place_type, original
return alternative_places[i]
end
end
--else
else
result = original_place
end
result = original_place
return result
end

View File

@ -233,7 +233,7 @@ npc.relationships.register_disliked_item("default:cobble", "male", {
hints = {"If I really hate something, that's cobblestone!"}
})
--npc.log("DEBUG", "Registered gift items: "..dump(npc.relationships.gift_items))
--npc.log("DEBUG", "Registered dialogues: "..dump(npc.dialogue.registered_dialogues))
npc.log("DEBUG", "Registered gift items: "..dump(npc.relationships.gift_items))
npc.log("DEBUG", "Registered dialogues: "..dump(npc.dialogue.registered_dialogues))
npc.log("INFO", "Registered gift items count: "..dump(#npc.relationships.gift_items))
npc.log("INFO", "Registered dialogues count: "..dump(#npc.dialogue.registered_dialogues))
npc.log("INFO", "Registered dialogues count: "..dump(#npc.dialogue.registered_dialogues))

View File

@ -325,7 +325,7 @@ function npc.dialogue.select_random_dialogues_for_npc(self, phase)
for i = 1, number_of_dialogues do
local key_id = math.random(1, #keys)
result.normal[i] = keys[key_id]
--npc.log("DEBUG", "Adding dialogue: "..dump(dialogues[keys[key_id]]))
npc.log("DEBUG", "Adding dialogue: "..dump(dialogues[keys[key_id]]))
end
-- Add item hints.
@ -352,7 +352,7 @@ function npc.dialogue.select_random_dialogues_for_npc(self, phase)
end
end
--npc.log("DEBUG", "Dialogue results:"..dump(result))
npc.log("DEBUG", "Dialogue results:"..dump(result))
return result
end
@ -446,7 +446,7 @@ function npc.dialogue.start_dialogue(self, player, show_married_dialogue)
dialogue = self.dialogues.normal[math.random(1, #self.dialogues.normal)]
elseif chance >= 90 then
-- Check if gift items hints are enabled
--minetest.log("Self gift data enable: "..dump(self.gift_data.enable_gift_items_hints))
minetest.log("Self gift data enable: "..dump(self.gift_data.enable_gift_items_hints))
if self.gift_data.enable_gift_items_hints then
-- Choose a random dialogue line from the favorite/disliked item hints
dialogue = self.dialogues.hints[math.random(1, 4)]
@ -669,7 +669,7 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
elseif player_response.is_custom_trade_dialogue == true then
-- Functions for a custom trade should be available from the same dialogue
-- object as they are created on demand
--minetest.log("Player response: "..dump(player_response.options[i]))
minetest.log("Player response: "..dump(player_response.options[i]))
player_response.options[i].action(player_response.npc, player)
else
-- Get dialogue from registered dialogues

90
doc/new_api.md Normal file
View File

@ -0,0 +1,90 @@
Advanced NPC 1.0 proposal
-------------------------
While Advanced NPC provides functionality and a level of intelligence that no other mob mod can, it is still limited in some features and to its ultimate purpose of creating functional towns and/or simulated communities. The following are the areas that has been identified as lacking:
- Idle/wandering
- When NPCs aren't executing actions, their movement is very dumb. They wander aimlessly, constantly and usually bump into obstacles and keep walking nevertheless. They get stuck at places they shouldn't.
- Relationships
- Relationships are very hardcoded, and there's no flexibility on them.
- Unable to add more functionality
- All actions are hardcoded. While the essentials are in, making a NPC operate another node that is not a furnace/chest/door is almost impossible. If a mod adds a node and wants NPC to be able to operate it, it is certainly very hard.
- More randomness in schedules
- While schedules are all about making NPCs do actions at certain times, it is not flexible enough to make it look more realistic. One morning a NPC can get up and make breakfast or not, put some music on a music player or not, go outside their home and wander around, etc.
- Unable to react to certain triggers
- When NPCs are punched, `mobs_redo` takes over and controls the NPC. Also, NPCs are unable to scan an area for certain things and perform actions continually based on it.
The above are all playability issues and deficiencies. Some technical issues has to be addressed as well regarding the API. Given all these, the following is a proposal to move the mod towards the correct direction.
##Proposed changes:
- Unify the actions/tasks/schedule property change/schedule query API into a `commands` API
- Add new commands to bring the NPC interaction level closer to that of a player
- Rename `flags` to `properties`
- Allow registering scripts, or collections of commands for external mods to provide extra functionality
Unified Commands API
--------------------
The goal of this API is to provide consistency and extensibility to the actions a NPC can perform. First of all, rename actions/tasks/property change/query to `commands`. Each command will have the following properties that determines how it is to be executed and what it does:
- Type: specifies the type of command. The following are valid types:
- `instruction`: Used for fundamental, atomic operations. This type maps directly to what are called now `actions`, which are for example, walk one step, dig, place, etc.
- `control`: Used for specific commands that are flow control statements. Example: If-else, for loops. The conditional statements is a Lua boolean expression.
- `script`: Used for collections of commands, executed on a sequential structure. This type maps directly to `tasks`.
- Execution: specifies how the command is to be executed. The following are valid valuesf for this parameter:
- `immediate`: Will execute this command immediately, without any enqueing. Very little commands should be able to do this. The `control` commands should be executed immediately as they need to enqueue certain commands depending on their conditions.
- `default`: Command will be enqueued and executed on the global command timer call.
- Interruptable: specifies whether the global command timer and/or the scheduler can interrupt the command. Boolean value, can be set to false or true.
- _Important_: Non-interruptable commands should be able to finish by themselves. The API will execute the default command once a non-interruptable command is done and if it doesn't executes another command.
- Parameters: a Lua table with all the parameters that the command requires. Depending on the type, some parameters are required. Below is a list of required parameters per type:
- `instruction`: Requires just the parameters required by the instruction to execute.
- `control`: Requires different parameters depending on the type of control.
- Required:
- `condition`: The condition to be evaluated. This is a Lua boolean expression.
- `match_commands`: A Lua array with the commands to be executed if condition evaluates to `true`.
- Dependent on type:
- `operation`: Only required in `for-loop` command. Operation to execute on the loop variable (e.g. increase/decrease)
- `repetition`: Optional for `for-loop` command. Can't be used together with `max` and `min`.
- `max`: Optional for `for-loop` command. Can't be used together with `repetition`. Requires `min`. Randomizes a loop execution and sets the upper bound of how many times the loop will execute.
- `min`: Optional for `for-loop` command. Can't be used together with `repetition`. Requires `max`. Randomizes a loop execution and sets the lower bound of how many times the loop will execute.
- `else_commands`: Only required in `if-else` command. A Lua array with the commands to be executed if condition evaluates to `false`.
- `script`: A Lua array of commands to execute, in order
The following `instruction` commands will be added to the default set:
- `do_punch`: Executes the `on_punch` function of a node, object or player
- `do_rightclick`: Executes the `on_rightclick` function of a node, object or player
- `set_property`: Sets the value of a variable in the `self.properties` object. If the variable doesn't exists, it is created. This command is executed immediately and is not enqueued.
- Parameters:
- `key`: The property key-name. This is a variable in the `self.properties` object
- `value`: The property value.
- `get_property`: Returns the value of a given property. This command is executed immediately and is not enqueued.
- Parameters:
- `key`: The property key-name.
- `set_internal_property`: Sets the value of a limited set of internal properties related to the NPC trading and personality variables.
- `get_internal_property`: Gets the value of a limited set of internal properties related to the NPC trading and personality variables.
- `add_item_to_npc`: Adds an item to the NPC inventory, without any specific source.
- `remove_item_from_npc`: Removes a specific item from the NPC inventory.
- `query`: Executes a query for nodes or objects. Returns a Lua table with none, single or many positions.
The following `control` commands will be added to the default set:
- `if-else`: An if-else control statement that will execute immediately. It will evaluate the given `condition` parameter and execute commands depending on the evaluation of the `condition`.
- Parameters:
- `condition`: A Lua boolean expression to be evaluated.
- `true-commands`: A Lua array of commands to be executed if `condition` evaluates to `true`.
- `else-commands`: A Lua array of commands to be executed if `condition` evaluates to `false`.
- `loop`: A flexible loop command. Supports for-loop and while-loops. The amount of loops done will be available in `npc.commands.current_loop_count`. Executes immediately, it is not enqueued.
- Parameters:
##Extensibility
Once the above commands has been added, it is possible to safely build scripts which don't touch directly many of the internal NPC mechanisms. An API will be provided for external mods to register scripts that let NPCs perform actions related to those mods, e.g. operating a node provided by the mod. The API for this will be:
`npc.commands.register_script(name, script)`
All registered scripts have the following properties:
- They are interruptable by the command queue/scheduler
- They are not immediately executed
The `script` parameter is a Lua array of commands that will be executed when the script is executed.

117
npc.lua
View File

@ -476,6 +476,8 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats, occupation_name)
-- relative to the last position
target_pos = {}
},
-- Execution context - map of user-declared variables when executing scripts
execution_context = {}
}
-- This flag is checked on every step. If it is true, the rest of
@ -556,9 +558,9 @@ function npc.initialize(entity, pos, is_lua_entity, npc_stats, occupation_name)
-- Set initialized flag on
ent.initialized = true
--npc.log("WARNING", "Spawned entity: "..dump(ent))
-- npc.log("INFO", "Successfully initialized NPC with name "..dump(ent.npc_name)
-- ..", sex: "..ent.sex..", is child: "..dump(ent.is_child)
-- ..", texture: "..dump(ent.textures))
npc.log("INFO", "Successfully initialized NPC with name "..dump(ent.npc_name)
..", sex: "..ent.sex..", is child: "..dump(ent.is_child)
..", texture: "..dump(ent.textures))
-- Refreshes entity
ent.object:set_properties(ent)
end
@ -745,10 +747,10 @@ end
-- This function removes the first action in the action queue
-- and then executes it
function npc.execute_action(self)
--npc.log("DEBUG_ACTION", "Current actions queue: "..dump(self.actions.queue))
npc.log("DEBUG_ACTION", "Current actions queue: "..dump(self.actions.queue))
-- Check if an action was interrupted
if self.actions.current_action_state == npc.action_state.interrupted then
--npc.log("DEBUG_ACTION", "Re-inserting interrupted action for NPC: '"..dump(self.npc_name).."': "..dump(self.actions.state_before_lock.interrupted_action))
npc.log("DEBUG_ACTION", "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
@ -780,7 +782,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
--npc.log("DEBUG_ACTION", "Executing task for NPC '"..dump(self.npc_name).."': "..dump(action_obj))
npc.log("DEBUG_ACTION", "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
@ -796,7 +798,7 @@ function npc.execute_action(self)
table.insert(self.actions.queue, backup_queue[i])
end
else
--npc.log("DEBUG_ACTION", "Executing action for NPC '"..dump(self.npc_name).."': "..dump(action_obj))
npc.log("DEBUG_ACTION", "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
@ -854,7 +856,7 @@ function npc.lock_actions(self)
-- Freeze mobs_redo API
self.freeze = false
--npc.log("DEBUG_ACTION", "Locking NPC "..dump(self.npc_id).." actions")
npc.log("DEBUG_ACTION", "Locking NPC "..dump(self.npc_id).." actions")
end
function npc.unlock_actions(self)
@ -883,7 +885,69 @@ function npc.unlock_actions(self)
self.freeze = true
end
--npc.log("DEBUG_ACTION", "Unlocked NPC "..dump(self.npc_id).." actions")
npc.log("DEBUG_ACTION", "Unlocked NPC "..dump(self.npc_id).." actions")
end
--------------------------------------------
-- Execution context management functions --
--------------------------------------------
-- These functions manage the execution context, where variables are
-- stored, whether internal (loops) or user-created.
-- The execution context is cleared at the end of each script.
npc.execution_context = {}
-- This function adds a value to the execution context.
-- Readonly defaults to false. Returns false if failed due to
-- key-name conflict, or returns true if successful
function npc.execution_context.put(self, key, value, readonly)
-- Check if variable exists
if self.actions.execution_context[key] ~= nil then
npc.log("ERROR", "Attempt to create new variable with name "..key.." failed"..
"due to variable already existing: "..dump(self.actions.execution_context[key]))
return false
end
self.actions.execution_context[key] = {value = value, readonly = readonly}
return true
end
-- Returns the value of a given key. If not found returns nil.
function npc.execution_context.get(self, key)
local result = self.actions.execution_context[key]
if result == nil then
return nil
else
return result.value
end
end
-- This function updates a value in the execution context.
-- Returns false if the value is read-only or if key isn't found.
-- Returns true if able to update value
function npc.execution_context.set(self, key, new_value)
local var = self.actions.execution_context[key]
if var == nil then
return false
else
if var.readonly == true then
npc.log("ERROR", "Attempt to set value of readonly variable: "..key)
return false
end
var.value = new_value
end
return true
end
-- This function removes a variable from the execution context.
-- If the key doesn't exist, returns nil, otherwise, returns
-- the value removed.
function npc.execution_context.remove(self, key)
local result = self.actions.execution_context[key]
if result == nil then
return nil
else
self.actions.execution_context[key] = nil
return result
end
end
---------------------------------------------------------------------------------------
@ -1044,8 +1108,8 @@ function npc.schedule_change_property(self, property, args)
local itemlist_entry = itemlist[i]
local current_itemstring = itemlist[i].name
if itemlist_entry.random == true then
-- current_itemstring = current_itemstring
-- .." "..dump(math.random(itemlist_entry.min, itemlist_entry.max))
current_itemstring = current_itemstring
.." "..dump(math.random(itemlist_entry.min, itemlist_entry.max))
else
current_itemstring = current_itemstring.." "..tostring(itemlist_entry.count)
end
@ -1118,7 +1182,7 @@ end
-- None-action: array of entries {action=<action_enum>, args={}}.
-- Will be executed when no node is found.
function npc.schedule_check(self)
--npc.log("DEBUG_SCHEDULE", "Prev Actions queue: "..dump(self.actions.queue))
npc.log("DEBUG_SCHEDULE", "Prev Actions queue: "..dump(self.actions.queue))
local range = self.schedules.current_check_params.range
local walkable_nodes = self.schedules.current_check_params.walkable_nodes
local nodes = self.schedules.current_check_params.nodes
@ -1129,7 +1193,7 @@ function npc.schedule_check(self)
-- Search nodes
local found_nodes = npc.places.find_node_nearby(start_pos, nodes, range)
-- Check if any node was found
--npc.log("DEBUG_SCHEDULE", "Found nodes using radius: "..dump(found_nodes))
npc.log("DEBUG_SCHEDULE", "Found nodes using radius: "..dump(found_nodes))
if found_nodes and #found_nodes > 0 then
local node_pos
local node
@ -1155,7 +1219,7 @@ function npc.schedule_check(self)
-- Set node as a place
-- Note: Code below isn't *adding* a node, but overwriting the
-- place with "schedule_target_pos" place type
--npc.log("DEBUG_SCHEDULE", "Found "..dump(node.name).." at pos: "..minetest.pos_to_string(node_pos))
npc.log("DEBUG_SCHEDULE", "Found "..dump(node.name).." at pos: "..minetest.pos_to_string(node_pos))
npc.places.add_shared_accessible_place(
self, {owner="", node_pos=node_pos}, npc.places.PLACE_TYPE.SCHEDULE.TARGET, true, walkable_nodes)
-- Get actions related to node and enqueue them
@ -1209,7 +1273,7 @@ function npc.schedule_check(self)
-- Speed is default wandering speed. Target pos is node_pos
-- Calculate dir if dir is random
local dir = npc.actions.get_direction(start_pos, node_pos)
--minetest.log("actions: "..dump(actions[node.name][i]))
minetest.log("actions: "..dump(actions[node.name][i]))
if actions[node.name][i].args.dir == "random" then
dir = math.random(0,7)
elseif type(actions[node.name][i].args.dir) == "number" then
@ -1271,7 +1335,7 @@ function npc.schedule_check(self)
< self.schedules.current_check_params.execution_times then
npc.add_schedule_check(self)
end
--npc.log("DEBUG_SCHEDULE", "Actions queue: "..dump(self.actions.queue))
npc.log("DEBUG_SCHEDULE", "Actions queue: "..dump(self.actions.queue))
else
-- No nodes found, enqueue none_actions
for i = 1, #none_actions do
@ -1289,7 +1353,7 @@ function npc.schedule_check(self)
npc.add_schedule_check(self)
end
-- No nodes found
--npc.log("DEBUG_SCHEDULE", "Actions queue: "..dump(self.actions.queue))
npc.log("DEBUG_SCHEDULE", "Actions queue: "..dump(self.actions.queue))
end
end
@ -1311,8 +1375,7 @@ function npc.after_activate(self)
if self.yaw_before_interaction then
self.object:setyaw(self.yaw_before_interaction)
end
else
if not self.actions then self.actions = {} end
else
-- Temporary code - adds the new state variables
self.actions.move_state = {
is_sitting = false,
@ -1333,7 +1396,7 @@ function npc.rightclick_interaction(self, clicker)
local item = clicker:get_wielded_item()
local name = clicker:get_player_name()
--npc.log("DEBUG", "Right-clicked NPC: "..dump(self))
npc.log("DEBUG", "Right-clicked NPC: "..dump(self))
-- Receive gift or start chat. If player has no item in hand
-- then it is going to start chat directly
@ -1389,7 +1452,7 @@ function npc.step(self, dtime)
self.texture = {self.selected_texture}
self.base_texture = {self.selected_texture}
self.object:set_properties(self)
--npc.log("WARNING", "Corrected textures on NPC child "..dump(self.npc_name))
npc.log("WARNING", "Corrected textures on NPC child "..dump(self.npc_name))
-- Set interval to large interval so this code isn't called frequently
npc.texture_check.interval = 60
end
@ -1476,7 +1539,7 @@ function npc.step(self, dtime)
time = (time) - (time % 1)
-- Check if there is a schedule entry for this time
-- Note: Currently only one schedule is supported, for day 0
--npc.log("DEBUG_SCHEDULE", "Time: "..dump(time))
npc.log("DEBUG_SCHEDULE", "Time: "..dump(time))
local schedule = self.schedules.generic[0]
if schedule ~= nil then
-- Check if schedule for this time exists
@ -1487,7 +1550,7 @@ function npc.step(self, dtime)
-- Check if schedule has a check function
if schedule[time][i].check then
-- Add parameters for check function and run for first time
--npc.log("DEBUG", "NPC "..dump(self.npc_id).." is starting check on "..minetest.pos_to_string(self.object:getpos()))
npc.log("DEBUG", "NPC "..dump(self.npc_id).." is starting check on "..minetest.pos_to_string(self.object:getpos()))
local check_params = schedule[time][i]
-- Calculates how many times check will be executed
local execution_times = check_params.count
@ -1509,8 +1572,8 @@ function npc.step(self, dtime)
-- Enqueue the schedule check
npc.add_schedule_check(self)
else
--npc.log("DEBUG_SCHEDULE", "Executing schedule entry for NPC "..dump(self.npc_id)..": "
--..dump(schedule[time][i]))
npc.log("DEBUG_SCHEDULE", "Executing schedule entry for NPC "..dump(self.npc_id)..": "
..dump(schedule[time][i]))
-- Run usual schedule entry
-- Check chance
local execution_chance = math.random(1, 100)
@ -1545,13 +1608,13 @@ function npc.step(self, dtime)
end
else
-- TODO: Change to debug
--npc.log("DEBUG", "Skipping schedule entry for time "..dump(time)..": "..dump(schedule[time][i]))
npc.log("DEBUG", "Skipping schedule entry for time "..dump(time)..": "..dump(schedule[time][i]))
end
end
end
-- Clear execution queue
self.schedules.temp_executed_queue = {}
--npc.log("DEBUG", "New action queue: "..dump(self.actions.queue))
npc.log("DEBUG", "New action queue: "..dump(self.actions.queue))
end
end
else

View File

@ -260,7 +260,7 @@ function npc.occupations.register_occupation(name, def)
-- Add to the dialogue tags the "occupation name"
table.insert(dialogue.tags, name)
-- Register dialogue
--npc.log("INFO", "Registering dialogue for occupation "..dump(name)..": "..dump(dialogue))
npc.log("INFO", "Registering dialogue for occupation "..dump(name)..": "..dump(dialogue))
local key = npc.dialogue.register_dialogue(dialogue)
-- Add key to set of dialogue keys
table.insert(dialogue_keys, key)
@ -287,7 +287,7 @@ function npc.occupations.register_occupation(name, def)
-- Save the definition
npc.occupations.registered_occupations[name] = def
--npc.log("INFO", "Successfully registered occupation with name: "..dump(name))
npc.log("INFO", "Successfully registered occupation with name: "..dump(name))
end
-- This function scans all registered occupations and filter them by
@ -345,11 +345,11 @@ function npc.occupations.initialize_occupation_values(self, occupation_name)
local def = npc.occupations.registered_occupations[occupation_name]
if not def then
--npc.log("WARNING", "No definition found for occupation name: "..dump(occupation_name))
npc.log("WARNING", "No definition found for occupation name: "..dump(occupation_name))
return
end
--npc.log("INFO", "Overriding NPC values using occupation '"..dump(occupation_name).."' values")
npc.log("INFO", "Overriding NPC values using occupation '"..dump(occupation_name).."' values")
-- Initialize textures, else it will leave the current textures
if def.textures and table.getn(def.textures) > 0 then
@ -439,7 +439,7 @@ function npc.occupations.initialize_occupation_values(self, occupation_name)
end
-- Initialize properties
--minetest.log("def.properties: "..dump(def.properties))
minetest.log("def.properties: "..dump(def.properties))
if def.properties then
-- Initialize trader status
if def.properties.initial_trader_status then

View File

@ -209,7 +209,7 @@ function npc.relationships.get_dialogues_for_gift_item(item_name, dialogue_type,
if phase ~= nil then
tags[5] = phase
end
--npc.log("DEBUG","Searching with tags: "..dump(tags))
npc.log("DEBUG","Searching with tags: "..dump(tags))
return npc.dialogue.search_dialogue_by_tags(tags, true)
end
@ -237,7 +237,7 @@ function npc.relationships.get_response_for_disliked_item(item_name, sex)
end
for i = 1, #items do
--minetest.log(dump(items[i]))
minetest.log(dump(items[i]))
if items[i].item == item_name then
--minetest.log("Returning: "..dump(items[i].response))
return items[i].response
@ -641,7 +641,7 @@ function npc.relationships.receive_gift(self, clicker)
clicker:set_wielded_item(item)
end
--npc.log("DEBUG", "NPC: "..dump(self))
npc.log("DEBUG", "NPC: "..dump(self))
-- Reset gift timer
reset_gift_timer(self, clicker_name)
return true

View File

@ -212,8 +212,8 @@ function npc.spawner.determine_npc_occupation(building_type, workplace_nodes, np
building_type,
surrounding_buildings_map
)
--npc.log("DEBUG", "Found occupations: "..dump(occupation_names).."\nfor local building type: "
--..dump(building_type).."\nAnd surrounding building types: "..dump(surrounding_buildings_map))
npc.log("DEBUG", "Found occupations: "..dump(occupation_names).."\nfor local building type: "
..dump(building_type).."\nAnd surrounding building types: "..dump(surrounding_buildings_map))
-- Insert default occupation into result
table.insert(result, {name=npc.occupations.basic_name, node={node_pos={}}})
@ -272,10 +272,10 @@ function npc.spawner.determine_npc_occupation(building_type, workplace_nodes, np
-- used by another NPC, then, use it
local meta = minetest.get_meta(workplace_nodes[j].node_pos)
local worker_data = minetest.deserialize(meta:get_string("work_data") or "")
--npc.log("DEBUG", "Found worker data: "..dump(worker_data))
npc.log("DEBUG", "Found worker data: "..dump(worker_data))
-- If no worker data is found, then create it
if not worker_data then
--npc.log("INFO", "Found suitable occupation and workplace: "..dump(result))
npc.log("INFO", "Found suitable occupation and workplace: "..dump(result))
table.insert(result, {name=occupation_names[i], node=workplace_nodes[j]})
end
end
@ -381,7 +381,7 @@ function npc.spawner.spawn_npc_on_plotmarker(pos)
else
-- Start another timer to spawn more NPC
local new_delay = math.random(npc.spawner.spawn_delay)
--npc.log("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
end
@ -404,7 +404,7 @@ function npc.spawner.spawn_npc(pos, area_info, occupation_name, occupation_workp
-- this is a manually spawned NPC
local can_spawn = false
if npc_count and spawned_npc_count then
--npc.log("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
can_spawn = true
end
@ -429,7 +429,7 @@ function npc.spawner.spawn_npc(pos, area_info, occupation_name, occupation_workp
npc.initialize(ent, pos, nil, nil, occupation)
end
-- If node_data is present, assign nodes
--minetest.log("Node data: "..dump(node_data))
minetest.log("Node data: "..dump(node_data))
if node_data then
npc.spawner.assign_places(ent:get_luaentity(), entrance, node_data, pos)
end
@ -448,7 +448,7 @@ function npc.spawner.spawn_npc(pos, area_info, occupation_name, occupation_workp
workplace = occupation_workplace_pos,
born_day = minetest.get_day_count()
}
--minetest.log("Area info: "..dump(area_info))
minetest.log("Area info: "..dump(area_info))
table.insert(area_info.npcs, entry)
-- Update and store stats
-- Increase total of NPCs for specific sex
@ -569,9 +569,9 @@ function npc.spawner.assign_places(self, entrance, node_data, pos)
if #node_data.workplace_type > 0 then
-- First, find the workplace_node that was marked
for i = 1, #node_data.workplace_type do
--minetest.log("In assign places: workplace nodes: "..dump(node_data.workplace_type))
--minetest.log("Condition? "..dump(node_data.workplace_type[i].occupation
-- and node_data.workplace_type[i].occupation == self.occupation_name))
minetest.log("In assign places: workplace nodes: "..dump(node_data.workplace_type))
minetest.log("Condition? "..dump(node_data.workplace_type[i].occupation
and node_data.workplace_type[i].occupation == self.occupation_name))
if node_data.workplace_type[i].occupation
and node_data.workplace_type[i].occupation == self.occupation_name then
-- Walkable nodes from occupation
@ -592,7 +592,7 @@ function npc.spawner.assign_places(self, entrance, node_data, pos)
end
end
--npc.log("DEBUG", "Places for NPC "..self.npc_name..": "..dump(self.places_map))
npc.log("DEBUG", "Places for NPC "..self.npc_name..": "..dump(self.places_map))
-- Make NPC go into their house
-- If entrance is available let NPC
@ -626,7 +626,7 @@ function npc.spawner.calculate_npc_spawning_on_plotmarker(pos)
-- Check number of beds
local beds_count = #node_data.bed_type--#spawner.filter_first_floor_nodes(node_data.bed_type, pos)
--npc.log("DEBUG", "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.
@ -637,7 +637,7 @@ function npc.spawner.calculate_npc_spawning_on_plotmarker(pos)
-- Spawn (beds_count/2) NPCs
npc_count = ((beds_count / 2) - ((beds_count / 2) % 1))
end
--npc.log("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
@ -873,14 +873,14 @@ if minetest.get_modpath("mg_villages") ~= nil then
--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))
--npc.log("DEBUG", "Start pos: "..minetest.pos_to_string(start_pos))
--npc.log("DEBUG", "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")))
--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))
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)}
@ -1099,7 +1099,7 @@ minetest.register_chatcommand("restore_area", {
privs = {server = true},
func = function(name, param)
local args = npc.utils.split(param, " ")
--minetest.log("Params: "..dump(args))
minetest.log("Params: "..dump(args))
if #args < 2 then
minetest.chat_send_player("Please specify horizontal and vertical radius.")
return

View File

@ -440,7 +440,7 @@ function npc.trade.get_dedicated_trade_offers(self)
local trade_list = self.trader_data.trade_list
--npc.log("INFO", "NPC Inventory: "..dump(self.inventory))
npc.log("INFO", "NPC Inventory: "..dump(self.inventory))
for item_name, trade_info in pairs(trade_list) do
-- Abort if more than 12 buy or sell offers are made
@ -451,8 +451,8 @@ function npc.trade.get_dedicated_trade_offers(self)
-- If it is, create a sell offer, else create a buy offer if possible.
-- Also, avoid creating sell offers immediately if the item was just bought
local item = npc.inventory_contains(self, item_name)
--minetest.log("Searched item: "..dump(item_name))
--minetest.log("Found: "..dump(item))
minetest.log("Searched item: "..dump(item_name))
minetest.log("Found: "..dump(item))
if item ~= nil and trade_info.last_offer_type ~= npc.trade.OFFER_BUY then
-- Check if item can be sold
if trade_info.item_sold_count == nil
@ -764,4 +764,4 @@ minetest.register_on_player_receive_fields(function (player, formname, fields)
end
end
end)
end)