Mineclonia/mods/ITEMS/minetest-3d_armor/3d_armor_stand/init.lua

261 lines
7.3 KiB
Lua
Raw Normal View History

2017-01-06 03:23:11 +00:00
local elements = {"head", "torso", "legs", "feet"}
local function get_stand_object(pos)
local object = nil
local objects = minetest.get_objects_inside_radius(pos, 0.5) or {}
for _, obj in pairs(objects) do
local ent = obj:get_luaentity()
if ent then
if ent.name == "3d_armor_stand:armor_entity" then
-- Remove duplicates
if object then
obj:remove()
else
object = obj
end
end
end
end
return object
end
local function update_entity(pos)
local node = minetest.get_node(pos)
local object = get_stand_object(pos)
if object then
if not string.find(node.name, "3d_armor_stand:") then
object:remove()
return
end
else
object = minetest.add_entity(pos, "3d_armor_stand:armor_entity")
end
if object then
local texture = "3d_armor_trans.png"
local textures = {}
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local yaw = 0
if inv then
for _, element in pairs(elements) do
local stack = inv:get_stack("armor_"..element, 1)
if stack:get_count() == 1 then
local item = stack:get_name() or ""
local def = stack:get_definition() or {}
local groups = def.groups or {}
if groups["armor_"..element] then
local texture = def.texture or item:gsub("%:", "_")
table.insert(textures, texture..".png")
end
end
end
end
if #textures > 0 then
texture = table.concat(textures, "^")
end
if node.param2 then
local rot = node.param2 % 4
if rot == 1 then
yaw = 3 * math.pi / 2
elseif rot == 2 then
yaw = math.pi
elseif rot == 3 then
yaw = math.pi / 2
end
end
object:setyaw(yaw)
object:set_properties({textures={texture}})
end
end
-- Drop all armor of the armor stand on the ground
local drop_armor = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
for _, element in pairs(elements) do
local stack = inv:get_stack("armor_"..element, 1)
if not stack:is_empty() then
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
minetest.add_item(p, stack)
end
end
end
2017-12-05 13:09:39 +00:00
local on_rotate
if minetest.get_modpath("screwdriver") then
on_rotate = screwdriver.disallow
end
2017-02-27 17:32:35 +00:00
-- FIXME: The armor stand should be an entity
2017-01-06 03:23:11 +00:00
minetest.register_node("3d_armor_stand:armor_stand", {
2017-01-06 03:29:38 +00:00
description = "Armor Stand",
2017-06-11 20:06:07 +00:00
_doc_items_longdesc = "An armor stand is a decorative object which can display different pieces of armor. Anything which players can wear as armor can also be put on an armor stand.",
2017-03-11 15:42:23 +00:00
_doc_items_usagehelp = "Hold an armor item in your hand and rightclick the armor stand to put it on the armor stand. To take a piece of armor from the armor stand, select your hand and rightclick the armor stand. You'll retrieve the first armor item from above.",
2017-01-06 03:23:11 +00:00
drawtype = "mesh",
mesh = "3d_armor_stand.obj",
2017-01-06 03:41:48 +00:00
inventory_image = "3d_armor_stand_item.png",
wield_image = "3d_armor_stand_item.png",
2017-06-11 12:21:52 +00:00
tiles = {"default_wood.png", "mcl_stairs_stone_slab_top.png"},
2017-01-06 03:23:11 +00:00
paramtype = "light",
paramtype2 = "facedir",
walkable = false,
is_ground_content = false,
2017-01-16 22:34:40 +00:00
stack_max = 16,
2017-01-06 03:23:11 +00:00
selection_box = {
type = "fixed",
fixed = {-0.5,-0.5,-0.5, 0.5,1.4,0.5}
},
2017-02-27 17:32:35 +00:00
-- FIXME: This should be breakable by 2 quick punches
groups = {handy=1, deco_block=1},
_mcl_hardness = 2,
sounds = mcl_sounds.node_sound_wood_defaults(),
2017-01-06 03:23:11 +00:00
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
for _, element in pairs(elements) do
inv:set_size("armor_"..element, 1)
end
end,
-- Drop all armor on the ground when it got destroyed
on_destruct = drop_armor,
-- Put piece of armor on armor stand, or take one away
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
-- Check if player wields armor
local name = itemstack:get_name()
local list
for e=1, #elements do
local g = minetest.get_item_group(name, "armor_" .. elements[e])
if g ~= nil and g ~= 0 then
list = "armor_" .. elements[e]
break
end
end
-- If player wields armor, put it on armor stand
local inv = minetest.get_inventory({type = "node", pos = pos})
local wielditem = clicker:get_wielded_item()
if not inv then return end
if list then
-- ... but only if the slot is free
local single_item = ItemStack(itemstack)
single_item:set_count(1)
if inv:is_empty(list) then
inv:add_item(list, single_item)
update_entity(pos)
itemstack:take_item()
return itmstack
end
end
-- Take armor from stand if player has a free hand or wields the same armor type (if stackable)
for e=1, #elements do
local stand_armor = inv:get_stack("armor_" .. elements[e], 1)
if not stand_armor:is_empty() then
local pinv = clicker:get_inventory()
local taken = false
-- Empty hand
if wielditem:get_name() == "" then
pinv:set_stack("main", clicker:get_wield_index(), stand_armor)
taken = true
-- Stackable armor type (if not already full). This is the case for e.g. mob heads.
-- This is done purely for convenience.
elseif (wielditem:get_name() == stand_armor:get_name() and wielditem:get_count() < wielditem:get_stack_max()) then
wielditem:set_count(wielditem:get_count()+1)
pinv:set_stack("main", clicker:get_wield_index(), wielditem)
taken = true
end
if taken then
stand_armor:take_item()
inv:set_stack("armor_" .. elements[e], 1, stand_armor)
update_entity(pos)
end
return clicker:get_wielded_item()
end
end
return itemstack
end,
2017-01-06 03:23:11 +00:00
after_place_node = function(pos)
minetest.add_entity(pos, "3d_armor_stand:armor_entity")
end,
allow_metadata_inventory_put = function(pos, listname, index, stack)
local def = stack:get_definition() or {}
local groups = def.groups or {}
if groups[listname] then
return 1
end
return 0
end,
allow_metadata_inventory_move = function(pos)
return 0
end,
on_metadata_inventory_put = function(pos)
update_entity(pos)
end,
on_metadata_inventory_take = function(pos)
update_entity(pos)
end,
after_destruct = function(pos)
update_entity(pos)
end,
on_blast = function(pos)
local object = get_stand_object(pos)
if object then
object:remove()
end
minetest.after(1, function(pos)
update_entity(pos)
end, pos)
end,
2017-12-05 13:09:39 +00:00
on_rotate = on_rotate,
2017-01-06 03:23:11 +00:00
})
minetest.register_entity("3d_armor_stand:armor_entity", {
physical = true,
visual = "mesh",
mesh = "3d_armor_entity.obj",
visual_size = {x=1, y=1},
collisionbox = {-0.1,-0.4,-0.1, 0.1,1.3,0.1},
2017-01-06 03:23:11 +00:00
textures = {"3d_armor_trans.png"},
pos = nil,
timer = 0,
on_activate = function(self)
local pos = self.object:getpos()
2017-02-14 19:22:34 +00:00
self.object:set_armor_groups({immortal=1})
2017-01-06 03:23:11 +00:00
if pos then
self.pos = vector.round(pos)
update_entity(pos)
end
end,
on_step = function(self, dtime)
if not self.pos then
return
end
self.timer = self.timer + dtime
if self.timer > 1 then
self.timer = 0
local pos = self.object:getpos()
if pos then
if vector.equals(vector.round(pos), self.pos) then
return
end
end
update_entity(self.pos)
self.object:remove()
end
end,
})
2017-03-21 03:03:33 +00:00
if minetest.get_modpath("doc_identifier") ~= nil then
doc.sub.identifier.register_object("3d_armor_stand:armor_entity", "nodes", "3d_armor_stand:armor_stand")
end
2017-01-06 03:23:11 +00:00
minetest.register_craft({
output = "3d_armor_stand:armor_stand",
recipe = {
2017-01-31 22:32:56 +00:00
{"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"},
{"", "mcl_core:stick", ""},
2017-06-05 16:40:56 +00:00
{"mcl_core:stick", "mcl_stairs:slab_stone", "mcl_core:stick"},
2017-01-06 03:23:11 +00:00
}
})