master
Ciaran Gultnieks 2015-05-24 10:25:51 +01:00
parent a5c2ff2ee1
commit eda0d51861
9 changed files with 579 additions and 183 deletions

View File

@ -104,7 +104,13 @@ functionality. When editing, select one of the presets from the dropdown and tha
preset will be used. If you subsequently select "Custom", the code from the
previously selected preset will be loaded as a base for further editing.
A brief description of these:
The presets can be reloaded from disk while the server is running, using the
chat command `/people reload_presets`. The new versions will start being used
immediately by any active person set to that preset (but obviously where a
preset has been used as a base for a "Custom" setting, that will not be
affected).
A brief description of some of the presets currently available:
####FollowOwner
When programmed, follows the programmer until they log off
@ -120,7 +126,15 @@ Responds to simple commands. Some examples:
Look at the code for more things it can do.
####RouteWalker
Follows a preset route (hard-coded, so you would want to edit it) indefinitely.
Follows a fixed route indefinitely. After programming, the person has no
route defined. To give it the first point on its route, you `/tell` it the
command "here". The place you're standing when you say that becomes the
first point on its route.
You can then follow that with any additional number of "then here" commands,
which add further points to the route.
The route is followed from start to finish, and then back the other way.
## Events
@ -240,7 +254,12 @@ Places an item (node). Must be in the inventory, and in range.
* Required parameter: pos={x,y,z}
* Required parameter: item=itemname
* Optional parameter: param2=value (e.g. for setting facedir)
* Optional parameter: againstdir={x,y,z}
* Optional parameter: againstdir={x,y,z} - this specifies a direction to the
node against which the placing will be done. If it's not specified, a
direction will automatically be figured out, if possible. Normally it's
fine to let this be figured out - you would specify it if it's essential
the node is placed against a specific one, for example, when placing a
torch against a wall.
#### stash
@ -387,6 +406,19 @@ Parameters:
towards the tunnel centre. (Try it with slabs, for
example!)
* `support_wall=item` - like support_side, but at wall level, not within.
* `sdist=n` - special things (lighting, supports) are placed in
a repeating 8 node pattern that begins where the
tunnelling starts. This can be used to shift the
start point of that. Generally 1-7 would be
specified here, if anything.
* 'openside={}` - if present, can have either left or right=true,
or both. The end (last three nodes) of the tunnel
will be left open on that/those sides.
* 'endface={} - as for openside, but after the tunneling is
complete, the person will fininsh positioned and
facing correctly to being a tunnel through that
opening. If both are specified, one is picked at
random.
#### building

View File

@ -33,12 +33,12 @@ people.actions.building = function(state)
dbg.v1(state.ent.name.." has invalid height for building action")
return true, false
end
if type(state.action.width) ~= "number" or state.action.width < 1
if type(state.action.width) ~= "number" or state.action.width < 3
or state.action.width > 15 or state.action.width % 2 == 0 then
dbg.v1(state.ent.name.." has invalid width for building action")
return true, false
end
if type(state.action.depth) ~= "number" or state.action.depth < 1
if type(state.action.depth) ~= "number" or state.action.depth < 3
or state.action.depth > 15 then
dbg.v1(state.ent.name.." has invalid depth for building action")
return true, false
@ -91,7 +91,18 @@ people.actions.building = function(state)
if wallpos then
for y = 0, state.action.height - 1 do
local hh = state.action.height
if not state.action.ceiling then
hh = hh - 1
end
for y = 0, hh do
local placeitem = state.action.wall
if y == hh then
placeitem = state.action.ceiling
end
local thisoff = {x=wallpos.x, y=y, z=wallpos.z}
local woff = rotate(thisoff, state.action.dir)
local thispos = vector.add(state.pos, woff)
@ -122,14 +133,15 @@ people.actions.building = function(state)
todir = {x=-1,y=0,z=0}
todir = rotate(todir, state.action.dir)
state.action = {"place", pos=thispos,
item=state.action.wall,
item=placeitem,
successaction=state.action,
againstdir=todir}
return false
elseif y >= starty and dignode.name == "air" then
state.action = {"place", pos=thispos, item=state.action.wall, successaction=state.action}
state.action = {"place", pos=thispos, item=placeitem,
successaction=state.action}
return false
elseif (y >= starty and dignode.name ~= state.action.wall)
elseif (y >= starty and dignode.name ~= placeitem)
or (y < starty and dignode.name ~= "air" and
dignode.name:sub(1, state.action.door:len())
~= state.action.door) then

View File

@ -12,6 +12,10 @@ local ANTP = -0.5
-- This is all very messy and needs rationalising!!
local PNTP = 0.5
-- Maximum distance from a destination at which we will attempt to use
-- pathfinding (e.g. after a collision)
local MAX_PATH_DIST = 48
people.actions.go = function(state)
if state.action.rel then
@ -37,10 +41,10 @@ people.actions.go = function(state)
if pathdestpos then
dbg.v2(state.ent.name.." selected path destination "..state.action.name)
-- Find the nearest footpath junction to us. We'll head to that
-- first (as a pos) and then follow the footpath network from
-- there.
-- there. (Note, the nearest junction could be the destination,
-- and that's ok!)
local pathstartnode = footpath.nearest_junction(state.pos)
if pathstartnode then
dbg.v2(state.ent.name.." selected path start "..pathstartnode.name.." at "..minetest.pos_to_string(pathstartnode.pos))
@ -70,8 +74,9 @@ people.actions.go = function(state)
if not state.action.pos and state.action.footpathdest then
-- path handling - only comes here when we've arrived at a new path square
-- (note, the range passed to nearest_junction determines our lookahead distance
-- path handling - only comes here when we've arrived at a new path
-- square (note, the range passed to nearest_junction determines our
-- lookahead distance
dbg.v3(state.ent.name.." at new footpath node at "..minetest.pos_to_string(state.pos))
local curpathnode, distance = footpath.nearest_junction(state.pos, nil, 10)
if curpathnode and curpathnode.pos.x == state.pos.x and curpathnode.pos.z == state.pos.z then
@ -300,7 +305,7 @@ people.actions.go = function(state)
-- We've hit something...
-- Apply some damage for bashing into something. Apart from being
-- the right thing to do, it will also kill of things that get
-- the right thing to do, it will also kill off things that get
-- stuck in a wall. ;)
state.damage = 0.4
end
@ -379,11 +384,12 @@ people.actions.go = function(state)
end
if unwholesome then
if distance < 32 then
if distance <= MAX_PATH_DIST then
if state.action.triedpath then
state.action.triedpath = false
dbg.v2(state.ent.name.." is waiting before trying a path again ")
state.action.intermediate = nil
state.action = {"wait", time=30, prevaction=state.action}
return false
end
@ -407,9 +413,7 @@ people.actions.go = function(state)
else
if not state.action.intermediate or #state.action.intermediate > 10 then
state.action.intermediate = {}
end
state.action.intermediate = {}
-- Start following the path from the rounded position, in case
-- we're off centre and will collide immediately...

View File

@ -45,7 +45,9 @@ people.actions.obtain = function(state)
local where = nil
if state.action.item == "default:wood" then
where = "Building Supplies 2"
elseif state.action.item == "default:stone" then
elseif state.action.item == "default:stone" or
state.action.item == "default:stonebrick" or
state.action.item == "default:cobble" then
where = "Building Supplies 1"
end
if where then

View File

@ -46,30 +46,44 @@ people.actions.place = function(state)
end
-- We need a node to build against...
local todir = state.action.againstdir
if not todir then
local trydirs
if state.action.againstdir then
trydirs = {againstdir}
else
trydirs = {{x=0, y=-1, z=0},
{x=0, y=1, z=0},
{x=-1, y=0, z=0},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=0, y=0, z=1}}
end
for _, trydir in pairs(trydirs) do
local n = minetest.get_node(vector.add(state.action.pos, trydir))
if n.name ~= "air" then
todir = trydir
break
local trydirs, todir
if state.action.againstdir then
trydirs = {state.action.againstdir}
else
trydirs = {{x=0, y=-1, z=0},
{x=0, y=1, z=0},
{x=-1, y=0, z=0},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=0, y=0, z=1}}
end
local reasons = ""
for _, trydir in pairs(trydirs) do
local n = minetest.get_node(vector.add(state.action.pos, trydir))
-- Certainly can't place against air (but maybe that's covered
-- by buildable_to? Check TODO
if n.name ~= "air" then
-- Don't try and place a slab against a slab of the same kind,
-- because they can end up combinining
if n.name:sub(1, 11) == "stairs:slab" and
n.name == state.action.item then
reasons = reasons.."/similar slab at "..minetest.pos_to_string(trydir)
else
local def = minetest.registered_nodes[n.name]
if def and not def.buildable_to then
todir = trydir
break
else
reasons = reasons.."/unknown or buildable_to node at "..minetest.pos_to_string(trydir)
end
end
else
reasons = reasons.."/air at "..minetest.pos_to_string(trydir)
end
if not todir then
dbg.v1(state.ent.name.." can't place - nothing to build against")
return true, false
end
end
if not todir then
dbg.v1(state.ent.name.." can't place - nothing to build against : "..reasons)
return true, false
end
local pointed_thing = {type="node",

View File

@ -24,7 +24,7 @@ people.actions.tunnel = function(state)
dbg.v1(state.ent.name.." has invalid dir for tunnel action")
return true, false
end
if state.action.dir.y ~= 0 then
if math.abs(state.action.dir.y) > 1 then
dbg.v1(state.ent.name.." has invalid y component of dir for tunnel action")
return true, false
end
@ -41,7 +41,31 @@ people.actions.tunnel = function(state)
state.action.startdist = state.action.distance
end
if(state.action.distance <= 0) then
if state.action.distance <= 0 then
if state.action.endface then
local endoff = {y=0, z=-1}
local endface = {y=0, z=-1}
if state.action.endface.left and state.action.endface.right then
if math.random() < 0.5 then
endoff.x = -1
else
endoff.x = 1
end
elseif state.action.endface.left then
endoff.x = -1
elseif state.action.endface.right then
endoff.x = 1
end
endface.x = 2 * endoff.x
endoff = rotate(endoff, state.action.dir)
endface = rotate(endface, state.action.dir)
state.action.endface = nil
state.action = {"go", rel=endoff, successaction={"face",
pos=vector.add(state.pos, endface),
successaction=state.action}}
return false
end
dbg.v1(state.ent.name.." completed tunnelling")
return true, true
end
@ -57,13 +81,6 @@ people.actions.tunnel = function(state)
digpos.y = digpos.y - 1
end
local relxaxis
if state.action.dir.x == 0 then
relxaxis = "x"
else
relxaxis = "z"
end
local height = 2
if state.action.dir.y ~= 0 then
if state.action.steps then
@ -73,6 +90,15 @@ people.actions.tunnel = function(state)
end
end
-- Work out if either or both sides of the tunnel should be open at
-- this point...
local leftopen = false
local rightopen = false
if state.action.distance < 4 and state.action.openside then
if state.action.openside.left then leftopen = true end
if state.action.openside.right then rightopen = true end
end
-- Make it so we dig from top to bottom when tunnelling downwards, and
-- bottom to top otherwise.
local yfrom, yto, ydir
@ -87,20 +113,31 @@ people.actions.tunnel = function(state)
end
-- "Special" positions are those where supports and lighting are placed
local special_sup = (state.action.startdist - state.action.distance + 2) % 8 == 7
local special_light = (state.action.startdist - state.action.distance) % 4 == 3
local sdist = 0
if state.action.sdist then
sdist = state.action.sdist
end
local special_sup = (state.action.startdist - state.action.distance - sdist + 2) % 8 == 7
local special_light = (state.action.startdist - state.action.distance - sdist) % 4 == 3
-- TODO - the following is all a bit ineffecient, because we look at the
-- whole cross-section every time through. We could keep track of
-- where we've got to during a run and skip some.
-- On the other hand, there are things like falling gravel and
-- sand to take into account.
for y = yfrom, yto, ydir do
for x = -1, 1 do
local thisoff = {x=0, y=y, z=0}
thisoff[relxaxis] = x
local thisoff = rotate({x=x, y=y, z=0}, state.action.dir)
local thispos = vector.add(digpos, thisoff)
local dignode = minetest.get_node(thispos)
local openside = false
if (x == -1 and leftopen) or
(x == 1 and rightopen) then
openside = true
end
-- Steps at the bottom row if needed.
if y == 0 and state.action.steps and state.action.dir.y ~= 0 then
@ -113,7 +150,8 @@ people.actions.tunnel = function(state)
return false
end
elseif y == 2 and x ~= 0 and state.action.lighting and special_light then
elseif y == 2 and x ~= 0 and not openside and state.action.lighting
and special_light then
-- We don't actually place lighting (e.g. torches) here,
-- because we do walls later and that would disturb them.
@ -124,7 +162,8 @@ people.actions.tunnel = function(state)
return false
end
elseif y == height and state.action.support_top and special_sup then
elseif y == height and not openside and state.action.support_top
and special_sup then
if dignode.name == "air" then
state.action = {"place", pos=thispos, item=state.action.support_top, successaction=state.action}
@ -134,29 +173,13 @@ people.actions.tunnel = function(state)
return false
end
elseif x ~= 0 and state.action.support_side and special_sup then
elseif x ~= 0 and not openside and state.action.support_side
and special_sup then
if dignode.name == "air" then
local param2
if state.action.support_side_facein then
local facevec = rotate({x=-x, y=0, z=0},
state.action.dir)
if facevec.x > 0 then
param2 = 4 * 4
elseif facevec.x < 0 then
param2 = 4 * 3
elseif facevec.z > 0 then
param2 = 4 * 2
else
param2 = 4 * 1
end
end
state.action = {"place", pos=thispos,
item=state.action.support_side,
successaction=state.action,
param2=param2}
return false
elseif dignode.name ~= state.action.support_side then
-- As with lighting, we don't actually put in the side supports
-- now, because they're placed against the wall which we might
-- not have done yet.
if dignode.name ~= "air" and dignode.name ~= state.action.support_side then
state.action = {"dig", pos=thispos, successaction=state.action}
return false
end
@ -175,8 +198,7 @@ people.actions.tunnel = function(state)
if state.action.floor and state.action.dir.y == 0 then
for x = -1, 1 do
local thisoff = {x=0, y=-1, z=0}
thisoff[relxaxis] = x
local thisoff = rotate({x=x, y=-1, z=0}, state.action.dir)
local thispos = vector.add(digpos, thisoff)
local dignode = minetest.get_node(thispos)
if dignode.name == "air" then
@ -195,11 +217,18 @@ people.actions.tunnel = function(state)
wall = state.action.support_wall
end
if wall then
if wall and not (leftopen and rightopen) then
local sx = -2
local fx = 2
if leftopen then
sx = fx
elseif rightopen then
fx = sx
end
for y = 0, height + 1 do
local thisoff = {x=0, y=y, z=0}
for x = -2, 2, 4 do
thisoff[relxaxis] = x
for x = sx, fx, 4 do
thisoff = rotate({x=x, y=y, z=0}, state.action.dir)
local thispos = vector.add(digpos, thisoff)
local dignode = minetest.get_node(thispos)
if dignode.name == "air" then
@ -213,15 +242,23 @@ people.actions.tunnel = function(state)
end
end
if state.action.lighting and special_light then
local thisoff = {x=0, y=2, z=0}
for x = -1, 1, 2 do
thisoff[relxaxis] = x
if state.action.lighting and special_light and
not (leftopen and rightopen) and
people.is_carrying(state.ent, state.action.lighting) > 0 then
local sx = -1
local fx = 1
if leftopen then
sx = fx
elseif rightopen then
fx = sx
end
for x = sx, fx, 2 do
local thisoff = rotate({x=x, y=2, z=0}, state.action.dir)
local thispos = vector.add(digpos, thisoff)
local dignode = minetest.get_node(thispos)
if dignode.name ~= state.action.lighting then
local againstdir = {x=0, y=0, z=0}
againstdir[relxaxis] = x
local againstdir = rotate({x=x, y=0, z=0}, state.action.dir)
state.action = {"place", pos=thispos, item=state.action.lighting, successaction=state.action,
againstdir=againstdir}
return false
@ -230,24 +267,64 @@ people.actions.tunnel = function(state)
end
if state.action.support_side and special_sup and
not (leftopen and rightopen) and
people.is_carrying(state.ent, state.action.support_side) > 0 then
local sx = -1
local fx = 1
if leftopen then
sx = fx
elseif rightopen then
fx = sx
end
local sy = 0
if state.action.steps then
sy = 1
end
for y = sy, height do
for x = sx, fx, 2 do
thisoff = rotate({x=x, y=y, z=0}, state.action.dir)
local thispos = vector.add(digpos, thisoff)
local dignode = minetest.get_node(thispos)
if dignode.name ~= state.action.support_side then
local param2
if state.action.support_side_facein then
local facevec = rotate({x=-x, y=0, z=0},
state.action.dir)
if facevec.x > 0 then
param2 = 4 * 3
elseif facevec.x < 0 then
param2 = 4 * 4
elseif facevec.z > 0 then
param2 = 4 * 1
else
param2 = 4 * 2
end
end
state.action = {"place", pos=thispos,
item=state.action.support_side,
successaction=state.action,
param2=param2}
return false
end
end
end
end
local ceiling = state.action.ceiling
if special_sup and state.action.support_ceiling then
ceiling = state.action.support_ceiling
end
if ceiling then
-- We need to place the ceiling nodes against something - we use
-- the walls.
local againstdir = {x=0, y=0, z=0}
againstdir[relxaxis] = -1
for x = -1, 1 do
local thisoff = {x=0, y=height+1, z=0}
thisoff[relxaxis] = x
local thisoff = rotate({x=x, y=height+1, z=0}, state.action.dir)
local thispos = vector.add(digpos, thisoff)
local dignode = minetest.get_node(thispos)
if dignode.name == "air" then
state.action = {"place", pos=thispos, item=ceiling, successaction=state.action,
againstdir=againstdir}
state.action = {"place", pos=thispos, item=ceiling,
successaction=state.action}
return false
elseif dignode.name ~= ceiling then
state.action = {"dig", pos=thispos, successaction=state.action}

View File

@ -56,6 +56,20 @@ subcmd.help = {
end
}
subcmd.reload_presets = {
params = "none",
desc = "Reload the presets from disk",
exec = function(playername, args)
if not minetest.check_player_privs(playername, {server=true}) then
return false, "Only admins can reload presets"
end
people.load_presets()
return true, "Reloaded presets"
end
}
subcmd.create = {
params = "<name>",
desc = "Create a person with the given name at your current location",
@ -211,7 +225,7 @@ subcmd.attach = {
if not ent then
return false, nil, true
end
player:set_attach(ent.object, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
player:set_attach(ent.object, "", {x=0,y=1,z=0}, {x=0,y=0,z=0})
return true, "Attached to "..person_name
end
}

View File

@ -38,24 +38,26 @@ dofile(people_modpath .. "/actions/tunnel.lua")
dofile(people_modpath .. "/actions/building.lua")
dofile(people_modpath .. "/actions/claimplot.lua")
people.presets = {}
for p, priv in pairs({FollowOwner=false,
SimpleCommands=false,
RouteWalker=false,
FarmHand=true,
CowTest=true,
Miner=true,
TreeFarmer=true}) do
local file = io.open(minetest.get_modpath("people").."/presets/"..p..".lua", "r")
local code
if file then
code = file:read("*all")
else
code = "MISSING"
people.load_presets = function()
people.presets = {}
for p, priv in pairs({FollowOwner=false,
SimpleCommands=false,
RouteWalker=false,
FarmHand=true,
CowTest=true,
Miner=true,
TreeFarmer=true}) do
local file = io.open(minetest.get_modpath("people").."/presets/"..p..".lua", "r")
local code
if file then
code = file:read("*all")
else
code = "MISSING"
end
table.insert(people.presets, {code=code, name=p, priv=priv})
end
table.insert(people.presets, {code=code, name=p, priv=priv})
end
people.load_presets()
people.is_valid_name = function(name)
if not name then return false end
@ -711,6 +713,18 @@ local code_prohibited = function(code)
end
end
people.is_carrying = function(ent, item)
local inv = ent.inventory
local count = 0
for i, stack in ipairs(inv:get_list("main")) do
local nn = stack:get_name()
if nn == item then
count = count + stack:get_count()
end
end
return count
end
people.exec_event = function(ent, event)
dbg.v3(ent.name.." exec event "..minetest.serialize(event))
@ -732,15 +746,7 @@ people.exec_event = function(ent, event)
env.gather = ent.gather
env.mem = ent.memory
env.carrying = function(item)
local inv = ent.inventory
local count = 0
for i, stack in ipairs(inv:get_list("main")) do
local nn = stack:get_name()
if nn == item then
count = count + stack:get_count()
end
end
return count
return people.is_carrying(ent, item)
end
env.has_money = function()
local inv = ent.inventory

View File

@ -7,11 +7,28 @@ local MODE_minebuilding = 5 -- Build the mine building
local MODE_homebuilding = 6 -- Build a home
local MODE_panic = 7 -- Don't know what to do
-- Items we sell, and (f0r now?) where to sell them
local sell_items = {
{item="default:iron_lump", shop="Mineral Shop"},
{item="default:copper_lump", shop="Mineral Shop"},
{item="default:gold_lump", shop="Mineral Shop"},
{item="default:mese_crystal", shop="Mineral Shop"},
{item="default:diamond", shop="Mineral Shop"},
-- Want to sell excess default:coal_lump, but the sell action
-- only allows selling all currently - TODO
}
local inventory_actions = {
-- All these have a prevaction on to prevent them raising errors.
-- We still (probably) want to try and carry on mining if we're
-- missing some materials - maybe we'll be able to get them later.
--
-- Note that many of these would be automatically obtained via
-- the 'needed' system. But f0r now, unt1l that's more intelligent
-- we do these basics in order here, because e.g. if a torch is
-- needed, the best thing to do is use wood to make sticks to make
-- the torches.
{"obtain", item="stairs:stair_cobble", num=40, prevaction={"wait", time=1}},
{"obtain", item="default:stone", num=40, prevaction={"wait", time=1}},
{"obtain", item="default:wood", num=40, prevaction={"wait", time=1}},
@ -28,8 +45,6 @@ local inventory_actions = {
}
}},
{"go", name="Miner Willy's"}
}
if event.type == "program" then
@ -66,20 +81,43 @@ elseif event.type == "act" then
if mem.mode == MODE_selling then
if carrying("default:iron_lump") > 0 then
action = {"go", name="Mineral Shop", successaction={"sell", item="default:iron_lump"}}
if mem.cur > #sell_items then
action = {"wait", time=0.5}
mem.mode = MODE_inventory
mem.cur = 1
return
end
-- TODO - need to sell excess coal here, but the sell action currently
-- doesn't allow an amount to be specified, so we'd sell it all!
mem.mode = MODE_inventory
mem.cur = 1
action = {"wait", time=1}
local item = sell_items[mem.cur].item
if carrying(item) > 0 then
action = {"go", name=sell_items[mem.cur].shop,
successaction={"sell", item=item,
prevaction={"wait", time=5}}}
else
action = {"wait", time=0.5}
end
mem.cur = mem.cur + 1
return
elseif mem.mode == MODE_inventory then
if #mem.needed > 0 then
action={"obtain", item=mem.needed[1], num=1, prevaction={"wait", time=1}}
local needitem = mem.needed[1]
local neednum = 1
-- When we need an item, sometimes we'll make a guess that
-- we'll need lots of it, to avoid going backwards and
-- f0rwards...
if needitem == "default:cobble" or
needitem == "default:wood" or
needitem == "default:stonebrick" or
needitem == "default:torch" or
needitem == "default:stick" or
needitem == "stairs:slab_wood" or
needitem == "stairs:stair_cobble" then
neednum = 20
end
action={"obtain", item=needitem, num=neednum,
prevaction={"wait", time=1}}
table.remove(mem.needed, 1)
return
end
@ -93,7 +131,7 @@ elseif event.type == "act" then
elseif mem.lastxmode == MODE_mining then
mem.mode = MODE_homebuilding
elseif mem.lastxmode == MODE_homebuilding then
mem.mode = MODE_mining
mem.mode = MODE_minebuilding
end
mem.lastxmode = mem.mode
mem.cur = 1
@ -101,63 +139,247 @@ elseif event.type == "act" then
elseif mem.mode == MODE_mining then
-- Select some materials to fancy up the tunnel, if we're carrying
-- them. If not, we'll do it without them and they'll get done
-- another time, but in the meantime we'll at least dig the basic
-- tunnel, which should get us the materials/money to get the
-- fancy stuff!
local steps = nil
local wall_and_floor = nil
local support_c = nil
local support_s = nil
local lighting = nil
if carrying("stairs:stair_cobble") > 3 then
steps = "stairs:stair_cobble"
end
if carrying("default:stone") > 10 then
wall_and_floor = "default:stone"
end
if carrying("default:wood") > 3 then
support_c = "default:wood"
end
-- We can set the following two regardless - the tunnel action only
-- places them when carried, and will proceed if they're not.
support_s = "stairs:slab_wood"
lighting = "default:torch"
local mine_jctname = "people_"..name.."_mine"
if mem.cur == 1 then
action = {"go", name="Miner Willy's",
successaction={"gather", items={"default:torch"}}}
mem.exitmine = {}
-- Attempt to claim our plot. If we already have it, this will fail
-- and we'll just do the wait.
action = {"claimplot", name=mine_jctname, prevaction={"wait", time=1}}
mem.cur = 2
elseif mem.cur == 2 then
action = {"go", name=mine_jctname, faceexit="@build"}
mem.cur = 3
elseif mem.cur == 3 then
-- Select some materials to fancy up the tunnel, if we're carrying
-- them. If not, we'll do it without them and they'll get done
-- another time.
local steps = nil
local wall_and_floor = nil
local support_c = nil
local support_s = nil
local lighting = nil
if carrying("stairs:stair_cobble") > 3 then
steps = "stairs:stair_cobble"
if carrying("default:wood") > 3 then
support_c = "default:wood"
end
if carrying("stairs:slab_wood") > 3 then
support_s = "stairs:slab_wood"
end
if carrying("default:stone") > 10 then
wall_and_floor = "default:stone"
end
end
if carrying("default:torch") > 1 then
lighting = "default:torch"
end
-- We'd better be facing the right way!!
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action = {"tunnel", distance=40, dir={x=0,y=-1,z=-1}, steps=steps,
-- In case we have a door on the mine, we'll put an exit
-- route inside and then outside. Pathfinding blocks on
-- doors, and if we crash on the way out we might need
-- it.
table.insert(mem.exitmine, {"go", name=mine_jctname})
table.insert(mem.exitmine, {"go", pos=vector.add(pos,
vector.add(bdir, bdir))})
action = {"go", rel=bdir}
action.successaction = {"gather", items={"default:torch"}}
action.successaction.successaction = {"tunnel", distance=40,
dir={x=bdir.x, y=-1, z=bdir.z}, steps=steps,
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
wall=wall_and_floor, floor=wall_and_floor}
action.successaction= {"tunnel", distance=8, dir={x=0,y=0,z=-1},
lighting=lighting, floor=wall_and_floor,
wall=wall_and_floor, floor=wall_and_floor,
ceiling=wall_and_floor}
action.successaction.successaction={"go", rel={x=1,y=0,z=2}}
table.insert(mem.exitmine, {"go", name="Miner Willy's"})
mem.cur = 3
elseif mem.cur == 3 then
action = {"tunnel", distance=20, dir={x=1,y=-1,z=0}, steps="stairs:stair_cobble",
lighting="default:torch", wall="default:stone", floor="default:stone"}
action.successaction=
{"tunnel", distance=8, dir={x=1,y=0,z=0}, lighting="default:torch", successaction=
{"go", rel={x=-1,y=0,z=1}} }
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, {x=1,y=0,z=0})})
action.successaction.successaction.successaction =
{"tunnel", distance=7, sdist=4,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor,
openside={left=true},
endface={left=true}}
mem.cur = 4
elseif mem.cur == 4 then
-- 4 is go down, and take a left turn to do it again
if pos.y < -200 then
mem.mode = MODE_exitmine
mem.cur = #mem.exitmine
action = {"wait", time=1}
return
end
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action = {"tunnel", distance=20,
dir={x=bdir.x, y=-1, z=bdir.z}, steps=steps,
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
wall=wall_and_floor, floor=wall_and_floor,
ceiling=wall_and_floor}
action.successaction =
{"tunnel", distance=7, sdist=4,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor,
openside={left=true, right=true},
endface={left=true}}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
if math.random() < 0.5 then
mem.cur = 5
end
elseif mem.cur == 5 then
-- 5 is go down, and take a right turn to mine on that level
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action = {"tunnel", distance=20,
dir={x=bdir.x, y=-1, z=bdir.z}, steps=steps,
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
wall=wall_and_floor, floor=wall_and_floor,
ceiling=wall_and_floor}
action.successaction =
{"tunnel", distance=7, sdist=4,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor,
openside={left=true, right=true},
endface={right=true}}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
mem.cur = 6
elseif mem.cur == 6 then
-- 6 is the very short tunnel to the right of the 'landing'
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action =
{"tunnel", distance=4, sdist=6,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor,
openside={right=true},
endface={right=true}}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
mem.cur = 7
elseif mem.cur == 7 then
-- 7 is the slightly longer tunnel taking us back in the opposite
-- direction to the stairs
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action =
{"tunnel", distance=13,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor,
openside={right=true},
endface={right=true}}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
mem.cur = 8
elseif mem.cur == 8 then
-- 8 is the first part of the cross-ways tunnel taking us under the
-- stairs (and also far enough to clear the other stairs when we
-- cross above)
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action =
{"tunnel", distance=9,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
mem.cur = 9
mem.cur_sections9 = 0
elseif mem.cur == 9 then
-- 9 is all subsequent parts of the cross-ways tunnel, with a choice
-- of three branches at the end of each
mem.cur_sections9 = mem.cur_sections9 + 1
local nxt = 9
if mem.cur_sections9 > 8 then
nxt = 99
end
local ef = nil
local r = math.random()
if r < 0.33 then
ef = {left=true}
nxt = 10
elseif r < 0.66 then
ef = {right=true}
nxt = 10
end
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action =
{"tunnel", distance=4,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor,
openside={left=true, right=true},
endface=ef}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
mem.cur = nxt
elseif mem.cur == 10 then
-- 10 is a long sideways shoot from the crossways tunnel (either
-- direction)
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action =
{"tunnel", distance=15,
dir={x=bdir.x,y=0,z=bdir.z},
lighting=lighting, support_ceiling=support_c,
support_side=support_s,
support_side_facein=true,
ceiling=wall_and_floor, floor=wall_and_floor,
wall=wall_and_floor}
table.insert(mem.exitmine, {"go", pos=vector.subtract(pos, bdir)})
mem.cur = 99
elseif mem.cur == 99 then
mem.mode = MODE_exitmine
mem.cur = #mem.exitmine
action = {"wait", time=1}
return
end
elseif mem.mode == MODE_exitmine then
@ -173,18 +395,30 @@ elseif event.type == "act" then
elseif mem.mode == MODE_minebuilding then
local mine_jctname = "people_"..name.."_mine"
if mem.cur == 1 then
action = {"go", name="Miner Willy's"}
-- Attempt to claim our plot. If we already have it, this will fail
-- and we'll just do the wait.
action = {"claimplot", name=mine_jctname, prevaction={"wait", time=1}}
mem.cur = 2
elseif mem.cur == 2 then
action = {"building", dir={x=0,y=-1,z=-1},
action = {"go", name=mine_jctname, faceexit="@build"}
mem.cur = 3
elseif mem.cur == 3 then
-- We'd better be facing the right way!!
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action= {"go", rel=bdir}
action.successaction = {"building", dir=bdir,
width=5, depth=7, height=5,
wall="default:stone",
ceiling="default:wood",
outside_floor={"default:dirt", "default:dirt_with_grass"},
door="doors:door_wood"
}
mem.cur = 3
mem.cur = 4
else
mem.mode = MODE_selling
mem.cur = 1
@ -208,10 +442,12 @@ elseif event.type == "act" then
-- We'd better be facing the right way!!
local bdir = vector.round(vector.from_speed_yaw(1, yaw))
action = {"building", dir=bdir,
width=5, depth=5, height=4,
wall="default:stone",
action = {"go", rel=bdir}
action.successaction = {"building", dir=bdir,
width=7, depth=7, height=4,
wall="default:stonebrick",
ceiling="default:wood",
floor="default:wood",
outside_floor={"default:dirt", "default:dirt_with_grass"},
door="doors:door_wood"
}
@ -226,6 +462,5 @@ elseif event.type == "act" then
action = {"wait", time=600}
end
end