2017-01-06 05:23:11 +02: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
2017-06-11 15:16:22 +03:00
-- 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-02-27 19:32:35 +02:00
-- FIXME: The armor stand should be an entity
2017-01-06 05:23:11 +02:00
minetest.register_node ( " 3d_armor_stand:armor_stand " , {
2017-01-06 05:29:38 +02:00
description = " Armor Stand " ,
2017-03-11 17:42:23 +02:00
_doc_items_longdesc = " An armor stand is a decorative object which displays different pieces of armor. " ,
_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 05:23:11 +02:00
drawtype = " mesh " ,
mesh = " 3d_armor_stand.obj " ,
2017-01-06 05:41:48 +02:00
inventory_image = " 3d_armor_stand_item.png " ,
2017-06-10 16:18:48 +03:00
wield_image = " 3d_armor_stand_item.png " ,
2017-06-11 15:21:52 +03:00
tiles = { " default_wood.png " , " mcl_stairs_stone_slab_top.png " } ,
2017-01-06 05:23:11 +02:00
paramtype = " light " ,
paramtype2 = " facedir " ,
walkable = false ,
2017-05-30 18:18:19 +03:00
is_ground_content = false ,
2017-01-17 00:34:40 +02:00
stack_max = 16 ,
2017-01-06 05:23:11 +02:00
selection_box = {
type = " fixed " ,
fixed = { - 0.5 , - 0.5 , - 0.5 , 0.5 , 1.4 , 0.5 }
} ,
2017-02-27 19:32:35 +02:00
-- FIXME: This should be breakable by 2 quick punches
groups = { handy = 1 , deco_block = 1 } ,
_mcl_hardness = 2 ,
2017-02-11 19:46:23 +02:00
sounds = mcl_sounds.node_sound_wood_defaults ( ) ,
2017-01-06 05:23:11 +02: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 ,
2017-06-11 15:16:22 +03:00
-- Drop all armor on the ground when it got destroyed
on_destruct = drop_armor ,
2017-06-11 16:31:14 +03:00
-- Put piece of armor on armor stand, or take one away
2017-02-19 03:09:49 +02:00
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
2017-06-11 16:31:14 +03:00
-- ... but only if the slot is free
local single_item = itemstack : get_name ( )
if inv : is_empty ( list ) then
inv : add_item ( list , single_item )
2017-02-19 03:09:49 +02:00
update_entity ( pos )
itemstack : take_item ( )
2017-06-11 22:08:19 +03:00
return itmstack
2017-02-19 03:09:49 +02:00
end
2017-06-11 22:08:19 +03:00
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
2017-02-19 03:09:49 +02:00
pinv : set_stack ( " main " , clicker : get_wield_index ( ) , stand_armor )
2017-06-11 22:08:19 +03:00
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
2017-02-19 03:09:49 +02:00
stand_armor : take_item ( )
inv : set_stack ( " armor_ " .. elements [ e ] , 1 , stand_armor )
update_entity ( pos )
end
2017-06-11 22:08:19 +03:00
return clicker : get_wielded_item ( )
2017-02-19 03:09:49 +02:00
end
end
return itemstack
end ,
2017-01-06 05:23:11 +02: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 ,
} )
minetest.register_entity ( " 3d_armor_stand:armor_entity " , {
physical = true ,
visual = " mesh " ,
mesh = " 3d_armor_entity.obj " ,
visual_size = { x = 1 , y = 1 } ,
2017-03-21 05:01:32 +02:00
collisionbox = { - 0.1 , - 0.4 , - 0.1 , 0.1 , 1.3 , 0.1 } ,
2017-01-06 05:23:11 +02:00
textures = { " 3d_armor_trans.png " } ,
pos = nil ,
timer = 0 ,
on_activate = function ( self )
local pos = self.object : getpos ( )
2017-02-14 21:22:34 +02:00
self.object : set_armor_groups ( { immortal = 1 } )
2017-01-06 05:23:11 +02: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 05:03:33 +02: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 05:23:11 +02:00
minetest.register_craft ( {
output = " 3d_armor_stand:armor_stand " ,
recipe = {
2017-02-01 00:32:56 +02:00
{ " mcl_core:stick " , " mcl_core:stick " , " mcl_core:stick " } ,
{ " " , " mcl_core:stick " , " " } ,
2017-06-05 19:40:56 +03:00
{ " mcl_core:stick " , " mcl_stairs:slab_stone " , " mcl_core:stick " } ,
2017-01-06 05:23:11 +02:00
}
} )