space_to_tab

This commit is contained in:
tacigar 2016-09-13 09:44:16 +09:00
parent 7887bc7b95
commit a46a55446f
10 changed files with 621 additions and 622 deletions

View File

@ -7,8 +7,8 @@ maidroid._aux = {}
-- get inventory of the maidroid -- get inventory of the maidroid
function maidroid._aux.get_maidroid_inventory(self) function maidroid._aux.get_maidroid_inventory(self)
return minetest.get_inventory{ return minetest.get_inventory{
type = "detached", type = "detached",
name = self.invname, name = self.invname,
} }
end end

258
api.lua
View File

@ -7,11 +7,11 @@ local _aux = maidroid._aux
-- aux function to generate serialnumber for inventories -- aux function to generate serialnumber for inventories
local gen_inv_serialnumber = (function () local gen_inv_serialnumber = (function ()
local serialnumber = 0 local serialnumber = 0
return function () return function ()
serialnumber = serialnumber + 1 serialnumber = serialnumber + 1
return serialnumber - 1 return serialnumber - 1
end end
end) () end) ()
local main_invsize = 16 local main_invsize = 16
@ -23,140 +23,140 @@ local module_invname = "module"
maidroid.registered_modules = {} maidroid.registered_modules = {}
function maidroid.register_module(module_name, def) function maidroid.register_module(module_name, def)
maidroid.registered_modules[module_name] = def maidroid.registered_modules[module_name] = def
minetest.register_craftitem(module_name, { minetest.register_craftitem(module_name, {
description = def.description, description = def.description,
stack_max = 1, stack_max = 1,
inventory_image = def.inventory_image, inventory_image = def.inventory_image,
}) })
end end
-- animation frame -- animation frame
maidroid.animations = { maidroid.animations = {
stand = {x = 0, y = 79}, stand = {x = 0, y = 79},
lay = {x = 162, y = 166}, lay = {x = 162, y = 166},
walk = {x = 168, y = 187}, walk = {x = 168, y = 187},
mine = {x = 189, y = 198}, mine = {x = 189, y = 198},
walk_mine = {x = 200, y = 219}, walk_mine = {x = 200, y = 219},
sit = {x = 81, y = 160}, sit = {x = 81, y = 160},
} }
function maidroid.register_maidroid(product_name, def) function maidroid.register_maidroid(product_name, def)
minetest.register_entity(product_name, { minetest.register_entity(product_name, {
hp_max = def.hp_max or 1, hp_max = def.hp_max or 1,
physical = true, physical = true,
weight = def.weight or 5, weight = def.weight or 5,
collistionbox = def.collistionbox or { -0.35, -0.5, -0.35, 0.35, 1.1, 0.35 }, collistionbox = def.collistionbox or { -0.35, -0.5, -0.35, 0.35, 1.1, 0.35 },
visual = "mesh", visual = "mesh",
visual_size = {x = 10, y = 10}, visual_size = {x = 10, y = 10},
mesh = def.mesh or "maidroid.b3d", mesh = def.mesh or "maidroid.b3d",
textures = def.textures or {"maidroid.png"}, textures = def.textures or {"maidroid.png"},
is_visible = true, is_visible = true,
makes_footstep_sound = true, makes_footstep_sound = true,
module = nil, module = nil,
invname = "", invname = "",
on_activate = function(self, staticdata) on_activate = function(self, staticdata)
self.invname = "maidroid"..tostring(gen_inv_serialnumber()) self.invname = "maidroid"..tostring(gen_inv_serialnumber())
local inv = minetest.create_detached_inventory(self.invname, { local inv = minetest.create_detached_inventory(self.invname, {
on_put = function(inv, listname, index, stack, player) on_put = function(inv, listname, index, stack, player)
if listname == module_invname then if listname == module_invname then
local module_name = stack:get_name() local module_name = stack:get_name()
local module_def = maidroid.registered_modules[module_name] local module_def = maidroid.registered_modules[module_name]
self.module = module_def self.module = module_def
module_def.initialize(self) module_def.initialize(self)
end end
end,
allow_put = function(inv, listname, index, stack, player)
local item_name = stack:get_name()
local is_module = maidroid.registered_modules[item_name]
if listname == main_invname
or (listname == module_invname and is_module) then
return stack:get_count()
end
return 0
end,
on_take = function(inv, listname, index, stack, player)
if listname == module_invname then
local module_name = stack:get_name()
local module_def = maidroid.registered_modules[module_name]
self.module = nil
module_def.finalize(self)
end
end,
})
inv:set_size(main_invname, main_invsize)
inv:set_size(module_invname, module_invsize)
-- process staticdata
if staticdata ~= "" then
local data = minetest.deserialize(staticdata)
if data.inv.module ~= "" then
module_stack = ItemStack(data.inv.module)
module_stack:set_count(1)
inv:add_item(module_invname, module_stack)
self.module = maidroid.registered_modules[data.inv.module]
end
for _, item in ipairs(data.inv.main) do
local itemstack = ItemStack(item.name)
itemstack:set_count(item.count)
inv:add_item(main_invname, itemstack)
end
end
-- initialize module
if self.module then self.module.initialize(self)
else
self.object:setvelocity{x = 0, y = 0, z = 0}
self.object:setacceleration{x = 0, y = -10, z = 0}
end
end, end,
allow_put = function(inv, listname, index, stack, player)
local item_name = stack:get_name() on_step = function(self, dtime)
local is_module = maidroid.registered_modules[item_name] if self.module then self.module.on_step(self, dtime) end
if listname == main_invname
or (listname == module_invname and is_module) then
return stack:get_count()
end
return 0
end, end,
on_take = function(inv, listname, index, stack, player)
if listname == module_invname then on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
local module_name = stack:get_name()
local module_def = maidroid.registered_modules[module_name]
self.module = nil
module_def.finalize(self)
end
end, end,
})
inv:set_size(main_invname, main_invsize) on_rightclick = function(self, clicker)
inv:set_size(module_invname, module_invsize) local formspec = "size[8,9]"
-- process staticdata .."list[detached:"..self.invname..";"..main_invname..";0,0;4,4;]"
if staticdata ~= "" then .."label[5,0;MODULE]"
local data = minetest.deserialize(staticdata) .."list[detached:"..self.invname..";"..module_invname..";6,0;1,1;]"
if data.inv.module ~= "" then .."list[current_player;"..main_invname..";0,5;8,1;]"
module_stack = ItemStack(data.inv.module) .."list[current_player;"..main_invname..";0,6.2;8,3;8]"
module_stack:set_count(1) minetest.show_formspec(clicker:get_player_name(), self.invname, formspec)
inv:add_item(module_invname, module_stack) end,
self.module = maidroid.registered_modules[data.inv.module]
get_staticdata = function(self)
local inv = _aux.get_maidroid_inventory(self)
local staticdata = {}
staticdata.inv = {}
local module_name = inv:get_list(module_invname)[1]:get_name()
staticdata.inv.module = module_name or ""
staticdata.inv.main = {}
for _, item in ipairs(inv:get_list(main_invname)) do
local count = item:get_count()
local itemname = item:get_name()
if count ~= 0 then
local itemdata = { count = count, name = itemname }
table.insert(staticdata.inv.main, itemdata)
end
end
return minetest.serialize(staticdata)
end,
})
-- register spawn egg
minetest.register_craftitem(product_name.."_spawn_egg", {
description = def.description.." Spawn Egg",
inventory_image = def.inventory_image,
stack_max = 1,
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.above ~= nil then
minetest.add_entity(pointed_thing.above, product_name)
return itemstack
end
return nil
end end
for _, item in ipairs(data.inv.main) do })
local itemstack = ItemStack(item.name)
itemstack:set_count(item.count)
inv:add_item(main_invname, itemstack)
end
end
-- initialize module
if self.module then self.module.initialize(self)
else
self.object:setvelocity{x = 0, y = 0, z = 0}
self.object:setacceleration{x = 0, y = -10, z = 0}
end
end,
on_step = function(self, dtime)
if self.module then self.module.on_step(self, dtime) end
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
end,
on_rightclick = function(self, clicker)
local formspec = "size[8,9]"
.."list[detached:"..self.invname..";"..main_invname..";0,0;4,4;]"
.."label[5,0;MODULE]"
.."list[detached:"..self.invname..";"..module_invname..";6,0;1,1;]"
.."list[current_player;"..main_invname..";0,5;8,1;]"
.."list[current_player;"..main_invname..";0,6.2;8,3;8]"
minetest.show_formspec(clicker:get_player_name(), self.invname, formspec)
end,
get_staticdata = function(self)
local inv = _aux.get_maidroid_inventory(self)
local staticdata = {}
staticdata.inv = {}
local module_name = inv:get_list(module_invname)[1]:get_name()
staticdata.inv.module = module_name or ""
staticdata.inv.main = {}
for _, item in ipairs(inv:get_list(main_invname)) do
local count = item:get_count()
local itemname = item:get_name()
if count ~= 0 then
local itemdata = { count = count, name = itemname }
table.insert(staticdata.inv.main, itemdata)
end
end
return minetest.serialize(staticdata)
end,
})
-- register spawn egg
minetest.register_craftitem(product_name.."_spawn_egg", {
description = def.description.." Spawn Egg",
inventory_image = def.inventory_image,
stack_max = 1,
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.above ~= nil then
minetest.add_entity(pointed_thing.above, product_name)
return itemstack
end
return nil
end
})
end end

View File

@ -4,21 +4,21 @@
------------------------------------------------------------ ------------------------------------------------------------
maidroid.register_maidroid("maidroid:maidroid", { maidroid.register_maidroid("maidroid:maidroid", {
hp_max = 10, hp_max = 10,
description = "Maidroid : Maidroid", description = "Maidroid : Maidroid",
inventory_image = "maidroid_maidroid.png", inventory_image = "maidroid_maidroid.png",
}) })
maidroid.register_maidroid("maidroid:maidroid_mk2", { maidroid.register_maidroid("maidroid:maidroid_mk2", {
hp_max = 10, hp_max = 10,
description = "Maidroid : Maidroid MkII", description = "Maidroid : Maidroid MkII",
textures = {"maidroid_mk2.png"}, textures = {"maidroid_mk2.png"},
inventory_image = "maidroid_maidroid_mk2.png", inventory_image = "maidroid_maidroid_mk2.png",
}) })
maidroid.register_maidroid("maidroid:maidroid_mk3", { maidroid.register_maidroid("maidroid:maidroid_mk3", {
hp_max = 10, hp_max = 10,
description = "Maidroid : Maidroid MkIII", description = "Maidroid : Maidroid MkIII",
textures = {"maidroid_mk3.png"}, textures = {"maidroid_mk3.png"},
inventory_image = "maidroid_maidroid_mk3.png", inventory_image = "maidroid_maidroid_mk3.png",
}) })

View File

@ -9,84 +9,84 @@ local velocity = 3
-- change direction to destination and velocity vector -- change direction to destination and velocity vector
function maidroid.modules._aux.change_dir_to(self, dest) function maidroid.modules._aux.change_dir_to(self, dest)
local pos = self.object:getpos() local pos = self.object:getpos()
local dir = vector.subtract(dest, pos) local dir = vector.subtract(dest, pos)
local vel = vector.multiply(vector.normalize(dir), velocity) local vel = vector.multiply(vector.normalize(dir), velocity)
self.object:setvelocity(vel) self.object:setvelocity(vel)
self.object:setyaw(math.atan2(vel.z, vel.x) + math.pi / 2) self.object:setyaw(math.atan2(vel.z, vel.x) + math.pi / 2)
end end
-- change direction and velocity vector -- change direction and velocity vector
function maidroid.modules._aux.change_dir(self) function maidroid.modules._aux.change_dir(self)
local rnd = function() return math.random(0, 5) * 2 - 5 end local rnd = function() return math.random(0, 5) * 2 - 5 end
local dir = {x = rnd(), y = 0, z = rnd()} local dir = {x = rnd(), y = 0, z = rnd()}
local vel = vector.multiply(vector.normalize(dir), velocity) local vel = vector.multiply(vector.normalize(dir), velocity)
self.object:setvelocity(vel) self.object:setvelocity(vel)
self.object:setyaw(math.atan2(vel.z, vel.x) + math.pi / 2) self.object:setyaw(math.atan2(vel.z, vel.x) + math.pi / 2)
end end
-- get direction vector by yaw -- get direction vector by yaw
function maidroid.modules._aux.get_forward(yaw) function maidroid.modules._aux.get_forward(yaw)
return { x = math.sin(yaw), y = 0.0, z = -math.cos(yaw) } return { x = math.sin(yaw), y = 0.0, z = -math.cos(yaw) }
end end
-- round direction vector -- round direction vector
function maidroid.modules._aux.get_round_forward(forward) function maidroid.modules._aux.get_round_forward(forward)
local rforward = { x = 0, y = 0, z = 0} local rforward = { x = 0, y = 0, z = 0}
if math.abs((forward.x / (math.abs(forward.x) + math.abs(forward.z)))) > 0.5 then if math.abs((forward.x / (math.abs(forward.x) + math.abs(forward.z)))) > 0.5 then
if forward.x > 0 then rforward.x = 1 if forward.x > 0 then rforward.x = 1
else rforward.x = -1 end else rforward.x = -1 end
end end
if math.abs((forward.z / (math.abs(forward.x) + math.abs(forward.z)))) > 0.5 then if math.abs((forward.z / (math.abs(forward.x) + math.abs(forward.z)))) > 0.5 then
if forward.z > 0 then rforward.z = 1 if forward.z > 0 then rforward.z = 1
else rforward.z = -1 end else rforward.z = -1 end
end end
return rforward return rforward
end end
function maidroid.modules._aux.get_under_pos(vec) function maidroid.modules._aux.get_under_pos(vec)
return { x = vec.x, y = vec.y - 1, z = vec.z } return { x = vec.x, y = vec.y - 1, z = vec.z }
end end
function maidroid.modules._aux.get_upper_pos(vec) function maidroid.modules._aux.get_upper_pos(vec)
return { x = vec.x, y = vec.y + 1, z = vec.z } return { x = vec.x, y = vec.y + 1, z = vec.z }
end end
-- pickup droped items -- pickup droped items
function maidroid.modules._aux.pickup_item(self, radius, target_pred) function maidroid.modules._aux.pickup_item(self, radius, target_pred)
local pos = self.object:getpos() local pos = self.object:getpos()
local pred = target_pred or (function(itemstring) return true end) local pred = target_pred or (function(itemstring) return true end)
local all_objects = minetest.get_objects_inside_radius(pos, radius) local all_objects = minetest.get_objects_inside_radius(pos, radius)
for _, obj in ipairs(all_objects) do for _, obj in ipairs(all_objects) do
if not obj:is_player() and obj:get_luaentity() then if not obj:is_player() and obj:get_luaentity() then
local itemstring = obj:get_luaentity().itemstring local itemstring = obj:get_luaentity().itemstring
if itemstring then if itemstring then
if pred(itemstring) then if pred(itemstring) then
local inv = maidroid._aux.get_maidroid_inventory(self) local inv = maidroid._aux.get_maidroid_inventory(self)
local stack = ItemStack(itemstring) local stack = ItemStack(itemstring)
local leftover = inv:add_item("main", stack) local leftover = inv:add_item("main", stack)
minetest.add_item(obj:getpos(), leftover) minetest.add_item(obj:getpos(), leftover)
obj:get_luaentity().itemstring = "" obj:get_luaentity().itemstring = ""
obj:remove() obj:remove()
end
end
end end
end
end end
end
end end
-- search surrounding nodes -- search surrounding nodes
function maidroid.modules._aux.search_surrounding(self, lenvec, pred) function maidroid.modules._aux.search_surrounding(self, lenvec, pred)
local pos = vector.round(self.object:getpos()) local pos = vector.round(self.object:getpos())
for xi = -lenvec.x, lenvec.x do for xi = -lenvec.x, lenvec.x do
for yi = -lenvec.y, lenvec.y do for yi = -lenvec.y, lenvec.y do
for zi = -lenvec.z, lenvec.z do for zi = -lenvec.z, lenvec.z do
local p = {x = pos.x + xi, y = pos.y + yi, z = pos.z + zi} local p = {x = pos.x + xi, y = pos.y + yi, z = pos.z + zi}
local node = minetest.get_node(p) local node = minetest.get_node(p)
if pred(self, p, node) then return true, p, node end if pred(self, p, node) then return true, p, node end
end end
end
end end
end return false, nil, nil
return false, nil, nil
end end

View File

@ -11,65 +11,65 @@ local view_of_range = 7
local stop_of_range = 2 local stop_of_range = 2
maidroid.register_module("maidroid:chasing_player_module", { maidroid.register_module("maidroid:chasing_player_module", {
description = "Maidroid Module : Chasing Player", description = "Maidroid Module : Chasing Player",
inventory_image = "maidroid_chasing_player_module.png", inventory_image = "maidroid_chasing_player_module.png",
initialize = function(self) initialize = function(self)
self.state = state.idle
self.object:setacceleration{x = 0, y = -10, z = 0}
self.object:setvelocity{x = 0, y = 0, z = 0}
end,
finalize = function(self)
self.state = nil
self.object:setvelocity{x = 0, y = 0, z = 0}
end,
on_step = function(self, dtime)
local pos = self.object:getpos()
local all_objects = minetest.get_objects_inside_radius(pos, view_of_range)
local player = nil
for _, obj in pairs(all_objects) do
if obj:is_player() then player = obj; break end
end
if not player then
self.object:set_animation(maidroid.animations.stand, 15, 0)
self.state = state.idle
return
end
local ppos = player:getpos()
local dir = vector.subtract(ppos, pos)
local vel = self.object:getvelocity()
if (vector.length(dir) < stop_of_range) then
if self.state == state.chase then
self.object:set_animation(maidroid.animations.stand, 15, 0)
self.state = state.idle self.state = state.idle
self.object:setvelocity({x = 0, y = vel.y, z = 0}) self.object:setacceleration{x = 0, y = -10, z = 0}
end self.object:setvelocity{x = 0, y = 0, z = 0}
else end,
if self.state == state.idle then
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.state = state.chase
end
self.object:setvelocity({x = dir.x, y = vel.y, z = dir.z})
end
local yaw = math.atan2(dir.z, dir.x) + math.pi/2
self.object:setyaw(yaw)
-- jump process finalize = function(self)
if vel.y == 0 and self.state == state.chase then self.state = nil
local rdir = vector.round(dir) self.object:setvelocity{x = 0, y = 0, z = 0}
local front_vec = { x = 0, y = 0, z = 0 } end,
if math.abs((rdir.x / (math.abs(rdir.x) + math.abs(rdir.z)))) > 0.5 then
if rdir.x > 0 then front_vec.x = 1 else front_vec.x = -1 end on_step = function(self, dtime)
end local pos = self.object:getpos()
if math.abs((rdir.z / (math.abs(rdir.x) + math.abs(rdir.z)))) > 0.5 then local all_objects = minetest.get_objects_inside_radius(pos, view_of_range)
if rdir.z > 0 then front_vec.z = 1 else front_vec.z = -1 end local player = nil
end for _, obj in pairs(all_objects) do
local front_pos = vector.add(vector.round(pos), front_vec) if obj:is_player() then player = obj; break end
if minetest.get_node(front_pos).name ~= "air" then end
self.object:setvelocity({x = dir.x, y = 5, z = dir.z}) if not player then
end self.object:set_animation(maidroid.animations.stand, 15, 0)
end self.state = state.idle
end, return
end
local ppos = player:getpos()
local dir = vector.subtract(ppos, pos)
local vel = self.object:getvelocity()
if (vector.length(dir) < stop_of_range) then
if self.state == state.chase then
self.object:set_animation(maidroid.animations.stand, 15, 0)
self.state = state.idle
self.object:setvelocity({x = 0, y = vel.y, z = 0})
end
else
if self.state == state.idle then
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.state = state.chase
end
self.object:setvelocity({x = dir.x, y = vel.y, z = dir.z})
end
local yaw = math.atan2(dir.z, dir.x) + math.pi/2
self.object:setyaw(yaw)
-- jump process
if vel.y == 0 and self.state == state.chase then
local rdir = vector.round(dir)
local front_vec = { x = 0, y = 0, z = 0 }
if math.abs((rdir.x / (math.abs(rdir.x) + math.abs(rdir.z)))) > 0.5 then
if rdir.x > 0 then front_vec.x = 1 else front_vec.x = -1 end
end
if math.abs((rdir.z / (math.abs(rdir.x) + math.abs(rdir.z)))) > 0.5 then
if rdir.z > 0 then front_vec.z = 1 else front_vec.z = -1 end
end
local front_pos = vector.add(vector.round(pos), front_vec)
if minetest.get_node(front_pos).name ~= "air" then
self.object:setvelocity({x = dir.x, y = 5, z = dir.z})
end
end
end,
}) })

View File

@ -4,9 +4,9 @@
------------------------------------------------------------ ------------------------------------------------------------
maidroid.register_module("maidroid:empty_module", { maidroid.register_module("maidroid:empty_module", {
description = "Maidroid Module : Empty Module", description = "Maidroid Module : Empty Module",
inventory_image = "maidroid_empty_module.png", inventory_image = "maidroid_empty_module.png",
initialize = function(self) end, initialize = function(self) end,
finalize = function(self) end, finalize = function(self) end,
on_step = function(self, dtime) end, on_step = function(self, dtime) end,
}) })

View File

@ -6,12 +6,12 @@
local _aux = maidroid.modules._aux local _aux = maidroid.modules._aux
local state = { local state = {
walk = 0, walk = 0,
punch = 1, punch = 1,
plant = 2, plant = 2,
walk_to_plant = 3, walk_to_plant = 3,
walk_to_soil = 4, walk_to_soil = 4,
walk_avoid = 5, walk_avoid = 5,
} }
local max_punch_time = 20 local max_punch_time = 20
local max_plant_time = 15 local max_plant_time = 15
@ -22,188 +22,188 @@ local search_lenvec = {x = 3, y = 0, z = 3}
-- find max size of each plants -- find max size of each plants
local target_plants_list = {} local target_plants_list = {}
minetest.after(0, function() minetest.after(0, function()
local max = {} local max = {}
for name, node in pairs(minetest.registered_nodes) do for name, node in pairs(minetest.registered_nodes) do
if minetest.get_item_group(name, "plant") > 0 then if minetest.get_item_group(name, "plant") > 0 then
local s, i = string.match(name, "(.+)_(%d+)") local s, i = string.match(name, "(.+)_(%d+)")
if (s and i) and (max[s] == nil or max[s] < i) then max[s] = i end if (s and i) and (max[s] == nil or max[s] < i) then max[s] = i end
end
end
for s, i in pairs(max) do
table.insert(target_plants_list, s.."_"..i)
end end
end
for s, i in pairs(max) do
table.insert(target_plants_list, s.."_"..i)
end
end) end)
-- check the maidroid has seed items -- check the maidroid has seed items
local function has_seed_item(self) local function has_seed_item(self)
local inv = maidroid._aux.get_maidroid_inventory(self) local inv = maidroid._aux.get_maidroid_inventory(self)
local stacks = inv:get_list("main") local stacks = inv:get_list("main")
for _, stack in ipairs(stacks) do for _, stack in ipairs(stacks) do
local item_name = stack:get_name() local item_name = stack:get_name()
if minetest.get_item_group(item_name, "seed") > 0 then if minetest.get_item_group(item_name, "seed") > 0 then
return true return true
end
end end
end return false
return false
end end
-- check can plant plants. -- check can plant plants.
local function can_plant(self, pos) local function can_plant(self, pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local upos = _aux.get_under_pos(pos) local upos = _aux.get_under_pos(pos)
local unode = minetest.get_node(upos) local unode = minetest.get_node(upos)
return node.name == "air" return node.name == "air"
and minetest.get_item_group(unode.name, "wet") > 0 and minetest.get_item_group(unode.name, "wet") > 0
and has_seed_item(self) and has_seed_item(self)
end end
-- check can punch plant -- check can punch plant
local function can_punch(self, pos) local function can_punch(self, pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
return maidroid.util.table_find_value(target_plants_list, node.name) return maidroid.util.table_find_value(target_plants_list, node.name)
end end
-- change state to walk -- change state to walk
local function to_walk(self) local function to_walk(self)
self.state = state.walk self.state = state.walk
self.destination = nil self.destination = nil
self.object:set_animation(maidroid.animations.walk, 15, 0) self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0 self.time_count = 0
_aux.change_dir(self) _aux.change_dir(self)
end end
local function to_walk_avoid(self) local function to_walk_avoid(self)
to_walk(self) to_walk(self)
self.state = state.walk_avoid self.state = state.walk_avoid
end end
maidroid.register_module("maidroid:farming_module", { maidroid.register_module("maidroid:farming_module", {
description = "Maidroid Module : Farming", description = "Maidroid Module : Farming",
inventory_image = "maidroid_farming_module.png", inventory_image = "maidroid_farming_module.png",
initialize = function(self) initialize = function(self)
self.object:set_animation(maidroid.animations.walk, 15, 0) self.object:set_animation(maidroid.animations.walk, 15, 0)
self.object:setacceleration{x = 0, y = -10, z = 0} self.object:setacceleration{x = 0, y = -10, z = 0}
self.state = state.walk
self.preposition = self.object:getpos()
self.time_count = 0
self.destination = nil -- for walk_to_*
_aux.change_dir(self)
end,
finalize = function(self)
self.state = nil
self.preposition = nil
self.time_count = nil
self.destination = nil
self.object:setvelocity{x = 0, y = 0, z = 0}
end,
on_step = function(self, dtime)
local pos = self.object:getpos()
local rpos = vector.round(pos)
local upos = _aux.get_under_pos(pos)
local yaw = self.object:getyaw()
_aux.pickup_item(self, 1.5, function(itemstring) -- pickup droped seed items
return minetest.get_item_group(itemstring, "seed") > 0
end)
if self.state == state.walk then -- searching plants or spaces
local b1, dest1 = _aux.search_surrounding(self, search_lenvec, can_plant)
local b2, dest2 = _aux.search_surrounding(self, search_lenvec, can_punch)
-- search soil node near
if b1 then -- to soil
self.state = state.walk_to_soil
self.destination = dest1
_aux.change_dir_to(self, dest1)
elseif b2 then
self.state = state.walk_to_plant
self.destination = dest2
_aux.change_dir_to(self, dest2)
elseif pos.x == self.preposition.x or pos.z == self.preposition.z then
_aux.change_dir(self)
end
elseif self.state == state.punch then
if self.time_count >= max_punch_time then
if can_punch(self, self.destination) then
local destnode = minetest.get_node(self.destination)
minetest.remove_node(self.destination)
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = minetest.get_node_drops(destnode.name)
for _, stack in ipairs(stacks) do
local leftover = inv:add_item("main", stack)
minetest.add_item(self.destination, leftover)
end
end
to_walk(self)
else
self.time_count = self.time_count + 1
end
elseif self.state == state.plant then
if self.time_count >= max_plant_time then
if can_plant(self, self.destination) then
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = inv:get_list("main")
for idx, stack in ipairs(stacks) do
local item_name = stack:get_name()
if minetest.get_item_group(item_name, "seed") > 0 then
minetest.add_node(self.destination, {name = item_name, param2 = 1})
stack:take_item(1)
inv:set_stack("main", idx, stack)
break
end
end
end
to_walk(self)
else
self.time_count = self.time_count + 1
end
elseif self.state == state.walk_to_soil then
if vector.distance(pos, self.destination) < 1.5 then -- to plant state
local destnode = minetest.get_node(self.destination)
if (can_plant(self, self.destination)) then
self.state = state.plant
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
else to_walk(self) end
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
to_walk_avoid(self)
end
end
elseif self.state == state.walk_to_plant then
if vector.distance(pos, self.destination) < 1.5 then
local destnode = minetest.get_node(self.destination)
if maidroid.util.table_find_value(target_plants_list, destnode.name) then
self.state = state.punch
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
else to_walk(self) end
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
to_walk_avoid(self)
end
end
elseif self.state == state.walk_avoid then
if self.time_count > max_avoid_time then
self.state = state.walk self.state = state.walk
self.preposition = self.object:getpos()
self.time_count = 0 self.time_count = 0
else self.destination = nil -- for walk_to_*
self.time_count = self.time_count + 1 _aux.change_dir(self)
end end,
finalize = function(self)
self.state = nil
self.preposition = nil
self.time_count = nil
self.destination = nil
self.object:setvelocity{x = 0, y = 0, z = 0}
end,
on_step = function(self, dtime)
local pos = self.object:getpos()
local rpos = vector.round(pos)
local upos = _aux.get_under_pos(pos)
local yaw = self.object:getyaw()
_aux.pickup_item(self, 1.5, function(itemstring) -- pickup droped seed items
return minetest.get_item_group(itemstring, "seed") > 0
end)
if self.state == state.walk then -- searching plants or spaces
local b1, dest1 = _aux.search_surrounding(self, search_lenvec, can_plant)
local b2, dest2 = _aux.search_surrounding(self, search_lenvec, can_punch)
-- search soil node near
if b1 then -- to soil
self.state = state.walk_to_soil
self.destination = dest1
_aux.change_dir_to(self, dest1)
elseif b2 then
self.state = state.walk_to_plant
self.destination = dest2
_aux.change_dir_to(self, dest2)
elseif pos.x == self.preposition.x or pos.z == self.preposition.z then
_aux.change_dir(self)
end
elseif self.state == state.punch then
if self.time_count >= max_punch_time then
if can_punch(self, self.destination) then
local destnode = minetest.get_node(self.destination)
minetest.remove_node(self.destination)
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = minetest.get_node_drops(destnode.name)
for _, stack in ipairs(stacks) do
local leftover = inv:add_item("main", stack)
minetest.add_item(self.destination, leftover)
end
end
to_walk(self)
else
self.time_count = self.time_count + 1
end
elseif self.state == state.plant then
if self.time_count >= max_plant_time then
if can_plant(self, self.destination) then
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = inv:get_list("main")
for idx, stack in ipairs(stacks) do
local item_name = stack:get_name()
if minetest.get_item_group(item_name, "seed") > 0 then
minetest.add_node(self.destination, {name = item_name, param2 = 1})
stack:take_item(1)
inv:set_stack("main", idx, stack)
break
end
end
end
to_walk(self)
else
self.time_count = self.time_count + 1
end
elseif self.state == state.walk_to_soil then
if vector.distance(pos, self.destination) < 1.5 then -- to plant state
local destnode = minetest.get_node(self.destination)
if (can_plant(self, self.destination)) then
self.state = state.plant
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
else to_walk(self) end
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
to_walk_avoid(self)
end
end
elseif self.state == state.walk_to_plant then
if vector.distance(pos, self.destination) < 1.5 then
local destnode = minetest.get_node(self.destination)
if maidroid.util.table_find_value(target_plants_list, destnode.name) then
self.state = state.punch
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
else to_walk(self) end
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
to_walk_avoid(self)
end
end
elseif self.state == state.walk_avoid then
if self.time_count > max_avoid_time then
self.state = state.walk
self.time_count = 0
else
self.time_count = self.time_count + 1
end
end
self.preposition = pos
return
end end
self.preposition = pos
return
end
}) })

View File

@ -7,11 +7,11 @@ local util = maidroid.util
local _aux = maidroid.modules._aux local _aux = maidroid.modules._aux
local state = { local state = {
walk = 0, walk = 0,
plant = 1, plant = 1,
punch = 2, punch = 2,
walk_to_tree = 3, walk_to_tree = 3,
walk_avoid = 4, walk_avoid = 4,
} }
local find_lenvec = {x = 3, y = 0, z = 3} local find_lenvec = {x = 3, y = 0, z = 3}
local plant_lenvec = {x = 2, y = 0, z = 2} local plant_lenvec = {x = 2, y = 0, z = 2}
@ -23,170 +23,170 @@ local target_sapling_list = { "default:sapling" }
-- check the maidroid need to start to punch -- check the maidroid need to start to punch
local function check_punch_flag(forward_pos) local function check_punch_flag(forward_pos)
local forward_upper_pos = util.table_shallow_copy(forward_pos) local forward_upper_pos = util.table_shallow_copy(forward_pos)
while true do while true do
local forward_upper_node = minetest.get_node(forward_upper_pos) local forward_upper_node = minetest.get_node(forward_upper_pos)
if util.table_find_value(target_tree_list, forward_upper_node.name) then if util.table_find_value(target_tree_list, forward_upper_node.name) then
return true, forward_upper_pos, forward_upper_node return true, forward_upper_pos, forward_upper_node
elseif forward_upper_node.name ~= "air" then break end elseif forward_upper_node.name ~= "air" then break end
forward_upper_pos.y = forward_upper_pos.y + 1 forward_upper_pos.y = forward_upper_pos.y + 1
end end
return false, nil, nil return false, nil, nil
end end
-- check the maidroid has sapling items -- check the maidroid has sapling items
local function has_sapling_item(self) local function has_sapling_item(self)
local inv = maidroid._aux.get_maidroid_inventory(self) local inv = maidroid._aux.get_maidroid_inventory(self)
local stacks = inv:get_list("main") local stacks = inv:get_list("main")
for _, stack in ipairs(stacks) do for _, stack in ipairs(stacks) do
local item_name = stack:get_name() local item_name = stack:get_name()
if util.table_find_value(target_sapling_list, item_name) then if util.table_find_value(target_sapling_list, item_name) then
return true return true
end
end end
end return false
return false
end end
maidroid.register_module("maidroid:lumberjack_module", { maidroid.register_module("maidroid:lumberjack_module", {
description = "Maidroid Module : Lumberjack", description = "Maidroid Module : Lumberjack",
inventory_image = "maidroid_lumberjack_module.png", inventory_image = "maidroid_lumberjack_module.png",
initialize = function(self) initialize = function(self)
self.state = state.walk
self.time_count = 0
self.object:setacceleration{x = 0, y = -10, z = 0}
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.preposition = self.object:getpos()
self.destination = nil
_aux.change_dir(self)
end,
finalize = function(self)
self.state = nil
self.time_count = nil
self.preposition = nil
self.object:setvelocity{x = 0, y = 0, z = 0}
self.destination = nil
end,
on_step = function(self, dtime)
local pos = self.object:getpos()
local rpos = vector.round(pos)
local yaw = self.object:getyaw()
local forward = _aux.get_forward(yaw)
local rforward = _aux.get_round_forward(forward)
local forward_pos = vector.add(rpos, rforward)
local forward_node = minetest.get_node(forward_pos)
local forward_under_pos = _aux.get_under_pos(forward_pos)
local forward_under_node = minetest.get_node(forward_under_pos)
if self.state == state.walk then
local b, dest = _aux.search_surrounding(self, find_lenvec, function(self, pos, node)
return util.table_find_value(target_tree_list, node.name)
end)
if b then -- walk to tree
self.state = state.walk_to_tree
self.destination = dest
_aux.change_dir_to(self, dest)
-- to plant sapling
elseif forward_node.name == "air"
and minetest.get_item_group(forward_under_node.name, "soil") > 0
and not _aux.search_surrounding(self, plant_lenvec, function(self, pos, node) -- no tree around
return util.table_find_value(target_tree_list, node.name)
or util.table_find_value(target_sapling_list, node.name)
end)
and has_sapling_item(self) then
self.state = state.plant
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
-- else continue to walk
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
_aux.change_dir(self)
end
end
-- pickup sapling items
_aux.pickup_item(self, 1.5, function(itemstring)
return util.table_find_value(target_sapling_list, itemstring)
end)
elseif self.state == state.punch then
if self.time_count >= max_punch_time then
local punch_flag, forward_upper_pos, forward_upper_node = check_punch_flag(self.destination)
if punch_flag then
minetest.remove_node(forward_upper_pos)
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = minetest.get_node_drops(forward_upper_node.name)
for _, stack in ipairs(stacks) do
local leftover = inv:add_item("main", stack)
minetest.add_item(forward_pos, leftover)
end
end
if (not forward_upper_pos) or (forward_upper_pos and
not check_punch_flag(_aux.get_upper_pos(forward_upper_pos))) then
self.state = state.walk
self.object:set_animation(maidroid.animations.walk, 15, 0)
_aux.change_dir(self)
end
self.time_count = 0
else
self.time_count = self.time_count + 1
end
elseif self.state == state.plant then
if self.time_count > max_plant_time then
if forward_node.name == "air"
and minetest.get_item_group(forward_under_node.name, "soil") > 0 then
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = inv:get_list("main")
for i, stack in ipairs(stacks) do
local itemname = stack:get_name()
if util.table_find_value(target_sapling_list, itemname) then
minetest.add_node(forward_pos, {name = itemname, param2 = 1})
stack:take_item(1)
inv:set_stack("main", i, stack)
break
end
end
end
self.state = state.walk self.state = state.walk
self.time_count = 0
self.object:setacceleration{x = 0, y = -10, z = 0}
self.object:set_animation(maidroid.animations.walk, 15, 0) self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0 self.preposition = self.object:getpos()
self.destination = nil
_aux.change_dir(self) _aux.change_dir(self)
else end,
self.time_count = self.time_count + 1
end
elseif self.state == state.walk_to_tree then finalize = function(self)
if vector.distance(pos, self.destination) < 1.5 then -- to punch state self.state = nil
local destnode = minetest.get_node(self.destination) self.time_count = nil
if (util.table_find_value(target_tree_list, destnode.name)) then self.preposition = nil
self.state = state.punch self.object:setvelocity{x = 0, y = 0, z = 0}
self.object:set_animation(maidroid.animations.mine, 15, 0) self.destination = nil
self.object:setvelocity{x = 0, y = 0, z = 0} end,
else
self.state = state.walk
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0
_aux.change_dir(self)
end
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
self.state = state.walk_avoid
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0
_aux.change_dir(self)
end
end
elseif self.state == state.walk_avoid then on_step = function(self, dtime)
if self.time_count > max_avoid_time then local pos = self.object:getpos()
self.state = state.walk local rpos = vector.round(pos)
self.time_count = 0 local yaw = self.object:getyaw()
else local forward = _aux.get_forward(yaw)
self.time_count = self.time_count + 1 local rforward = _aux.get_round_forward(forward)
end local forward_pos = vector.add(rpos, rforward)
end local forward_node = minetest.get_node(forward_pos)
self.preposition = pos local forward_under_pos = _aux.get_under_pos(forward_pos)
end local forward_under_node = minetest.get_node(forward_under_pos)
})
if self.state == state.walk then
local b, dest = _aux.search_surrounding(self, find_lenvec, function(self, pos, node)
return util.table_find_value(target_tree_list, node.name)
end)
if b then -- walk to tree
self.state = state.walk_to_tree
self.destination = dest
_aux.change_dir_to(self, dest)
-- to plant sapling
elseif forward_node.name == "air"
and minetest.get_item_group(forward_under_node.name, "soil") > 0
and not _aux.search_surrounding(self, plant_lenvec, function(self, pos, node) -- no tree around
return util.table_find_value(target_tree_list, node.name)
or util.table_find_value(target_sapling_list, node.name)
end)
and has_sapling_item(self) then
self.state = state.plant
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
-- else continue to walk
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
_aux.change_dir(self)
end
end
-- pickup sapling items
_aux.pickup_item(self, 1.5, function(itemstring)
return util.table_find_value(target_sapling_list, itemstring)
end)
elseif self.state == state.punch then
if self.time_count >= max_punch_time then
local punch_flag, forward_upper_pos, forward_upper_node = check_punch_flag(self.destination)
if punch_flag then
minetest.remove_node(forward_upper_pos)
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = minetest.get_node_drops(forward_upper_node.name)
for _, stack in ipairs(stacks) do
local leftover = inv:add_item("main", stack)
minetest.add_item(forward_pos, leftover)
end
end
if (not forward_upper_pos) or (forward_upper_pos and
not check_punch_flag(_aux.get_upper_pos(forward_upper_pos))) then
self.state = state.walk
self.object:set_animation(maidroid.animations.walk, 15, 0)
_aux.change_dir(self)
end
self.time_count = 0
else
self.time_count = self.time_count + 1
end
elseif self.state == state.plant then
if self.time_count > max_plant_time then
if forward_node.name == "air"
and minetest.get_item_group(forward_under_node.name, "soil") > 0 then
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = inv:get_list("main")
for i, stack in ipairs(stacks) do
local itemname = stack:get_name()
if util.table_find_value(target_sapling_list, itemname) then
minetest.add_node(forward_pos, {name = itemname, param2 = 1})
stack:take_item(1)
inv:set_stack("main", i, stack)
break
end
end
end
self.state = state.walk
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0
_aux.change_dir(self)
else
self.time_count = self.time_count + 1
end
elseif self.state == state.walk_to_tree then
if vector.distance(pos, self.destination) < 1.5 then -- to punch state
local destnode = minetest.get_node(self.destination)
if (util.table_find_value(target_tree_list, destnode.name)) then
self.state = state.punch
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
else
self.state = state.walk
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0
_aux.change_dir(self)
end
else
if pos.x == self.preposition.x or pos.z == self.preposition.z then
self.state = state.walk_avoid
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.time_count = 0
_aux.change_dir(self)
end
end
elseif self.state == state.walk_avoid then
if self.time_count > max_avoid_time then
self.state = state.walk
self.time_count = 0
else
self.time_count = self.time_count + 1
end
end
self.preposition = pos
end
})

View File

@ -5,66 +5,65 @@
-- maidroids -- maidroids
minetest.register_craft{ minetest.register_craft{
output = "maidroid:maidroid_spawn_egg", output = "maidroid:maidroid_spawn_egg",
recipe = { recipe = {
{"default:diamond", "default:diamond", "default:diamond"}, {"default:diamond", "default:diamond", "default:diamond"},
{"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"}, {"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"},
{"default:papyrus", "default:mese_crystal", "default:papyrus"}, {"default:papyrus", "default:mese_crystal", "default:papyrus"},
}, },
} }
minetest.register_craft{ minetest.register_craft{
output = "maidroid:maidroid_mk2_spawn_egg", output = "maidroid:maidroid_mk2_spawn_egg",
recipe = { recipe = {
{"dye:blue", "dye:blue", "dye:blue"}, {"dye:blue", "dye:blue", "dye:blue"},
{"dye:blue", "maidroid:maidroid_spawn_egg", "dye:blue"}, {"dye:blue", "maidroid:maidroid_spawn_egg", "dye:blue"},
{"dye:blue", "dye:blue", "dye:blue"}, {"dye:blue", "dye:blue", "dye:blue"},
}, },
} }
minetest.register_craft{ minetest.register_craft{
output = "maidroid:maidroid_mk3_spawn_egg", output = "maidroid:maidroid_mk3_spawn_egg",
recipe = { recipe = {
{"dye:pink", "dye:pink", "dye:pink"}, {"dye:pink", "dye:pink", "dye:pink"},
{"dye:pink", "maidroid:maidroid_spawn_egg", "dye:pink"}, {"dye:pink", "maidroid:maidroid_spawn_egg", "dye:pink"},
{"dye:pink", "dye:pink", "dye:pink"}, {"dye:pink", "dye:pink", "dye:pink"},
}, },
} }
-- modules -- modules
minetest.register_craft{ minetest.register_craft{
output = "maidroid:empty_module", output = "maidroid:empty_module",
recipe = { recipe = {
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
{"default:steel_ingot", "default:obsidian", "default:steel_ingot"}, {"default:steel_ingot", "default:obsidian", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
}, },
} }
minetest.register_craft{ minetest.register_craft{
output = "maidroid:chasing_player_module", output = "maidroid:chasing_player_module",
recipe = { recipe = {
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
{"default:steel_ingot", "maidroid:empty_module", "default:steel_ingot"}, {"default:steel_ingot", "maidroid:empty_module", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
}, },
} }
minetest.register_craft{ minetest.register_craft{
output = "maidroid:farming_module", output = "maidroid:farming_module",
recipe = { recipe = {
{"default:gold_ingot", "default:gold_ingot", "default:gold_ingot"}, {"default:gold_ingot", "default:gold_ingot", "default:gold_ingot"},
{"default:gold_ingot", "maidroid:empty_module", "default:gold_ingot"}, {"default:gold_ingot", "maidroid:empty_module", "default:gold_ingot"},
{"default:gold_ingot", "default:gold_ingot", "default:gold_ingot"}, {"default:gold_ingot", "default:gold_ingot", "default:gold_ingot"},
}, },
} }
minetest.register_craft{ minetest.register_craft{
output = "maidroid:lumberjack_module", output = "maidroid:lumberjack_module",
recipe = { recipe = {
{"default:diamond", "default:diamond", "default:diamond"}, {"default:diamond", "default:diamond", "default:diamond"},
{"default:diamond", "maidroid:empty_module", "default:diamond"}, {"default:diamond", "maidroid:empty_module", "default:diamond"},
{"default:diamond", "default:diamond", "default:diamond"}, {"default:diamond", "default:diamond", "default:diamond"},
}, },
} }

View File

@ -7,17 +7,17 @@ maidroid.util = {}
-- check that the table has the value -- check that the table has the value
function maidroid.util.table_find_value(tbl, value) function maidroid.util.table_find_value(tbl, value)
for k, v in ipairs(tbl) do for k, v in ipairs(tbl) do
if v == value then return true, k end if v == value then return true, k end
end end
return false, nil return false, nil
end end
-- table shallow copy -- table shallow copy
function maidroid.util.table_shallow_copy(source) function maidroid.util.table_shallow_copy(source)
local copy = {} local copy = {}
for key, value in pairs(source) do for key, value in pairs(source) do
copy[key] = value copy[key] = value
end end
return copy return copy
end end