armor.lua 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. -- Global Defaults - use armor.conf to override these
  2. ARMOR_INIT_DELAY = 1
  3. ARMOR_INIT_TIMES = 1
  4. ARMOR_BONES_DELAY = 1
  5. ARMOR_UPDATE_TIME = 1
  6. ARMOR_DROP = minetest.get_modpath("bones") ~= nil
  7. ARMOR_DESTROY = false
  8. ARMOR_LEVEL_MULTIPLIER = 1
  9. ARMOR_HEAL_MULTIPLIER = 1
  10. ARMOR_MATERIALS = {
  11. wood = "group:wood",
  12. cactus = "default:cactus",
  13. steel = "default:steel_ingot",
  14. bronze = "default:bronze_ingot",
  15. diamond = "default:diamond",
  16. gold = "default:gold_ingot",
  17. mithril = "moreores:mithril_ingot",
  18. crystal = "ethereal:crystal_ingot",
  19. }
  20. ARMOR_FIRE_PROTECT = minetest.get_modpath("ethereal") ~= nil
  21. ARMOR_FIRE_NODES = {
  22. {"default:lava_source", 5, 4},
  23. {"default:lava_flowing", 5, 4},
  24. {"fire:basic_flame", 3, 4},
  25. {"ethereal:crystal_spike", 2, 1},
  26. {"bakedclay:safe_fire", 2, 1},
  27. {"default:torch", 1, 1},
  28. }
  29. -- Load Armor Configs
  30. local modpath = minetest.get_modpath("lottarmor")
  31. local worldpath = minetest.get_worldpath()
  32. local input = io.open(modpath.."/armor.conf", "r")
  33. if input then
  34. dofile(modpath.."/armor.conf")
  35. input:close()
  36. input = nil
  37. end
  38. input = io.open(worldpath.."/armor.conf", "r")
  39. if input then
  40. dofile(worldpath.."/armor.conf")
  41. input:close()
  42. input = nil
  43. end
  44. if not minetest.get_modpath("moreores") then
  45. ARMOR_MATERIALS.mithril = nil
  46. end
  47. if not minetest.get_modpath("ethereal") then
  48. ARMOR_MATERIALS.crystal = nil
  49. end
  50. -- override hot nodes so they do not hurt player anywhere but mod
  51. if ARMOR_FIRE_PROTECT == true then
  52. for _, row in ipairs(ARMOR_FIRE_NODES) do
  53. if minetest.registered_nodes[row[1]] then
  54. minetest.override_item(row[1], {damage_per_second = 0})
  55. end
  56. end
  57. end
  58. -- Armor API
  59. local inv_mod = nil
  60. local time = 0
  61. gui_bg_img = "background[5,5;1,1;gui_formbg.png;true]"
  62. gui_slots = "listcolors[#606060AA;#606060;#141318;#30434C;#FFF]"
  63. armor = {
  64. player_hp = {},
  65. elements = {"head", "torso", "legs", "feet"},
  66. physics = {"jump","speed","gravity"},
  67. formspec = "size[8,8.5]"
  68. ..gui_bg_img
  69. ..gui_slots
  70. .."image[0,0;1,1;lottarmor_helmet.png]"
  71. .."image[0,1;1,1;lottarmor_chestplate.png]"
  72. .."image[0,2;1,1;lottarmor_leggings.png]"
  73. .."image[0,3;1,1;lottarmor_boots.png]"
  74. .."image[3,0;1,1;lottarmor_helmet.png]"
  75. .."image[3,1;1,1;lottarmor_shirt.png]"
  76. .."image[3,2;1,1;lottarmor_trousers.png]"
  77. .."image[3,3;1,1;lottarmor_shoes.png]"
  78. .."image[4,0;1,1;lottarmor_cloak.png]"
  79. .."list[detached:player_name_armor;armor;0,0;1,4;]"
  80. .."list[detached:player_name_armor;armor;2,2;1,1;4]"
  81. .."list[detached:player_name_clothing;clothing;3,0;1,4;]"
  82. .."list[detached:player_name_clothing;clothing;4,0;1,1;4]"
  83. .."image[1.16,0.25;2,4;armor_preview]"
  84. .."image[2,2;1,1;lottarmor_shield.png]"
  85. .."list[current_player;main;0,4.25;8,1;]"
  86. .."list[current_player;main;0,5.5;8,3;8]"
  87. .."image[5.05,0;3.5,1;lottarmor_crafting.png]"
  88. .."list[current_player;craft;4,1;3,3;]"
  89. .."list[current_player;craftpreview;7,2;1,1;]"
  90. .."listring[current_player;main]"
  91. .."listring[current_player;craft]"
  92. .."image[7,3;1,1;lottarmor_trash.png]"
  93. .."list[detached:armor_trash;main;7,3;1,1;]"
  94. .."image_button[7,1;1,1;bags.png;bags;]",
  95. textures = {},
  96. def = {state=0, count = 0},
  97. version = "0.4.4",
  98. }
  99. if minetest.setting_getbool("creative_mode") then
  100. armor.formspec = armor.formspec .. "tabheader[-0.12,-0.12;creative_tabs;Main,Creative;1;true;false"
  101. end
  102. local get_formspec = function(player,page)
  103. if page=="bags" then
  104. return "size[8,7.5]"
  105. .."list[current_player;main;0,3.5;8,4;]"
  106. .."button[0,0;2,0.5;main;Back]"
  107. .."button[0,2;2,0.5;bag1;Bag 1]"
  108. .."button[2,2;2,0.5;bag2;Bag 2]"
  109. .."button[4,2;2,0.5;bag3;Bag 3]"
  110. .."button[6,2;2,0.5;bag4;Food Bag]"
  111. .."list[detached:"..player:get_player_name().."_bags;bag1;0.5,1;1,1;]"
  112. .."list[detached:"..player:get_player_name().."_bags;bag2;2.5,1;1,1;]"
  113. .."list[detached:"..player:get_player_name().."_bags;bag3;4.5,1;1,1;]"
  114. .."list[detached:"..player:get_player_name().."_bags;bag4;6.5,1;1,1;]"
  115. .."background[5,5;1,1;gui_formbg.png;true]"
  116. end
  117. for i=1,4 do
  118. if page=="bag"..i then
  119. local image = player:get_inventory():get_stack("bag"..i, 1):get_definition().inventory_image
  120. return "size[8,8.5]"
  121. .."list[current_player;main;0,4.5;8,4;]"
  122. .."button[0,0;2,0.5;main;Main]"
  123. .."button[2,0;2,0.5;bags;Bags]"
  124. .."image[7,0;1,1;"..image.."]"
  125. .."list[current_player;bag"..i.."contents;0,1;8,3;]"
  126. .."listring[]"
  127. .."background[5,5;1,1;gui_formbg.png;true]"
  128. end
  129. end
  130. end
  131. --- Bags
  132. minetest.register_on_player_receive_fields(function(player, formname, fields)
  133. if fields.bags then
  134. inventory_plus.set_inventory_formspec(player, get_formspec(player,"bags"))
  135. return
  136. end
  137. for i=1,4 do
  138. local page = "bag"..i
  139. if fields[page] then
  140. if player:get_inventory():get_stack(page, 1):get_definition().groups.bagslots==nil then
  141. page = "bags"
  142. end
  143. inventory_plus.set_inventory_formspec(player, get_formspec(player,page))
  144. return
  145. end
  146. end
  147. end)
  148. --Trash
  149. local trash = minetest.create_detached_inventory("armor_trash", {
  150. allow_put = function(inv, listname, index, stack, player)
  151. return stack:get_count()
  152. end,
  153. on_put = function(inv, listname, index, stack, player)
  154. inv:set_stack(listname, index, "")
  155. end,
  156. })
  157. trash:set_size("main", 1)
  158. armor.update_player_visuals = function(self, player)
  159. multiskin:update_player_visuals(player)
  160. end
  161. armor.set_player_armor = function(self, player)
  162. local name, player_inv = armor:get_valid_player(player, "[set_player_armor]")
  163. if not name then
  164. return
  165. end
  166. local armor_texture = "lottarmor_trans.png"
  167. local armor_level = 0
  168. local armor_heal = 0
  169. local armor_fire = 0
  170. local state = 0
  171. local items = 0
  172. local elements = {}
  173. local textures = {}
  174. local physics_o = {speed=1,gravity=1,jump=1}
  175. local material = {type=nil, count=1}
  176. local preview = multiskin:get_preview(name) or "character_preview.png"
  177. for _,v in ipairs(self.elements) do
  178. elements[v] = false
  179. end
  180. for i = 1, 5 do
  181. local stack = player_inv:get_stack("armor", i)
  182. local item = stack:get_name()
  183. if stack:get_count() == 1 then
  184. local def = stack:get_definition()
  185. for k, v in pairs(elements) do
  186. if v == false then
  187. local level = def.groups["armor_"..k]
  188. if level and not def.groups["clothes"] then
  189. local texture = item:gsub("%:", "_")
  190. table.insert(textures, texture..".png")
  191. preview = preview.."^"..texture.."_preview.png"
  192. armor_level = armor_level + level
  193. state = state + stack:get_wear()
  194. items = items + 1
  195. local heal = def.groups["armor_heal"] or 0
  196. armor_heal = armor_heal + heal
  197. local fire = def.groups["armor_fire"] or 0
  198. armor_fire = armor_fire + fire
  199. for kk,vv in ipairs(self.physics) do
  200. local o_value = def.groups["physics_"..vv]
  201. if o_value then
  202. physics_o[vv] = physics_o[vv] + o_value
  203. end
  204. end
  205. local mat = string.match(item, "%:.+_(.+)$")
  206. if material.type then
  207. if material.type == mat then
  208. material.count = material.count + 1
  209. end
  210. else
  211. material.type = mat
  212. end
  213. elements[k] = true
  214. end
  215. end
  216. end
  217. end
  218. end
  219. if minetest.get_modpath("shields") then
  220. armor_level = armor_level * 0.9
  221. end
  222. if material.type and material.count == #self.elements then
  223. armor_level = armor_level * 1.1
  224. end
  225. armor_level = armor_level * ARMOR_LEVEL_MULTIPLIER
  226. armor_heal = armor_heal * ARMOR_HEAL_MULTIPLIER
  227. if #textures > 0 then
  228. armor_texture = table.concat(textures, "^")
  229. end
  230. local armor_groups = {fleshy=100}
  231. if armor_level > 0 then
  232. armor_groups.level = math.floor(armor_level / 20)
  233. armor_groups.fleshy = 100 - armor_level
  234. end
  235. player:set_armor_groups(armor_groups)
  236. if player:get_attribute("lott:immunity") ~= nil then
  237. player:set_armor_groups({fleshy = 1})
  238. else player:set_armor_groups(armor_groups)
  239. end
  240. player:set_physics_override(physics_o)
  241. self.textures[name].armor = armor_texture
  242. self.textures[name].preview = preview
  243. self.def[name].state = state
  244. self.def[name].count = items
  245. self.def[name].level = armor_level
  246. self.def[name].heal = armor_heal
  247. self.def[name].jump = physics_o.jump
  248. self.def[name].speed = physics_o.speed
  249. self.def[name].gravity = physics_o.gravity
  250. self.def[name].fire = armor_fire
  251. multiskin[name].armor = armor_texture
  252. multiskin:update_player_visuals(player)
  253. end
  254. armor.update_armor = function(self, player)
  255. local name, player_inv, armor_inv, pos = armor:get_valid_player(player, "[update_armor]")
  256. if not name then
  257. return
  258. end
  259. local hp = player:get_hp() or 0
  260. if ARMOR_FIRE_PROTECT == true then
  261. pos.y = pos.y + 1.4 -- head level
  262. local node_head = minetest.get_node(pos).name
  263. pos.y = pos.y - 1.2 -- feet level
  264. local node_feet = minetest.get_node(pos).name
  265. -- is player inside a hot node?
  266. for _, row in ipairs(ARMOR_FIRE_NODES) do
  267. -- check for fire protection, if not enough then get hurt
  268. if row[1] == node_head or row[1] == node_feet then
  269. if hp > 0 and armor.def[name].fire < row[2] then
  270. hp = hp - row[3] * ARMOR_UPDATE_TIME
  271. player:set_hp(hp)
  272. break
  273. end
  274. end
  275. end
  276. end
  277. if hp <= 0 or hp == self.player_hp[name] then
  278. return
  279. end
  280. if self.player_hp[name] > hp then
  281. local heal_max = 0
  282. local state = 0
  283. local items = 0
  284. for i = 1, 5 do
  285. local stack = player_inv:get_stack("armor", i)
  286. if stack:get_count() > 0 then
  287. local clothes = stack:get_definition().groups["clothes"] or 0
  288. local use = stack:get_definition().groups["armor_use"] or 0
  289. local heal = stack:get_definition().groups["armor_heal"] or 0
  290. local item = stack:get_name()
  291. stack:add_wear(use)
  292. armor_inv:set_stack("armor", i, stack)
  293. player_inv:set_stack("armor", i, stack)
  294. state = state + stack:get_wear()
  295. if clothes ~= 1 then
  296. items = items + 1
  297. end
  298. if stack:get_count() == 0 then
  299. local desc = minetest.registered_items[item].description
  300. if desc then
  301. minetest.chat_send_player(name, "Your "..desc.." got destroyed!")
  302. end
  303. self:set_player_armor(player)
  304. armor:update_inventory(player)
  305. end
  306. heal_max = heal_max + heal
  307. end
  308. end
  309. self.def[name].state = state
  310. self.def[name].count = items
  311. heal_max = heal_max * ARMOR_HEAL_MULTIPLIER
  312. if heal_max > math.random(100) then
  313. player:set_hp(self.player_hp[name])
  314. return
  315. end
  316. end
  317. self.player_hp[name] = hp
  318. end
  319. armor.get_armor_formspec = function(self, name)
  320. if not armor.textures[name] then
  321. minetest.log("error", "lottarmor: Player texture["..name.."] is nil [get_armor_formspec]")
  322. return ""
  323. end
  324. if not armor.def[name] then
  325. minetest.log("error", "lottarmor: Armor def["..name.."] is nil [get_armor_formspec]")
  326. return ""
  327. end
  328. local formspec = armor.formspec:gsub("player_name", name)
  329. formspec = formspec:gsub("armor_preview", armor.textures[name].preview)
  330. formspec = formspec:gsub("armor_level", armor.def[name].level)
  331. formspec = formspec:gsub("armor_heal", armor.def[name].heal)
  332. formspec = formspec:gsub("armor_fire", armor.def[name].fire)
  333. return formspec
  334. end
  335. armor.update_inventory = function(self, player)
  336. local name = armor:get_valid_player(player, "[set_player_armor]")
  337. if not name or inv_mod == "inventory_enhanced" then
  338. return
  339. end
  340. if inv_mod == "unified_inventory" then
  341. if unified_inventory.current_page[name] == "armor" then
  342. unified_inventory.set_inventory_formspec(player, "armor")
  343. end
  344. else
  345. local formspec = armor:get_armor_formspec(name)
  346. if inv_mod == "inventory_plus" then
  347. local page = player:get_inventory_formspec()
  348. if page:find("detached:"..name.."_armor") then
  349. inventory_plus.set_inventory_formspec(player, formspec)
  350. end
  351. else
  352. player:set_inventory_formspec(formspec)
  353. end
  354. end
  355. end
  356. armor.get_valid_player = function(self, player, msg)
  357. msg = msg or ""
  358. if not player then
  359. minetest.log("error", "lottarmor: Player reference is nil "..msg)
  360. return
  361. end
  362. local name = player:get_player_name()
  363. if not name then
  364. minetest.log("error", "lottarmor: Player name is nil "..msg)
  365. return
  366. end
  367. local pos = player:getpos()
  368. local player_inv = player:get_inventory()
  369. local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
  370. if not pos then
  371. minetest.log("error", "lottarmor: Player position is nil "..msg)
  372. return
  373. elseif not player_inv then
  374. minetest.log("error", "lottarmor: Player inventory is nil "..msg)
  375. return
  376. elseif not armor_inv then
  377. minetest.log("error", "lottarmor: Detached armor inventory is nil "..msg)
  378. return
  379. end
  380. return name, player_inv, armor_inv, pos
  381. end
  382. -- Register Callbacks
  383. minetest.register_on_player_receive_fields(function(player, formname, fields)
  384. local name = armor:get_valid_player(player, "[on_player_receive_fields]")
  385. if not name or inv_mod == "inventory_enhanced" then
  386. return
  387. end
  388. if inv_mod == "inventory_plus" and fields.armor then
  389. local formspec = armor:get_armor_formspec(name)
  390. inventory_plus.set_inventory_formspec(player, formspec)
  391. return
  392. end
  393. end)
  394. minetest.register_on_joinplayer(function(player)
  395. multiskin:init(player)
  396. local name = player:get_player_name()
  397. local player_inv = player:get_inventory()
  398. local armor_inv = minetest.create_detached_inventory(name.."_armor", {
  399. on_put = function(inv, listname, index, stack, player)
  400. player:get_inventory():set_stack(listname, index, stack)
  401. armor:set_player_armor(player)
  402. armor:update_inventory(player)
  403. lottachievements.equip(stack, player, 1)
  404. end,
  405. on_take = function(inv, listname, index, stack, player)
  406. player:get_inventory():set_stack(listname, index, nil)
  407. armor:set_player_armor(player)
  408. armor:update_inventory(player)
  409. lottachievements.equip(stack, player, -1)
  410. end,
  411. on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
  412. local plaver_inv = player:get_inventory()
  413. local stack = inv:get_stack(to_list, to_index)
  414. player_inv:set_stack(to_list, to_index, stack)
  415. player_inv:set_stack(from_list, from_index, nil)
  416. armor:set_player_armor(player)
  417. armor:update_inventory(player)
  418. end,
  419. allow_put = function(inv, listname, index, stack, player)
  420. if index == 1 then
  421. if stack:get_definition().groups.armor_head == nil then
  422. return 0
  423. else
  424. return 1
  425. end
  426. elseif index == 2 then
  427. if stack:get_definition().groups.armor_torso == nil then
  428. return 0
  429. else
  430. return 1
  431. end
  432. elseif index == 3 then
  433. if stack:get_definition().groups.armor_legs == nil then
  434. return 0
  435. else
  436. return 1
  437. end
  438. elseif index == 4 then
  439. if stack:get_definition().groups.armor_feet == nil then
  440. return 0
  441. else
  442. return 1
  443. end
  444. elseif index == 5 then
  445. if stack:get_definition().groups.armor_shield == nil then
  446. return 0
  447. else
  448. return 1
  449. end
  450. end
  451. end,
  452. allow_take = function(inv, listname, index, stack, player)
  453. return stack:get_count()
  454. end,
  455. allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
  456. return 0
  457. end,
  458. }, name)
  459. if inv_mod == "inventory_plus" then
  460. inventory_plus.register_button(player,"armor", "Armor")
  461. end
  462. armor_inv:set_size("armor", 5)
  463. player_inv:set_size("armor", 5)
  464. for i = 1, 5 do
  465. local stack = player_inv:get_stack("armor", i)
  466. armor_inv:set_stack("armor", i, stack)
  467. end
  468. --Bags
  469. local name = player:get_player_name()
  470. local bags_inv = minetest.create_detached_inventory(name.."_bags",{
  471. on_put = function(inv, listname, index, stack, player)
  472. player:get_inventory():set_stack(listname, index, stack)
  473. player:get_inventory():set_size(listname.."contents", stack:get_definition().groups.bagslots)
  474. end,
  475. on_take = function(inv, listname, index, stack, player)
  476. player:get_inventory():set_stack(listname, index, nil)
  477. end,
  478. allow_put = function(inv, listname, index, stack, player)
  479. if stack:get_definition().groups.bagslots then
  480. return 1
  481. else
  482. return 0
  483. end
  484. end,
  485. allow_take = function(inv, listname, index, stack, player)
  486. if player:get_inventory():is_empty(listname.."contents")==true then
  487. return stack:get_count()
  488. else
  489. return 0
  490. end
  491. end,
  492. allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
  493. return 0
  494. end,
  495. }, name)
  496. for i=1,4 do
  497. local bag = "bag"..i
  498. player_inv:set_size(bag, 1)
  499. bags_inv:set_size(bag, 1)
  500. bags_inv:set_stack(bag,1,player_inv:get_stack(bag,1))
  501. end
  502. armor.player_hp[name] = 0
  503. armor.def[name] = {
  504. state = 0,
  505. count = 0,
  506. level = 0,
  507. heal = 0,
  508. jump = 1,
  509. speed = 1,
  510. gravity = 1,
  511. fire = 0,
  512. }
  513. armor.textures[name] = {
  514. armor = "lottarmor_trans.png",
  515. preview = "character_preview.png"
  516. }
  517. for i=1, ARMOR_INIT_TIMES do
  518. minetest.after(ARMOR_INIT_DELAY * i, function(player)
  519. armor:set_player_armor(player)
  520. if not inv_mod and not minetest.setting_getbool("creative_mode") then
  521. armor:update_inventory(player)
  522. end
  523. end, player)
  524. end
  525. end)
  526. if ARMOR_DROP == true or ARMOR_DESTROY == true then
  527. armor.drop_armor = function(pos, stack)
  528. local obj = minetest.add_item(pos, stack)
  529. if obj then
  530. obj:setvelocity({x=math.random(-1, 1), y=5, z=math.random(-1, 1)})
  531. end
  532. end
  533. minetest.register_on_dieplayer(function(player)
  534. local name, player_inv, armor_inv, pos = armor:get_valid_player(player, "[on_dieplayer]")
  535. if not name or minetest.setting_getbool("creative_mode") == true then
  536. return
  537. end
  538. local drop = {}
  539. for i=1, player_inv:get_size("armor") do
  540. local stack = armor_inv:get_stack("armor", i)
  541. if stack:get_count() > 0 then
  542. table.insert(drop, stack)
  543. armor_inv:set_stack("armor", i, nil)
  544. player_inv:set_stack("armor", i, nil)
  545. end
  546. end
  547. armor:set_player_armor(player)
  548. if inv_mod == "unified_inventory" then
  549. unified_inventory.set_inventory_formspec(player, "craft")
  550. elseif inv_mod == "inventory_plus" then
  551. local formspec = inventory_plus.get_formspec(player,"main")
  552. inventory_plus.set_inventory_formspec(player, formspec)
  553. else
  554. armor:update_inventory(player)
  555. end
  556. if ARMOR_DESTROY == false then
  557. minetest.after(ARMOR_BONES_DELAY, function()
  558. local node = minetest.get_node(vector.round(pos))
  559. if node then
  560. if node.name == "bones:bones" then
  561. local meta = minetest.get_meta(vector.round(pos))
  562. local owner = meta:get_string("owner")
  563. local inv = meta:get_inventory()
  564. for _,stack in ipairs(drop) do
  565. if name == owner and inv:room_for_item("main", stack) then
  566. inv:add_item("main", stack)
  567. else
  568. armor.drop_armor(pos, stack)
  569. end
  570. end
  571. end
  572. else
  573. for _,stack in ipairs(drop) do
  574. armor.drop_armor(pos, stack)
  575. end
  576. end
  577. end)
  578. end
  579. end)
  580. end
  581. minetest.register_globalstep(function(dtime)
  582. time = time + dtime
  583. if time > ARMOR_UPDATE_TIME then
  584. for _,player in ipairs(minetest.get_connected_players()) do
  585. armor:update_armor(player)
  586. end
  587. time = 0
  588. end
  589. end)