technic-cd2025/technic/tools/flashlight.lua
Zefram 99fd5dfee5 Genericise handling of multiple meanings of wear
The tool workshop is meant to repair mechanical damage to tools, so
is at risk of `repairing' tools that use the wear bar to represent
something other than mechanical wear.  It had special-case recognition
of the water and lava cans, which use the wear bar to represent how much
content they're carrying, and wouldn't repair them.  But it didn't avoid
`repairing' RE chargeable items, which use the wear bar to represent
how much energy they have stored.  It would modify the wear bar without
actually affecting the charge, so the wear bar would jump back to the
correct place when the next charging or discharging event occurred.

To genericise, introduce a new item property, "wear_represents", which
indicates how the wear bar is used for this item.  Currently defined
values are "mechanical_wear" (straightforward damage to tools that
start out perfect), "technic_RE_charge" (electrical energy, canonically
represented in the meta rather than the wear bar), and "content_level"
(how full a container is).  For backcompat, nil is interpreted as
"mechanical_wear".  The tool workshop will only repair "mechanical_wear"
tools.  As a bonus, set_RE_wear() will only set the wear bar for
"technic_RE_charge" items: this means developers will notice if they
forget to declare wear_represents, but also means that with no further
changes it's possible to have an RE chargeable item that uses its wear
bar to represent something else.
2014-04-30 00:21:55 +01:00

117 lines
3.5 KiB
Lua

-- Original code comes from walkin_light mod by Echo
-- http://minetest.net/forum/viewtopic.php?id=2621
local flashlight_max_charge = 30000
local S = technic.getter
technic.register_power_tool("technic:flashlight", flashlight_max_charge)
minetest.register_alias("technic:light_off", "air")
minetest.register_tool("technic:flashlight", {
description = S("Flashlight"),
inventory_image = "technic_flashlight.png",
stack_max = 1,
wear_represents = "technic_RE_charge",
})
minetest.register_craft({
output = "technic:flashlight",
recipe = {
{"technic:rubber", "default:glass", "technic:rubber"},
{"technic:stainless_steel_ingot", "technic:battery", "technic:stainless_steel_ingot"},
{"", "technic:battery", ""}
}
})
local player_positions = {}
local was_wielding = {}
local function check_for_flashlight(player)
if player == nil then
return false
end
local inv = player:get_inventory()
local hotbar = inv:get_list("main")
for i = 1, 8 do
if hotbar[i]:get_name() == "technic:flashlight" then
local meta = minetest.deserialize(hotbar[i]:get_metadata())
if meta and meta.charge and meta.charge >= 2 then
meta.charge = meta.charge - 2;
technic.set_RE_wear(hotbar[i], meta.charge, flashlight_max_charge)
hotbar[i]:set_metadata(minetest.serialize(meta))
inv:set_stack("main", i, hotbar[i])
return true
end
end
end
return false
end
minetest.register_on_joinplayer(function(player)
local player_name = player:get_player_name()
local pos = player:getpos()
local rounded_pos = vector.round(pos)
rounded_pos.y = rounded_pos.y + 1
player_positions[player_name] = rounded_pos
was_wielding[player_name] = true
end)
minetest.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
local pos = player_positions[player_name]
local nodename = minetest.get_node(pos).name
if nodename == "technic:light" then
minetest.remove_node(pos)
end
player_positions[player_name] = nil
end)
minetest.register_globalstep(function(dtime)
for i, player in pairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
local flashlight_weared = check_for_flashlight(player)
local pos = player:getpos()
local rounded_pos = vector.round(pos)
rounded_pos.y = rounded_pos.y + 1
local old_pos = player_positions[player_name]
local player_moved = not vector.equals(old_pos, rounded_pos)
-- Remove light, flashlight weared out or was removed from hotbar
if was_wielding[player_name] and not flashlight_weared then
was_wielding[player_name] = false
local node = minetest.get_node_or_nil(old_pos)
if node and node.name == "technic:light" then
minetest.remove_node(old_pos)
end
elseif (player_moved or not was_wielding[player_name]) and flashlight_weared then
local node = minetest.get_node_or_nil(rounded_pos)
if node and node.name == "air" then
minetest.set_node(rounded_pos, {name="technic:light"})
end
local node = minetest.get_node_or_nil(old_pos)
if node and node.name == "technic:light" then
minetest.remove_node(old_pos)
end
player_positions[player_name] = rounded_pos
was_wielding[player_name] = true
end
end
end)
minetest.register_node("technic:light", {
drawtype = "glasslike",
tile_images = {"technic_light.png"},
paramtype = "light",
groups = {not_in_creative_inventory=1},
drop = "",
walkable = false,
buildable_to = true,
sunlight_propagates = true,
light_source = LIGHT_MAX,
pointable = false,
})