@@ -319,12 +319,85 @@ end end }); end + +local function enchpwrhud(user, flash, fac) + -- this function displays or changes the HUD element + -- that shows how much energy is left in an enchanted + -- item. it is called by the dig handler and sequences + -- callbacks to remove the HUD from the screen once + -- its timeleft property has been used up. timeleft is + -- reset if the 'flash' argument, which indicates + -- whether the enchantment has just been used, is set + -- to true; otherwise, it is left alone. + -- + -- this whole thing is really unfriendly and without + -- FP tricks it would have been intolerably painful + -- to implement. minetest needs better primitives. + local frame = math.ceil(16 * (1-math.min(1,fac))) + if tostring(frame) == '-0' then frame = '0' -- ?????? + else frame = tostring(frame) end + local tex = 'sorcery_ui_manaring_' .. (flash and 'flash_' or '') .. frame .. '.png'; + local c = sorcery.ctx.get(user) + if not c.hud_ench then + local hid = user:hud_add { + name = 'sorcery:manaring'; + hud_elem_type = 'image'; + text = tex; + position = { x = 0.5, y = 0.5 }; + offset = { x = 0, y = 0 }; + scale = { x = 2.0, y = 2.0 }; + z_index = 0; + } + c.hud_ench = { + id = hid; + timeleft = 2.0; + fn = false; + fac = fac; + } + c = c.hud_ench + else + c = c.hud_ench + c.fac = fac + user:hud_change(c.id,'text',tex) + if flash then c.timeleft = 2.0 end + end + if c.fn == false then + c.fn = true + local delta = 0.10 + -- tried making Δ conditional on 'flash' but it + -- turns out that causes the flash not to always + -- disappear in a timely manner. solving this + -- efficiently would be a major, complex headache + -- so i'm just compromising and setting delta to a + -- constant :/ + minetest.after(delta, function() + if not sorcery.ctx.stat(user) then return end + local u = sorcery.ctx.get(user) + local h = u.hud_ench + if not h then return end + print('timeleft,delta',h.timeleft,delta) + if h.timeleft - delta <= 0 then + user:hud_remove(h.id) + u.hud_ench = nil + else + h.timeleft = h.timeleft - delta + h.fn = false + enchpwrhud(user, false, h.fac) + end + end) + end +end minetest.register_on_dignode(function(pos, node, puncher) if puncher == nil then return end -- i don't know why -- this is necessary but you get rare crashes without it + + -- perform leyline checks and call notify if necessary + if minetest.get_item_group(node.name, 'sorcery_ley_device') ~= 0 then + sorcery.lib.node.notifyneighbors(pos) + end -- we're goint to do something VERY evil here and -- replace the air with a "glow-air" that removes -- itself after a short period of time, to create @@ -366,11 +439,13 @@ count = strength * 7; } ::skip::end end if totalcost > 0 then - local conservation = sorcery.enchant.strength(tool,'conserve') * 0.5 - totalcost = totalcost - (totalcost * conservation) - ench.energy = math.max(0,ench.energy - (totalcost - (material.data.energysource or 0))) + local conservation = math.floor(sorcery.enchant.strength(tool,'conserve') * 6) + -- totalcost = totalcost - (totalcost * conservation) + if conservation == 0 or math.random(conservation) == 1 then + ench.energy = math.max(0,ench.energy - (totalcost - (material.data.energysource or 0))) + end end if #sparks == 0 then return end if math.random(5) == 1 then minetest.set_node(pos, {name='sorcery:air_flash_' .. tostring(math.random(10))}) @@ -421,24 +496,7 @@ sorcery.enchant.set(tool,ench,true) end puncher:set_wielded_item(tool) - -- perform leyline checks and call notify if necessary - if minetest.get_item_group(node.name, 'sorcery_ley_device') ~= 0 then - sorcery.lib.node.notifyneighbors(pos) - end + local epct = ench.energy / material.data.maxenergy + enchpwrhud(puncher, true, epct) end) - -minetest.register_chatcommand('enchants', { - description = 'Log information about the currently held object\'s enchantment'; - privs = { server = true }; - func = function(caller,params) - local tool = minetest.get_player_by_name(caller):get_wielded_item() - minetest.chat_send_player(caller, dump(sorcery.enchant.get(tool))) - local binary = tool:get_meta():get_string('sorcery_enchantment_recs') - local dumpout = '' - for i=1,string.len(binary) do - dumpout = dumpout .. string.format('%x%s',string.byte(binary,i),(i%16==0 and '\n') or ' ') - end - print(dumpout) - end; -})