Add forcefields, and start building the map.

This commit is contained in:
Signal 2025-11-20 03:15:30 -05:00
parent 5fd67703c0
commit dd73665a23
19 changed files with 511 additions and 15 deletions

View file

@ -0,0 +1,346 @@
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,
})