local MODNAME = minetest.get_current_modname() local api = rawget(_G, MODNAME) function api.get_bullet_start_data(player) local look_dir = player:get_look_dir() local spawnpos = vector.offset(player:get_pos(), 0, player:get_properties().eye_height, 0) spawnpos = vector.add(spawnpos, player:get_eye_offset()) spawnpos = vector.add(spawnpos, vector.multiply(look_dir, 0.4)) return spawnpos, look_dir end function api.bulletcast(bullet, pos1, pos2, objects, liquids) minetest.add_particle({ pos = pos1, velocity = vector.multiply(vector.direction(pos1, pos2), bullet.particle_speed or 400), acceleration = {x=0, y=0, z=0}, expirationtime = 0.1, size = 1, collisiondetection = true, collision_removal = true, object_collision = objects, texture = bullet.texture or bullet, glow = bullet.glow or 0 }) local raycast = minetest.raycast(pos1, pos2, objects, liquids) local bulletcast = { raycast = raycast, hit_object_or_node = function(self, options) if not options then options = {} end for hitpoint in self.raycast do if hitpoint.type == "node" then if not options.node or options.node(minetest.registered_nodes[minetest.get_node(hitpoint.under).name]) then return hitpoint end elseif hitpoint.type == "object" then if not options.object or options.object(hitpoint.ref) then return hitpoint end end end end, } setmetatable(bulletcast, { __index = function(table, key) local not_raycast_func = rawget(table, key) if not_raycast_func then return not_raycast_func else return function(self, ...) local sraycast = rawget(self, "raycast") return sraycast[key](sraycast, ...) end end end, __call = function(table, ...) return rawget(table, "raycast")(...) end }) return bulletcast end function api.spread_bulletcast(bullet, pos1, pos2, objects, liquids) local rays = {} for i=1, bullet.amount or 1, 1 do rays[i] = api.bulletcast( bullet, pos1, vector.offset(pos2, math.random(-bullet.spread, bullet.spread), math.random(-bullet.spread, bullet.spread), math.random(-bullet.spread, bullet.spread) ), objects, liquids ) end return rays end