]> git.lizzy.rs Git - Crafter.git/blob - mods/armor/init.lua
Inventory UI improvements
[Crafter.git] / mods / armor / init.lua
1 local
2 minetest,math,pairs
3 =
4 minetest,math,pairs
5
6 local get_item_group = minetest.get_item_group
7 local get_itemdef    = minetest.get_itemdef
8
9
10 local ceil  = math.ceil
11 local random = math.random
12
13 local inv
14 local player_skin
15 local armor_skin
16 local stack
17 local skin_element
18 function recalculate_armor(player, reload_inv)
19     
20     if not player or (player and not player:is_player()) then return end
21
22     inv = player:get_inventory()
23
24     player_skin = get_skin(player)
25     armor_skin = "blank_skin.png"
26
27     stack = inv:get_stack("armor_head",1):get_name()
28     if stack ~= "" and get_item_group(stack,"helmet") > 0 then
29         skin_element = get_itemdef(stack, "wearing_texture")
30         player_skin = player_skin.."^"..skin_element
31     end
32
33     stack = inv:get_stack("armor_torso",1):get_name()
34     if stack ~= "" and get_item_group(stack,"chestplate") > 0 then
35         skin_element = get_itemdef(stack, "wearing_texture")
36         armor_skin = armor_skin.."^"..skin_element
37     end
38
39     stack = inv:get_stack("armor_legs",1):get_name()
40     if stack ~= "" and get_item_group(stack,"leggings") > 0 then
41         skin_element = get_itemdef(stack, "wearing_texture")
42         armor_skin = armor_skin.."^"..skin_element
43     end
44
45     stack = inv:get_stack("armor_feet",1):get_name()
46     if stack ~= "" and get_item_group(stack,"boots") > 0 then
47         skin_element = get_itemdef(stack, "wearing_texture")
48         armor_skin = armor_skin.."^"..skin_element
49     end
50     player:set_properties({textures = {player_skin,armor_skin}})
51     
52     if reload_inv then
53                 inventory.reload(player)
54         else
55                 inventory.set(player)
56         end
57 end
58
59 local inv
60 local armor_absorbtion
61 local level
62 local defense
63 local stack
64 function calculate_armor_absorbtion(player)
65     if not player or (player and not player:is_player()) then return end
66
67     inv = player:get_inventory()
68     armor_absorbtion = 0
69
70     stack = inv:get_stack("armor_head",1):get_name()
71     if stack ~= "" then
72         level = get_item_group(stack,"armor_level")
73         defense = get_item_group(stack,"armor_defense")
74         armor_absorbtion = armor_absorbtion + (level*defense)
75     end
76
77     stack = inv:get_stack("armor_torso",1):get_name()
78     if stack ~= "" then
79         level = get_item_group(stack,"armor_level")
80         defense = get_item_group(stack,"armor_defense")
81         armor_absorbtion = armor_absorbtion + (level*defense)
82     end
83
84     stack = inv:get_stack("armor_legs",1):get_name()
85     if stack ~= "" then
86         level = get_item_group(stack,"armor_level")
87         defense = get_item_group(stack,"armor_defense")
88         armor_absorbtion = armor_absorbtion + (level*defense)
89     end
90
91     stack = inv:get_stack("armor_feet",1):get_name()
92     if stack ~= "" then
93         level = get_item_group(stack,"armor_level")
94         defense = get_item_group(stack,"armor_defense")
95         armor_absorbtion = armor_absorbtion + (level*defense)
96     end
97     if armor_absorbtion > 0 then
98         armor_absorbtion = ceil(armor_absorbtion/4)
99     end
100     return(armor_absorbtion)
101 end
102
103 local level
104 function set_armor_gui(player)
105     if not player or (player and not player:is_player()) then return end
106     level = calculate_armor_absorbtion(player)
107     hud_manager.change_hud({
108                 player    =  player ,
109                 hud_name  = "armor_fg",
110                 element   = "number",
111                 data      =  level
112         })
113 end
114
115
116 local inv
117 local recalc
118 local stack
119 local name
120 local wear_level
121 local new_stack
122
123 function damage_armor(player,damage)
124     if not player or (player and not player:is_player()) then return end
125
126     inv = player:get_inventory()
127     
128     recalc = false
129
130     stack = inv:get_stack("armor_head",1)
131     name = stack:get_name()
132     if name ~= "" then
133         wear_level = ((9-get_item_group(name,"armor_level"))*8)*(5-get_item_group(name,"armor_type"))*damage
134         stack:add_wear(wear_level)
135         inv:set_stack("armor_head", 1, stack)
136         new_stack = inv:get_stack("armor_head",1):get_name()
137         if new_stack == "" then
138             recalc = true
139         end
140     end
141
142     stack = inv:get_stack("armor_torso",1)
143     name = stack:get_name()
144     if name ~= "" then
145         wear_level = ((9-get_item_group(name,"armor_level"))*4)*(5-get_item_group(name,"armor_type"))*damage
146         stack:add_wear(wear_level)
147         inv:set_stack("armor_torso", 1, stack)
148         new_stack = inv:get_stack("armor_torso",1):get_name()
149         if new_stack == "" then
150             recalc = true
151         end
152     end
153
154     stack = inv:get_stack("armor_legs",1)
155     name = stack:get_name()
156     if name ~= "" then
157         wear_level = ((9-get_item_group(name,"armor_level"))*6)*(5-get_item_group(name,"armor_type"))*damage
158         stack:add_wear(wear_level)
159         inv:set_stack("armor_legs", 1, stack)
160         new_stack = inv:get_stack("armor_legs",1):get_name()
161         if new_stack == "" then
162             recalc = true
163         end
164     end
165
166     stack = inv:get_stack("armor_feet",1)
167     name = stack:get_name()
168     if name ~= "" then
169         wear_level = ((9-get_item_group(name,"armor_level"))*10)*(5-get_item_group(name,"armor_type"))*damage
170         stack:add_wear(wear_level)
171         inv:set_stack("armor_feet", 1, stack)
172         new_stack = inv:get_stack("armor_feet",1):get_name()
173         if new_stack == "" then
174             recalc = true
175         end
176     end
177
178     if recalc == true then
179         minetest.sound_play("armor_break",{to_player=player:get_player_name(),gain=1,pitch=random(80,100)/100})
180         recalculate_armor(player)
181         set_armor_gui(player)
182         --do particles too
183     end
184 end
185
186 local inv
187 minetest.register_on_joinplayer(function(player)
188         hud_manager.add_hud(player,"armor_bg",{
189                 hud_elem_type = "statbar",
190                 position = {x = 0.5, y = 1},
191                 text = "armor_icon_bg.png",
192                 number = 20,
193                 size = {x = 24, y = 24},
194                 offset = {x = (-10 * 24) - 25, y = -(48 + 50 + 39)},
195         })
196         hud_manager.add_hud(player,"armor_fg",{
197                 hud_elem_type = "statbar",
198                 position = {x = 0.5, y = 1},
199                 text = "armor_icon.png",
200                 number = calculate_armor_absorbtion(player),
201                 size = {x = 24, y = 24},
202                 offset = {x = (-10 * 24) - 25, y = -(48 + 50 + 39)},
203         })
204     
205     inv = player:get_inventory()
206     inv:set_size("armor_head" ,1)
207     inv:set_size("armor_torso",1)
208     inv:set_size("armor_legs" ,1)
209     inv:set_size("armor_feet" ,1)
210 end)
211
212 minetest.register_on_dieplayer(function(player)
213     set_armor_gui(player)
214 end)
215
216 local acceptable = {
217     ["armor_head"]  = true,
218     ["armor_torso"] = true,
219     ["armor_legs"]  = true,
220     ["armor_feet"]  = true,
221 }
222 minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
223     if acceptable[inventory_info.from_list] or acceptable[inventory_info.to_list] then
224         minetest.after(0,function()
225             recalculate_armor(player, true)
226             set_armor_gui(player)
227         end)
228     end
229 end)
230
231 --only allow players to put armor in the right slots to stop exploiting chestplates
232 local stack
233 local item
234 minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
235     if inventory_info.to_list == "armor_head" then
236         stack = inventory:get_stack(inventory_info.from_list,inventory_info.from_index)
237         item = stack:get_name()
238         if get_item_group(item, "helmet") == 0 then
239             return(0)
240         end
241     elseif inventory_info.to_list == "armor_torso" then
242         stack = inventory:get_stack(inventory_info.from_list,inventory_info.from_index)
243         item = stack:get_name()
244         if get_item_group(item, "chestplate") == 0 then
245             return(0)
246         end
247     elseif inventory_info.to_list == "armor_legs" then
248         stack = inventory:get_stack(inventory_info.from_list,inventory_info.from_index)
249         item = stack:get_name()
250         if get_item_group(item, "leggings") == 0 then
251             return(0)
252         end
253     elseif inventory_info.to_list == "armor_feet" then
254         stack = inventory:get_stack(inventory_info.from_list,inventory_info.from_index)
255         item = stack:get_name()
256         if get_item_group(item, "boots") == 0 then
257             return(0)
258         end
259     end
260 end)
261
262 local materials = {["coal"]=1,["lapis"]=2,["iron"]=3,["chain"]=4,["gold"]=2,["diamond"]=5,["emerald"]=6,["sapphire"]=7,["ruby"]=8} --max 8
263 local armor_type = {["helmet"]=2,["chestplate"]=4,["leggings"]=3,["boots"]=1} --max 4
264
265 local function bool_int(state)
266     if state == true then return(1) end
267     if state == false or not state then return(0) end
268 end
269
270 for material_id,material in pairs(materials) do
271     for armor_id,armor in pairs(armor_type) do
272         --print(material_id,material,"|",armor_id,armor)
273         minetest.register_tool("armor:"..material_id.."_"..armor_id,{
274             description = material_id:gsub("^%l", string.upper).." "..armor_id:gsub("^%l", string.upper),
275     
276             groups = {
277                 armor         = 1,
278                 armor_level   = material,
279                 armor_defense = armor,
280                 helmet        = bool_int(armor_id == "helmet"),
281                 chestplate    = bool_int(armor_id == "chestplate"),
282                 leggings      = bool_int(armor_id == "leggings"),
283                 boots         = bool_int(armor_id == "boots"),
284             },
285             inventory_image = material_id.."_"..armor_id.."_item.png",
286             stack_max = 1,
287             wearing_texture = material_id.."_"..armor_id..".png",
288             tool_capabilities = {
289                 full_punch_interval = 0,
290                 max_drop_level = 0,
291                 groupcaps = {
292                 },
293                 damage_groups = {
294
295                 },
296                 punch_attack_uses = 0,
297             }
298         })
299
300         if armor_id == "helmet" then
301             minetest.register_craft({
302                 output = "armor:"..material_id.."_"..armor_id,
303                 recipe = {
304                     {"main:"..material_id, "main:"..material_id, "main:"..material_id},
305                     {"main:"..material_id, ""                  , "main:"..material_id},
306                     {""                  , ""                  , ""                  }
307                 }
308             })
309         elseif armor_id == "chestplate" then
310             minetest.register_craft({
311                 output = "armor:"..material_id.."_"..armor_id,
312                 recipe = {
313                     {"main:"..material_id, ""                  , "main:"..material_id},
314                     {"main:"..material_id, "main:"..material_id, "main:"..material_id},
315                     {"main:"..material_id, "main:"..material_id, "main:"..material_id}
316                 }
317             })
318         elseif armor_id == "leggings" then
319             minetest.register_craft({
320                 output = "armor:"..material_id.."_"..armor_id,
321                 recipe = {
322                     {"main:"..material_id, "main:"..material_id, "main:"..material_id},
323                     {"main:"..material_id, ""                  , "main:"..material_id},
324                     {"main:"..material_id, ""                  , "main:"..material_id}
325                 }
326             })
327         elseif armor_id == "boots" then
328             minetest.register_craft({
329                 output = "armor:"..material_id.."_"..armor_id,
330                 recipe = {
331                     {""                  , "", ""                  },
332                     {"main:"..material_id, "", "main:"..material_id},
333                     {"main:"..material_id, "", "main:"..material_id}
334                 }
335             })
336             minetest.register_node("armor:"..material_id.."_"..armor_id.."particletexture", {
337                 description = "NIL",
338                 tiles = {material_id.."_"..armor_id.."_item.png"},
339                 groups = {},
340                 drop = "",
341                 drawtype = "allfaces",
342                 on_construct = function(pos)
343                     minetest.remove_node(pos)
344                 end,
345             })
346         end
347         
348     end
349 end