Add spread option and update shotgun definition
This commit is contained in:
parent
88750a0353
commit
8e18c0b117
4 changed files with 104 additions and 21 deletions
|
@ -2,7 +2,6 @@ allow_defined_top = true
|
|||
|
||||
read_globals = {
|
||||
"ItemStack",
|
||||
"vector",
|
||||
"VoxelArea",
|
||||
"VoxelManip",
|
||||
"PseudoRandom",
|
||||
|
@ -11,6 +10,7 @@ read_globals = {
|
|||
}
|
||||
|
||||
globals = {
|
||||
"vector",
|
||||
"minetest",
|
||||
}
|
||||
|
||||
|
|
|
@ -188,6 +188,11 @@ Used by `shooter.register_weapon`
|
|||
-- Range (in nodes) of each shot
|
||||
step = 30,
|
||||
-- Distance per `shooter_rounds_update_time`
|
||||
shots = 1,
|
||||
-- Number of shots fired per `round`
|
||||
spread = 10,
|
||||
-- Spread of shots in degrees if `shots` > 1
|
||||
-- Uses a sunflower seed arrangement for even distributuion
|
||||
tool_caps = {
|
||||
-- Tool capabilities, used for object/player damage
|
||||
full_punch_interval = 1.0,
|
||||
|
|
|
@ -59,6 +59,11 @@ local shooting = {}
|
|||
local config = shooter.config
|
||||
local server_step = minetest.settings:get("dedicated_server_step")
|
||||
local v3d = vector
|
||||
local PI = math.pi
|
||||
local sin = math.sin
|
||||
local cos = math.cos
|
||||
local sqrt = math.sqrt
|
||||
local phi = (math.sqrt(5) + 1) / 2 -- Golden ratio
|
||||
|
||||
shooter.register_weapon = function(name, def)
|
||||
-- Fix definition table
|
||||
|
@ -240,6 +245,74 @@ shooter.punch_object = function(object, tool_caps, dir, on_blast)
|
|||
end
|
||||
end
|
||||
|
||||
local function matrix_from_quat(q)
|
||||
local m = {{}, {}, {}}
|
||||
m[1][1] = 1 - 2 * q.y * q.y - 2 * q.z * q.z
|
||||
m[1][2] = 2 * q.x * q.y + 2 * q.z * q.w
|
||||
m[1][3] = 2 * q.x * q.z - 2 * q.y * q.w
|
||||
m[2][1] = 2 * q.x * q.y - 2 * q.z * q.w
|
||||
m[2][2] = 1 - 2 * q.x * q.x - 2 * q.z * q.z
|
||||
m[2][3] = 2 * q.z * q.y + 2 * q.x * q.w
|
||||
m[3][1] = 2 * q.x * q.z + 2 * q.y * q.w
|
||||
m[3][2] = 2 * q.z * q.y - 2 * q.x * q.w
|
||||
m[3][3] = 1 - 2 * q.x * q.x - 2 * q.y * q.y
|
||||
return m
|
||||
end
|
||||
|
||||
local function quat_from_angle_axis(angle, axis)
|
||||
local t = angle / 2
|
||||
local s = sin(t)
|
||||
return {
|
||||
x = s * axis.x,
|
||||
y = s * axis.y,
|
||||
z = s * axis.z,
|
||||
w = cos(t),
|
||||
}
|
||||
end
|
||||
|
||||
v3d.cross = function(v1, v2)
|
||||
return {
|
||||
x = v1.y * v2.z - v2.y * v1.z,
|
||||
y = v1.z * v2.x - v2.z * v1.x,
|
||||
z = v1.x * v2.y - v2.x * v1.y,
|
||||
}
|
||||
end
|
||||
|
||||
v3d.mult_matrix = function(v, m)
|
||||
return {
|
||||
x = m[1][1] * v.x + m[1][2] * v.y + m[1][3] * v.z,
|
||||
y = m[2][1] * v.x + m[2][2] * v.y + m[2][3] * v.z,
|
||||
z = m[3][1] * v.x + m[3][2] * v.y + m[3][3] * v.z,
|
||||
}
|
||||
end
|
||||
|
||||
v3d.rotate = function(v, angle, axis)
|
||||
local q = quat_from_angle_axis(angle, axis)
|
||||
local m = matrix_from_quat(q)
|
||||
return v3d.mult_matrix(v, m)
|
||||
end
|
||||
|
||||
local function get_directions(dir, spec)
|
||||
local directions = {dir}
|
||||
local n = spec.shots or 1
|
||||
if n > 1 then
|
||||
local right = v3d.normalize(v3d.cross(dir, {x=0, y=1, z=0}))
|
||||
local up = v3d.normalize(v3d.cross(dir, right))
|
||||
local s = spec.spread or 10
|
||||
s = s * 0.017453 -- Convert to radians
|
||||
for k = 1, n - 1 do
|
||||
-- Sunflower seed arrangement
|
||||
local r = sqrt(k - 0.5) / sqrt(n - 0.5)
|
||||
local theta = 2 * PI * k / (phi * phi)
|
||||
local x = r * cos(theta) * s
|
||||
local y = r * sin(theta) * s
|
||||
local d = v3d.rotate(dir, y, up)
|
||||
directions[k + 1] = v3d.rotate(d, x, right)
|
||||
end
|
||||
end
|
||||
return directions
|
||||
end
|
||||
|
||||
local function process_hit(pointed_thing, spec, dir)
|
||||
local def = minetest.registered_items[spec.name] or {}
|
||||
if type(def.on_hit) == "function" then
|
||||
|
@ -295,10 +368,12 @@ local function fire_weapon(player, itemstack, spec, extended)
|
|||
local interval = spec.tool_caps.full_punch_interval
|
||||
shots[spec.user] = minetest.get_us_time() / 1000000 + interval
|
||||
minetest.sound_play(spec.sound, {object=player})
|
||||
local directions = get_directions(dir, spec)
|
||||
for _, d in pairs(directions) do
|
||||
if spec.bullet_image then
|
||||
minetest.add_particle({
|
||||
pos = pos,
|
||||
velocity = v3d.multiply(dir, 30),
|
||||
velocity = v3d.multiply(d, 30),
|
||||
acceleration = {x=0, y=0, z=0},
|
||||
expirationtime = 0.5,
|
||||
size = 0.25,
|
||||
|
@ -308,9 +383,10 @@ local function fire_weapon(player, itemstack, spec, extended)
|
|||
process_round({
|
||||
spec = spec,
|
||||
pos = v3d.new(spec.origin),
|
||||
dir = dir,
|
||||
dir = d,
|
||||
dist = 0,
|
||||
})
|
||||
end
|
||||
if extended then
|
||||
itemstack:add_wear(spec.wear)
|
||||
if itemstack:get_count() == 0 then
|
||||
|
|
|
@ -62,14 +62,16 @@ shooter.register_weapon("shooter_guns:shotgun", {
|
|||
rounds = 50,
|
||||
range = 30,
|
||||
step = 15,
|
||||
tool_caps = {full_punch_interval=1.5, damage_groups={fleshy=4}},
|
||||
groups = {cracky=3, snappy=2, crumbly=2, choppy=2, fleshy=1, oddly_breakable_by_hand=1},
|
||||
shots = 15,
|
||||
spread = 10,
|
||||
tool_caps = {full_punch_interval=0.5, damage_groups={fleshy=2}},
|
||||
groups = {snappy=3, fleshy=3, oddly_breakable_by_hand=3},
|
||||
sound = "shooter_shotgun",
|
||||
bullet_image = "smoke_puff.png",
|
||||
bullet_image = "shooter_cap.png",
|
||||
particles = {
|
||||
amount = 16,
|
||||
minsize = 1,
|
||||
maxsize = 2,
|
||||
amount = 8,
|
||||
minsize = 0.25,
|
||||
maxsize = 0.75,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue