Fix armor stand repairing damaged armor
[MineClone/MineClone2/killajk2201.git] / mods / ITEMS / minetest-3d_armor / 3d_armor_stand / init.lua
blob65407ff4a04f11e022f24f905e10453bd2a9cfeb
1 local elements = {"head", "torso", "legs", "feet"}
3 local function get_stand_object(pos)
4 local object = nil
5 local objects = minetest.get_objects_inside_radius(pos, 0.5) or {}
6 for _, obj in pairs(objects) do
7 local ent = obj:get_luaentity()
8 if ent then
9 if ent.name == "3d_armor_stand:armor_entity" then
10 -- Remove duplicates
11 if object then
12 obj:remove()
13 else
14 object = obj
15 end
16 end
17 end
18 end
19 return object
20 end
22 local function update_entity(pos)
23 local node = minetest.get_node(pos)
24 local object = get_stand_object(pos)
25 if object then
26 if not string.find(node.name, "3d_armor_stand:") then
27 object:remove()
28 return
29 end
30 else
31 object = minetest.add_entity(pos, "3d_armor_stand:armor_entity")
32 end
33 if object then
34 local texture = "3d_armor_trans.png"
35 local textures = {}
36 local meta = minetest.get_meta(pos)
37 local inv = meta:get_inventory()
38 local yaw = 0
39 if inv then
40 for _, element in pairs(elements) do
41 local stack = inv:get_stack("armor_"..element, 1)
42 if stack:get_count() == 1 then
43 local item = stack:get_name() or ""
44 local def = stack:get_definition() or {}
45 local groups = def.groups or {}
46 if groups["armor_"..element] then
47 local texture = def.texture or item:gsub("%:", "_")
48 table.insert(textures, texture..".png")
49 end
50 end
51 end
52 end
53 if #textures > 0 then
54 texture = table.concat(textures, "^")
55 end
56 if node.param2 then
57 local rot = node.param2 % 4
58 if rot == 1 then
59 yaw = 3 * math.pi / 2
60 elseif rot == 2 then
61 yaw = math.pi
62 elseif rot == 3 then
63 yaw = math.pi / 2
64 end
65 end
66 object:setyaw(yaw)
67 object:set_properties({textures={texture}})
68 end
69 end
71 -- Drop all armor of the armor stand on the ground
72 local drop_armor = function(pos)
73 local meta = minetest.get_meta(pos)
74 local inv = meta:get_inventory()
75 for _, element in pairs(elements) do
76 local stack = inv:get_stack("armor_"..element, 1)
77 if not stack:is_empty() then
78 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}
79 minetest.add_item(p, stack)
80 end
81 end
82 end
84 -- FIXME: The armor stand should be an entity
85 minetest.register_node("3d_armor_stand:armor_stand", {
86 description = "Armor Stand",
87 _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.",
88 _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.",
89 drawtype = "mesh",
90 mesh = "3d_armor_stand.obj",
91 inventory_image = "3d_armor_stand_item.png",
92 wield_image = "3d_armor_stand_item.png",
93 tiles = {"default_wood.png", "mcl_stairs_stone_slab_top.png"},
94 paramtype = "light",
95 paramtype2 = "facedir",
96 walkable = false,
97 is_ground_content = false,
98 stack_max = 16,
99 selection_box = {
100 type = "fixed",
101 fixed = {-0.5,-0.5,-0.5, 0.5,1.4,0.5}
103 -- FIXME: This should be breakable by 2 quick punches
104 groups = {handy=1, deco_block=1},
105 _mcl_hardness = 2,
106 sounds = mcl_sounds.node_sound_wood_defaults(),
107 on_construct = function(pos)
108 local meta = minetest.get_meta(pos)
109 local inv = meta:get_inventory()
110 for _, element in pairs(elements) do
111 inv:set_size("armor_"..element, 1)
113 end,
114 -- Drop all armor on the ground when it got destroyed
115 on_destruct = drop_armor,
116 -- Put piece of armor on armor stand, or take one away
117 on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
118 -- Check if player wields armor
119 local name = itemstack:get_name()
120 local list
121 for e=1, #elements do
122 local g = minetest.get_item_group(name, "armor_" .. elements[e])
123 if g ~= nil and g ~= 0 then
124 list = "armor_" .. elements[e]
125 break
129 -- If player wields armor, put it on armor stand
130 local inv = minetest.get_inventory({type = "node", pos = pos})
131 local wielditem = clicker:get_wielded_item()
132 if not inv then return end
133 if list then
134 -- ... but only if the slot is free
135 local single_item = ItemStack(itemstack)
136 single_item:set_count(1)
137 if inv:is_empty(list) then
138 inv:add_item(list, single_item)
139 update_entity(pos)
140 itemstack:take_item()
141 return itmstack
145 -- Take armor from stand if player has a free hand or wields the same armor type (if stackable)
146 for e=1, #elements do
147 local stand_armor = inv:get_stack("armor_" .. elements[e], 1)
148 if not stand_armor:is_empty() then
149 local pinv = clicker:get_inventory()
150 local taken = false
151 -- Empty hand
152 if wielditem:get_name() == "" then
153 pinv:set_stack("main", clicker:get_wield_index(), stand_armor)
154 taken = true
155 -- Stackable armor type (if not already full). This is the case for e.g. mob heads.
156 -- This is done purely for convenience.
157 elseif (wielditem:get_name() == stand_armor:get_name() and wielditem:get_count() < wielditem:get_stack_max()) then
158 wielditem:set_count(wielditem:get_count()+1)
159 pinv:set_stack("main", clicker:get_wield_index(), wielditem)
160 taken = true
162 if taken then
163 stand_armor:take_item()
164 inv:set_stack("armor_" .. elements[e], 1, stand_armor)
165 update_entity(pos)
167 return clicker:get_wielded_item()
170 return itemstack
171 end,
172 after_place_node = function(pos)
173 minetest.add_entity(pos, "3d_armor_stand:armor_entity")
174 end,
175 allow_metadata_inventory_put = function(pos, listname, index, stack)
176 local def = stack:get_definition() or {}
177 local groups = def.groups or {}
178 if groups[listname] then
179 return 1
181 return 0
182 end,
183 allow_metadata_inventory_move = function(pos)
184 return 0
185 end,
186 on_metadata_inventory_put = function(pos)
187 update_entity(pos)
188 end,
189 on_metadata_inventory_take = function(pos)
190 update_entity(pos)
191 end,
192 after_destruct = function(pos)
193 update_entity(pos)
194 end,
195 on_blast = function(pos)
196 local object = get_stand_object(pos)
197 if object then
198 object:remove()
200 minetest.after(1, function(pos)
201 update_entity(pos)
202 end, pos)
203 end,
206 minetest.register_entity("3d_armor_stand:armor_entity", {
207 physical = true,
208 visual = "mesh",
209 mesh = "3d_armor_entity.obj",
210 visual_size = {x=1, y=1},
211 collisionbox = {-0.1,-0.4,-0.1, 0.1,1.3,0.1},
212 textures = {"3d_armor_trans.png"},
213 pos = nil,
214 timer = 0,
215 on_activate = function(self)
216 local pos = self.object:getpos()
217 self.object:set_armor_groups({immortal=1})
218 if pos then
219 self.pos = vector.round(pos)
220 update_entity(pos)
222 end,
223 on_step = function(self, dtime)
224 if not self.pos then
225 return
227 self.timer = self.timer + dtime
228 if self.timer > 1 then
229 self.timer = 0
230 local pos = self.object:getpos()
231 if pos then
232 if vector.equals(vector.round(pos), self.pos) then
233 return
236 update_entity(self.pos)
237 self.object:remove()
239 end,
242 if minetest.get_modpath("doc_identifier") ~= nil then
243 doc.sub.identifier.register_object("3d_armor_stand:armor_entity", "nodes", "3d_armor_stand:armor_stand")
246 minetest.register_craft({
247 output = "3d_armor_stand:armor_stand",
248 recipe = {
249 {"mcl_core:stick", "mcl_core:stick", "mcl_core:stick"},
250 {"", "mcl_core:stick", ""},
251 {"mcl_core:stick", "mcl_stairs:slab_stone", "mcl_core:stick"},