artifact_one/mods/artifact_characters/vix.lua
2025-11-29 17:24:33 -05:00

131 lines
4.5 KiB
Lua

local ns = artifact
minetest.register_entity(":artifact:burst", {
initial_properties = {
visual = "sprite",
textures = {"blank.png"},
pointable = false,
physical = true,
collide_with_objects = false,
collisionbox = {
-0.2, -0.2, -0.2,
0.2, 0.2, 0.2
},
static_save = false,
},
on_activate = function(e)
e.object:set_armor_groups{immortal = 1}
end,
on_deactivate = function(e)
for _, x in ipairs(e._particles or {}) do
minetest.delete_particlespawner(x)
end
end,
on_step = function(e, dtime, movement)
-- Minetest's collision is rather bad, but we also shouldn't collide with players,
-- hence we must implement our own rudimentary collision detection.
-- In this case, any intersection on the segment between our last position and our
-- current one should be considered a collision and result in detonation (and
-- at the exact intersection point, if available).
local collision
if not e._critical then
for x in minetest.raycast(e.old_pos or e.object:get_pos(), e.object:get_pos(), true, true, {nodes = {}, objects = {playser = false}}) do
collision = x
break
end
end
if collision or movement and movement.collides then
if collision then
e.object:set_pos(collision.intersection_point)
end
minetest.add_particlespawner {
pos = e.object:get_pos(),
radius = 0.1,
texture = {
name = "artifact_light.png",
alpha_tween = {1, 0}
},
glow = 8,
size_tween = {
{min = 2, max = 3},
{min = 4, max = 5}
},
attract = {
kind = "point",
strength = {
min = -50,
max = -20,
},
origin = e.object:get_pos()
},
amount = 25,
exptime = 0.5,
drag = 1,
time = 0.1,
}
artifact.play_sound {
name = "artifact_burst_impact",
pos = e.object:get_pos()
}
e.object:remove()
if movement and movement.collisions[1] and movement.collisions[1].type == "node" then
local pos = movement.collisions[1].node_pos
local name = minetest.get_node(pos).name
if minetest.registered_nodes[name].on_impact then
minetest.registered_nodes[name].on_impact(pos)
end
end
return
end
e.old_pos = e.object:get_pos()
end,
impulse = function(e, vel)
-- The documentation said that `vel` is relative to the parent entity...
-- I guess the documentation is wrong?
local rot = vel:normalize():dir_to_rotation()
local min, max = vector.sort(vector.new(-1,-1,-1):rotate(rot), vector.new(1,1,0):rotate(rot))
e._particles = {
-- Tail
minetest.add_particlespawner {
attached = e.object,
pos = {
min = vector.new(-1,-1,-1) *0.2,
max = vector.new(1,1,1) *0.2
},
vel = {
min = min,
max = max
},
texture = {
name = "artifact_light.png",
alpha_tween = {1, 0}
},
size = 0.4,
glow = 10,
amount = 450,
time = 0
},
-- Head
minetest.add_particlespawner {
attached = e.object,
pos = vector.zero(),
vel = vel,
texture = "[fill:16x16:0,0:#fff",
size_tween = {3, 0},
glow = 14,
amount = 150,
time = 0,
exptime = 0.1
}
}
e.object:set_velocity(vel)
end
})
function ns.do_shoot(m, dir)
artifact.play_sound {
name = "artifact_burst_fire",
pos = dir and m or m.pos
}
minetest.add_entity(dir and m +dir or m.pos +m.dir, "artifact:burst"):get_luaentity():impulse((dir or m.dir) *30)
end