2020-04-22 02:01:27 +00:00
|
|
|
------------------
|
|
|
|
-- Private data --
|
|
|
|
------------------
|
|
|
|
|
2020-06-10 15:46:25 +00:00
|
|
|
-- Locally cache rifle defs for fast and easy access
|
|
|
|
local rifles = {}
|
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
-- Keep track of players who are scoping in, and their wielded item
|
|
|
|
local scoped = {}
|
|
|
|
|
|
|
|
-- Timer for scope-check globalstep
|
|
|
|
local timer = 0.2
|
|
|
|
|
2020-12-19 01:37:48 +00:00
|
|
|
-- List of IDs for players scoped, for use in hide_scope(). NOTE: for HUD overlay
|
|
|
|
local scoped_hud_id = {}
|
|
|
|
|
|
|
|
-- Scale constant, for crosshair. This is to ensure the crosshair will be centered.
|
|
|
|
local scale_const = 6
|
|
|
|
|
2020-06-10 15:46:25 +00:00
|
|
|
local default_physics_overrides = {
|
|
|
|
speed = 0.1,
|
|
|
|
jump = 0
|
|
|
|
}
|
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
-------------
|
|
|
|
-- Helpers --
|
|
|
|
-------------
|
|
|
|
|
|
|
|
local function show_scope(name, item_name, fov_mult)
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
|
|
if not player then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
scoped[name] = item_name
|
2020-12-19 01:37:48 +00:00
|
|
|
scoped_hud_id[name] = player:hud_add({
|
|
|
|
hud_elem_type = "image",
|
|
|
|
position = {x = 0.5, y = 0.5},
|
|
|
|
offset = {x = (-65*scale_const)/2, y = (-65*scale_const)/2},
|
|
|
|
text = "rifle_crosshair.png",
|
|
|
|
scale = {x = scale_const, y = scale_const},
|
|
|
|
alignment = {x = 1, y = 1},
|
|
|
|
})
|
2020-04-22 02:01:27 +00:00
|
|
|
-- e.g. if fov_mult == 8, then FOV = 1/8 * current_FOV, a.k.a 8x zoom
|
|
|
|
player:set_fov(1 / fov_mult, true)
|
2020-06-10 15:46:25 +00:00
|
|
|
physics.set(name, "sniper_rifles:scoping", rifles[item_name].physics_overrides)
|
2020-04-22 02:01:27 +00:00
|
|
|
player:hud_set_flags({ wielditem = false })
|
2020-12-19 01:37:48 +00:00
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local function hide_scope(name)
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
|
|
if not player then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
scoped[name] = nil
|
2020-12-19 01:37:48 +00:00
|
|
|
player:hud_remove(scoped_hud_id[name])
|
|
|
|
scoped_hud_id[name] = nil
|
2020-04-22 02:01:27 +00:00
|
|
|
player:set_fov(0)
|
2020-06-10 15:46:25 +00:00
|
|
|
physics.remove(name, "sniper_rifles:scoping")
|
2020-04-22 02:01:27 +00:00
|
|
|
player:hud_set_flags({ wielditem = true })
|
2020-12-19 01:37:48 +00:00
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
end
|
|
|
|
|
2020-12-27 05:01:36 +00:00
|
|
|
-- Be absolutely certain crosshair HUD gets removed on death
|
|
|
|
minetest.register_on_dieplayer(function(player)
|
|
|
|
if scoped_hud_id[player:get_player_name()] then
|
|
|
|
hide_scope(player:get_player_name())
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
2020-06-10 15:46:25 +00:00
|
|
|
local function on_use(stack, user, pointed)
|
|
|
|
if scoped[user:get_player_name()] then
|
|
|
|
-- shooter checks for the return value of def.on_use, and executes
|
|
|
|
-- the rest of the code only if this function returns non-nil
|
|
|
|
return stack
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
local function on_rclick(item, placer, pointed_thing)
|
2020-09-22 15:52:11 +00:00
|
|
|
local name = placer:get_player_name()
|
|
|
|
|
|
|
|
-- Prioritize on "un-scoping", if player is using the scope
|
|
|
|
if not scoped[name] and pointed_thing.type == "node" then
|
|
|
|
return minetest.item_place(item, placer, pointed_thing)
|
2020-04-22 02:01:27 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if scoped[name] then
|
|
|
|
hide_scope(name)
|
|
|
|
else
|
|
|
|
-- Remove _loaded suffix added to item name by shooter
|
|
|
|
local item_name = item:get_name():gsub("_loaded", "")
|
|
|
|
local fov_mult = shooter.registered_weapons[item_name].fov_mult
|
|
|
|
show_scope(name, item_name, fov_mult)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
------------------
|
2020-12-27 05:01:36 +00:00
|
|
|
-- Scope-check --
|
2020-04-22 02:01:27 +00:00
|
|
|
------------------
|
|
|
|
|
|
|
|
-- Hide scope if currently wielded item is not the same item
|
|
|
|
-- player wielded when scoping
|
|
|
|
|
|
|
|
local time = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
time = time + dtime
|
|
|
|
if time < timer then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
time = 0
|
|
|
|
for name, original_item in pairs(scoped) do
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
|
|
if not player then
|
|
|
|
scoped[name] = nil
|
|
|
|
else
|
|
|
|
local wielded_item = player:get_wielded_item():get_name():gsub("_loaded", "")
|
|
|
|
if wielded_item ~= original_item then
|
|
|
|
hide_scope(name)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
----------------------------
|
|
|
|
-- Rifle registration API --
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
sniper_rifles = {}
|
|
|
|
|
|
|
|
function sniper_rifles.register_rifle(name, def)
|
|
|
|
assert(def.fov_mult, "Rifle definition must contain FOV multiplier (fov_mult)!")
|
|
|
|
|
2020-06-10 15:46:25 +00:00
|
|
|
-- Override on_use to allow firing weapon only when using the scope
|
|
|
|
def.on_use = on_use
|
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
shooter.register_weapon(name, def)
|
|
|
|
|
|
|
|
-- Manually add extra fields to itemdef that shooter doesn't allow
|
|
|
|
-- Also modify the _loaded variant
|
|
|
|
local overrides = {
|
2020-09-22 15:52:11 +00:00
|
|
|
on_place = on_rclick,
|
2020-04-22 02:01:27 +00:00
|
|
|
on_secondary_use = on_rclick,
|
|
|
|
wield_scale = vector.new(2, 2, 1.5)
|
|
|
|
}
|
|
|
|
minetest.override_item(name, overrides)
|
|
|
|
minetest.override_item(name .. "_loaded", overrides)
|
|
|
|
|
2020-06-10 15:46:25 +00:00
|
|
|
def.physics_overrides = def.physics_overrides or default_physics_overrides
|
|
|
|
|
|
|
|
rifles[name] = table.copy(def)
|
2020-04-22 02:01:27 +00:00
|
|
|
end
|
|
|
|
|
2021-01-06 17:45:18 +00:00
|
|
|
local old_is_protected = minetest.is_protected
|
|
|
|
local r = ctf.setting("flag.nobuild_radius") + 5
|
|
|
|
local rs = r * r
|
|
|
|
function minetest.is_protected(pos, name, info, ...)
|
|
|
|
if r <= 0 or rs == 0 or not info or not info.is_gun then
|
|
|
|
return old_is_protected(pos, name, info, ...)
|
|
|
|
end
|
|
|
|
|
|
|
|
local flag, distSQ = ctf_flag.get_nearest(pos)
|
|
|
|
if flag and pos.y >= flag.y - 1 and distSQ < rs then
|
|
|
|
minetest.chat_send_player(name,
|
|
|
|
"You can't shoot blocks within "..r.." nodes of a flag!")
|
|
|
|
return true
|
|
|
|
else
|
|
|
|
return old_is_protected(pos, name, info, ...)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-04-22 02:01:27 +00:00
|
|
|
dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/rifles.lua")
|