elepower/elepower_lighting/i_functions.lua
Sirrobzeroone 5d14083f2c Standalone Powercell, Lighting Fix's
Powercells can now power machines so long as they are charged up and connected to a machine/light bulb etc ie powercells can be a provider on there own now.

Lighting fixed a few issues:
Lights weren't getting power if you added them to a network while it was on powercell power rather than provider power.
Floodlights had the wrong drops listed
2021-09-26 22:35:44 +10:00

938 lines
31 KiB
Lua

------------------------------------------------------
-- ___ _ --
-- | __| |___ _ __ _____ __ _____ _ _ --
-- | _|| / -_) '_ \/ _ \ V V / -_) '_| --
-- |___|_\___| .__/\___/\_/\_/\___|_| --
-- _ _ |_| _ _ _ --
-- | | (_)__ _| |_| |_(_)_ _ __ _ --
-- | |__| / _` | ' \ _| | ' \/ _` | --
-- |____|_\__, |_||_\__|_|_||_\__, | --
-- |___/ |___/ --
------------------------------------------------------
-- Functions --
------------------------------------------------------
-------------------------------------------
-- Floodlight Formspec --
-------------------------------------------
local function get_formspec_flood(power,tilt,rotate)
local rotate = rotate or 0
local tilt = tilt or 0
local per_rot = (math.abs(rotate)/45)*100
local percent = (math.abs(tilt)/20)*100
local final ="size[8,3]"..
ele.formspec.power_meter(power)..
-- rotate
"image[3.5,0.25;2.8,1;elepower_gui_barbg.png^[transformR90]"..
"image[4.43,2.4;0.5,0.5;elepower_lighting_flood_arrow_icon.png^[transformR90]"..
"tooltip[3.5,1.45;2.25,0.4;"..rotate.." Degrees;#30434c;#f9f9f9]"..
--"button[5.15,1.45;0.75,0.75;rot;+]"..
--"tooltip[5.15,1.45;0.75,0.75;+1 Degrees;#30434c;#f9f9f9]"..
--"button[4.35,1.45;0.75,0.75;rot;0]"..
--"tooltip[4.35,1.45;0.75,0.75;Reset;#30434c;#f9f9f9]"..
--"button[3.5,1.45;0.75,0.75;rot;-]"..
--"tooltip[3.5,1.45;0.75,0.75;-1 Degrees;#30434c;#f9f9f9]"..
--"image[3.5,0.25;2.8,1;elepower_lighting_flood_tilt_gauge.png^[transformR90]"..
"scrollbaroptions[min=-45;max=45;smallstep=1;largestep=5;arrows=show]"..
"scrollbar[3.5,1.45;2.25,0.45;horizontal;rot;"..rotate.."]"..
"scrollbaroptions[min=-20;max=20;smallstep=1;largestep=5;arrows=show]"..
"scrollbar[7.25,0;0.4,2.4;vertical;tilt;"..(tilt).."]"..
-- tilt
"image[6.25,0;1,2.8;elepower_gui_barbg.png]"..
"image[6.5,2.45;0.5,0.5;elepower_lighting_flood_arrow_icon.png]"..
"tooltip[7.25,0;1,2.6;"..(tilt).." Degrees;#30434c;#f9f9f9]"
--"button[7.25,0.05;0.75,0.75;tilt;+]"..
--"tooltip[7.25,0.05;0.75,0.75;+1 Degrees;#30434c;#f9f9f9]"..
--"button[7.25,.9;0.75,0.75;tilt;0]"..
--"tooltip[7.25,.9;0.75,0.75;Reset;#30434c;#f9f9f9]"..
--"button[7.25,1.75;0.75,0.75;tilt;-]"..
--"tooltip[7.25,1.75;0.75,0.75;-1 Degrees;#30434c;#f9f9f9]"
if rotate > 0 then
final = final.."image[4.62,0.25;1.4,1;elepower_gui_barbg.png^[lowpart:"..per_rot..":elepower_gui_bar.png^[transformR270]"
elseif rotate < 0 then
final = final.."image[3.5,0.25;1.4,1;elepower_gui_barbg.png^[lowpart:"..per_rot..":elepower_gui_bar.png^[transformR90]"
end
if tilt < 0 then
final = final.."image[6.25,0;1,1.4;elepower_gui_barbg.png^[lowpart:"..percent..":elepower_gui_bar.png]"
elseif tilt > 0 then
final = final.."image[6.25,1.22;1,1.4;elepower_gui_barbg.png^[lowpart:"..percent..":elepower_gui_bar.png^[transformR180]"
end
final = final.."image[3.5,0.25;2.8,1;elepower_lighting_flood_rotate_gauge.png^[transformR90]"
final = final.."image[6.25,0;1,2.8;elepower_lighting_flood_tilt_gauge.png]"
return final
end
-- register flood on_recieve fields
function elepower_lighting.flood_on_recieve_fields(pos, formname, fields, player)
local meta = minetest.get_meta(pos)
if fields.quit then
return
end
if fields.rot then
local split = string.split(fields.rot, ":")
local new_rot = tonumber(split[2])
meta:set_int("rotate",new_rot)
if meta:get_int("on_off") == 1 then
elepower_lighting.remove_flood_light_fill(pos)
elepower_lighting.add_flood_light_fill(pos)
end
end
if fields.tilt then
local split = string.split(fields.tilt, ":")
local new_tilt = tonumber(split[2])
meta:set_int("tilt", new_tilt)
if meta:get_int("on_off") == 1 then
elepower_lighting.remove_flood_light_fill(pos)
elepower_lighting.add_flood_light_fill(pos)
end
end
--minetest.debug(dump(fields))
end
-------------------------------------------
-- Converts node param2 into a primary --
-- axis and the secondary axis, needed --
-- to workout and place light_fill --
-------------------------------------------
function elepower_lighting.p2_to_axis(node_param2)
-- first_key = primary axis, num_key = param2, value = secondary axis/+-
local p2_conv_table = {x = {[0]="z:+1",[2]="z:-1", [4]="y:-1", [6]="y:+1", [8]="y:+1",[10]="y:-1",[20]="z:+1",[22]="z:-1"},
y = {[5]="x:+1",[7]="x:-1", [9]="x:+1",[11]="x:-1",[12]="z:+1",[14]="z:-1",[16]="z:+1",[18]="z:-1"},
z = {[1]="x:+1",[3]="x:-1",[13]="y:-1",[15]="y:+1",[17]="y:+1",[19]="y:-1",[21]="x:-1",[23]="x:+1"}}
local light_strip_axis
for xyz,all_p2 in pairs(p2_conv_table) do
for p2,sec_axis in pairs(all_p2) do
if node_param2 == p2 then
local second_axis_v = string.split(sec_axis, ":")
light_strip_axis = {[xyz] = 1,[second_axis_v[1].."s"] = tonumber(second_axis_v[2])}
break
end
end
end
return light_strip_axis
end
---------------------------------------------
-- Simply adds or removes light_fill --
---------------------------------------------
function elepower_lighting.add_remove_light_fill(pos,light_strip_axis,light_shape,add_remove)
local x = light_strip_axis.x or 0
local y = light_strip_axis.y or 0
local z = light_strip_axis.z or 0
local xs = light_strip_axis.xs or 0
local ys = light_strip_axis.ys or 0
local zs = light_strip_axis.zs or 0
local mt_add_remove = minetest.remove_node
local node_name = "elepower_lighting:light_fill"
local add_node
-- used for adding/setting nodes
if add_remove == 1 then
mt_add_remove = minetest.set_node
node_name = "air"
add_node = {name = "elepower_lighting:light_fill"}
end
if light_shape == "3x1" then
local pos_p = {x=pos.x+x, y=pos.y+y, z=pos.z+z}
local pos_n = {x=pos.x-x, y=pos.y-y, z=pos.z-z}
local poses = {pos_p,pos_n}
for k,p in pairs(poses) do
if minetest.get_node(p).name == node_name then
mt_add_remove(p,add_node)
end
end
elseif light_shape == "3x2" then
local pos_p = {x=pos.x+x, y=pos.y+y, z=pos.z+z}
local pos_n = {x=pos.x-x, y=pos.y-y, z=pos.z-z}
local pos_ps = {x=pos.x+x+xs, y=pos.y+y+ys, z=pos.z+z+zs}
local pos_cs = {x=pos.x+xs, y=pos.y+ys, z=pos.z+zs}
local pos_ns = {x=pos.x-x+xs, y=pos.y-y+ys, z=pos.z-z+zs}
local poses = {pos_p,pos_n,pos_ps,pos_cs,pos_ns}
for k,p in pairs(poses) do
if minetest.get_node(p).name == node_name then
mt_add_remove(p,add_node)
end
end
end
end
---------------------------------------------
-- Add Flood Light Light nodes --
---------------------------------------------
function elepower_lighting.add_flood_light_fill(pos)
local meta = minetest.get_meta(pos)
local node_p2 = minetest.get_node(pos).param2
local rel_x_y
--1st axis = face dir, 2nd axis = relative vertical(tilt)
local face_dir = {["z:+1"] = {[0]="y:+1",[12]="x:+1",[16]="x:-1",[20]="y:-1"}, -- North
["x:+1"] = {[1]="y:+1", [5]="z:+1", [9]="z:-1",[23]="y:-1"}, -- East
["z:-1"] = {[2]="y:+1",[14]="x:+1",[18]="x:-1",[22]="y:-1"}, -- South
["x:-1"] = {[3]="y:+1", [7]="z:-1",[11]="z:-1",[21]="y:-1"}, -- West
["y:+1"] = {[6]="z:+1", [8]="z:-1",[15]="x:+1",[17]="x:-1"}, -- Up
["y:-1"] = {[4]="z:+1",[10]="z:-1",[13]="x:+1",[19]="x:-1"}} -- Down
-- Rotation reference table
local rot_dir = {[0] = {x = "x",x_v = "+1",y = "z",y_v = "+1", z="y"},
[1] = {x = "z",x_v = "-1",y = "x",y_v = "+1", z="y"},
[2] = {x = "x",x_v = "-1",y = "z",y_v = "-1", z="y"},
[3] = {x = "z",x_v = "+1",y = "x",y_v = "-1", z="y"},
[4] = {x = "x",x_v = "+1",y = "y",y_v = "-1",z="z"},
[5] = {x = "y",x_v = "+1",y = "x",y_v = "+1",z="z"},
[6] = {x = "x",x_v = "-1",y = "y",y_v = "+1",z="z"},
[7] = {x = "y",x_v = "-1",y = "x",y_v = "-1",z="z"},
[8] = {x = "x",x_v = "+1",y = "y",y_v = "+1",z="z"},
[9] = {x = "y",x_v = "-1",y = "x",y_v = "+1",z="z"},
[10] = {x = "x",x_v = "-1",y = "y",y_v = "-1",z="z"},
[11] = {x = "y",x_v = "+1",y = "x",y_v = "-1",z="z"},
[12] = {x = "y",x_v = "-1",y = "z",y_v = "+1",z="x"},
[13] = {x = "z",x_v = "-1",y = "y",y_v = "-1",z="x"},
[14] = {x = "y",x_v = "+1",y = "z",y_v = "-1",z="x"},
[15] = {x = "z",x_v = "+1",y = "y",y_v = "+1",z="x"},
[16] = {x = "y",x_v = "+1",y = "z",y_v = "+1",z="x"},
[17] = {x = "z",x_v = "-1",y = "y",y_v = "+1",z="x"},
[18] = {x = "y",x_v = "-1",y = "z",y_v = "-1",z="x"},
[19] = {x = "z",x_v = "+1",y = "y",y_v = "-1",z="x"},
[20] = {x = "x",x_v = "+1",y = "z",y_v = "+1", z="y"},
[21] = {x = "z",x_v = "+1",y = "x",y_v = "-1", z="y"},
[22] = {x = "x",x_v = "-1",y = "z",y_v = "-1", z="y"},
[23] = {x = "z",x_v = "-1",y = "x",y_v = "+1", z="y"},
}
for axis,p2s in pairs(face_dir) do
for p2,rel_vert in pairs(p2s) do
if node_p2 == p2 then
local sep_rel_x_axis = string.split(axis,":")
local sep_rel_y_axis = string.split(rel_vert,":")
rel_x_y = {[sep_rel_x_axis[1].."x"] = sep_rel_x_axis[2],
[sep_rel_y_axis[1].."y"] = sep_rel_y_axis[2],
[sep_rel_y_axis[1].."z"] = sep_rel_y_axis[4],
x = sep_rel_x_axis[1],
x_val = sep_rel_x_axis[2],
y = sep_rel_y_axis[1],
y_val = sep_rel_y_axis[2]
}
rot_x_y = rot_dir[node_p2]
end
end
end
local light_range = 30
local tilt_angle = meta:get_int("tilt")
local rot_angle = meta:get_int("rotate")
local angle = 90 - rot_angle
-- Start of Raycast Calculations --
-- work out rotation find pt on circle - x = cx + r * cos(a) // y = cy + r * sin(a)
-- eg x = rel-x-origin + (light_range*cos((90-rot_angle)*radians)
local x_rel = pos[rot_x_y.x] + (math.floor((30*math.cos(angle*0.0174533))))*tonumber(rot_x_y.x_v)
local y_rel = pos[rot_x_y.y] + (math.floor((30*math.sin(angle*0.0174533))))*tonumber(rot_x_y.y_v)
local pos_rot = {[rot_x_y.x] = x_rel,[rot_x_y.y] = y_rel, [rot_x_y.z] = pos[rot_x_y.z]}
-- work out gradient from angle (math.tan needs radians=degrees*0.0174533...)
local grad = math.tan(tilt_angle*0.0174533)
local y_end = math.floor(light_range*grad)
local xx = (rel_x_y.xx or 0)*light_range
local yx = (rel_x_y.yx or 0)*light_range
local zx = (rel_x_y.zx or 0)*light_range
local xy = (rel_x_y.xy or 0)*y_end
local yy = (rel_x_y.yy or 0)*y_end
local zy = (rel_x_y.zy or 0)*y_end
-- pos_s (start) simply add relative x
local pos_s = {x=pos.x+(xx/light_range),y=pos.y+(yx/light_range),z=pos.z+(zx/light_range)}
-- pos_e (end) add both relative x and relative y
local pos_e = {x=pos_rot.x+xx+xy,y=pos_rot.y+yx+yy,z=pos_rot.z+zx+zy}
meta:set_string("flood_light_pos_s", minetest.serialize(pos_s))
meta:set_string("flood_light_pos_e", minetest.serialize(pos_e))
local ray = minetest.raycast(pos_s,pos_e,false,true)
local ray_next = ray:next()
local end_pos
while ray_next do
local name = minetest.get_node(ray_next.under).name
local node_draw = minetest.registered_items[name].drawtype
if node_draw ~= "plantlike" and
node_draw ~= "firelike" and
node_draw ~= "raillike" and
node_draw ~= "torchlike" and
node_draw ~= "signlike" and
name ~= "elepower_lighting:light_fill" then
local e_pos = ray_next.under
meta:set_string("flood_light_end", minetest.serialize(e_pos))
end_pos = {x=e_pos.x-(xx/light_range),y=e_pos.y-(yx/light_range),z=e_pos.z-(zx/light_range)}
break
end
ray_next = ray:next()
end
local tot = 30
if end_pos then
tot = math.abs(end_pos[rel_x_y.x] - pos[rel_x_y.x])
end
-- Start of light fill calculations
local flood_fill_pos = {}
for i = 1,tot,1 do
local new_pos = table.copy(pos)
-- calculate rotation position
local x_rel = new_pos[rot_x_y.x] + ((math.floor((i*math.cos(angle*0.0174533))))*tonumber(rot_x_y.x_v)) + 1*tonumber(rot_x_y.x_v) -- last + removes offset from carrier "1"
local y_rel = new_pos[rot_x_y.y] + (math.floor((i*math.sin(angle*0.0174533))))*tonumber(rot_x_y.y_v)
local pos_rot = {[rot_x_y.x] = x_rel,[rot_x_y.y] = y_rel, [rot_x_y.z] = new_pos[rot_x_y.z]}
-- adjust for tilt
pos_rot[rel_x_y.x] = (pos_rot[rel_x_y.x] + (1*rel_x_y.x_val)) -- relative X axis
pos_rot[rel_x_y.y] = (pos_rot[rel_x_y.y] + math.ceil((i*rel_x_y.y_val)*grad)) -- relative Y axis
--new_pos.x = new_pos.x+(math.floor(0.85*i))
if minetest.get_node(pos_rot).name == "air" or
minetest.get_node(pos_rot).name == "elepower_lighting:light_fill" then
table.insert(flood_fill_pos,pos_rot)
minetest.set_node(pos_rot,{name = "elepower_lighting:light_fill"})
--minetest.debug(rot_x_y.y..":".. rot_x_y.y_v)
end
end
meta:set_string("flood_fill_pos", minetest.serialize(flood_fill_pos))
end
---------------------------------------------
-- Removes Flood Light Light nodes --
---------------------------------------------
function elepower_lighting.remove_flood_light_fill(pos)
local meta = minetest.get_meta(pos)
local flood_fill_pos = minetest.deserialize(meta:get_string("flood_fill_pos"))
if type(flood_fill_pos) == "table" then
meta:set_string("flood_light_pos_s","")
meta:set_string("flood_light_pos_e","")
meta:set_string("flood_light_end","")
for k,pos in pairs(flood_fill_pos) do
if minetest.get_node(pos).name == "elepower_lighting:light_fill" then
minetest.remove_node(pos)
end
end
end
end
-------------------------------------------
-- A rotate and place that allows lights --
-- to mount into wall sockets --
-- thanks mt forums for below soln idea --
-------------------------------------------
function elepower_lighting.rot_and_place(itemstack, placer, pointed_thing)
local p0 = pointed_thing.under
local p1 = pointed_thing.above
local param2 = 0
if placer then
local placer_pos = placer:get_pos()
if placer_pos then
param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
end
if p0.x<p1.x then -- -X
param2 = 12 + param2
elseif p0.x>p1.x then -- +X
param2 = 16 + param2
elseif p0.z<p1.z then -- +Z
param2 = 4 + param2
elseif p0.z>p1.z then -- -Z
param2 = 8 + param2
elseif p0.y<p1.y then -- +Y
param2 = param2
elseif p0.y>p1.y then -- -Y
param2 = 20 + param2
end
end
return minetest.item_place(itemstack, placer, pointed_thing, param2)
end
-------------------------------------
-- Light State Function --
-- "Active", "Off", "Out of Power" --
-------------------------------------
function elepower_lighting.status(on_off,storage,usage)
local status = "Active"
if on_off == 0 then
status = "Off"
elseif storage < usage then
status = "Out of Power!"
end
return status
end
------------------------------------
-- Main Lighting timer, what uses --
-- EpU's and allows lights to be --
-- switched on and off --
------------------------------------
function elepower_lighting.light_timer(pos)
local meta = minetest.get_meta(pos)
local on_off = meta:get_int("on_off")
local reg_name = minetest.get_node(pos).name
local node_p2 = minetest.get_node(pos).param2
local name = minetest.registered_items[minetest.get_node(pos).name].description
local light_shape = minetest.registered_items[minetest.get_node(pos).name].ele_light_shape or nil
local capacity = ele.helpers.get_node_property(meta, pos, "capacity")
local storage = ele.helpers.get_node_property(meta, pos, "storage")
local usage = ele.helpers.get_node_property(meta, pos, "usage")
local pow_percent = {capacity = capacity, storage = storage, usage = usage}
local light_strip_axis
local flood_light_change = false
if light_shape ~= "flood" then
light_strip_axis = elepower_lighting.p2_to_axis(node_p2)
elseif light_shape == "flood" then
-- need an overide in the event a wall/tree etc is built infront of an "on" flood light beam
local flood_light_end = minetest.deserialize(meta:get_string("flood_light_end"))
local pos_s = minetest.deserialize(meta:get_string("flood_light_pos_s"))
local pos_e = minetest.deserialize(meta:get_string("flood_light_pos_e"))
local e_pos
local bulb_type = string.match(reg_name, ':(.-)_')
if light_shape == "flood" then
-- change floodlight node for angled/tilted version
local tilt = meta:get_int("tilt") or 0
local rotate = meta:get_int("rotate") or 0
local rpn = "p"
local tpn = "p"
local new_name
if rotate < 0 then
if rotate < -10 then
rpn = "n"
end
rotate = rotate*-1
end
if tilt < 0 then
if tilt < -5 then
tpn = "n"
end
tilt = tilt*-1
end
if rotate > 10 then
rotate = 45
else
rotate = 0
end
if tilt > 5 then
tilt = 20
else
tilt = 0
end
if not string.find(reg_name, "active") then
new_name = "elepower_lighting:"..bulb_type.."_floodlight_x"..rpn..rotate.."_y"..tpn..tilt
else
new_name = "elepower_lighting:"..bulb_type.."_floodlight_x"..rpn..rotate.."_y"..tpn..tilt.."_active"
end
if new_name ~= reg_name then
ele.helpers.swap_node(pos, new_name)
end
end
if pos_s then
local ray = minetest.raycast(pos_s,pos_e,false,true)
local ray_next = ray:next()
while ray_next do
local name = minetest.get_node(ray_next.under).name
local node_draw = minetest.registered_items[name].drawtype
if node_draw ~= "plantlike" and
node_draw ~= "firelike" and
node_draw ~= "raillike" and
node_draw ~= "torchlike" and
node_draw ~= "signlike" and
name ~= "elepower_lighting:light_fill" then
e_pos = ray_next.under
break
end
ray_next = ray:next()
end
if minetest.serialize(e_pos) ~= minetest.serialize(flood_light_end) then
flood_light_change = true
end
end
end
if (storage >= usage and on_off == 1) then
if not string.find(reg_name, "active") or flood_light_change == true then
if flood_light_change == false then
ele.helpers.swap_node(pos, reg_name.."_active")
elseif flood_light_change == true then
elepower_lighting.remove_flood_light_fill(pos)
end
if light_shape == "flood" then
elepower_lighting.add_flood_light_fill(pos)
elseif light_shape then
elepower_lighting.add_remove_light_fill(pos,light_strip_axis,light_shape,1)
end
end
pow_percent.storage = pow_percent.storage - usage
storage = pow_percent.storage
meta:set_int("storage", pow_percent.storage)
else
if string.find(reg_name, "active") then
local name = string.sub(reg_name, 1, -8)
ele.helpers.swap_node(pos, name)
if light_shape then
if light_shape == "flood" then
elepower_lighting.remove_flood_light_fill(pos)
elseif light_shape then
elepower_lighting.add_remove_light_fill(pos,light_strip_axis,light_shape)
end
end
end
end
local status = elepower_lighting.status(on_off,pow_percent.storage,pow_percent.usage)
meta:set_string("infotext", name.." "..status.."\n" .. ele.capacity_text(capacity, storage))
if light_shape == "flood" then
local tilt = meta:get_int("tilt") or 0
local rotate = meta:get_int("rotate") or 0
meta:set_string("formspec", get_formspec_flood(pow_percent,tilt,rotate))
end
return true
end
---------------------------------------------
-- Main Colored Lighting timer, what uses --
-- EpU's and allows lights to be switched --
-- on and off --
---------------------------------------------
elepower_lighting.colors = {{"#ff0500", "Red"},
{"#ff3500", "Dark Orange"},
{"#ff6300", "Orange"},
{"#ff9100", "Light Orange"},
{"#ffc000", "Golden"},
{"#ffef00", "Yellow"},
{"#e1ff00", "Lemon Lime"},
{"#b3ff00", "Lime"},
{"#84ff00", "Lawn Green"},
{"#56ff00", "Bright Green"},
{"#00ff36", "Green"},
{"#00ff65", "Spring Green"},
{"#00ff93", "Sea Green"},
{"#00ffc2", "Aqua"},
{"#00fff0", "Turquoise Blue"},
{"#00dfff", "Sky Blue"},
{"#00b1ff", "Vivid Blue"},
{"#0082ff", "Azure"},
{"#0053ff", "Blue"},
{"#0024ff", "Blue Bonnet"},
{"#0900ff", "Dark Blue"},
{"#3800ff", "Blue Purple"},
{"#6700ff", "Indigo"},
{"#9500ff", "Violet"},
{"#c400ff", "Orchid"},
{"#f200ff", "Magenta"},
{"#ff00dd", "Hot Pink"},
{"#ff00af", "Shocking Pink"},
{"#ff0080", "Pink"},
{"#ff0051", "Apple Red"},
{"#ffffff", "White"},
{"#000000", "Black"}
}
local function get_formspec_panel_color(power,color_mode,color_sync)
local color_m = color_mode
local color_s = color_sync
if tonumber(color_m) then
color_m = "Single Color-"..elepower_lighting.colors[(color_m/8)][2]
else
color_m = color_m:gsub("^%l", string.upper)
end
local final ="size[8,3]"..
"container[0,0.1]"..
ele.formspec.power_meter(power)..
"container_end[]"..
"label[1,-0.05;Current Selection: "..color_m.."]"..
"checkbox[6,-0.25;sync;Synchronize;"..color_s.."]"..
"image_button[1,0.4;2,0.75;elepower_lighting_gui_rainbow_button.png;r_color;Rainbow;false;true;elepower_lighting_gui_rainbow_button.png^[opacity:127]"..
"image_button[1,1.1;2,0.75;elepower_lighting_gui_strobe_button.png;r_color;Strobe;false;true;elepower_lighting_gui_strobe_button.png^[opacity:127]"..
"image_button[1,1.8;2,0.75;elepower_lighting_gui_blue_button.png;r_color;Blues;false;true;elepower_lighting_gui_blue_button.png^[opacity:127]"..
"image_button[1,2.5;2,0.75;elepower_lighting_gui_red_button.png;r_color;Reds;false;true;elepower_lighting_gui_red_button.png^[opacity:127]"
for k,def in pairs(elepower_lighting.colors) do
local image_end = "elepower_lighting_gui_color_button.png^[multiply:"..
def[1]..";f_color;"..((k)*8)..
";false;true;elepower_lighting_gui_color_button.png^[multiply:"..
def[1].."^[opacity:127]]"
final = final.."style[f_color;font_size=0;textcolor="..def[1].."]"
if k <= 8 then
final = final.."image_button["..(3.0+((k-1)*0.6))..",0.4;0.75,0.75;"..image_end
final = final.."tooltip["..(3.0+((k-1)*0.6))..",0.4;0.55,0.65;"..def[2]..";#30434c;#f9f9f9]"
elseif k > 8 and k < 17 then
final = final.."image_button["..(3.0+((k-9)*0.6))..",1.1;0.75,0.75;"..image_end
final = final.."tooltip["..(3.0+((k-9)*0.6))..",1.1;0.55,0.65;"..def[2]..";#30434c;#f9f9f9]"
elseif k > 16 and k < 25 then
final = final.."image_button["..(3.0+((k-17)*0.6))..",1.8;0.75,0.75;"..image_end
final = final.."tooltip["..(3.0+((k-17)*0.6))..",1.8;0.55,0.65;"..def[2]..";#30434c;#f9f9f9]"
else
final = final.."image_button["..(3.0+((k-25)*0.6))..",2.5;0.75,0.75;"..image_end
final = final.."tooltip["..(3.0+((k-25)*0.6))..",2.5;0.55,0.65;"..def[2]..";#30434c;#f9f9f9]"
end
end
return final
end
-- register color on_recieve fields
function elepower_lighting.color_on_recieve_fields(pos, formname, fields, player)
local meta = minetest.get_meta(pos)
if fields.quit then
return
end
if fields.r_color == "Rainbow" then
meta:set_string("color_mode","rainbow")
elseif fields.r_color == "Strobe" then
meta:set_string("color_mode","strobe")
elseif fields.r_color == "Blues" then
meta:set_string("color_mode","blues")
elseif fields.r_color == "Reds" then
meta:set_string("color_mode","reds")
elseif fields.f_color then
meta:set_string("color_mode",fields.f_color)
elseif fields.sync then
meta:set_string("color_sync",tostring(fields.sync))
end
--minetest.debug(dump(fields))
end
function elepower_lighting.light_timer_colored(pos)
local meta = minetest.get_meta(pos)
local on_off = meta:get_int("on_off")
local cycles = meta:get_int("light_color_count")
local color_mode = meta:get_string("color_mode") or "rainbow"
local color_sync = meta:get_string("color_sync") or "false"
local run_bwd = meta:get_string("run_bwd") or "false"
local node = minetest.get_node(pos)
local name = minetest.registered_items[minetest.get_node(pos).name].description
local reg_name = minetest.get_node(pos).name
local capacity = ele.helpers.get_node_property(meta, pos, "capacity")
local storage = ele.helpers.get_node_property(meta, pos, "storage")
local usage = ele.helpers.get_node_property(meta, pos, "usage")
local pow_percent = {capacity = capacity, storage = storage, usage = usage}
local strobe_ok = true
local is_timer = true
if cycles == 5 then --(1 second)
if (storage >= usage and on_off == 1) then
if not string.find(reg_name, "active") and color_mode ~= "strobe" then
ele.helpers.swap_node(pos, reg_name.."_active")
end
pow_percent.storage = pow_percent.storage - usage
storage = pow_percent.storage
meta:set_int("storage", pow_percent.storage)
else
if string.find(reg_name, "active") then
local name = string.sub(reg_name, 1, -8)
ele.helpers.swap_node(pos, name)
strobe_ok = false
end
end
local status = elepower_lighting.status(on_off,pow_percent.storage,pow_percent.usage)
meta:set_string("formspec", get_formspec_panel_color(pow_percent,color_mode,color_sync))
meta:set_string("infotext", name .." "..status.. "\n" .. ele.capacity_text(capacity, storage))
cycles = 0
end
node = minetest.get_node(pos)
if string.find(node.name, "active") or strobe_ok then
if color_mode == "rainbow" then
if color_sync == "true" then
local sync_total = 30
local node_plain_p2 = node.param2 % 8
col_seq = math.ceil(sync_total*((((elepower_lighting.timer/0.2))/sync_total)%1))
node.param2 = node_plain_p2 + ((col_seq*8)-8)
minetest.swap_node(pos, node)
else
node.param2 = node.param2+8
if node.param2 >=240 then
node.param2 = (node.param2 % 32)
end
minetest.swap_node(pos, node)
end
elseif color_mode == "blues" or color_mode == "reds" then
local blues_seq_p2 = {120,128,136,144,152,160,168}
local reds_seq_p2 = {200,208,216,224,232,0}
local node_plain_p2 = node.param2 % 8
local cur_color_p2 = math.floor(node.param2/8)*8
local col_seq = 1
local change = 1
local col_seq_p2 = blues_seq_p2
local sync_total = #blues_seq_p2-1
if color_mode == "reds" then
col_seq_p2 = reds_seq_p2
sync_total = #reds_seq_p2-1
end
if color_sync == "true" then
if math.floor(((elepower_lighting.timer/0.2)/sync_total)%2) == 0 then
--minetest.debug("bwd: ".. (sync_total+1)-math.ceil(sync_total*((((elepower_lighting.timer/0.2))/sync_total)%1)))
col_seq = (sync_total+1)-math.ceil(sync_total*((((elepower_lighting.timer/0.2))/sync_total)%1))
change = 0
meta:set_string("run_bwd", "true")
else
--minetest.debug("fwd: ".. 1+math.ceil(sync_total*((((elepower_lighting.timer/0.2))/sync_total)%1)))
col_seq = 1+math.ceil(sync_total*((((elepower_lighting.timer/0.2))/sync_total)%1))
change = 0
meta:set_string("run_bwd", "false")
end
else
for k,v in pairs(col_seq_p2 ) do
if v == cur_color_p2 then
col_seq = k
end
end
if (col_seq == #col_seq_p2 or run_bwd == "true") and col_seq ~= 1 then
meta:set_string("run_bwd", "true")
change = -1
elseif col_seq == 1 then
meta:set_string("run_bwd", "false")
end
end
--minetest.debug(col_seq+change)
node.param2 = col_seq_p2[col_seq+change] + node_plain_p2
minetest.swap_node(pos, node)
elseif color_mode == "strobe" then
if color_sync == "true" then
local col_seq = math.ceil(math.floor((elepower_lighting.timer/0.2)+0.5)%2)
if col_seq == 1 then
if not string.find(reg_name, "active") then
ele.helpers.swap_node(pos, reg_name.."_active")
end
else
if string.find(reg_name, "active") then
local name = string.sub(reg_name, 1, -8)
ele.helpers.swap_node(pos, name)
end
end
else
if string.find(reg_name, "active") then
local name = string.sub(reg_name, 1, -8)
ele.helpers.swap_node(pos, name)
else
ele.helpers.swap_node(pos, reg_name.."_active")
end
end
elseif type(tonumber(color_mode)) == "number" then
local node_plain_p2 = node.param2 % 8
local cur_color_p2 = math.floor(node.param2/8)*8
if color_mode-8 ~= cur_color_p2 then
node.param2 = color_mode-8 + node_plain_p2
minetest.swap_node(pos, node)
end
else
-- catch error state set to white
local node_plain_p2 = node.param2 % 8
node.param2 = node_plain_p2 + 240
minetest.swap_node(pos, node)
end
end
local timer = minetest.get_node_timer(pos)
if timer:get_timeout() ~= 0.2 then
timer:start(0.2)
is_timer = false
end
meta:set_int("light_color_count",cycles+1)
return is_timer
end
elepower_lighting.timer = 0
minetest.register_globalstep(function(dtime)
-- note counter shouldn't cause an issue until uptime exceeds about 7million yrs
elepower_lighting.timer = elepower_lighting.timer + dtime;
end)
-----------------------------------------
-- Lighting simple functions for basic --
-- node functionality --
-----------------------------------------
-- set light on/off by punch
function elepower_lighting.light_punch(pos,player)
local meta = minetest.get_meta(pos)
local on_off = meta:get_int("on_off") or 1
if on_off == 1 then
on_off = 0
else
on_off = 1
end
meta:set_int("on_off",on_off)
end
-- set lights to on when constructed
function elepower_lighting.light_construct(pos)
local meta = minetest.get_meta(pos)
meta:set_int("on_off",1)
meta:set_string("infotext", "Active")
local is_colored = minetest.registered_items[minetest.get_node(pos).name].palette or nil
if is_colored then
meta:set_string("color_mode","rainbow")
local timer = minetest.get_node_timer(pos)
timer:start(0.2)
end
end
-- Main place function
function elepower_lighting.light_place(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
return elepower_lighting.rot_and_place(itemstack, placer, pointed_thing)
end
-- For lights more than 1x1 cleanup light_fill on destruction
function elepower_lighting.light_strip_cleanup(pos)
local node_p2 = minetest.get_node(pos).param2
local light_shape = minetest.registered_items[minetest.get_node(pos).name].ele_light_shape or nil
local light_strip_axis = elepower_lighting.p2_to_axis(node_p2)
if light_shape == "flood" then
elepower_lighting.remove_flood_light_fill(pos)
else
elepower_lighting.add_remove_light_fill(pos,light_strip_axis,light_shape)
end
end