272 lines
8.3 KiB
Lua
272 lines
8.3 KiB
Lua
local function after_shoot() end
|
|
local function kill() end
|
|
|
|
|
|
|
|
function quake.register_weapon(name, def)
|
|
|
|
minetest.register_node(name, {
|
|
|
|
description = def.description,
|
|
drawtype = "mesh",
|
|
mesh = def.mesh,
|
|
tiles = def.tiles,
|
|
wield_scale = def.wield_scale,
|
|
inventory_image = def.inventory_image,
|
|
stack_max = 1,
|
|
groups = {oddly_breakable_by_hand = "2"},
|
|
on_drop = function() end,
|
|
on_place = function() end,
|
|
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
|
|
----- gestione delay dell'arma -----
|
|
if user:get_meta():get_int("quake_weap_delay") == 1 then
|
|
return end
|
|
|
|
user:get_meta():set_int("quake_weap_delay", 1)
|
|
|
|
local inv = user:get_inventory()
|
|
|
|
minetest.after(def.weap_delay, function()
|
|
if inv:contains_item("main", "quake:match_over") then return end
|
|
user:get_meta():set_int("quake_weap_delay", 0)
|
|
end)
|
|
-----fine gestione delay -----
|
|
|
|
|
|
--se sono immune e sparo, perdo l'immunità
|
|
if inv:contains_item("main", "arena_lib:immunity") then
|
|
inv:remove_item("main", "arena_lib:immunity")
|
|
end
|
|
|
|
-- riproduzione suono
|
|
minetest.sound_play(def.weap_sound_shooting, {
|
|
to_player = user:get_player_name(),
|
|
max_hear_distance = 5,
|
|
})
|
|
|
|
local dir = user:get_look_dir()
|
|
local pos = user:get_pos()
|
|
local pos_head = {x = pos.x, y = pos.y+1.475, z = pos.z} -- deve sparare all'altezza mirino, ovvero dalla testa
|
|
local username = user:get_player_name()
|
|
|
|
-- controllo se è hitscan o usa proiettili, e sparo
|
|
if def.is_hitscan then
|
|
local pointed_players = get_pointed_players(pos_head, dir, def.range, username)
|
|
if not pointed_players then return end
|
|
|
|
quake.shoot(user:get_player_name(), pointed_players, def.weap_damage, def.has_knockback)
|
|
|
|
else
|
|
local bullet = def.bullet
|
|
quake.shoot_bullet(user, bullet, pos_head, dir)
|
|
end
|
|
|
|
end,
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- ritorna un array di player con il numero di player trovati a index 1. Se non
|
|
-- trova player diversi da se stessi ritorna nil
|
|
function get_pointed_players(head_pos, dir, dist, username)
|
|
local p1 = vector.add(head_pos, vector.divide(dir,4))
|
|
local p2 = vector.add(head_pos, vector.multiply(dir, dist))
|
|
local ray = minetest.raycast(p1, p2, true, true)
|
|
|
|
minetest.add_particlespawner({
|
|
amount = 20,
|
|
time = 0.3,
|
|
minpos = p1,
|
|
maxpos = p1,
|
|
minvel = vector.multiply(dir,120),
|
|
maxvel = vector.multiply(dir,120),
|
|
minexptime = 0.2,
|
|
maxexptime = 0.2,
|
|
size = 2,
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
texture = "quake_railgun_trail.png"
|
|
})
|
|
|
|
local players = {}
|
|
|
|
-- check su ogni cosa attraversata dal raycast (p1 a p2)
|
|
for hit in ray do
|
|
-- se è un oggetto
|
|
if hit.type == "object" and hit.ref then
|
|
-- se è un giocatore
|
|
if hit.ref:is_player() then
|
|
-- e non è colui che spara
|
|
if hit.ref:get_player_name() ~= username then
|
|
table.insert(players, hit.ref)
|
|
end
|
|
end
|
|
else
|
|
-- se è un nodo mi fermo, e ritorno l'array se > 0 (ovvero ha trovato giocatori)
|
|
if hit.type == "node" then
|
|
if #players > 0 then
|
|
return players
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- se ho sparato a qualcuno puntando in aria (quindi senza incrociare blocchi)
|
|
if #players > 0 then
|
|
return players
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- può avere uno o più target: formato ObjectRef
|
|
function quake.shoot(p_name, targets, damage, has_knockback)
|
|
|
|
local arena = arena_lib.get_arena_by_player(p_name)
|
|
local killed_players = 0
|
|
|
|
if not arena then return end
|
|
|
|
if type(targets) ~= "table" then
|
|
targets = {targets}
|
|
end
|
|
|
|
-- per ogni giocatore colpito
|
|
for _, target in pairs(targets) do
|
|
|
|
if target:get_hp() <= 0 or arena.in_celebration then return end
|
|
|
|
-- controllo le immunità
|
|
if target:get_inventory():contains_item("main", "arena_lib:immunity") then
|
|
--TODO: sostituire con un suono
|
|
minetest.chat_send_player(p_name, minetest.colorize("#d7ded7", S("You can't hit @1 due to immunity", target:get_player_name())))
|
|
return end
|
|
|
|
-- eventuale knockback
|
|
if has_knockback then
|
|
local dir = minetest.get_player_by_name(p_name):get_look_dir()
|
|
local knockback = vector.multiply(dir,14)
|
|
target:add_player_velocity(knockback)
|
|
end
|
|
|
|
local t_name = target:get_player_name()
|
|
local remaining_HP = target:get_hp() - damage
|
|
|
|
-- controllo se è shutdown PRIMA di ucciderlo, sennò si resetta killstreak
|
|
if remaining_HP <= 0 and arena.players[t_name].killstreak >= 3 then
|
|
quake.add_achievement(p_name, 4)
|
|
quake.show_achievement(p_name, 4)
|
|
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", t_name .. " ") .. minetest.colorize("#d7ded7", S("has been stopped by @1", minetest.colorize("#eea160", p_name))))
|
|
end
|
|
|
|
-- applico il danno
|
|
target:set_hp(remaining_HP)
|
|
|
|
-- eventuale morte
|
|
if target:get_hp() <= 0 then
|
|
kill(arena, p_name, target)
|
|
killed_players = killed_players +1
|
|
end
|
|
|
|
end
|
|
|
|
-- calcoli post-danno
|
|
after_shoot(arena, p_name, killed_players)
|
|
end
|
|
|
|
|
|
|
|
function after_shoot(arena, p_name, killed_players)
|
|
|
|
-- eventuale achievement doppia/tripla uccisione
|
|
if killed_players > 1 then
|
|
|
|
if killed_players == 2 then
|
|
quake.add_achievement(p_name, 6)
|
|
quake.show_achievement(p_name, 6)
|
|
elseif killed_players >= 3 then
|
|
quake.add_achievement(p_name, 7)
|
|
quake.show_achievement(p_name, 7)
|
|
end
|
|
|
|
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", p_name .. " ") .. minetest.colorize("#d7ded7", S("has killed @1 players in a row!", killed_players)))
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function kill(arena, p_name, target)
|
|
|
|
-- riproduco suono morte
|
|
minetest.sound_play("quake_kill", {
|
|
to_player = p_name,
|
|
max_hear_distance = 1,
|
|
})
|
|
|
|
local t_name = target:get_player_name()
|
|
|
|
-- informo dell'uccisione
|
|
minetest.chat_send_player(p_name, minetest.colorize("#d7ded7", S("You've killed @1", minetest.colorize("#eea160", t_name))))
|
|
minetest.chat_send_player(t_name, minetest.colorize("#d7ded7", S("You've been killed by @1", minetest.colorize("#eea160", p_name))))
|
|
|
|
local p_stats = arena.players[p_name]
|
|
|
|
-- aggiungo la kill
|
|
p_stats.kills = p_stats.kills +1
|
|
p_stats.killstreak = p_stats.killstreak +1
|
|
quake.calc_kill_leader(arena, p_name)
|
|
|
|
--eventuale first blood
|
|
if arena.first_blood == "" then
|
|
arena.first_blood = p_name
|
|
quake.add_achievement(p_name, 5)
|
|
quake.show_achievement(p_name, 5)
|
|
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", p_name .. " ") .. minetest.colorize("#d7ded7", S("drew first blood")))
|
|
end
|
|
|
|
-- visibilità kill leader
|
|
local kill_leader = arena.kill_leader
|
|
for pl_name, stats in pairs(arena.players) do
|
|
quake.update_HUD(arena, pl_name, "KLR_data", arena.players[kill_leader].kills .. " | " .. kill_leader)
|
|
end
|
|
|
|
-- eventuale killstreak
|
|
if p_stats.killstreak == 3 then
|
|
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", p_name .. " ") .. minetest.colorize("#d7ded7", S("is on a @1", minetest.colorize("#eea160", S("killing spree")))) .. minetest.colorize("#d7ded7", "!"))
|
|
--quake.add_xp(p_name, 10)
|
|
quake.add_achievement(p_name, 1)
|
|
quake.show_achievement(p_name, 1)
|
|
elseif p_stats.killstreak == 5 then
|
|
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", p_name .. " ") .. minetest.colorize("#d7ded7", S("is @1", minetest.colorize("#eea160", S("unstoppable")))) .. minetest.colorize("#d7ded7", "!"))
|
|
--quake.add_xp(p_name, 25)
|
|
quake.add_achievement(p_name, 2)
|
|
quake.show_achievement(p_name, 2)
|
|
elseif p_stats.killstreak == 7 then
|
|
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", p_name .. " ") .. minetest.colorize("#d7ded7", S("made a @1", string.upper(minetest.colorize("#eea160", S("bloodbath"))))) .. minetest.colorize("#d7ded7", "!"))
|
|
--quake.add_xp(p_name, 50)
|
|
quake.add_achievement(p_name, 3)
|
|
quake.show_achievement(p_name, 3)
|
|
end
|
|
|
|
-- aggiorno HUD
|
|
quake.update_HUD(arena, p_name, "KLS_data", p_stats.kills)
|
|
quake.update_stats(arena)
|
|
|
|
-- aggiungo XP
|
|
--quake.add_xp(p_name, 5)
|
|
|
|
-- se kill cap raggiunto finisce match
|
|
if arena.players[p_name].kills == arena.kill_cap then
|
|
local mod = arena_lib.get_mod_by_player(p_name)
|
|
arena_lib.load_celebration(mod, arena, p_name)
|
|
end
|
|
|
|
end
|