First commit

This commit is contained in:
d 2016-05-31 13:26:54 +09:00
commit e7e158052f
17 changed files with 651 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

17
_aux.lua Normal file
View File

@ -0,0 +1,17 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
maidroid._aux = {}
-- maidroidのインベントリを得る
function maidroid._aux.get_maidroid_inventory(self)
return minetest.get_inventory{
type = "detached",
name = self.invname,
}
end

159
api.lua Normal file
View File

@ -0,0 +1,159 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
local _aux = maidroid._aux
-- インベントリにユニークな値を与えるための補助関数
local gen_inv_serialnumber = (function ()
local serialnumber = 0
return function ()
serialnumber = serialnumber + 1
return serialnumber - 1
end
end) ()
local main_invsize = 16
local main_invname = "main"
local module_invsize = 1
local module_invname = "module"
-- モジュール名と定義を対応づけるテーブル
maidroid.registered_modules = {}
-- 新しいmoduleを登録する関数
function maidroid.register_module(module_name, def)
maidroid.registered_modules[module_name] = def
minetest.register_craftitem(module_name, {
description = def.description,
stack_max = 1,
})
end
-- アニメーションの区切りフレーム
maidroid.animations = {
stand = {x = 0, y = 79},
lay = {x = 162, y = 166},
walk = {x = 168, y = 187},
mine = {x = 189, y = 198},
walk_mine = {x = 200, y = 219},
sit = {x = 81, y = 160},
}
-- 新しいmaidroidを登録する関数
function maidroid.register_maidroid(product_name, def)
minetest.register_entity(product_name, {
hp_max = def.hp_max or 1,
physical = true,
weight = def.weight or 5,
collistionbox = def.collistionbox or { -0.35, -0.5, -0.35, 0.35, 1.1, 0.35 },
visual = "mesh",
visual_size = {x = 10, y = 10},
mesh = def.mesh or "maidroid.b3d",
textures = def.textures or {"maidroid.png"},
is_visible = true,
makes_footstep_sound = true,
module = nil,
invname = "",
on_activate = function(self, staticdata)
self.invname = "maidroid"..tostring(gen_inv_serialnumber())
local inv = minetest.create_detached_inventory(self.invname, {
on_put = 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 = module_def
module_def.initialize(self)
end
end,
arrow_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)
if self.module then self.module.initialize(self) end
-- process staticdata
if staticdata ~= "" then
local data = minetest.deserialize(staticdata)
local stack = ItemStack(data.inv.module)
stack:set_count(1)
inv:add_item(module_invname, stack)
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
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 = {}
staticdata.inv.module = inv:get_list(module_invname)[1]:get_name()
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,
})
-- スポーンエッグを登録
minetest.register_craftitem(product_name.."_swawn_egg", {
description = def.description.." Swapn Egg",
on_use = function(itemstack, user, pointed_thing)
minetest.add_entity(pointed_thing.above, "maidroid:maidroid")
return itemstack
end
})
-- 野生のmaidroidのentityの登録
minetest.register_entity(product_name.."_wild", {
hp_max = def.hp_max or 1,
physical = true,
weight = def.weight or 5,
on_activate = function(self, staticdata)
end,
on_step = function(self, dtime)
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
end,
on_rightclick = function(self, clicker)
end,
get_staticdata = function(self)
end,
})
end

15
init.lua Normal file
View File

@ -0,0 +1,15 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
maidroid = {}
maidroid.modname = "maidroid"
maidroid.modpath = minetest.get_modpath("maidroid")
dofile(maidroid.modpath.."/_aux.lua")
dofile(maidroid.modpath.."/util.lua")
dofile(maidroid.modpath.."/api.lua")
dofile(maidroid.modpath.."/modules.lua")
dofile(maidroid.modpath.."/maidroids.lua")

19
maidroids.lua Normal file
View File

@ -0,0 +1,19 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
maidroid.register_maidroid("maidroid:maidroid", {
hp_max = 10,
description = "Maidroid : Maidroid",
})
maidroid.register_maidroid("maidroid:maidroid_mk2", {
hp_max = 10,
description = "Maidroid : Maidroid MkII",
})
maidroid.register_maidroid("maidroid:maidroid_mk3", {
hp_max = 10,
description = "Maidroid : Maidroid MkIII",
})

3
maidroids/maidroid.lua Normal file
View File

@ -0,0 +1,3 @@

BIN
models/maidroid.b3d Executable file

Binary file not shown.

BIN
models/maidroid.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

10
module_generator.lua Normal file
View File

@ -0,0 +1,10 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
minetest.register_node("maidroid:module_generator", {
drawtype = "nodebox",
visual_scale = 1.0,
tiles = {},
})

12
modules.lua Normal file
View File

@ -0,0 +1,12 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
maidroid.modules = {}
local modules_dir = maidroid.modpath.."/modules"
dofile(modules_dir.."/_aux.lua")
dofile(modules_dir.."/chasing_player_module.lua")
dofile(modules_dir.."/farming_module.lua")
dofile(modules_dir.."/lumberjack_module.lua")

64
modules/_aux.lua Normal file
View File

@ -0,0 +1,64 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
-- いい感じにモジュール化出来ないので名前空間に隠す
maidroid.modules._aux = {}
-- 向いている方向と速度ベクトルを変える
function maidroid.modules._aux.change_dir(self)
local rnd = function() return math.random(0, 5) * 2 - 5 end
local dir = {x = rnd(), y = 0, z = rnd()}
local vel = vector.multiply(vector.normalize(dir), 3)
self.object:setvelocity(vel)
self.object:setyaw(math.atan2(vel.z, vel.x) + math.pi / 2)
end
-- yawから向いている方向ベクトルを得る
function maidroid.modules._aux.get_forward(yaw)
return { x = math.sin(yaw), y = 0.0, z = -math.cos(yaw) }
end
-- 方向ベクトルを丸める
function maidroid.modules._aux.get_round_forward(forward)
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 forward.x > 0 then rforward.x = 1
else rforward.x = -1 end
end
if math.abs((forward.z / (math.abs(forward.x) + math.abs(forward.z)))) > 0.5 then
if forward.z > 0 then rforward.z = 1
else rforward.z = -1 end
end
return rforward
end
-- 真下の位置を返すだけ
function maidroid.modules._aux.get_under_pos(vec)
return { x = vec.x, y = vec.y - 1, z = vec.z }
end
-- 真上の位置を返すだけ
function maidroid.modules._aux.get_upper_pos(vec)
return { x = vec.x, y = vec.y + 1, z = vec.z }
end
-- 落ちているアイテムを拾う
function maidroid.modules._aux.get_item(self, radius, target_pred)
local pos = self.object:getpos()
local pred = target_list or (function() return true end)
local all_objects = minetest.get_objects_inside_radius(pos, radius)
for _, obj in ipairs(all_objects) do
if not obj:is_player() and obj:get_luaentity() then
local itemstring = obj:get_luaentity().itemstring
if itemstring then
if pred(itemstring) then
local inv = maidroid._aux.get_maidroid_inventory(self)
local stack = ItemStack(itemstring)
local leftover = inv:add_item("main", stack)
end
end
end
end
end

View File

@ -0,0 +1,72 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
local util = maidroid.util
local _aux = maidroid.modules._aux
local state = { idle = 0, chase = 1}
local view_of_range = 7 -- 発見可能距離
local stop_of_range = 2 -- 止まる距離
-- プレーヤを追跡するだけのモジュール
maidroid.register_module("maidroid:chasing_player_module", {
description = "Maidroid Module : Chasing Player",
inventory_image = "maidroid_chasing_player_module.png",
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.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,
})

125
modules/farming_module.lua Normal file
View File

@ -0,0 +1,125 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
local _aux = maidroid.modules._aux
local state = {walk = 0, punch = 1, plant = 2}
-- 各植物ノードの種類の最大番号を探し出す
local target_plants_list = {}
minetest.after(0, function()
local max = {}
for name, node in pairs(minetest.registered_nodes) do
if minetest.get_item_group(name, "plant") > 0 then
local s, i = string.match(name, "(.+)_(%d+)")
if 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)
local max_punch_time = 20
local max_plant_time = 15
-- 種を持っているか否かを確認する
local function has_seed_item(self)
local inv = maidroid._aux.get_maidroid_inventory(self)
local stacks = inv:get_list("main")
for _, stack in ipairs(stacks) do
local item_name = stack:get_name()
if minetest.get_item_group(item_name, "seed") > 0 then
return true
end
end
return false
end
-- 農業を行うモジュール
maidroid.register_module("maidroid:farming_module", {
description = "Maidroid Module : Farming",
inventory_image = "maidroid_farming_module.png",
initialize = function(self)
self.object:set_animation(maidroid.animations.walk, 15, 0)
self.object:setacceleration{x = 0, y = -10, z = 0}
self.state = state.walk
self.preposition = self.object:getpos()
self.time_count = 0
_aux.change_dir(self)
end,
finalize = function(self)
self.state = nil
self.preposition = nil
self.time_count = 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 yaw = self.object:getyaw()
local forward_vec = _aux.get_forward(yaw)
local forward_vec2 = _aux.get_round_forward(forward_vec)
local forward_pos = vector.add(rpos, forward_vec2)
local forward_node = minetest.get_node(forward_pos)
local forward_under_pos = vector.subtract(forward_pos, {x = 0, y = 1, z = 0})
if self.state == state.walk then -- searching plants or spaces
if maidroid.util.table_find_value(target_plants_list, forward_node.name) then
self.state = state.punch
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
elseif pos.x == self.preposition.x or pos.z == self.preposition.z then
_aux.change_dir(self)
elseif forward_node.name == "air"
and minetest.get_item_group(inetest.get_node(forward_under_pos).name, "wet") > 0
and has_seed_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}
end
elseif self.state == state.punch then
if self.time_count >= max_punch_time then
if maidroid.util.table_find_value(target_plants_list, forward_node.name) then
local inv = minetest.get_inventory{type = "detached", name = self.invname}
local stacks = minetest.get_node_drops(forward_node.name)
for _, stack in ipairs(stacks) do
local leftover = inv:add_item("main", stack)
minetest.add_item(forward_pos, leftover)
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.plant then
if self.time_count >= max_plant_time then
if forward_node.name == "air" and minetest.get_item_group(
minetest.get_node(forward_under_pos).name, "soil") > 0 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(forward_pos, {name = item_name, param2 = 1})
stack:take_item(1)
inv:set_stack("main", idx, 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
end
self.preposition = pos
return
end
})

View File

@ -0,0 +1,132 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
local util = maidroid.util
local _aux = maidroid.modules._aux
local state = {walk = 0, plant = 1, punch = 2}
local max_punch_time = 20
local max_plant_time = 20
local target_tree_list = { "default:tree" }
local target_sapling_list = { "default:sapling" }
-- punchを始める必要があるか否かを調べる
local function check_punch_flag(forward_pos)
local forward_upper_pos = util.table_shallow_copy(forward_pos)
while true do
local forward_upper_node = minetest.get_node(forward_upper_pos)
if util.table_find_value(target_tree_list, forward_upper_node.name) then
return true, forward_upper_pos, forward_upper_node
elseif forward_upper_node.name ~= "air" then break end
forward_upper_pos.y = forward_upper_pos.y + 1
end
return false, nil, nil
end
-- 苗木を持っているかを調べる
local function has_sapling_item(self)
local inv = maidroid._aux.get_maidroid_inventory(self)
local stacks = inv:get_list("main")
for _, stack in ipairs(stacks) do
local item_name = stack:get_name()
if util.table_find_value(target_sapling_list, item_name) then
return true
end
end
return false
end
-- 木こりモジュールを登録する
maidroid.register_module("maidroid:lumberjack", {
description = "Maidroid Module : Lumberjack",
inventory_image = "maidroid_lumberjack_module.png",
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()
_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}
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
if check_punch_flag(forward_pos) then -- punch tree node
self.state = state.punch
self.object:set_animation(maidroid.animations.mine, 15, 0)
self.object:setvelocity{x = 0, y = 0, z = 0}
elseif pos.x == self.preposition.x or pos.z == self.preposition.z then
_aux.change_dir(self)
elseif forward_node.name == "air"
and minetest.get_item_group(forward_under_node.name, "soil") > 0
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}
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(forward_pos)
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
end
self.preposition = pos
end
})

BIN
textures/normal_maidroid.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

BIN
textures/normal_module.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

23
util.lua Normal file
View File

@ -0,0 +1,23 @@
------------------------------------------------------------
-- Copyright (c) 2016 tacigar
-- https://github.com/tacigar/maidroid
------------------------------------------------------------
maidroid.util = {}
-- ある値を持つキーが存在するかを調べる
function maidroid.util.table_find_value(tbl, value)
for k, v in ipairs(tbl) do
if v == value then return true, k end
end
return false, nil
end
-- テーブルの浅いコピー
function maidroid.util.table_shallow_copy(source)
local copy = {}
for key, value in pairs(source) do
copy[key] = value
end
return copy
end