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