More tweaks and fixes
parent
93091fe3a6
commit
bcdc792990
|
@ -4,15 +4,17 @@ if moddebug then dbg=moddebug.dbg("people") else dbg={v1=function() end,v2=funct
|
|||
|
||||
people.actions.face = function(state)
|
||||
if state.action.pos and state.action.pos.x and state.action.pos.y and state.action.pos.z then
|
||||
state.yaw = vector.get_yaw(statepos, state.action.pos)
|
||||
dbg.v3(state.ent.name.." setting calculated yaw to "..state.action.yaw)
|
||||
elseif state.action.yaw then
|
||||
dbg.v3(state.ent.name.." setting yaw to "..state.action.yaw)
|
||||
state.yaw = state.action.yaw
|
||||
else
|
||||
dbg.v1(state.ent.name.." has invalid face action "..dump(state.action))
|
||||
state.yaw = vector.get_yaw(state.pos, state.action.pos)
|
||||
dbg.v3(state.ent.name.." setting calculated yaw to "..state.yaw)
|
||||
return true, true
|
||||
elseif state.action.yaw then
|
||||
dbg.v3(state.ent.name.." setting yaw to "..state.action.yaw)
|
||||
state.yaw = state.action.yaw
|
||||
return true, true
|
||||
end
|
||||
return true, true
|
||||
|
||||
dbg.v1(state.ent.name.." has invalid face action "..dump(state.action))
|
||||
return true, false
|
||||
end
|
||||
|
||||
|
||||
|
|
104
actions/go.lua
104
actions/go.lua
|
@ -2,11 +2,15 @@
|
|||
local dbg
|
||||
if moddebug then dbg=moddebug.dbg("people") else dbg={v1=function() end,v2=function() end,v3=function() end} end
|
||||
|
||||
-- "Path Node To Pos". Footpath nodes are 1x1 areas ABOVE the path. People
|
||||
-- "Area Node To Pos". Footpath area nodes are 1x1 areas ABOVE the path. People
|
||||
-- positions (to match player positions) are 0.5 above the node they are
|
||||
-- standing on. Add this to the Y coordinate to convert from a path node
|
||||
-- position to a people position.
|
||||
local PNTP = -0.5
|
||||
local ANTP = -0.5
|
||||
|
||||
-- "Path Node To Pos". But the nodes that form the actual path are below.
|
||||
-- This is all very messy and needs rationalising!!
|
||||
local PNTP = 0.5
|
||||
|
||||
people.actions.go = function(state)
|
||||
|
||||
|
@ -38,7 +42,7 @@ people.actions.go = function(state)
|
|||
if pathstartarea then
|
||||
dbg.v2(state.ent.name.." selected path start "..pathstartarea.name.." at "..minetest.pos_to_string(pathstartarea.pos1))
|
||||
state.action.pos = vector.new(pathstartarea.pos1)
|
||||
state.action.pos.y = state.action.pos.y + PNTP
|
||||
state.action.pos.y = state.action.pos.y + ANTP
|
||||
state.action.footpathdest = pathdestarea
|
||||
return false
|
||||
end
|
||||
|
@ -97,7 +101,7 @@ people.actions.go = function(state)
|
|||
return true, false
|
||||
end
|
||||
dbg.v2(state.ent.name.." leaving junction via "..nextpathdest.name)
|
||||
state.action.pos = vector.add(nextpathdest.pos1, {x=0, y=PNTP, z=0})
|
||||
state.action.pos = vector.add(nextpathdest.pos1, {x=0, y=ANTP, z=0})
|
||||
return false
|
||||
|
||||
end
|
||||
|
@ -111,6 +115,11 @@ people.actions.go = function(state)
|
|||
local thispathpos = vector.round({x=state.pos.x, y=state.pos.y + 0.5, z=state.pos.z})
|
||||
thispathpos.y = thispathpos.y - 1
|
||||
local nextpathpos = people.footpath_findnext(thispathpos, state.action.lastpathpos, false)
|
||||
if nextpathpos == "unloaded" then
|
||||
state.wait = 1
|
||||
dbg.v3(state.ent.name.." waiting for block load")
|
||||
return false
|
||||
end
|
||||
if not nextpathpos then
|
||||
dbg.v1(state.ent.name.." can't find next footpath node at "..
|
||||
minetest.pos_to_string(thispathpos).." after "..
|
||||
|
@ -118,10 +127,15 @@ people.actions.go = function(state)
|
|||
return true, false
|
||||
end
|
||||
|
||||
if not distance then distance = 10 end
|
||||
if not distance or distance > 10 then distance = 10 end
|
||||
while distance > 2 do
|
||||
-- Look ahead a bit while going in a straight line, to increase speed
|
||||
local aheadpathpos = people.footpath_findnext(nextpathpos, thispathpos, true)
|
||||
if aheadpathpos == "unloaded" then
|
||||
state.wait = 1
|
||||
dbg.v3(state.ent.name.." waiting for block load for lookahead")
|
||||
return false
|
||||
end
|
||||
if aheadpathpos then
|
||||
thispathpos = nextpathpos
|
||||
nextpathpos = aheadpathpos
|
||||
|
@ -131,7 +145,7 @@ people.actions.go = function(state)
|
|||
end
|
||||
end
|
||||
state.action.lastpathpos = thispathpos
|
||||
state.action.pos = vector.add(nextpathpos, {x=0, y=PNTP, z=0})
|
||||
state.action.pos = vector.add(nextpathpos, {x=0, y=0.5, z=0})
|
||||
dbg.v3(state.ent.name.." set next footpath dest "..minetest.pos_to_string(state.action.pos))
|
||||
return false
|
||||
|
||||
|
@ -167,7 +181,7 @@ people.actions.go = function(state)
|
|||
if pathdestarea and psdist < distance then
|
||||
state.action.endpos = state.action.pos
|
||||
state.action.pos = vector.new(pathstartarea.pos1)
|
||||
state.action.pos.y = state.action.pos.y + PNTP
|
||||
state.action.pos.y = state.action.pos.y + ANTP
|
||||
state.action.footpathdest = pathdestarea
|
||||
dbg.v2(state.ent.name.." using footpath from "..pathstartarea.name.." to "..pathdestarea.name.." for intermediate route")
|
||||
return false
|
||||
|
@ -188,12 +202,13 @@ people.actions.go = function(state)
|
|||
dbg.v2(state.ent.name.." arrived near "..minetest.pos_to_string(curdest))
|
||||
state.setpos = vector.round(curdest)
|
||||
state.setpos.y = state.pos.y
|
||||
if state.action.footpathdest or state.action.intermediate then
|
||||
-- If we arrived at the pos, but we still have a
|
||||
-- pathdest or intermediate dest, we carry on to do that.
|
||||
if state.action.footpathdest then
|
||||
state.action.pos = nil
|
||||
end
|
||||
-- If we arrived at the pos, but we still have a
|
||||
-- pathdest or intermediate dest, we carry on to do that.
|
||||
if state.action.intermediate then
|
||||
state.action.pos = state.action.intermediate[1]
|
||||
return false
|
||||
elseif state.action.footpathdest then
|
||||
state.action.pos = nil
|
||||
return false
|
||||
end
|
||||
-- We've finished!
|
||||
|
@ -215,25 +230,29 @@ people.actions.go = function(state)
|
|||
-- Apply some damage for bashing into something. Apart from being
|
||||
-- the right thing to do, it will also kill of things that get
|
||||
-- stuck in a wall. ;)
|
||||
state.damage = 0.5
|
||||
state.damage = 0.4
|
||||
end
|
||||
|
||||
if not unwholesome and distance > 1 then
|
||||
if not unwholesome and distance > 1 then
|
||||
local erk = nil
|
||||
local ahead = state.speed
|
||||
if ahead > 1 then ahead = 1 end
|
||||
local nd = vector.from_speed_yaw(ahead, state.yaw)
|
||||
local nextpos = vector.add(vector.round(state.pos), nd)
|
||||
nextpos.y = nextpos.y + 1
|
||||
nextpos.y = nextpos.y + 2
|
||||
-- How far down we'll look, which needs to be at least this to
|
||||
-- be able to descend stairs.
|
||||
local ncount = 5
|
||||
local ncount = 6
|
||||
local diags = "at:" ..minetest.pos_to_string(state.pos)
|
||||
local notwalkable = 0
|
||||
local unloaded = false
|
||||
diags = diags .. " next+1:" ..minetest.pos_to_string(nextpos)
|
||||
while ncount > 0 do
|
||||
local nn = minetest.get_node(nextpos).name
|
||||
diags = diags .. ":" .. nn
|
||||
if nn == "default:water_flowing" or nn == "default:water_source" or nn == "default:lava_flowing" or nn == "default:lava_source" then
|
||||
if nn == "ignore" then
|
||||
unloaded = true
|
||||
elseif nn == "default:water_flowing" or nn == "default:water_source" or nn == "default:lava_flowing" or nn == "default:lava_source" then
|
||||
erk = nn
|
||||
break
|
||||
end
|
||||
|
@ -242,13 +261,26 @@ people.actions.go = function(state)
|
|||
erk = "mysterious " .. nn
|
||||
break
|
||||
end
|
||||
if nd.walkable then
|
||||
if nd.walkable and ncount < 6 then
|
||||
break
|
||||
end
|
||||
if not nd.walkable then
|
||||
notwalkable = notwalkable + 1
|
||||
end
|
||||
nextpos.y = nextpos.y - 1
|
||||
ncount = ncount - 1
|
||||
end
|
||||
if ncount == 0 then erk = "fall" end
|
||||
if unloaded then
|
||||
-- If we hit an unloaded block, just wait until it loads.
|
||||
dbg.v3(state.ent.name.." waiting for unloaded to check ahead")
|
||||
state.wait = 1
|
||||
return false
|
||||
end
|
||||
if ncount == 0 then
|
||||
erk = "fall"
|
||||
elseif notwalkable < 2 then
|
||||
erk = "bump"
|
||||
end
|
||||
if erk then
|
||||
dbg.v1(state.ent.name.." aborted go due to fear of " ..
|
||||
erk .. " - " .. diags)
|
||||
|
@ -258,7 +290,17 @@ people.actions.go = function(state)
|
|||
|
||||
if unwholesome then
|
||||
if distance < 32 then
|
||||
local path = minetest.find_path(state.pos, curdest,
|
||||
|
||||
if state.action.triedpath then
|
||||
dbg.v2(state.ent.name.." is not trying a path to "..minetest.pos_to_string(curdest).." again")
|
||||
return true, false
|
||||
end
|
||||
|
||||
local spos = vector.new(state.pos)
|
||||
if state.ent.yoffset then
|
||||
spos.y = spos.y - state.ent.yoffset
|
||||
end
|
||||
local path = minetest.find_path(spos, curdest,
|
||||
distance + 16, 1, 3, "A*_noprefetch")
|
||||
if not path then
|
||||
|
||||
|
@ -272,13 +314,21 @@ people.actions.go = function(state)
|
|||
return true, false
|
||||
|
||||
else
|
||||
|
||||
if not state.action.intermediate or #state.action.intermediate > 10 then
|
||||
state.action.intermediate = {}
|
||||
end
|
||||
for i = #path, 2, -1 do
|
||||
table.insert(state.action.intermediate, 1, {x=path[i].x, y=path[i].y + PNTP, z=path[i].z})
|
||||
|
||||
-- Start following the path from the rounded position, in case
|
||||
-- we're off centre and will collide immediately...
|
||||
table.insert(state.action.intermediate, vector.round(state.pos))
|
||||
|
||||
for i = 2, #path do
|
||||
table.insert(state.action.intermediate, {x=path[i].x, y=path[i].y -0.5, z=path[i].z})
|
||||
end
|
||||
dbg.v3(state.ent.name.." found path: "..dump(path))
|
||||
|
||||
dbg.v3(state.ent.name.." found path to "..minetest.pos_to_string(curdest).." : "..dump(path))
|
||||
state.action.triedpath = true
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -307,6 +357,12 @@ people.actions.go = function(state)
|
|||
else
|
||||
state.speed = 3
|
||||
end
|
||||
|
||||
-- Apply max speed if there is one
|
||||
if state.ent.maxspeed and state.speed > state.ent.maxspeed then
|
||||
state.speed = state.ent.maxspeed
|
||||
end
|
||||
|
||||
state.yaw = vector.get_yaw(state.pos, curdest)
|
||||
|
||||
return false
|
||||
|
|
24
commands.lua
24
commands.lua
|
@ -101,6 +101,30 @@ subcmd.create = {
|
|||
end
|
||||
}
|
||||
|
||||
subcmd.forget = {
|
||||
params = "<name>",
|
||||
desc = "Completely forget the person with the given name. If activated, they will be deleted.",
|
||||
exec = function(playername, args)
|
||||
|
||||
local person, person_name
|
||||
person_name, person, args = get_person(args)
|
||||
if not person then
|
||||
return false, "Specify a valid person"
|
||||
end
|
||||
if not minetest.check_player_privs(playername, {server=true}) then
|
||||
if playername ~= ent.owner then
|
||||
return false, person_name.." isn't yours, so so can't do that"
|
||||
end
|
||||
end
|
||||
local ent = people.people[person_name].entity
|
||||
if ent then
|
||||
ent.object:remove()
|
||||
end
|
||||
people.people[person_name] = nil
|
||||
return true, "Forgot "..person_name
|
||||
end
|
||||
}
|
||||
|
||||
subcmd.delete = {
|
||||
params = "<name>",
|
||||
desc = "Delete the person with the given name",
|
||||
|
|
|
@ -240,7 +240,9 @@ end
|
|||
-- @param curpos The position of a current footpath node
|
||||
-- @param lastpos The position of the previous footpath node
|
||||
-- @param samedironly True to only look in the current direction of travel
|
||||
-- @return The position of the next footpath node, or nil
|
||||
-- @return The position of the next footpath node, or nil if there isn't
|
||||
-- one, or "unloaded" if there may or may not be one, but we can't
|
||||
-- tell because of unloaded blocks.
|
||||
people.footpath_findnext = function(curpos, lastpos, samedironly)
|
||||
--dbg.v3("footpath_findnext, cur="..minetest.pos_to_string(curpos)..", last="..minetest.pos_to_string(lastpos)..", same="..dump(samedironly))
|
||||
local xz
|
||||
|
@ -260,7 +262,9 @@ people.footpath_findnext = function(curpos, lastpos, samedironly)
|
|||
local npos = vector.add(curpos, vector.new(x, y, z))
|
||||
if not vector.equals(npos, lastpos) then
|
||||
local n = minetest.get_node(npos)
|
||||
if n.name == "ignore" then return "unloaded" end
|
||||
if n.name == 'default:cobble' or
|
||||
n.name == 'default:mossycobble' or
|
||||
n.name == 'stairs:stair_cobble' or
|
||||
n.name == 'default:wood' or
|
||||
n.name == 'stairs:stair_wood' then
|
||||
|
|
46
init.lua
46
init.lua
|
@ -141,42 +141,35 @@ minetest.register_entity("people:person" ,{
|
|||
mesh = "people_character.x",
|
||||
textures = {"people_character.png"},
|
||||
makes_footstep_sound = true,
|
||||
name = "APerson",
|
||||
owner = "",
|
||||
code = "@"..people.presets[1].name,
|
||||
|
||||
memory = {},
|
||||
|
||||
-- Current action. A table, as described in README.md
|
||||
-- Is nil when it's time for the person to select a new action.
|
||||
action = nil,
|
||||
|
||||
-- The following controls gathering, which is the digging of nodes and
|
||||
-- picking up of items, which happens in parallel with any other action.
|
||||
--
|
||||
gather = {
|
||||
nodes = {}, -- list of nodes to dig up
|
||||
topnodes = {}, -- list of topnodes to dig
|
||||
items = {}, -- list of items to pick up
|
||||
plant = nil, -- name of seed to plant, or nil
|
||||
},
|
||||
|
||||
-- Time (game time) to wait until before doing anything else
|
||||
wait = 0,
|
||||
|
||||
-- Lua environment
|
||||
env = {},
|
||||
|
||||
stepheight = 1.1,
|
||||
|
||||
-- Customised properties
|
||||
props = {},
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
|
||||
local setactive = false
|
||||
self.memory = {}
|
||||
self.env = {}
|
||||
self.props = {}
|
||||
-- The following controls gathering, which is the digging of nodes and
|
||||
-- picking up of items, which happens in parallel with any other action.
|
||||
--
|
||||
self.gather = {
|
||||
nodes = {}, -- list of nodes to dig up
|
||||
topnodes = {}, -- list of topnodes to dig
|
||||
items = {}, -- list of items to pick up
|
||||
plant = nil, -- name of seed to plant, or nil
|
||||
}
|
||||
self.name = "<new person>"
|
||||
|
||||
dbg.v3("on_activate, staticdata = "..dump(staticdata))
|
||||
local restored
|
||||
if staticdata and staticdata ~= "" then
|
||||
restored = minetest.deserialize(staticdata)
|
||||
|
@ -251,6 +244,8 @@ minetest.register_entity("people:person" ,{
|
|||
local err = people.exec_event(self, event)
|
||||
if err then dbg.v1("Lua error "..err) end
|
||||
|
||||
dbg.v3("Done on_activate for "..self.name)
|
||||
|
||||
end,
|
||||
|
||||
update_props = function(self)
|
||||
|
@ -318,11 +313,16 @@ minetest.register_entity("people:person" ,{
|
|||
on_step = function(self, dtime)
|
||||
|
||||
if self.wait ~= 0 then
|
||||
if minetest.get_gametime() < self.wait then return end
|
||||
if minetest.get_gametime() < self.wait then
|
||||
self.object:setvelocity({x=0,y=-10,z=0})
|
||||
return
|
||||
end
|
||||
dbg.v3(self.name.." finished wait at "..minetest.get_gametime())
|
||||
self.wait = 0
|
||||
end
|
||||
|
||||
local pos = self.object:getpos()
|
||||
|
||||
-- If we don't have a current action, we let the lua code choose one...
|
||||
if not self.action then
|
||||
|
||||
|
@ -333,14 +333,12 @@ minetest.register_entity("people:person" ,{
|
|||
if err then dbg.v1("Lua error "..err) end
|
||||
if not self.action then
|
||||
self.action = {"wait", time=120}
|
||||
dbg.v2(self.name.." failed to choose action - setting wait")
|
||||
dbg.v2(self.name.." failed to choose action - setting wait, at "..minetest.pos_to_string(pos))
|
||||
else
|
||||
dbg.v1(self.name.." set new action: "..dump(self.action))
|
||||
end
|
||||
end
|
||||
|
||||
local pos = self.object:getpos()
|
||||
|
||||
-- Handle gathering
|
||||
-- TODO: Only happens during go and follow currently. Can't happen
|
||||
-- during "dig" or any subaction that "dig" might set - which poses
|
||||
|
|
|
@ -37,15 +37,40 @@ if event.type == "program" then
|
|||
{"gather"},
|
||||
|
||||
|
||||
-- ********************
|
||||
-- Head f0r the cactus farm, but get some flowers on the way
|
||||
--
|
||||
{"go", name="Jeiffel Station"},
|
||||
{"gather", nodes={"flowers:geranium",
|
||||
"flowers:rose",
|
||||
"flowers:dandelion_white",
|
||||
"flowers:dandelion_yellow",
|
||||
"flowers:viola",
|
||||
"flowers:tulip"}},
|
||||
{"go", name="Cactus Approach"},
|
||||
{"gather"},
|
||||
|
||||
-- ********************
|
||||
-- Cactus Farm
|
||||
{"go", name="Cactus Farm"},
|
||||
{"wait", time=10},
|
||||
{"gather", topnodes={"default:cactus"}},
|
||||
{"go", pos={x=-40, y=11.5, z=-462}},
|
||||
{"go", pos={x=-34, y=11.5, z=-462}},
|
||||
{"go", pos={x=-34, y=11.5, z=-459}},
|
||||
{"go", pos={x=-40, y=11.5, z=-459}},
|
||||
{"go", pos={x=-40, y=11.5, z=-465}},
|
||||
{"go", pos={x=-33, y=11.5, z=-465}},
|
||||
{"go", pos={x=-34, y=11.5, z=-462}},
|
||||
{"gather"},
|
||||
{"go", name="Cactusville Square"},
|
||||
{"stash", items={"*default:cactus"}, dest="default:chest"},
|
||||
{"stash", items={"*default:cactus",
|
||||
"*flowers:geranium",
|
||||
"*flowers:rose",
|
||||
"*flowers:dandelion_white",
|
||||
"*flowers:dandelion_yellow",
|
||||
"*flowers:viola",
|
||||
"*flowers:tulip",
|
||||
}, dest="default:chest"},
|
||||
|
||||
|
||||
-- *****************
|
||||
|
@ -76,6 +101,7 @@ if event.type == "program" then
|
|||
"farming:seed_cotton 20",
|
||||
"farming_plus:carrot_seed 20",
|
||||
"farming_plus:tomato_seed 20",
|
||||
"farming_plus:potato_seed 20",
|
||||
"farming_plus:strawberry_seed 20"}},
|
||||
{"go", name="Ciaran's Farm"},
|
||||
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
if event.type == "program" then
|
||||
if not mem.cur then
|
||||
mem.positions = {pos}
|
||||
mem.cur = 1
|
||||
mem.dir = 1
|
||||
mem.wait = true
|
||||
elseif event.type == "tell" then
|
||||
if event.message == "here" then
|
||||
mem.positions = {event.senderpos}
|
||||
mem.wait = false
|
||||
mem.cur = 1
|
||||
elseif event.message == "then here" then
|
||||
table.insert(mem.positions, event.senderpos)
|
||||
end
|
||||
if not mem.dir then
|
||||
mem.dir = 1
|
||||
end
|
||||
mem.positions = {
|
||||
{x=182, y=6.5, z=214},
|
||||
"wait",
|
||||
{x=163, y=6.5, z=213},
|
||||
"wait",
|
||||
{x=163, y=6.5, z=194},
|
||||
"wait",
|
||||
{x=181, y=6.5, z=194},
|
||||
}
|
||||
|
||||
elseif event.type == "act" then
|
||||
|
||||
if mem.positions[mem.cur] ~= "wait" then
|
||||
action = {"go", pos=mem.positions[mem.cur]}
|
||||
else
|
||||
if mem.wait then
|
||||
action = {"wait", time=20}
|
||||
mem.wait = false
|
||||
return
|
||||
end
|
||||
|
||||
action = {"go", pos=mem.positions[mem.cur]}
|
||||
mem.wait = true
|
||||
mem.cur = mem.cur + mem.dir
|
||||
if mem.cur > #mem.positions then
|
||||
mem.cur = #mem.positions
|
||||
|
|
|
@ -120,7 +120,7 @@ people.people_wake = function()
|
|||
|
||||
-- Wake the entity by (yuk) setting a forceload. The activation
|
||||
-- of the entity will cause the forceload to be freed.
|
||||
dbg.v2("Set forceload for "..minetest.pos_to_string(v.pos))
|
||||
dbg.v2("Set forceload for "..minetest.pos_to_string(v.pos).." to activate "..k)
|
||||
minetest.forceload_block(v.pos)
|
||||
|
||||
-- Only one at a time, even though this will introduce some
|
||||
|
|
Loading…
Reference in New Issue