minetest-quake/_weapons/weapons.lua

272 lines
8.3 KiB
Lua
Raw Normal View History

2020-05-27 08:17:35 -07:00
local function after_shoot() end
local function kill() end
2020-05-27 08:16:05 -07:00
2020-04-20 04:53:23 -07:00
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"},
2020-05-26 15:19:41 -07:00
on_drop = function() end,
on_place = function() end,
2020-04-20 04:53:23 -07:00
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()
2020-05-26 18:06:29 -07:00
minetest.after(def.weap_delay, function()
2020-04-20 04:53:23 -07:00
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
2020-04-20 07:28:31 -07:00
-- riproduzione suono
2020-05-26 18:06:29 -07:00
minetest.sound_play(def.weap_sound_shooting, {
2020-04-20 07:28:31 -07:00
to_player = user:get_player_name(),
max_hear_distance = 5,
})
2020-04-20 04:53:23 -07:00
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()
2020-05-26 08:30:00 -07:00
-- controllo se è hitscan o usa proiettili, e sparo
2020-04-20 04:53:23 -07:00
if def.is_hitscan then
2020-05-26 18:06:29 -07:00
local pointed_players = get_pointed_players(pos_head, dir, def.range, username)
2020-05-26 15:19:41 -07:00
if not pointed_players then return end
2020-05-26 18:06:29 -07:00
quake.shoot(user:get_player_name(), pointed_players, def.weap_damage, def.has_knockback)
2020-04-20 04:53:23 -07:00
else
2020-05-25 16:30:52 -07:00
local bullet = def.bullet
2020-05-26 08:30:00 -07:00
quake.shoot_bullet(user, bullet, pos_head, dir)
2020-04-20 04:53:23 -07:00
end
end,
})
2020-04-09 05:21:35 -07:00
2020-04-20 04:53:23 -07:00
end
2020-03-27 12:46:48 -07:00
2020-05-26 08:30:00 -07:00
2020-05-26 15:19:41 -07:00
-- ritorna un array di player con il numero di player trovati a index 1. Se non
2020-04-20 03:58:28 -07:00
-- trova player diversi da se stessi ritorna nil
function get_pointed_players(head_pos, dir, dist, username)
2020-04-10 08:20:48 -07:00
local p1 = vector.add(head_pos, vector.divide(dir,4))
2020-04-01 03:23:28 -07:00
local p2 = vector.add(head_pos, vector.multiply(dir, dist))
2020-04-01 14:04:08 -07:00
local ray = minetest.raycast(p1, p2, true, true)
2020-04-20 03:58:28 -07:00
2020-04-01 03:23:28 -07:00
minetest.add_particlespawner({
2020-04-10 08:20:48 -07:00
amount = 20,
time = 0.3,
2020-04-01 14:04:08 -07:00
minpos = p1,
maxpos = p1,
2020-04-10 08:20:48 -07:00
minvel = vector.multiply(dir,120),
maxvel = vector.multiply(dir,120),
2020-04-01 14:04:08 -07:00
minexptime = 0.2,
maxexptime = 0.2,
size = 2,
collisiondetection = false,
vertical = false,
2020-04-10 08:20:48 -07:00
texture = "quake_railgun_trail.png"
2020-04-01 03:23:28 -07:00
})
2020-04-20 03:58:28 -07:00
2020-05-26 15:19:41 -07:00
local players = {}
2020-04-20 03:58:28 -07:00
-- 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
2020-05-26 18:06:29 -07:00
table.insert(players, hit.ref)
end
end
2020-04-19 13:04:21 -07:00
else
2020-04-20 03:58:28 -07:00
-- se è un nodo mi fermo, e ritorno l'array se > 0 (ovvero ha trovato giocatori)
if hit.type == "node" then
2020-05-26 15:19:41 -07:00
if #players > 0 then
return players
2020-04-19 13:27:21 -07:00
else
return nil
end
end
2020-04-20 03:58:28 -07:00
end
2020-04-01 03:23:28 -07:00
end
2020-05-27 08:16:05 -07:00
2020-04-20 03:58:28 -07:00
-- se ho sparato a qualcuno puntando in aria (quindi senza incrociare blocchi)
2020-05-26 15:19:41 -07:00
if #players > 0 then
return players
2020-04-19 13:04:21 -07:00
end
2020-03-27 12:46:48 -07:00
end
2020-05-27 08:16:05 -07:00
2020-05-26 18:06:29 -07:00
-- può avere uno o più target: formato ObjectRef
function quake.shoot(p_name, targets, damage, has_knockback)
2020-05-23 03:39:10 -07:00
local arena = arena_lib.get_arena_by_player(p_name)
2020-05-26 18:06:29 -07:00
local killed_players = 0
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
if not arena then return end
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
if type(targets) ~= "table" then
targets = {targets}
end
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
-- per ogni giocatore colpito
for _, target in pairs(targets) do
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
if target:get_hp() <= 0 or arena.in_celebration then return end
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
-- controllo le immunità
if target:get_inventory():contains_item("main", "arena_lib:immunity") then
--TODO: sostituire con un suono
2020-06-11 11:20:27 -07:00
minetest.chat_send_player(p_name, minetest.colorize("#d7ded7", S("You can't hit @1 due to immunity", target:get_player_name())))
2020-05-26 18:06:29 -07:00
return end
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
-- 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
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
local t_name = target:get_player_name()
local remaining_HP = target:get_hp() - damage
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
-- 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)
2020-06-11 11:20:27 -07:00
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))))
2020-05-26 18:06:29 -07:00
end
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
-- applico il danno
target:set_hp(remaining_HP)
2020-05-23 03:39:10 -07:00
2020-05-27 08:16:05 -07:00
-- eventuale morte
if target:get_hp() <= 0 then
kill(arena, p_name, target)
killed_players = killed_players +1
2020-05-26 18:06:29 -07:00
end
2020-05-23 03:39:10 -07:00
2020-05-27 08:16:05 -07:00
end
2020-05-23 03:39:10 -07:00
2020-05-27 08:16:05 -07:00
-- calcoli post-danno
after_shoot(arena, p_name, killed_players)
end
2020-05-23 03:39:10 -07:00
2020-05-27 08:16:05 -07:00
function after_shoot(arena, p_name, killed_players)
2020-05-26 18:06:29 -07:00
-- eventuale achievement doppia/tripla uccisione
if killed_players > 1 then
2020-05-23 03:39:10 -07:00
2020-05-26 18:06:29 -07:00
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
2020-05-23 03:39:10 -07:00
2020-06-11 11:20:27 -07:00
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)))
2020-05-23 03:39:10 -07:00
end
end
2020-05-27 08:16:05 -07:00
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
2020-06-11 11:20:27 -07:00
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))))
2020-05-27 08:16:05 -07:00
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)
2020-06-11 11:20:27 -07:00
arena_lib.send_message_players_in_arena(arena, minetest.colorize("#eea160", p_name .. " ") .. minetest.colorize("#d7ded7", S("drew first blood")))
2020-05-27 08:16:05 -07:00
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
2020-06-11 11:20:27 -07:00
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)
2020-05-27 08:16:05 -07:00
quake.add_achievement(p_name, 1)
quake.show_achievement(p_name, 1)
elseif p_stats.killstreak == 5 then
2020-06-11 11:20:27 -07:00
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)
2020-05-27 08:16:05 -07:00
quake.add_achievement(p_name, 2)
quake.show_achievement(p_name, 2)
elseif p_stats.killstreak == 7 then
2020-06-11 11:20:27 -07:00
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)
2020-05-27 08:16:05 -07:00
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
2020-06-11 11:20:27 -07:00
--quake.add_xp(p_name, 5)
2020-05-27 08:16:05 -07:00
-- 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