346 lines
13 KiB
Lua
346 lines
13 KiB
Lua
|
|
|
|
artifact.register_node("forcefield", {
|
|
drawtype = "glasslike_framed",
|
|
use_texture_alpha = "blend",
|
|
light_source = 6,
|
|
tiles = {"artifact_forcefield_border.png", "artifact_forcefield_inner.png"},
|
|
visual_scale = 0.75,
|
|
diggable = false
|
|
})
|
|
|
|
local vm_data = {}
|
|
local vm_p2_data = {}
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_forcefield = minetest.get_content_id("forcefield")
|
|
function artifact.place_forcefield(pos, def)
|
|
if def.type == "cube" then
|
|
if def.offset then pos = pos:add(def.offset) end
|
|
local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius))
|
|
local va = VoxelArea(vm:get_emerged_area())
|
|
vm:get_data(vm_data)
|
|
vm:get_param2_data(vm_p2_data)
|
|
for x = pos.x -def.radius, pos.x +def.radius, def.radius *2 do
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x, y, z)
|
|
if vm_data[idx] == c_air then
|
|
vm_data[idx] = c_forcefield
|
|
vm_p2_data[idx] = 1
|
|
elseif vm_data[idx] == c_forcefield then
|
|
vm_p2_data[idx] = vm_p2_data[idx] +1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for y = pos.y -def.radius, pos.y +def.radius, def.radius *2 do
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x, y, z)
|
|
if vm_data[idx] == c_air then
|
|
vm_data[idx] = c_forcefield
|
|
vm_p2_data[idx] = 1
|
|
elseif vm_data[idx] == c_forcefield then
|
|
vm_p2_data[idx] = vm_p2_data[idx] +1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for z = pos.z -def.radius, pos.z +def.radius, def.radius *2 do
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
local idx = va:index(x, y, z)
|
|
if vm_data[idx] == c_air then
|
|
vm_data[idx] = c_forcefield
|
|
vm_p2_data[idx] = 1
|
|
elseif vm_data[idx] == c_forcefield then
|
|
vm_p2_data[idx] = vm_p2_data[idx] +1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
vm:set_data(vm_data)
|
|
vm:set_param2_data(vm_p2_data)
|
|
vm:write_to_map()
|
|
elseif def.type == "plane" then
|
|
local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius))
|
|
local va = VoxelArea(vm:get_emerged_area())
|
|
vm:get_data(vm_data)
|
|
vm:get_param2_data(vm_p2_data)
|
|
|
|
local x
|
|
local y
|
|
local z
|
|
if def.axis == "x" then
|
|
local x = pos.x
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z)
|
|
if vm_data[idx] == c_air then
|
|
vm_data[idx] = c_forcefield
|
|
vm_p2_data[idx] = 1
|
|
elseif vm_data[idx] == c_forcefield and vm_p2_data[idx] > 0 then
|
|
vm_p2_data[idx] = vm_p2_data[idx] +1
|
|
end
|
|
end
|
|
end
|
|
elseif def.axis == "y" then
|
|
local y = pos.y
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z)
|
|
if vm_data[idx] == c_air then
|
|
vm_data[idx] = c_forcefield
|
|
vm_p2_data[idx] = 1
|
|
elseif vm_data[idx] == c_forcefield and vm_p2_data[idx] > 0 then
|
|
vm_p2_data[idx] = vm_p2_data[idx] +1
|
|
end
|
|
end
|
|
end
|
|
elseif def.axis == "z" then
|
|
local z = pos.z
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z)
|
|
if vm_data[idx] == c_air then
|
|
vm_data[idx] = c_forcefield
|
|
vm_p2_data[idx] = 1
|
|
elseif vm_data[idx] == c_forcefield and vm_p2_data[idx] > 0 then
|
|
vm_p2_data[idx] = vm_p2_data[idx] +1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(vm_data)
|
|
vm:set_param2_data(vm_p2_data)
|
|
vm:write_to_map()
|
|
end
|
|
end
|
|
|
|
function artifact.remove_forcefield(pos, def)
|
|
if def.type == "cube" then
|
|
if def.offset then pos = pos:add(def.offset) end
|
|
local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius))
|
|
local va = VoxelArea(vm:get_emerged_area())
|
|
vm:get_data(vm_data)
|
|
vm:get_param2_data(vm_p2_data)
|
|
for x = pos.x -def.radius, pos.x +def.radius, def.radius *2 do
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x, y, z)
|
|
if vm_data[idx] == c_forcefield then
|
|
if vm_p2_data[idx] <= 1 then
|
|
vm_data[idx] = c_air
|
|
vm_p2_data[idx] = 0
|
|
else
|
|
vm_p2_data[idx] = vm_p2_data[idx] -1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for y = pos.y -def.radius, pos.y +def.radius, def.radius *2 do
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x, y, z)
|
|
if vm_data[idx] == c_forcefield then
|
|
if vm_p2_data[idx] <= 1 then
|
|
vm_data[idx] = c_air
|
|
vm_p2_data[idx] = 0
|
|
else
|
|
vm_p2_data[idx] = vm_p2_data[idx] -1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for z = pos.z -def.radius, pos.z +def.radius, def.radius *2 do
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
local idx = va:index(x, y, z)
|
|
if vm_data[idx] == c_forcefield then
|
|
if vm_p2_data[idx] <= 1 then
|
|
vm_data[idx] = c_air
|
|
vm_p2_data[idx] = 0
|
|
else
|
|
vm_p2_data[idx] = vm_p2_data[idx] -1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
vm:set_data(vm_data)
|
|
vm:set_param2_data(vm_p2_data)
|
|
vm:write_to_map()
|
|
elseif def.type == "plane" then
|
|
local vm = minetest.get_voxel_manip(pos:offset(-def.radius,-def.radius,-def.radius), pos:offset(def.radius,def.radius,def.radius))
|
|
local va = VoxelArea(vm:get_emerged_area())
|
|
vm:get_data(vm_data)
|
|
vm:get_param2_data(vm_p2_data)
|
|
|
|
local x
|
|
local y
|
|
local z
|
|
if def.axis == "x" then
|
|
local x = pos.x
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z)
|
|
if vm_data[idx] == c_forcefield then
|
|
if vm_p2_data[idx] <= 1 then
|
|
vm_data[idx] = c_air
|
|
vm_p2_data[idx] = 0
|
|
else
|
|
vm_p2_data[idx] = vm_p2_data[idx] -1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
elseif def.axis == "y" then
|
|
local y = pos.y
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
for z = pos.z -def.radius, pos.z +def.radius do
|
|
local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z)
|
|
if vm_data[idx] == c_forcefield then
|
|
if vm_p2_data[idx] <= 1 then
|
|
vm_data[idx] = c_air
|
|
vm_p2_data[idx] = 0
|
|
else
|
|
vm_p2_data[idx] = vm_p2_data[idx] -1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
elseif def.axis == "z" then
|
|
local z = pos.z
|
|
for y = pos.y -def.radius, pos.y +def.radius do
|
|
for x = pos.x -def.radius, pos.x +def.radius do
|
|
local idx = va:index(x +def.offset.x, y +def.offset.y, z +def.offset.z)
|
|
if vm_data[idx] == c_forcefield then
|
|
if vm_p2_data[idx] <= 1 then
|
|
vm_data[idx] = c_air
|
|
vm_p2_data[idx] = 0
|
|
else
|
|
vm_p2_data[idx] = vm_p2_data[idx] -1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(vm_data)
|
|
vm:set_param2_data(vm_p2_data)
|
|
vm:write_to_map()
|
|
end
|
|
end
|
|
|
|
|
|
local function onload(pos)
|
|
local m = minetest.get_meta(pos)
|
|
if not m:contains("initialized") then
|
|
local conf = minetest.deserialize(m:get("config") or "return nil") or {type = "plane", radius = 5, axis = "x", offset = vector.new(3,0,0)}
|
|
m:set_string("_config", minetest.serialize(conf))
|
|
m:set_string("config", minetest.serialize(conf))
|
|
artifact.place_forcefield(pos, conf)
|
|
end
|
|
end
|
|
|
|
artifact.register_node("forcefield_generator", {
|
|
drawtype = "mesh",
|
|
mesh = "artifact_forcefield_generator.gltf",
|
|
tiles = {"artifact_forcefield_generator.png"},
|
|
paramtype = "light",
|
|
light_source = 10,
|
|
paramtype2 = "facedir",
|
|
groups = {whackable = 1},
|
|
collision_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
-1, -0.5, -0.5,
|
|
1, 0.5, 0.5
|
|
}
|
|
},
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
-1, -0.5, -0.5,
|
|
1, 0.5, 0.5
|
|
}
|
|
},
|
|
on_construct = onload,
|
|
on_load = onload,
|
|
on_rightclick = artifact.debug and function(pos)
|
|
local m = minetest.get_meta(pos)
|
|
artifact.remove_forcefield(pos, minetest.deserialize(m:get("_config") or "return nil") or {type = "plane", radius = 5, axis = "x", offset = vector.new(3,0,0)})
|
|
local conf = minetest.deserialize(m:get("config") or "return nil") or {type = "plane", radius = 5, axis = "x", offset = 3}
|
|
m:set_string("_config", minetest.serialize(conf))
|
|
artifact.place_forcefield(pos, conf)
|
|
end or nil,
|
|
on_destruct = function(pos)
|
|
local m = minetest.get_meta(pos)
|
|
local conf = minetest.deserialize(m:get("config") or "return nil") or {type = "cube", radius = 5}
|
|
artifact.remove_forcefield(pos, conf)
|
|
local node = minetest.get_node(pos)
|
|
node.name = "forcefield_generator_off"
|
|
minetest.after(0, function()
|
|
minetest.set_node(pos, node)
|
|
end)
|
|
minetest.add_particlespawner {
|
|
pos = pos,
|
|
vel = vector.zero(),
|
|
acc = vector.new(0, -9.81, 0),
|
|
drag = vector.new(3, 0, 3),
|
|
radius = 0.1,
|
|
attract = {
|
|
kind = "point",
|
|
origin = pos,
|
|
strength = -50
|
|
},
|
|
texture = {
|
|
name = "artifact_light_gold.png",
|
|
alpha_tween = {1, 0}
|
|
},
|
|
size_tween = {
|
|
{
|
|
min = 3,
|
|
max = 6
|
|
},
|
|
{
|
|
min = 1,
|
|
max = 2
|
|
}
|
|
},
|
|
time = 0.3,
|
|
amount = 100,
|
|
}
|
|
end
|
|
})
|
|
|
|
artifact.register_node("forcefield_generator_off", {
|
|
drawtype = "mesh",
|
|
mesh = "artifact_forcefield_generator.gltf",
|
|
tiles = {"artifact_forcefield_generator_off.png"},
|
|
paramtype = "light",
|
|
light_source = 6,
|
|
paramtype2 = "facedir",
|
|
collision_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
-1, -0.5, -0.5,
|
|
1, 0.5, 0.5
|
|
}
|
|
},
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
-1, -0.5, -0.5,
|
|
1, 0.5, 0.5
|
|
}
|
|
},
|
|
on_impact = artifact.debug and function(pos)
|
|
local node = minetest.get_node(pos)
|
|
node.name = "forcefield_generator"
|
|
minetest.set_node(pos, node)
|
|
end or nil,
|
|
})
|