Page MenuHome1F616EMO Bugtracker

No OneTemporary

Size
13 KB
Referenced Files
None
Subscribers
None
diff --git a/ctf_ranged/init.lua b/ctf_ranged/init.lua
index a704d5f..a5a3fa0 100644
--- a/ctf_ranged/init.lua
+++ b/ctf_ranged/init.lua
@@ -1,455 +1,498 @@
local hud = mhud.init()
function PlayerName(player)
local type = type(player)
if type == "string" then
return player
elseif type == "userdata" and player:is_player() then
return player:get_player_name()
end
end
local shoot_cooldown = {
players = {},
set = function(self, player, time)
local pname = PlayerName(player)
if self.players[pname] then
self.players[pname]._timer:cancel()
if not time then
self.players[pname] = nil
return
end
end
if type(time) ~= "table" then
time = { _time = time }
end
time._timer = minetest.after(time._time, function()
if time._on_end then
local copy = table.copy(self.players[pname])
self.players[pname] = nil
time._on_end(copy)
else
self.players[pname] = nil
end
end)
time.start_time = os.clock()
self.players[pname] = time
end,
get = function(self, player)
return self.players[PlayerName(player)]
end
}
ctf_ranged = {
scoped = {}
}
local scoped = ctf_ranged.scoped
local scale_const = 6
local S = minetest.get_translator(minetest.get_current_modname())
minetest.register_craftitem("ctf_ranged:ammo", {
description = S("Ammo") .. "\n" .. S("Used to reload guns"),
inventory_image = "ctf_ranged_ammo.png",
})
local function process_ray(ray, user, look_dir, def)
local hitpoint = ray:hit_object_or_node({
node = function(ndef)
return (ndef.walkable == true and ndef.pointable == true) or ndef.groups.liquid
end,
object = function(obj)
return not obj:is_player() or obj ~= user
end
})
if hitpoint then
if hitpoint.type == "node" then
local node = minetest.get_node(hitpoint.under)
local nodedef = minetest.registered_nodes[node.name]
if (nodedef.on_ranged_shoot or nodedef.groups.snappy or (nodedef.groups.oddly_breakable_by_hand or 0) >= 3)
and not minetest.is_protected(hitpoint.under, user:get_player_name()) then
if nodedef.on_ranged_shoot then
nodedef.on_ranged_shoot(hitpoint.under, node, user, def.type)
else
minetest.dig_node(hitpoint.under)
end
else
if nodedef.walkable and nodedef.pointable then
minetest.add_particle({
pos = vector.subtract(hitpoint.intersection_point, vector.multiply(look_dir, 0.04)),
velocity = vector.new(),
acceleration = { x = 0, y = 0, z = 0 },
expirationtime = def.bullethole_lifetime or 3,
size = 1,
collisiondetection = false,
texture = "ctf_ranged_bullethole.png",
})
minetest.sound_play("ctf_ranged_ricochet", { pos = hitpoint.intersection_point })
elseif nodedef.groups.liquid then
minetest.add_particlespawner({
amount = 10,
time = 0.1,
minpos = hitpoint.intersection_point,
maxpos = hitpoint.intersection_point,
minvel = { x = look_dir.x * 3, y = 4, z = -look_dir.z * 3 },
maxvel = { x = look_dir.x * 4, y = 6, z = look_dir.z * 4 },
minacc = { x = 0, y = -10, z = 0 },
maxacc = { x = 0, y = -13, z = 0 },
minexptime = 1,
maxexptime = 1,
minsize = 0,
maxsize = 0,
collisiondetection = false,
glow = 3,
node = { name = nodedef.name },
})
if def.liquid_travel_dist then
process_ray(rawf.bulletcast(
def.bullet, hitpoint.intersection_point,
vector.add(hitpoint.intersection_point, vector.multiply(look_dir, def.liquid_travel_dist)),
true, false
), user, look_dir, def)
end
end
end
elseif hitpoint.type == "object" then
hitpoint.ref:punch(user, def.fire_interval or 0.1, {
full_punch_interval = def.fire_interval or 0.1,
damage_groups = { ranged = 1, [def.type] = 1, fleshy = def.damage }
}, look_dir)
end
end
end
-- Can be overridden for custom behaviour
function ctf_ranged.can_use_gun(player, name)
return true
end
--- Play ephemeral sound on the spot of a player.
-- @param user ObjectRef: The player object.
-- @param sound_name str: The name of the sound to be played.
-- @param spec? table: The SimpleSoundSpec of the sound. Some fields are overriden.
local function play_player_positional_sound(user, sound_name, spec)
-- This function handles positional sounds that are
-- supposed to be heared equally on both left and right channel
-- by the user, while being heared at the position of the player
-- by other players.
-- Such a mechanism is mainly used on gunshot sounds,
-- so the ephemeral flag is set.
-- The spec table is copied as a base for the SimpleSoundSpec.
-- If not supplied, one is created without any customizations.
local user_name = user:get_player_name()
-- Two copies of SimpleSoundSpec
local non_user_spec = spec and table.copy(spec) or {}
non_user_spec.pos = user:get_pos()
non_user_spec.exclude_player = user_name
local user_spec = spec and table.copy(spec) or {}
user_spec.to_player = user_name
minetest.sound_play(sound_name, non_user_spec, true)
minetest.sound_play(sound_name, user_spec, true)
end
function ctf_ranged.simple_register_gun(name, def)
minetest.register_tool(rawf.also_register_loaded_tool(name, {
description = def.description ..
("\nDMG: %d | Shots/s: %0.1f | Mag: %d"):format(
def.damage * (def.bullet and def.bullet.amount or 1),
1 / def.fire_interval,
def.rounds
),
inventory_image = def.texture .. "^[colorize:#F44:42",
ammo = def.ammo or "ctf_ranged:ammo",
rounds = def.rounds,
_g_category = def.type,
groups = { ranged = 1, [def.type] = 1, tier = def.tier or 1, not_in_creative_inventory = 1 },
on_use = function(itemstack, user)
if not ctf_ranged.can_use_gun(user, name) then
play_player_positional_sound(user, "ctf_ranged_click")
return
end
local result = rawf.load_weapon(itemstack, user:get_inventory())
local sound_name
if result:get_name() == itemstack:get_name() then
sound_name = "ctf_ranged_click"
else
sound_name = "ctf_ranged_reload"
end
play_player_positional_sound(user, sound_name)
return result
end,
},
function(loaded_def)
loaded_def.description = def.description ..
("\nDMG: %d | Shots/s: %0.1f | Mag: %d"):format(
def.damage * (def.bullet and def.bullet.amount or 1),
1 / def.fire_interval,
def.rounds
) ..
" (Loaded)"
loaded_def.inventory_image = def.texture
loaded_def.inventory_overlay = def.texture_overlay
loaded_def.wield_image = def.wield_texture or def.texture
loaded_def.groups.not_in_creative_inventory = nil
loaded_def.on_secondary_use = def.on_secondary_use
loaded_def.on_use = function(itemstack, user)
if not ctf_ranged.can_use_gun(user, name) then
play_player_positional_sound(user, "ctf_ranged_click")
return
end
if shoot_cooldown:get(user) then
return
end
if def.automatic then
if not rawf.enable_automatic(def.fire_interval, itemstack, user) then
return
end
else
shoot_cooldown:set(user, def.fire_interval)
end
local spawnpos, look_dir = rawf.get_bullet_start_data(user)
local endpos = vector.add(spawnpos, vector.multiply(look_dir, def.range))
local rays
if type(def.bullet) == "table" then
def.bullet.texture = "ctf_ranged_bullet.png"
else
def.bullet = { texture = "ctf_ranged_bullet.png" }
end
if not def.bullet.spread then
rays = { rawf.bulletcast(
def.bullet,
spawnpos, endpos, true, true
) }
else
rays = rawf.spread_bulletcast(def.bullet, spawnpos, endpos, true, true)
end
play_player_positional_sound(user, def.fire_sound)
for _, ray in pairs(rays) do
process_ray(ray, user, look_dir, def)
end
if def.rounds > 0 then
return rawf.unload_weapon(itemstack)
end
end
if def.rightclick_func then
loaded_def.on_place = function(itemstack, user, pointed, ...)
local pointed_def = false
local node
if pointed and pointed.under then
node = minetest.get_node(pointed.under)
pointed_def = minetest.registered_nodes[node.name]
end
if pointed_def and pointed_def.on_rightclick then
return minetest.item_place(itemstack, user, pointed)
else
return def.rightclick_func(itemstack, user, pointed, ...)
end
end
loaded_def.on_secondary_use = def.rightclick_func
end
end))
end
minetest.register_on_joinplayer(function(player)
if shoot_cooldown:get(player) then
minetest.log("error", "Player is rejoining with a cooldown: " .. dump(shoot_cooldown:get(player)))
end
end)
minetest.register_on_leaveplayer(function(player)
scoped[player:get_player_name()] = nil
end)
function ctf_ranged.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 = item_name,
wielditem = player:hud_get_flags().wielditem
}
hud:add(player, "ctf_ranged:scope", {
hud_elem_type = "image",
position = { x = 0.5, y = 0.5 },
text = "ctf_ranged_rifle_crosshair.png",
scale = { x = scale_const, y = scale_const },
alignment = { x = "center", y = "center" },
})
player:set_fov(1 / fov_mult, true)
player_monoids.speed:add_change(player, 0.1, "sniper_rifles:scoping_speed")
player_monoids.jump:add_change(player, 0, "sniper_rifles:scoping_jump")
player:hud_set_flags({ wielditem = false })
end
function ctf_ranged.hide_scope(name)
local player = minetest.get_player_by_name(name)
if not player then
return
end
hud:remove(name, "ctf_ranged:scope")
player:set_fov(0)
player_monoids.speed:del_change(player, "sniper_rifles:scoping_speed")
player_monoids.jump:del_change(player, "sniper_rifles:scoping_jump")
player:hud_set_flags({ wielditem = scoped[name].wielditem })
scoped[name] = nil
end
ctf_ranged.simple_register_gun("ctf_ranged:pistol", {
type = "pistol",
description = S("Pistol"),
texture = "ctf_ranged_pistol.png",
fire_sound = "ctf_ranged_pistol",
rounds = 75,
range = 75,
damage = 2,
automatic = true,
fire_interval = 0.6,
liquid_travel_dist = 2
})
ctf_ranged.simple_register_gun("ctf_ranged:rifle", {
type = "rifle",
description = S("Rifle"),
texture = "ctf_ranged_rifle.png",
fire_sound = "ctf_ranged_rifle",
rounds = 40,
range = 150,
damage = 4,
automatic = true,
fire_interval = 0.8,
liquid_travel_dist = 4,
})
ctf_ranged.simple_register_gun("ctf_ranged:shotgun", {
type = "shotgun",
description = S("Shotgun"),
texture = "ctf_ranged_shotgun.png",
fire_sound = "ctf_ranged_shotgun",
bullet = {
amount = 28,
spread = 4,
},
rounds = 10,
range = 24,
damage = 1,
fire_interval = 2,
})
ctf_ranged.simple_register_gun("ctf_ranged:smg", {
type = "smg",
description = S("Submachinegun"),
texture = "ctf_ranged_smgun.png",
fire_sound = "ctf_ranged_pistol",
bullet = {
spread = 1.5,
},
automatic = true,
rounds = 36,
range = 75,
damage = 1,
fire_interval = 0.1,
liquid_travel_dist = 2,
})
ctf_ranged.simple_register_gun("ctf_ranged:sniper", {
type = "sniper",
description = S("Sniper Rifle"),
texture = "ctf_ranged_sniper_rifle.png",
fire_sound = "ctf_ranged_sniper",
rounds = 25,
range = 300,
damage = 12,
fire_interval = 2,
liquid_travel_dist = 10,
rightclick_func = function(itemstack, user, pointed, ...)
if scoped[user:get_player_name()] then
ctf_ranged.hide_scope(user:get_player_name())
else
local item_name = itemstack:get_name()
ctf_ranged.show_scope(user:get_player_name(), item_name, 4)
end
end
})
ctf_ranged.simple_register_gun("ctf_ranged:sniper_magnum", {
type = "sniper",
description = S("Magnum Sniper Rifle"),
texture = "ctf_ranged_sniper_rifle_magnum.png",
fire_sound = "ctf_ranged_sniper",
rounds = 20,
range = 400,
damage = 16,
fire_interval = 2,
liquid_travel_dist = 15,
rightclick_func = function(itemstack, user, pointed, ...)
if scoped[user:get_player_name()] then
ctf_ranged.hide_scope(user:get_player_name())
else
local item_name = itemstack:get_name()
ctf_ranged.show_scope(user:get_player_name(), item_name, 8)
end
end
})
------------------
-- Scope-check --
------------------
-- 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 < 1 then
return
end
time = 0
for name, info in pairs(scoped) do
local player = minetest.get_player_by_name(name)
local wielded_item = player:get_wielded_item():get_name()
if wielded_item ~= info.item_name then
ctf_ranged.hide_scope(name)
end
end
end)
+
+-- Crafting recipes
+
+minetest.register_craft({
+ output = "ctf_ranged:ammo",
+ type = "shapeless",
+ recipe = {"tnt:gunpowder", "default:bronze_ingot"},
+})
+
+minetest.register_craft({
+ output = "ctf_ranged:pistol 1 65535",
+ recipe = {
+ {"default:steel_ingot", "default:steel_ingot"},
+ {"", "default:mese_crystal"},
+ },
+})
+
+minetest.register_craft({
+ output = "ctf_ranged:rifle 1 65535",
+ recipe = {
+ {"default:steel_ingot", "", ""},
+ {"", "default:bronze_ingot", ""},
+ {"", "default:mese_crystal", "default:bronze_ingot"},
+ },
+})
+
+minetest.register_craft({
+ output = "ctf_ranged:shotgun 1 65535",
+ recipe = {
+ {"default:steel_ingot", "", ""},
+ {"", "default:steel_ingot", ""},
+ {"", "default:mese_crystal", "default:bronze_ingot"},
+ },
+})
+
+minetest.register_craft({
+ output = "ctf_ranged:smg 1 65535",
+ recipe = {
+ {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
+ {"", "default:bronze_ingot", "default:mese_crystal"},
+ {"", "default:bronze_ingot", ""},
+ },
+})

File Metadata

Mime Type
text/x-diff
Expires
Mon, Mar 2, 5:28 AM (23 h, 23 m ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
5f/f5/70a1c723ad45fddf09f8f8313e21
Default Alt Text
(13 KB)

Event Timeline