shooter/shooter.lua

202 lines
5.3 KiB
Lua
Raw Normal View History

2013-11-26 21:22:21 +00:00
shooter = {}
SHOOTER_EXPLOSION_TEXTURE = "shooter_hit.png"
SHOOTER_ALLOW_NODES = true
2013-12-05 20:45:29 +00:00
SHOOTER_ALLOW_ENTITIES = false
SHOOTER_NODE_RANGE = 50
SHOOTER_OBJECT_RANGE = 50
local modpath = minetest.get_modpath(minetest.get_current_modname())
local input = io.open(modpath.."/shooter.conf", "r")
if input then
dofile(modpath.."/shooter.conf")
input:close()
input = nil
end
if minetest.is_singleplayer() == true then
SHOOTER_ALLOW_ENTITIES = true
end
local timer = 0
local shots = {}
local function spawn_particles(p, v, d, texture)
if type(texture) ~= "string" then
texture = SHOOTER_EXPLOSION_TEXTURE
end
local pos = vector.add(p, vector.multiply(v, {x=d, y=d, z=d}))
pos.y = pos.y + 0.75
local spread = {x=0.1, y=0.1, z=0.1}
minetest.add_particlespawner(15, 0.3,
vector.subtract(pos, spread), vector.add(pos, spread),
{x=-1, y=1, z=-1}, {x=1, y=2, z=1},
{x=-2, y=-2, z=-2}, {x=2, y=-2, z=2},
0.1, 0.75, 1, 2, false, texture
)
end
local function is_valid_object(object)
if object:is_player() == true then
2013-11-26 21:22:21 +00:00
return true
end
if SHOOTER_ALLOW_ENTITIES == true then
local luaentity = object:get_luaentity()
if luaentity then
if minetest.registered_entities[luaentity.name] then
return true
end
end
end
2013-11-26 21:22:21 +00:00
return false
end
local function punch_node(pos, def)
local node = minetest.get_node(pos)
if not node then
return
end
local item = minetest.registered_items[node.name]
2014-06-02 18:11:58 +00:00
if not item then
return
end
if item.groups then
for k, v in pairs(def.groups) do
local level = item.groups[k] or 0
if level >= v then
minetest.remove_node(pos)
local sounds = item.sounds
if sounds then
local soundspec = sounds.dug
if soundspec then
soundspec.pos = pos
minetest.sound_play(soundspec.name, soundspec)
end
end
local tiles = item.tiles
if tiles then
return tiles[1]
end
break
end
end
end
end
function shooter:fire_weapon(user, pointed_thing, def)
local name = user:get_player_name()
if shots[name] then
if timer < shots[name] then
return
end
end
shots[name] = timer + def.tool_caps.full_punch_interval
2013-11-26 21:22:21 +00:00
minetest.sound_play(def.sound, {object=user})
local v1 = user:get_look_dir()
2013-11-26 21:22:21 +00:00
local p1 = user:getpos()
minetest.add_particle({x=p1.x, y=p1.y + 1.6, z=p1.z},
vector.multiply(v1, {x=30, y=30, z=30}),
{x=0, y=0, z=0}, 0.5, 0.25,
false, def.particle
)
if pointed_thing.type == "node" and SHOOTER_ALLOW_NODES == true then
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
local texture = punch_node(pos, def)
if texture then
spawn_particles({x=p1.x, y=p1.y + 0.75, z=p1.z},
v1, vector.distance(p1, pos), texture)
end
return
elseif pointed_thing.type == "object" then
local object = pointed_thing.ref
if is_valid_object(object) == true then
object:punch(user, nil, def.tool_caps, v1)
local p2 = object:getpos()
spawn_particles({x=p1.x, y=p1.y + 0.75, z=p1.z}, v1,
vector.distance(p1, p2), SHOOTER_EXPLOSION_TEXTURE)
return
end
end
if def.range > 100 then
def.range = 100
end
local target = {object=nil, distance=100}
local objects = {}
if SHOOTER_ALLOW_ENTITIES == true then
local range = def.range
if range > SHOOTER_OBJECT_RANGE then
range = SHOOTER_OBJECT_RANGE
end
local r = math.ceil(range * 0.5)
local p = vector.add(p1, vector.multiply(v1, {x=r, y=r, z=r}))
objects = minetest.get_objects_inside_radius(p, r)
else
objects = minetest.get_connected_players()
end
for _,object in ipairs(objects) do
if is_valid_object(object) == true then
local p2 = object:getpos()
if p1 and p2 then
local x = vector.distance(p1, p2)
p2.y = p2.y - 0.75
if x > 0 and x < target.distance and x < def.range then
local yx = 0
2013-12-13 18:29:48 +00:00
if x > 30 then
yx = 0.001 * (10 - x * 0.1)
else
2013-12-13 18:29:48 +00:00
yx = 0.00002 * (x * x) - 0.002 * x + 0.05
end
local yy = yx * 3
2013-11-26 21:22:21 +00:00
local v2 = vector.normalize(vector.direction(p1, p2))
local vd = vector.subtract(v1, v2)
if math.abs(vd.x) < yx and
math.abs(vd.z) < yx and
math.abs(vd.y) < yy then
2013-11-26 21:22:21 +00:00
target = {
object = object,
2013-11-26 21:22:21 +00:00
distance = x,
pos = {x=p2.x, z=p2.z, y=p2.y+1.75},
2013-11-26 21:22:21 +00:00
}
end
end
end
end
end
local view_pos = {x=p1.x, y=p1.y + 1.75, z=p1.z}
if target.object then
local success, pos = minetest.line_of_sight(view_pos, target.pos, 1)
if success then
target.object:punch(user, nil, def.tool_caps, v1)
spawn_particles({x=p1.x, y=p1.y + 0.75, z=p1.z}, v1,
target.distance, SHOOTER_EXPLOSION_TEXTURE)
elseif pos and SHOOTER_ALLOW_NODES == true then
local texture = punch_node(pos, def)
if texture then
spawn_particles({x=p1.x, y=p1.y + 0.75, z=p1.z},
v1, vector.distance(p1, pos), texture)
end
end
elseif SHOOTER_ALLOW_NODES == true then
local d = def.range
if d > SHOOTER_NODE_RANGE then
d = SHOOTER_NODE_RANGE
end
local p2 = vector.add(view_pos, vector.multiply(v1, {x=d, y=d, z=d}))
local success, pos = minetest.line_of_sight(view_pos, p2, 1)
if pos then
local texture = punch_node(pos, def)
if texture then
spawn_particles({x=p1.x, y=p1.y + 0.75, z=p1.z},
v1, vector.distance(p1, pos), texture)
end
2013-11-26 21:22:21 +00:00
end
end
end
minetest.register_on_joinplayer(function(player)
player:hud_set_flags({crosshair = true})
end)
minetest.register_globalstep(function(dtime)
timer = timer + dtime
end)