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-21 12:45:36 -07:00
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-15 12:02:33 -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 )
2020-04-10 09:55:02 -07:00
end
2020-04-10 09:42:20 -07:00
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
2020-04-10 09:42:20 -07:00
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-22 09:05:01 -07:00
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