Pathfinding: Fix for mod security - joining up Jumper library code (WIP)
This commit is contained in:
parent
afe8dc8f6e
commit
297dd379a6
@ -9,29 +9,6 @@
|
|||||||
-- by Roland Yonaba (https://github.com/Yonaba/Jumper).
|
-- by Roland Yonaba (https://github.com/Yonaba/Jumper).
|
||||||
-- Mapping algorithm: transforms a Minetest map surface to a 2d grid.
|
-- Mapping algorithm: transforms a Minetest map surface to a 2d grid.
|
||||||
|
|
||||||
local path = minetest.get_modpath("advanced_npc")
|
|
||||||
|
|
||||||
-- Below code for require is taken and slightly modified
|
|
||||||
-- from irc mod by Diego Martinez (kaeza)
|
|
||||||
-- https://github.com/minetest-mods/irc
|
|
||||||
-- Handle mod security if needed
|
|
||||||
local ie, req_ie = _G, minetest.request_insecure_environment
|
|
||||||
if req_ie then ie = req_ie() end
|
|
||||||
if not ie then
|
|
||||||
error("The Advances NPC mod requires access to insecure functions in "..
|
|
||||||
"order to work. Please add the Advanced NPC mod to the "..
|
|
||||||
"secure.trusted_mods setting or disable the mod.")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Modify package path so that it can find the Jumper library files
|
|
||||||
ie.package.path =
|
|
||||||
path .. "/Jumper/?.lua;"..
|
|
||||||
ie.package.path
|
|
||||||
|
|
||||||
-- Require the main files from Jumper
|
|
||||||
local Grid = ie.require("jumper.grid")
|
|
||||||
local Pathfinder = ie.require("jumper.pathfinder")
|
|
||||||
|
|
||||||
pathfinder = {}
|
pathfinder = {}
|
||||||
|
|
||||||
pathfinder.node_types = {
|
pathfinder.node_types = {
|
||||||
@ -238,7 +215,7 @@ function pathfinder.normalize_map(map)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This function returns an array of tables with to parameters: type and pos.
|
-- This function returns an array of tables with two parameters: type and pos.
|
||||||
-- The position parameter is the actual coordinate on the Minetest map. The
|
-- The position parameter is the actual coordinate on the Minetest map. The
|
||||||
-- type is the type of the node at the coordinate defined as pathfinder.node_types.
|
-- type is the type of the node at the coordinate defined as pathfinder.node_types.
|
||||||
function pathfinder.get_path(map, path_nodes)
|
function pathfinder.get_path(map, path_nodes)
|
||||||
|
274
actions/pathfinder2.lua
Normal file
274
actions/pathfinder2.lua
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
-- Pathfinder by Zorman2000
|
||||||
|
-- Pathfinding code with included A* implementation, customized
|
||||||
|
-- for Minetest. At the moment, paths can only be found in flat
|
||||||
|
-- terrain (only 2D pathfinding)
|
||||||
|
|
||||||
|
-- Public namespace
|
||||||
|
pathfinder = {}
|
||||||
|
-- Private namespace for pathfinder functions
|
||||||
|
local finder = {}
|
||||||
|
|
||||||
|
pathfinder.node_types = {
|
||||||
|
start = 0,
|
||||||
|
goal = 1,
|
||||||
|
walkable = 2,
|
||||||
|
openable = 3,
|
||||||
|
non_walkable = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
pathfinder.nodes = {
|
||||||
|
openable_prefix = {
|
||||||
|
"doors:",
|
||||||
|
"cottages:gate",
|
||||||
|
"cottages:half_door"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pathfinder.find_path(start_pos, end_pos, extra_range, walkable_nodes)
|
||||||
|
-- Create map
|
||||||
|
local map = finder.create_map(start_pos, end_pos, extra_range, walkable_nodes)
|
||||||
|
minetest.log("Number of nodes in map: "..dump(#map))
|
||||||
|
-- Use A* algorithm
|
||||||
|
local path = minetest.find_path(start_pos, end_pos, 30, 1, 1, "Dijkstra")
|
||||||
|
minetest.log("Path: "..dump(path))
|
||||||
|
return path
|
||||||
|
--return finder.astar({name="air", pos=start_pos}, {name="air", pos=end_pos}, map)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This function is used to determine if a node is walkable
|
||||||
|
-- or openable, in which case is good to use when finding a path
|
||||||
|
function finder.is_good_node(node, exceptions)
|
||||||
|
-- Is openable is to support doors, fence gates and other
|
||||||
|
-- doors from other mods. Currently, default doors, gates
|
||||||
|
-- and cottages doors are supported.
|
||||||
|
local is_openable = false
|
||||||
|
for _,node_prefix in pairs(pathfinder.nodes.openable_prefix) do
|
||||||
|
local start_i,end_i = string.find(node.name, node_prefix)
|
||||||
|
if start_i ~= nil then
|
||||||
|
is_openable = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if node ~= nil and node.name ~= nil and not minetest.registered_nodes[node.name].walkable then
|
||||||
|
return pathfinder.node_types.walkable
|
||||||
|
elseif is_openable then
|
||||||
|
return pathfinder.node_types.openable
|
||||||
|
else
|
||||||
|
for i = 1, #exceptions do
|
||||||
|
if node.name == exceptions[i] then
|
||||||
|
return pathfinder.node_types.walkable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return pathfinder.node_types.non_walkable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Maps a 2D slice of Minetest terrain into an array of nodes
|
||||||
|
-- Extra range is a number that will be added in the x and the z coordinates
|
||||||
|
-- to allow more room to find paths.
|
||||||
|
-- Walkables is an array of node names which are considered walkable,
|
||||||
|
-- even if they are not.
|
||||||
|
function finder.create_map(start_pos, end_pos, extra_range, walkables)
|
||||||
|
|
||||||
|
minetest.log("Start pos: "..minetest.pos_to_string(start_pos))
|
||||||
|
minetest.log("End pos: "..minetest.pos_to_string(end_pos))
|
||||||
|
|
||||||
|
-- Calculate all signs to ensure:
|
||||||
|
-- 1. Correct area calculation
|
||||||
|
-- 2. Iterate in the correct direction
|
||||||
|
local start_x_sign = (start_pos.x - end_pos.x) / math.abs(start_pos.x - end_pos.x)
|
||||||
|
local start_z_sign = (start_pos.z - end_pos.z) / math.abs(start_pos.z - end_pos.z)
|
||||||
|
local end_x_sign = (end_pos.x - start_pos.x) / math.abs(end_pos.x - start_pos.x)
|
||||||
|
local end_z_sign = (end_pos.z - start_pos.z) / math.abs(end_pos.z - start_pos.z)
|
||||||
|
|
||||||
|
-- Correct the signs if they are nan
|
||||||
|
if math.abs(start_pos.x - end_pos.x) == 0 then
|
||||||
|
start_x_sign = -1
|
||||||
|
end_x_sign = 1
|
||||||
|
end
|
||||||
|
if math.abs(start_pos.z - end_pos.z) == 0 then
|
||||||
|
start_z_sign = -1
|
||||||
|
end_z_sign = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get starting and ending positions, adding the extra nodes to the area
|
||||||
|
local pos1 = {x=start_pos.x + (extra_range * start_x_sign), y = start_pos.y - 1, z=start_pos.z + (extra_range * start_z_sign)}
|
||||||
|
local pos2 = {x=end_pos.x + (extra_range * end_x_sign), y = end_pos.y, z=end_pos.z + (extra_range * end_z_sign)}
|
||||||
|
|
||||||
|
minetest.log("Recalculated pos1: "..minetest.pos_to_string(pos1))
|
||||||
|
minetest.log("Recalculated pos2: "..minetest.pos_to_string(pos2))
|
||||||
|
|
||||||
|
local grid = {}
|
||||||
|
|
||||||
|
-- Loop through the area and classify nodes
|
||||||
|
for z = 1, math.abs(pos1.z - pos2.z) do
|
||||||
|
--local current_row = {}
|
||||||
|
for x = 1, math.abs(pos1.x - pos2.x) do
|
||||||
|
-- Calculate current position
|
||||||
|
local current_pos = {x=pos1.x + (x*end_x_sign), y=pos1.y, z=pos1.z + (z*end_z_sign)}
|
||||||
|
-- Get node info
|
||||||
|
local node = minetest.get_node(current_pos)
|
||||||
|
-- Check if this is the starting position
|
||||||
|
if current_pos.x == start_pos.x and current_pos.z == start_pos.z then
|
||||||
|
-- Is start position
|
||||||
|
table.insert(grid, {name=node.name, pos=current_pos, type=pathfinder.node_types.start})
|
||||||
|
elseif current_pos.x == end_pos.x and current_pos.z == end_pos.z then
|
||||||
|
-- Is ending position or goal position
|
||||||
|
table.insert(grid, {name=node.name, pos=current_pos, type=pathfinder.node_types.goal})
|
||||||
|
else
|
||||||
|
-- Check if node is walkable
|
||||||
|
if node.name == "air" then
|
||||||
|
-- If air do no more checks
|
||||||
|
table.insert(grid, {name=node.name, pos=current_pos, type=pathfinder.node_types.walkable})
|
||||||
|
else
|
||||||
|
-- Check if it is of a walkable or openable type
|
||||||
|
table.insert(grid, {name=node.name, pos=current_pos, type=finder.is_good_node(node, walkables)})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Insert the converted row into the grid
|
||||||
|
--table.insert(grid, current_row)
|
||||||
|
end
|
||||||
|
|
||||||
|
return grid
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- A* algorithm implementation
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Utility functions
|
||||||
|
function finder.distance(node1, node2)
|
||||||
|
return math.sqrt(math.pow(node2.pos.x - node1.pos.x, 2) + math.pow(node2.pos.z - node1.pos.z, 2))
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.is_valid_neighbor(node1, node2)
|
||||||
|
-- Consider only orthogonal nodes
|
||||||
|
if (node1.pos.x == node2.pos.x and node1.pos.z ~= node2.pos.z)
|
||||||
|
or (node1.pos.z == node2.pos.z and node1.pos.x ~= node2.pos.z) then
|
||||||
|
if (finder.distance(node1, node2) < 2) then
|
||||||
|
return finder.is_good_node(node2, {})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.cost_estimate(node1, node2)
|
||||||
|
return finder.distance(node1, node2)
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.get_lowest_fscore(nodes, f_scores)
|
||||||
|
local lowest = 1/0
|
||||||
|
local best_node = nil
|
||||||
|
for _, node in pairs(nodes) do
|
||||||
|
local score = f_scores[node]
|
||||||
|
if score < lowest then
|
||||||
|
lowest = score
|
||||||
|
best_node = node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return best_node
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.get_neighbor(node, nodes)
|
||||||
|
local neighbors = {}
|
||||||
|
for _, current_node in pairs(nodes) do
|
||||||
|
if current_node ~= node then
|
||||||
|
if finder.is_valid_neighbor(node, current_node) then
|
||||||
|
table.insert(neighbors, current_node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return neighbors
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.contains_node(node, all_nodes)
|
||||||
|
for _,current_node in pairs(all_nodes) do
|
||||||
|
if current_node == node then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.remove_node(node, all_nodes)
|
||||||
|
--minetest.log("On remove_node: "..dump(all_nodes))
|
||||||
|
for key, current_node in pairs(all_nodes) do
|
||||||
|
if current_node == node then
|
||||||
|
--minetest.log("Table before: "..dump(all_nodes))
|
||||||
|
table.remove(all_nodes, key)
|
||||||
|
--minetest.log("Table after: "..dump(all_nodes))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.create_path(path, grid, node)
|
||||||
|
if grid[node] ~= nil then
|
||||||
|
table.insert(path, 1, grid[node])
|
||||||
|
return create_path(path, grid, grid[node])
|
||||||
|
else
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function finder.astar(start_pos, end_pos, nodes)
|
||||||
|
|
||||||
|
local closed_set = {}
|
||||||
|
local open_set = {
|
||||||
|
start_pos
|
||||||
|
}
|
||||||
|
local came_from = {}
|
||||||
|
|
||||||
|
local g_score = {}
|
||||||
|
local f_score = {}
|
||||||
|
g_score[start_pos] = 0
|
||||||
|
f_score[start_pos] = g_score[start_pos] + finder.cost_estimate(start_pos, end_pos)
|
||||||
|
|
||||||
|
minetest.log("Open set: "..dump(#open_set))
|
||||||
|
|
||||||
|
while #open_set > 0 do
|
||||||
|
minetest.log("Nodes size: "..dump(#nodes))
|
||||||
|
|
||||||
|
local current = finder.get_lowest_fscore(open_set, f_score)
|
||||||
|
minetest.log("Node with best fscore: "..dump(current))
|
||||||
|
if current == end_pos then
|
||||||
|
minetest.log("Creating path: "..dump(came_from))
|
||||||
|
local path = create_path({}, came_from, end_pos)
|
||||||
|
table.insert(path, end_pos)
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.log("Removing node from openset..."..dump(#open_set))
|
||||||
|
finder.remove_node(current, open_set)
|
||||||
|
minetest.log("Removed. Open set size: "..dump(#open_set))
|
||||||
|
minetest.log("Adding to closed set..."..dump(#closed_set))
|
||||||
|
table.insert(closed_set, current)
|
||||||
|
minetest.log("Added. New closed set size: "..dump(#closed_set))
|
||||||
|
|
||||||
|
local neighbors = finder.get_neighbor(current, nodes)
|
||||||
|
minetest.log("Found "..dump(#neighbors).." neighbors for current node")--dump(neighbors))
|
||||||
|
for _, neighbor in pairs(neighbors) do
|
||||||
|
minetest.log("Currently looking at neighbor: "..minetest.pos_to_string(neighbor.pos))
|
||||||
|
if finder.contains_node(neighbor, closed_set) == false then
|
||||||
|
minetest.log("Node is not in closed set")
|
||||||
|
|
||||||
|
local tentative_g_score = g_score[current] + finder.distance(current, neighbor)
|
||||||
|
minetest.log("Tentative g score is: "..dump(tentative_g_score))
|
||||||
|
minetest.log("Logic: "..dump(finder.contains_node(neighbor, open_set) == false or tentative_g_score < g_score[neighbor]))
|
||||||
|
if finder.contains_node(neighbor, open_set) == false or tentative_g_score < g_score[neighbor] then
|
||||||
|
came_from[neighbor] = current
|
||||||
|
minetest.log("Added node to came_from set: "..dump(table.getn(came_from)))
|
||||||
|
g_score[neighbor] = tentative_g_score
|
||||||
|
f_score[neighbor] = g_score[neighbor] + finder.cost_estimate(neighbor, end_pos)
|
||||||
|
if finder.contains_node(neighbor, open_set) == false then
|
||||||
|
minetest.log("Adding neighbor node to open_set: "..dump(#open_set))
|
||||||
|
table.insert(open_set, neighbor)
|
||||||
|
minetest.log("Added. New open set size: "..dump(#open_set))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Path not found
|
||||||
|
return nil
|
||||||
|
end
|
1311
actions/pathfinding.lua
Normal file
1311
actions/pathfinding.lua
Normal file
File diff suppressed because it is too large
Load Diff
@ -146,6 +146,7 @@ function npc.places.openable_node_is_entrance(pos)
|
|||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
local x_adj = 0
|
local x_adj = 0
|
||||||
local z_adj = 0
|
local z_adj = 0
|
||||||
|
minetest.log(node.param2)
|
||||||
if node.param2 then
|
if node.param2 then
|
||||||
if node.param2 == 0 then
|
if node.param2 == 0 then
|
||||||
|
|
||||||
@ -157,7 +158,8 @@ function npc.places.openable_node_is_entrance(pos)
|
|||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--local first_check_pos = {x=, y=, z=}
|
local y_adj = 2
|
||||||
|
local first_check_pos = {x=pos.x + x_adj, y=pos.y + y_adj, z=pos.z + z_adj}
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
26
init.lua
26
init.lua
@ -1,6 +1,30 @@
|
|||||||
-- Advanced NPC mod by Zorman2000
|
-- Advanced NPC mod by Zorman2000
|
||||||
local path = minetest.get_modpath("advanced_npc")
|
local path = minetest.get_modpath("advanced_npc")
|
||||||
|
|
||||||
|
-- Below code for require is taken and slightly modified
|
||||||
|
-- from irc mod by Diego Martinez (kaeza)
|
||||||
|
-- https://github.com/minetest-mods/irc
|
||||||
|
-- Handle mod security if needed
|
||||||
|
-- local ie = minetest.request_insecure_environment()
|
||||||
|
-- -- local req_ie = minetest.request_insecure_environment()
|
||||||
|
-- -- if req_ie then
|
||||||
|
-- -- ie = req_ie
|
||||||
|
-- -- end
|
||||||
|
-- if not ie then
|
||||||
|
-- error("The Advanced NPC mod requires access to insecure functions in "..
|
||||||
|
-- "order to work. Please add the Advanced NPC mod to the "..
|
||||||
|
-- "secure.trusted_mods setting or disable the mod.")
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- -- Modify package path so that it can find the Jumper library files
|
||||||
|
-- ie.package.path =
|
||||||
|
-- path .. "/Jumper/?.lua;"..
|
||||||
|
-- ie.package.path
|
||||||
|
|
||||||
|
-- -- Require the main files from Jumper
|
||||||
|
-- Grid = ie.require("jumper.grid")
|
||||||
|
-- Pathfinder = ie.require("jumper.pathfinder")
|
||||||
|
|
||||||
-- Intllib
|
-- Intllib
|
||||||
local S
|
local S
|
||||||
if minetest.get_modpath("intllib") then
|
if minetest.get_modpath("intllib") then
|
||||||
@ -33,6 +57,8 @@ dofile(path .. "/trade/prices.lua")
|
|||||||
dofile(path .. "/actions/actions.lua")
|
dofile(path .. "/actions/actions.lua")
|
||||||
dofile(path .. "/actions/places.lua")
|
dofile(path .. "/actions/places.lua")
|
||||||
dofile(path .. "/actions/pathfinder.lua")
|
dofile(path .. "/actions/pathfinder.lua")
|
||||||
|
dofile(path .. "/actions/pathfinding.lua")
|
||||||
|
--dofile(path .. "/actions/pathfinder2.lua")
|
||||||
dofile(path .. "/actions/node_registry.lua")
|
dofile(path .. "/actions/node_registry.lua")
|
||||||
dofile(path .. "/random_data.lua")
|
dofile(path .. "/random_data.lua")
|
||||||
|
|
||||||
|
83
npc.lua
83
npc.lua
@ -269,9 +269,11 @@ function npc.initialize(entity, pos, is_lua_entity)
|
|||||||
|
|
||||||
-- Temporary initialization of actions for testing
|
-- Temporary initialization of actions for testing
|
||||||
local nodes = npc.places.find_node_nearby(ent.object:getpos(), {"cottages:bench"}, 20)
|
local nodes = npc.places.find_node_nearby(ent.object:getpos(), {"cottages:bench"}, 20)
|
||||||
--minetest.log("Found nodes: "..dump(nodes))
|
|
||||||
|
|
||||||
--local path = pathfinder.find_path(ent.object:getpos(), nodes[1], 20)
|
|
||||||
|
minetest.log("Self destination: "..minetest.pos_to_string(nodes[1]))
|
||||||
|
|
||||||
|
local path = pathfinder.find_path(ent.object:getpos(), nodes[1], 20, {})
|
||||||
--minetest.log("Path to node: "..dump(path))
|
--minetest.log("Path to node: "..dump(path))
|
||||||
--npc.add_action(ent, npc.actions.use_door, {self = ent, pos = nodes[1], action = npc.actions.door_action.OPEN})
|
--npc.add_action(ent, npc.actions.use_door, {self = ent, pos = nodes[1], action = npc.actions.door_action.OPEN})
|
||||||
--npc.add_action(ent, npc.actions.stand, {self = ent})
|
--npc.add_action(ent, npc.actions.stand, {self = ent})
|
||||||
@ -861,6 +863,8 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
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!")
|
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.initialize(self, self.object:getpos(), true)
|
npc.initialize(self, self.object:getpos(), true)
|
||||||
else
|
else
|
||||||
|
self.tamed = false
|
||||||
|
self.owner = nil
|
||||||
-- NPC is initialized, check other variables
|
-- NPC is initialized, check other variables
|
||||||
-- Timer function for casual traders to reset their trade offers
|
-- Timer function for casual traders to reset their trade offers
|
||||||
self.trader_data.change_offers_timer = self.trader_data.change_offers_timer + dtime
|
self.trader_data.change_offers_timer = self.trader_data.change_offers_timer + dtime
|
||||||
@ -971,6 +975,81 @@ mobs:register_mob("advanced_npc:npc", {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- if self.follow_path then
|
||||||
|
-- self.home_timer = (self.home_timer or 0) + dtime
|
||||||
|
-- if self.home_timer < 1 then return end -- every 1 second
|
||||||
|
-- self.home_timer = 0
|
||||||
|
|
||||||
|
-- -- if self.time_of_day > 0.2 and self.time_of_day < 0.8 then
|
||||||
|
-- -- return -- return if not night time
|
||||||
|
-- -- end
|
||||||
|
|
||||||
|
-- local h = self.destination
|
||||||
|
-- --local h = {x = 1, y = 8, z = 2} -- destination coords
|
||||||
|
-- local p = self.object:getpos() -- mob position
|
||||||
|
|
||||||
|
-- -- lets try find a path, first take care of positions
|
||||||
|
-- -- since pathfinder is very sensitive
|
||||||
|
-- local pheight = self.collisionbox[5] - self.collisionbox[2]
|
||||||
|
|
||||||
|
-- -- round position to center of node to avoid stuck in walls
|
||||||
|
-- -- also adjust height for player models!
|
||||||
|
-- p.x = math.floor(p.x + 0.5)
|
||||||
|
-- p.y = math.floor(p.y + 0.5) - pheight
|
||||||
|
-- p.z = math.floor(p.z + 0.5)
|
||||||
|
|
||||||
|
-- local ssight, sground = minetest.line_of_sight(p, {
|
||||||
|
-- x = p.x, y = p.y - 4, z = p.z}, 1)
|
||||||
|
|
||||||
|
-- -- determine node above ground
|
||||||
|
-- if not ssight then
|
||||||
|
-- p.y = sground.y + 1
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- h.x = math.floor(h.x + 0.5)
|
||||||
|
-- h.y = math.floor(h.y + 0.5)
|
||||||
|
-- h.z = math.floor(h.z + 0.5)
|
||||||
|
|
||||||
|
|
||||||
|
-- local x, y, z = p.x - h.x, p.y - h.y, p.z - h.z
|
||||||
|
-- local dist = math.floor(math.sqrt(x * x + y * y + z * z))
|
||||||
|
|
||||||
|
-- minetest.log("Self pos : "..minetest.pos_to_string(p))
|
||||||
|
-- minetest.log("Self dest: "..minetest.pos_to_string(h))
|
||||||
|
|
||||||
|
-- if dist <= 1 then
|
||||||
|
-- print ("--- home!")
|
||||||
|
-- self.homepath = nil
|
||||||
|
-- self.state = "stand"
|
||||||
|
-- return
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- if self.homepath == nil then
|
||||||
|
-- self.homepath = minetest.find_path(p, h, 50, 3, 6, "A*")
|
||||||
|
-- print ("--- finding route", self.homepath, dist)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- if self.homepath then
|
||||||
|
-- print ("--- following path", dist, #self.homepath)
|
||||||
|
|
||||||
|
-- local np = self.homepath[1] ; if not np then return end
|
||||||
|
|
||||||
|
-- if math.abs(np.x - p.x) + math.abs(np.z - p.z) < 0.6 then
|
||||||
|
-- table.remove(self.homepath, 1) ; print ("-- removed entry")
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- np = {x = np.x, y = np.y, z = np.z}
|
||||||
|
|
||||||
|
-- local vec = {x = np.x - p.x, z = np.z - p.z}
|
||||||
|
-- local yaw = (math.atan(vec.z / vec.x) + math.pi / 2) - self.rotate
|
||||||
|
|
||||||
|
-- if np.x > p.x then yaw = yaw + math.pi end
|
||||||
|
|
||||||
|
-- self.object:setyaw(yaw)
|
||||||
|
-- set_velocity(self, self.walk_velocity)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
return self.freeze
|
return self.freeze
|
||||||
end
|
end
|
||||||
|
@ -327,12 +327,55 @@ npc.data.FIRST_NAMES = {
|
|||||||
female = {
|
female = {
|
||||||
"Kimy",
|
"Kimy",
|
||||||
"Lili",
|
"Lili",
|
||||||
"Cora",
|
"Coraline",
|
||||||
"Caroline",
|
|
||||||
"Gloria",
|
"Gloria",
|
||||||
"Mary",
|
"Mary",
|
||||||
"Mayra",
|
"Mayra",
|
||||||
"Arlene"
|
"Arlene",
|
||||||
|
"Tita",
|
||||||
|
"Lola",
|
||||||
|
"Olivia",
|
||||||
|
"Katherine",
|
||||||
|
"Cataline",
|
||||||
|
"Pinky",
|
||||||
|
"Kathleen",
|
||||||
|
"Marilyn",
|
||||||
|
"Sunshine",
|
||||||
|
"April",
|
||||||
|
"Rainy",
|
||||||
|
"Lulu",
|
||||||
|
"Sandra",
|
||||||
|
"Marlene",
|
||||||
|
"Lany",
|
||||||
|
"Zoe",
|
||||||
|
"Jolie",
|
||||||
|
"Vicky",
|
||||||
|
"Natalia",
|
||||||
|
"Evelyn",
|
||||||
|
"Elizabeth",
|
||||||
|
"Giselle",
|
||||||
|
"Jasmine",
|
||||||
|
"Karla",
|
||||||
|
"Leslie",
|
||||||
|
"Karen",
|
||||||
|
"Dana",
|
||||||
|
"Merry",
|
||||||
|
"Helena",
|
||||||
|
"Rose",
|
||||||
|
"Thalia",
|
||||||
|
"Luna",
|
||||||
|
"Valery",
|
||||||
|
"Carol",
|
||||||
|
"Paulette",
|
||||||
|
"Rosie",
|
||||||
|
"Leti",
|
||||||
|
"Sophie",
|
||||||
|
"Miranda",
|
||||||
|
"Arianne",
|
||||||
|
"Lizzy",
|
||||||
|
"Amy",
|
||||||
|
"Chole",
|
||||||
|
"Alisson"
|
||||||
},
|
},
|
||||||
male = {
|
male = {
|
||||||
"Jote",
|
"Jote",
|
||||||
@ -341,7 +384,9 @@ npc.data.FIRST_NAMES = {
|
|||||||
"Joseph",
|
"Joseph",
|
||||||
"Gerald",
|
"Gerald",
|
||||||
"Kiko",
|
"Kiko",
|
||||||
"Michael"
|
"Michael",
|
||||||
|
"Alexis",
|
||||||
|
"Rafa"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user