forked from thunderdog1138/star_wars
Upload files to 'mods/gunkit'
This commit is contained in:
parent
bd0dab3eb5
commit
a1cf7e5646
|
@ -0,0 +1,129 @@
|
||||||
|
# gunkit
|
||||||
|
|
||||||
|
Adds an api to easily register advanced firearms within Minetest.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Full auto guns
|
||||||
|
* Mags
|
||||||
|
* Mag Types
|
||||||
|
* Alternate fire mode
|
||||||
|
* ADS (Aim Down Sights)
|
||||||
|
|
||||||
|
## Usage (mods):
|
||||||
|
Registering a firearm:
|
||||||
|
`gunkit.register_firearm(name, firearm definition)`
|
||||||
|
|
||||||
|
Registering a mag:
|
||||||
|
`gunkit.register_mag(name, mag definition)`
|
||||||
|
|
||||||
|
Firearm Definition
|
||||||
|
------------------
|
||||||
|
Used by `gunkit.register_firearm`
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
description = "Super cool Firearm",
|
||||||
|
|
||||||
|
wield_scale = {x = 1, y = 1, z = 1},
|
||||||
|
-- Firearm wield scale (see Minetest lua_api.txt).
|
||||||
|
|
||||||
|
inventory_image = "your_firearm.png",
|
||||||
|
|
||||||
|
mag_type = "smg",
|
||||||
|
-- Type of mag the gun will load.
|
||||||
|
|
||||||
|
sounds = {
|
||||||
|
mag_load = "mymod:mag_load",
|
||||||
|
-- Sound to be played when loading a mag.
|
||||||
|
|
||||||
|
mag_drop = "mymod:mag_drop",
|
||||||
|
-- Sound to be played when dropping a mag.
|
||||||
|
|
||||||
|
fire_empty = "mymod:fire_empty",
|
||||||
|
-- Sound to be played when firing a gun with an empty mag.
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Table fields used for both fire and alt_fire.
|
||||||
|
{
|
||||||
|
bullet_texture = "my_bullet.png",
|
||||||
|
-- Texture to be used for bullet projectiles.
|
||||||
|
|
||||||
|
sounds = {
|
||||||
|
fire = "mymod:fire",
|
||||||
|
-- Sound to be played when firing the gun.
|
||||||
|
|
||||||
|
shell_drop = "mymod:shell_drop",
|
||||||
|
-- Sound to be played when firing the gun.
|
||||||
|
|
||||||
|
fire_toggle = "mymod:fire_toggle",
|
||||||
|
-- Sound to be played when swapping from this fire mode.
|
||||||
|
},
|
||||||
|
|
||||||
|
range = 60,
|
||||||
|
-- Firearms bullet range.
|
||||||
|
|
||||||
|
speed = 300,
|
||||||
|
-- Speed of bullet projectiles, time to projectile hit is always range / speed.
|
||||||
|
|
||||||
|
spread = 1,
|
||||||
|
-- Max bullet spread (in degrees).
|
||||||
|
|
||||||
|
dmg = 3,
|
||||||
|
-- Bullet damage.
|
||||||
|
|
||||||
|
shots = 1,
|
||||||
|
-- Amount of bullets fired each shot.
|
||||||
|
|
||||||
|
interval = 0.1,
|
||||||
|
-- Time between shots (in seconds).
|
||||||
|
|
||||||
|
zoom = 2,
|
||||||
|
-- Level of zoom when using ADS (if applicable).
|
||||||
|
|
||||||
|
zoom_time = 1,
|
||||||
|
-- Time in seconds till fov hits fov*zoom
|
||||||
|
},
|
||||||
|
|
||||||
|
callbacks = {
|
||||||
|
-- Table fields used for both fire and alt_fire
|
||||||
|
fire = {
|
||||||
|
on_fire = function({itemstack, user}),
|
||||||
|
-- Function to be called when firearm is used.
|
||||||
|
-- Return false to prevent default behavior.
|
||||||
|
|
||||||
|
on_hit = function({itemstack, hitter, object}),
|
||||||
|
-- Function to be called when an object is hit by a bullet.
|
||||||
|
-- Return false to prevent default behavior.
|
||||||
|
},
|
||||||
|
|
||||||
|
on_drop_mag = function({itemstack, user}),
|
||||||
|
-- Function to be called when a player attempts to drop a guns mag.
|
||||||
|
-- Return false to prevent default behavior.
|
||||||
|
|
||||||
|
on_load_mag = function({itemstack, user}),
|
||||||
|
-- Function to be called when a player attempts to load a gun.
|
||||||
|
-- Return false to prevent default behavior.
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Magazine Definition
|
||||||
|
-------------------
|
||||||
|
Used by `gunkit.register_mag`
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
description = "Super cool gun magazine",
|
||||||
|
|
||||||
|
inventory_image = "your_firearm_magazine.png",
|
||||||
|
|
||||||
|
mag_type = "smg",
|
||||||
|
-- Set this magazine as loadable by all guns with corresponding mag type.
|
||||||
|
|
||||||
|
ammo = "mymod:bullet",
|
||||||
|
-- Ammo used by this magazine (Itemstring).
|
||||||
|
|
||||||
|
max_ammo = 120,
|
||||||
|
-- Amount of ammo this magazine can hold.
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,518 @@
|
||||||
|
gunkit = {}
|
||||||
|
gunkit.firing = {}
|
||||||
|
gunkit.timer = {}
|
||||||
|
|
||||||
|
--Interval for gun-cooldown checks
|
||||||
|
gunkit.count_interval = 0.1
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Initate some helper functions
|
||||||
|
--
|
||||||
|
|
||||||
|
function get_random_float(lower, upper)
|
||||||
|
return lower + math.random() * (upper - lower)
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_table_size(tbl)
|
||||||
|
local count = 0
|
||||||
|
for k, v in pairs(tbl) do
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Lets define some functions to register guns/mags
|
||||||
|
--
|
||||||
|
|
||||||
|
function gunkit.register_firearm(name, def)
|
||||||
|
--Check if mag_type and bullet textures are specified
|
||||||
|
|
||||||
|
if not def.mag_type or not def.fire.bullet_texture or def.alt_fire
|
||||||
|
and not def.alt_fire.bullet_texture then return end
|
||||||
|
|
||||||
|
--Define some default values
|
||||||
|
local fire = {
|
||||||
|
range = 60,
|
||||||
|
speed = 300,
|
||||||
|
spread = 1,
|
||||||
|
dmg = 7,
|
||||||
|
shots = 1,
|
||||||
|
interval = 0.15,
|
||||||
|
zoom = 2,
|
||||||
|
zoom_time = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
--Use defaults for any value not set if def.fire is present
|
||||||
|
if def.fire then
|
||||||
|
for k, value in pairs(def.fire) do
|
||||||
|
fire[k] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--Get callbacks table
|
||||||
|
local calls = def.callbacks
|
||||||
|
|
||||||
|
--Fancy item descrips
|
||||||
|
local descrip = {
|
||||||
|
def.description,
|
||||||
|
minetest.colorize("#dbc217", "Mag type: " .. def.mag_type),
|
||||||
|
}
|
||||||
|
|
||||||
|
minetest.register_tool(name, {
|
||||||
|
description = table.concat(descrip, "\n"),
|
||||||
|
inventory_image = def.inventory_image,
|
||||||
|
wield_scale = def.wield_scale or nil,
|
||||||
|
|
||||||
|
--[[We set range to 0 so that the gun cant interact with
|
||||||
|
nodes when a user tries to ADS (Aim Down Sights)]]
|
||||||
|
range = 0,
|
||||||
|
|
||||||
|
--Fields defined by the api
|
||||||
|
|
||||||
|
fire = fire,
|
||||||
|
alt_fire = def.alt_fire or nil,
|
||||||
|
mag_type = def.mag_type,
|
||||||
|
|
||||||
|
sounds = def.sounds or nil,
|
||||||
|
|
||||||
|
callbacks = calls or nil,
|
||||||
|
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
--Get the guns meta
|
||||||
|
local meta = itemstack:get_meta()
|
||||||
|
|
||||||
|
--Get the itemdef of the wielded firearm
|
||||||
|
local gun = minetest.registered_items[name]
|
||||||
|
|
||||||
|
--Set the guns fire mode if not already done
|
||||||
|
if not meta:contains("mode") then
|
||||||
|
meta:set_string("mode", "fire")
|
||||||
|
end
|
||||||
|
|
||||||
|
--Check if gun is loaded
|
||||||
|
if not meta:contains("mag") and (not calls or not calls.on_load_mag
|
||||||
|
or calls.on_load_mag({user = user, itemstack = itemstack})) then
|
||||||
|
|
||||||
|
--[[Search through the players inv looking for the mag with the most ammo,
|
||||||
|
mag must have > 0 bullets]]
|
||||||
|
local upper, upper_bullets, index
|
||||||
|
|
||||||
|
for idx, stack in ipairs(user:get_inventory():get_list("main")) do
|
||||||
|
--Get stack meta
|
||||||
|
local stack_meta = stack:get_meta()
|
||||||
|
|
||||||
|
--Check if stack exists and if it 'contains bullets'
|
||||||
|
if not stack:is_empty() and stack_meta:contains("bullets") then
|
||||||
|
--Get meta field and itemdef
|
||||||
|
local bullets = stack_meta:get_int("bullets")
|
||||||
|
local itemdef = minetest.registered_items[stack:get_name()]
|
||||||
|
|
||||||
|
if bullets > 0 and itemdef.mag_type == gun.mag_type
|
||||||
|
and (not upper or bullets > upper_bullets) then
|
||||||
|
|
||||||
|
upper, upper_bullets, index = stack, bullets, idx
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--Load the mag
|
||||||
|
if upper and upper_bullets and index then
|
||||||
|
if gun.sounds and gun.sounds.mag_load then
|
||||||
|
minetest.sound_play(gun.sounds.mag_load, {object = user})
|
||||||
|
end
|
||||||
|
|
||||||
|
meta:set_string("mag", upper:get_name() .. "," .. upper_bullets)
|
||||||
|
itemstack:set_wear(upper:get_wear())
|
||||||
|
user:get_inventory():set_stack("main", index, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
|
||||||
|
--Fire the gun
|
||||||
|
else
|
||||||
|
local temp = itemstack:get_meta():get_string("mag"):split(",")
|
||||||
|
local mag, ammo = temp[1], tonumber(temp[2])
|
||||||
|
|
||||||
|
if ammo > 0 then
|
||||||
|
if not gunkit.firing[user] then
|
||||||
|
--Add to firing queue
|
||||||
|
gunkit.firing[user] = {
|
||||||
|
stack = itemstack,
|
||||||
|
wield_index = user:get_wield_index(),
|
||||||
|
mag = {name = mag, ammo = ammo}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
elseif gun.sounds and gun.sounds.fire_empty then
|
||||||
|
minetest.sound_play(gun.sounds.fire_empty, {object = user})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_secondary_use = function(itemstack, user, pointed_thing)
|
||||||
|
--Get the guns meta
|
||||||
|
local meta = itemstack:get_meta()
|
||||||
|
|
||||||
|
--Set the guns fire mode if not already done
|
||||||
|
if not meta:contains("mode") then
|
||||||
|
meta:set_string("mode", "fire")
|
||||||
|
end
|
||||||
|
|
||||||
|
--Check if gun is loaded
|
||||||
|
if meta:contains("mag") then
|
||||||
|
local temp = meta:get_string("mag"):split(",")
|
||||||
|
local mag, ammo = temp[1], tonumber(temp[2])
|
||||||
|
|
||||||
|
if ammo > 0 and not gunkit.firing[user] then
|
||||||
|
--Get mode def
|
||||||
|
local mode_def = minetest.registered_items[itemstack:get_name()][meta:get_string("mode")]
|
||||||
|
|
||||||
|
if user:get_fov() == 0 and mode_def.zoom and mode_def.zoom_time then
|
||||||
|
user:set_fov(1 / mode_def.zoom, true, mode_def.zoom_time)
|
||||||
|
end
|
||||||
|
|
||||||
|
--Add to firing queue
|
||||||
|
gunkit.firing[user] = {
|
||||||
|
stack = itemstack,
|
||||||
|
wield_index = user:get_wield_index(),
|
||||||
|
mag = {name = mag, ammo = ammo}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_drop = function(itemstack, dropper, pos)
|
||||||
|
local meta = itemstack:get_meta()
|
||||||
|
local wield = dropper:get_wield_index()
|
||||||
|
local inv = dropper:get_inventory()
|
||||||
|
local gun = minetest.registered_items[itemstack:get_name()]
|
||||||
|
|
||||||
|
--Check if gun is loaded
|
||||||
|
if meta:contains("mag") then
|
||||||
|
local temp = meta:get_string("mag"):split(",")
|
||||||
|
local mag, ammo = temp[1], tonumber(temp[2])
|
||||||
|
|
||||||
|
--Check if mag is empty
|
||||||
|
if ammo == 0 and (not calls or not calls.on_drop_mag
|
||||||
|
or calls.on_drop_mag({user = dropper, itemstack = itemstack})) then
|
||||||
|
|
||||||
|
if gun.sounds and gun.sounds.mag_drop then
|
||||||
|
minetest.sound_play(gun.sounds.mag_drop, {object = dropper})
|
||||||
|
end
|
||||||
|
|
||||||
|
local stack = ItemStack(mag)
|
||||||
|
stack:set_wear(65534)
|
||||||
|
|
||||||
|
if inv:room_for_item("main", stack) then
|
||||||
|
inv:add_item("main", stack)
|
||||||
|
else
|
||||||
|
minetest.item_drop(stack, dropper, pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
itemstack:set_wear(0)
|
||||||
|
meta:set_string("mag", "")
|
||||||
|
|
||||||
|
--If not then swap fire mode
|
||||||
|
elseif meta:contains("mode") then
|
||||||
|
meta:set_string("mode", gunkit.swap_mode(dropper, gun, meta:get_string("mode")))
|
||||||
|
end
|
||||||
|
|
||||||
|
--Otherwise drop gun
|
||||||
|
else
|
||||||
|
minetest.item_drop(itemstack, dropper, pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
inv:set_stack("main", wield, itemstack)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function gunkit.register_mag(name, def)
|
||||||
|
--Fancy item descrips
|
||||||
|
local descrip = {
|
||||||
|
def.description,
|
||||||
|
minetest.colorize("#dbc217", "Mag type: " .. def.mag_type),
|
||||||
|
minetest.colorize("#40c3cb", "Ammo: " .. def.ammo),
|
||||||
|
}
|
||||||
|
|
||||||
|
minetest.register_tool(name, {
|
||||||
|
description = table.concat(descrip, "\n"),
|
||||||
|
inventory_image = def.inventory_image,
|
||||||
|
|
||||||
|
--Fields defined by the api
|
||||||
|
|
||||||
|
mag_type = def.mag_type,
|
||||||
|
ammo = def.ammo,
|
||||||
|
max_ammo = def.max_ammo,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = name,
|
||||||
|
recipe = {name, def.ammo},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = name .. " 1 65534",
|
||||||
|
recipe = {name},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
|
||||||
|
local mag, ammo, meta, count
|
||||||
|
|
||||||
|
--Check for corresponding mag and ammo
|
||||||
|
for idx, stack in pairs(old_craft_grid) do
|
||||||
|
--Get stack name
|
||||||
|
local stack_name = stack:get_name()
|
||||||
|
|
||||||
|
if mag and ammo then
|
||||||
|
break
|
||||||
|
elseif not mag and stack_name == name then
|
||||||
|
mag = stack
|
||||||
|
meta = mag:get_meta()
|
||||||
|
count = meta:get_int("bullets")
|
||||||
|
elseif not ammo and stack_name == def.ammo then
|
||||||
|
ammo = stack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--Empty mag
|
||||||
|
if mag and not ammo then
|
||||||
|
meta:set_int("bullets", 0)
|
||||||
|
craft_inv:add_item("craft", {name = def.ammo, count = count})
|
||||||
|
|
||||||
|
--Fill empty mag
|
||||||
|
elseif mag and ammo then
|
||||||
|
local bullets = ammo:get_count()
|
||||||
|
local needs = def.max_ammo - count
|
||||||
|
|
||||||
|
if needs == 0 then
|
||||||
|
craft_inv:add_item("craft", {name = def.ammo})
|
||||||
|
itemstack:get_meta():set_int("bullets", count)
|
||||||
|
|
||||||
|
return
|
||||||
|
else
|
||||||
|
local use
|
||||||
|
|
||||||
|
if needs > bullets then
|
||||||
|
use = bullets
|
||||||
|
else
|
||||||
|
use = needs
|
||||||
|
end
|
||||||
|
|
||||||
|
craft_inv:remove_item("craft", {name = def.ammo, count = use})
|
||||||
|
itemstack:get_meta():set_int("bullets", count + use)
|
||||||
|
itemstack:set_wear(65534 - (65534 / def.max_ammo * (count + use - 1)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Create some internal functions that we will call later
|
||||||
|
--
|
||||||
|
|
||||||
|
--This should be pretty obvious
|
||||||
|
function gunkit.swap_mode(user, def, mode)
|
||||||
|
local modes = {fire = "alt_fire", alt_fire = "fire"}
|
||||||
|
|
||||||
|
--Get alternate mode
|
||||||
|
local alt_mode = modes[mode]
|
||||||
|
|
||||||
|
--Check for alternate mode
|
||||||
|
if def[alt_mode] then
|
||||||
|
local sounds = def[mode].sounds
|
||||||
|
|
||||||
|
if sounds.fire_toggle then
|
||||||
|
minetest.sound_play(sounds.fire_toggle, {object = user})
|
||||||
|
end
|
||||||
|
|
||||||
|
return alt_mode
|
||||||
|
else
|
||||||
|
|
||||||
|
return mode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[get the end of a vector calculated from user pos, look dir, and item range.
|
||||||
|
best not to touch the math here, im not completely sure how it works either]]
|
||||||
|
function gunkit.get_vector(user, p_pos, def)
|
||||||
|
--Add eyeheight offset
|
||||||
|
p_pos.y = p_pos.y + user:get_properties().eye_height or 1.625
|
||||||
|
|
||||||
|
local cam = {
|
||||||
|
x = minetest.yaw_to_dir(user:get_look_horizontal()),
|
||||||
|
z = user:get_look_dir()
|
||||||
|
}
|
||||||
|
|
||||||
|
local dir = vector.multiply(minetest.yaw_to_dir(math.rad(1)), def.range)
|
||||||
|
|
||||||
|
local e_pos = vector.add(p_pos, vector.multiply(cam.z, dir.z))
|
||||||
|
e_pos = vector.add(e_pos, vector.multiply(cam.x, dir.x))
|
||||||
|
|
||||||
|
return p_pos, e_pos
|
||||||
|
end
|
||||||
|
|
||||||
|
--Handle weapon firing
|
||||||
|
function gunkit.fire(user, stack, mag, p_pos, e_pos)
|
||||||
|
local mode = stack:get_meta():get_string("mode")
|
||||||
|
local def = minetest.registered_items[stack:get_name()]
|
||||||
|
local mode_def = def[mode]
|
||||||
|
|
||||||
|
local shots = mode_def.shots
|
||||||
|
if shots > mag.ammo then
|
||||||
|
shots = mag.ammo
|
||||||
|
end
|
||||||
|
|
||||||
|
mag.ammo = math.max(0, mag.ammo - shots)
|
||||||
|
stack:set_wear(65534 - (65534 / minetest.registered_items[mag.name].max_ammo * mag.ammo))
|
||||||
|
|
||||||
|
--Get mode_def sounds table
|
||||||
|
local sounds = mode_def.sounds
|
||||||
|
|
||||||
|
--Check if table exists
|
||||||
|
if sounds then
|
||||||
|
if sounds.fire then
|
||||||
|
minetest.sound_play(sounds.fire, {pos = p_pos})
|
||||||
|
end
|
||||||
|
if sounds.shell_drop then
|
||||||
|
minetest.sound_play(sounds.shell_drop, {pos = p_pos})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, shots do
|
||||||
|
--3d bullet spread (in degrees)
|
||||||
|
e_pos = vector.apply(e_pos, function(n)
|
||||||
|
return n + math.rad(get_random_float(-mode_def.spread, mode_def.spread)) * mode_def.range
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.add_particle({
|
||||||
|
pos = p_pos,
|
||||||
|
velocity = vector.multiply(vector.direction(p_pos, e_pos), 80),
|
||||||
|
expirationtime = 3,
|
||||||
|
collisiondetection = true,
|
||||||
|
collision_removal = true,
|
||||||
|
size = 2,
|
||||||
|
texture = mode_def.bullet_texture,
|
||||||
|
})
|
||||||
|
|
||||||
|
for pointed_thing in minetest.raycast(p_pos, e_pos, true, false) do
|
||||||
|
if pointed_thing.type == "node" then
|
||||||
|
break
|
||||||
|
|
||||||
|
elseif pointed_thing.type == "object" and pointed_thing.ref ~= user then
|
||||||
|
local luaent = pointed_thing.ref:get_luaentity()
|
||||||
|
|
||||||
|
if not luaent or not luaent.name:find("builtin") then
|
||||||
|
local calls = def.callbacks
|
||||||
|
|
||||||
|
if not calls or not calls[mode] or not calls[mode].on_hit
|
||||||
|
or calls[mode].on_hit({itemstack = stack, user = user, obj = pointed_thing.ref}) then
|
||||||
|
|
||||||
|
pointed_thing.ref:punch(user, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy = mode_def.dmg}})
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return mag
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Globalstep to keep track of firing players and weapon cooldowns
|
||||||
|
--
|
||||||
|
|
||||||
|
local counter = 0
|
||||||
|
|
||||||
|
minetest.register_globalstep(
|
||||||
|
function(dtime)
|
||||||
|
local current = minetest.get_us_time() / 1000000
|
||||||
|
|
||||||
|
counter = counter + dtime
|
||||||
|
|
||||||
|
if counter > gunkit.count_interval then
|
||||||
|
--Check users gun cooldowns
|
||||||
|
for user, items in pairs(gunkit.timer) do
|
||||||
|
for item, modes in pairs(items) do
|
||||||
|
for mode, time in pairs(modes) do
|
||||||
|
if current - time > minetest.registered_items[item][mode].interval then
|
||||||
|
gunkit.timer[user][item][mode] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if get_table_size(modes) == 0 then
|
||||||
|
gunkit.timer[user][item] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if get_table_size(items) == 0 then
|
||||||
|
gunkit.timer[user] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--Loop through currently firing users
|
||||||
|
for user, tbl in pairs(gunkit.firing) do
|
||||||
|
local def = minetest.registered_items[user:get_wielded_item():get_name()]
|
||||||
|
|
||||||
|
if def.name == tbl.stack:get_name() and user:get_wield_index() == tbl.wield_index then
|
||||||
|
local name = def.name
|
||||||
|
local meta = tbl.stack:get_meta()
|
||||||
|
local mode = meta:get_string("mode")
|
||||||
|
local mode_def = def[mode]
|
||||||
|
local keys = user:get_player_control()
|
||||||
|
|
||||||
|
if keys.LMB then
|
||||||
|
local timer = gunkit.timer[user]
|
||||||
|
local calls = def.callbacks
|
||||||
|
|
||||||
|
if (not timer or not timer[name] or not timer[name][mode] or current - timer[name][mode] > mode_def.interval)
|
||||||
|
and (not calls or not calls[mode] or not calls[mode].on_fire or calls[mode].on_fire({itemstack = tbl.stack, user = user})) then
|
||||||
|
if meta:contains("mag") and tbl.mag.ammo > 0 then
|
||||||
|
|
||||||
|
local p_pos, e_pos = gunkit.get_vector(user, user:get_pos(), mode_def)
|
||||||
|
|
||||||
|
minetest.after(mode_def.range / mode_def.speed, gunkit.fire, user, tbl.stack, tbl.mag, p_pos, e_pos)
|
||||||
|
|
||||||
|
gunkit.timer[user] = gunkit.timer[user] or {}
|
||||||
|
gunkit.timer[user][name] = gunkit.timer[user][name] or {}
|
||||||
|
gunkit.timer[user][name][mode] = current
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local fov = user:get_fov()
|
||||||
|
local zoom = mode_def.zoom
|
||||||
|
local zoom_time = mode_def.zoom_time
|
||||||
|
|
||||||
|
if zoom and zoom_time then
|
||||||
|
if not keys.RMB and fov ~= 0 then
|
||||||
|
user:set_fov(0, true, zoom_time)
|
||||||
|
elseif keys.RMB and fov == 0 then
|
||||||
|
user:set_fov(1 / zoom, true, zoom_time)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not keys.LMB and not keys.RMB then
|
||||||
|
gunkit.firing[user] = nil
|
||||||
|
meta:set_string("mag", tbl.mag.name .. "," .. tbl.mag.ammo)
|
||||||
|
user:set_wielded_item(tbl.stack)
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
gunkit.firing[user] = nil
|
||||||
|
tbl.stack:get_meta():set_string("mag", tbl.mag.name .. "," .. tbl.mag.ammo)
|
||||||
|
user:get_inventory():set_stack("main", tbl.wield_index, tbl.stack)
|
||||||
|
user:set_fov(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/api.lua")
|
|
@ -0,0 +1,18 @@
|
||||||
|
Copyright 2020 Cahrs (MIT)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1 @@
|
||||||
|
name = gunkit
|
Loading…
Reference in New Issue