Initial commit.

master
David G 2019-12-28 16:59:29 -07:00
commit fb960fa730
5 changed files with 213 additions and 0 deletions

49
README.md Normal file
View File

@ -0,0 +1,49 @@
Wand of Illumination [wand\_of\_illumination]
===========================================
Provides a wand that when used lights up an entire room, but only for a moment.
![Wand of Illumination Screenshot](screenshot.png "Wand of Illumination")
Features
--------
- On right click, places an array of invisible light nodes around the player, in a sphere with a current radius of 15 nodes, and with a light spacing of four nodes.
- Scans only through air, and only replaces air nodes.
- Uses an abm to cause these light nodes to revert back to air nodes after a short amount of time.
- Uses mana mod if available. Current cost for use is 100 mana.
- Note that narrow passages, like dungeon corridors, may not light up, if they don't fall on the 4x light spacing grid.
WIP—Things that still need to be done.
----------------------------------
- Come up with a crafting recipe.
- Determine if I should be using an abm or something else.
- Optimize mana cost.
- Tune light generated: brightness, spacing, radius, and decay rate.
- Come up with a better wand texture.
- Maybe add option to give bigger sphere of light on shift-right-click, at the cost of more mana.
Dependencies
------------
- Currently has no default dependency. *(However, I'll probably have to add default when a crafting recipe is added.)*
- Optionally depends on Wuzzy's mana mod. *(Thanks to his Mirror of Returning mod, it was easy to figure out how to add mana support.)*
Licenses
--------
Source code
> The MIT License (MIT)
Media (textures)
> Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
Current wand texture based on farming\_tool\_stonehoe.png by BlockMen

161
init.lua Normal file
View File

@ -0,0 +1,161 @@
-- Wand of Illumination [wand_of_illumination]
-- by David G (kestral246@gmail.com)
-- 2019-12-28
-- Provides a wand that when used lights up an entire room, but only for a moment.
local brightness_value = 9 -- How bright to make lights.
local MAX_DIST_SQUARED = 15^2 -- Radius of sphere (squared).
local maxcount = 15000 -- Maximum number of nodes to check.
local mana_cost = 100
local using_mana = false
if minetest.get_modpath("mana") ~= nil then
using_mana = true
end
local scanned = {} -- Set containing scanned nodes, so they don't get scanned multiple times.
local tocheck = {} -- Table of nodes to check.
local tolight = {} -- Table of nodes that need to be converted to fill lights.
minetest.register_on_joinplayer(function(player)
local pname = player:get_player_name()
scanned[pname] = {}
tocheck[pname] = {}
tolight[pname] = {}
end)
minetest.register_on_leaveplayer(function(player)
local pname = player:get_player_name()
scanned[pname] = nil
tocheck[pname] = nil
tolight[pname] = nil
end)
local mana_check = function(player, cost)
local allowed
if using_mana then
if mana.subtract(player:get_player_name(), cost) then
allowed = true
else
allowed = false
end
else
allowed = true
end
return allowed
end
minetest.register_node("wand_of_illumination:light", {
description = "Wand of Illumination Light",
drawtype = "airlike",
walkable = false,
paramtype = "light",
sunlight_propagates = true,
light_source = brightness_value,
pointable = false,
buildable_to = true,
drops = "",
groups = {cracky = 3, oddly_breakable_by_hand = 3, fill_hidden = 1, not_in_creative_inventory = 1},
})
minetest.register_abm({
nodenames = {"wand_of_illumination:light"},
interval = 2.0, -- need to tune
chance = 10, -- need to tune
action = function(pos, node, active_object_count, active_object_count_wider)
minetest.set_node(pos, {name = "air"})
end
})
-- Determine number of elements in table, for summary output.
local tlength = function(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
local square = function(x)
return x * x
end
-- Scan neighboring nodes, flag for checking if air.
local scan_node = function(pname, pos, origin, maxdist2)
-- Add y to test, so make search pattern a sphere
if square(pos.x - origin.x) + square(pos.y - origin.y) + square(pos.z - origin.z) <= maxdist2 then
local enc_pos = minetest.hash_node_position(pos)
if scanned[pname][enc_pos] ~= true then -- hasn't been scanned
local name = minetest.get_node(pos).name
if name == "air" then -- checkable
table.insert(tocheck[pname], enc_pos) -- add to check list
end
scanned[pname][enc_pos] = true -- don't scan again
end
end
end
-- To check, scan all neighbors and determine if this node needs to be converted to light.
local check_node = function(pname, pos, origin, maxdist2)
local enc_pos = minetest.hash_node_position(pos)
local name = minetest.get_node(pos).name
scan_node(pname, vector.add(pos, {x=0,y=0,z=1}), origin, maxdist2) -- north
scan_node(pname, vector.add(pos, {x=1,y=0,z=0}), origin, maxdist2) -- east
scan_node(pname, vector.add(pos, {x=0,y=0,z=-1}), origin, maxdist2) -- south
scan_node(pname, vector.add(pos, {x=-1,y=0,z=0}), origin, maxdist2) -- west
scan_node(pname, vector.add(pos, {x=0,y=-1,z=0}), origin, maxdist2) -- down
scan_node(pname, vector.add(pos, {x=0,y=1,z=0}), origin, maxdist2) -- up
if name == "air" and ((pos.x%4 == 0 and pos.y%8 == 0 and pos.z%4 == 0) or
(pos.x%4 == 2 and pos.y%8 == 4 and pos.z%4 == 2)) then
table.insert(tolight[pname], enc_pos)
end
end
local use_wand = function(pname, pos)
-- Initialize temporary tables for safety.
scanned[pname] = {}
tocheck[pname] = {}
tolight[pname] = {}
-- Search starts at wand position.
table.insert(tocheck[pname], minetest.hash_node_position(pos))
local count = 1
while count <= table.getn(tocheck[pname]) and count <= maxcount do
check_node(pname, minetest.get_position_from_hash(tocheck[pname][count]),
pos, MAX_DIST_SQUARED) -- fifo
count = count + 1
end
count = count - 1
local toadd = tlength(tolight[pname])
-- Print statistics.
--minetest.debug("wand_of_illumination: y = "..tostring(pos.y)..", scan = "..
-- tostring(tlength(scanned[pname]))..", check = "..tostring(count)..", lights = "..
-- tostring(tlength(tolight[pname])))
-- Add lights to all locations flagged for lighting.
for _,v in ipairs(tolight[pname]) do
local fpos = minetest.get_position_from_hash(v)
minetest.set_node(fpos, {name="wand_of_illumination:light"})
end
-- Clear temporary tables, which could be large.
scanned[pname] = {}
tocheck[pname] = {}
tolight[pname] = {}
end
minetest.register_tool("wand_of_illumination:wand", {
description = "Wand of Illumination",
inventory_image = "wand_of_illumination.png",
stack_max = 1,
on_place = function(itemstack, player, pointed_thing)
local pname = player:get_player_name()
local pos = vector.add(vector.round(player:get_pos()), {x=0,y=1,z=0}) -- position of wand
if mana_check(player, mana_cost) then
use_wand(pname, pos)
end
end,
on_secondary_use = function(itemstack, player, pointed_thing)
local pname = player:get_player_name()
local pos = vector.add(vector.round(player:get_pos()), {x=0,y=1,z=0}) -- position of wand
if mana_check(player, mana_cost) then
use_wand(pname, pos)
end
end,
})

3
mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = wand_of_illumination
description = Light up an entire room, but only for a moment.
optional_depends = mana

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB