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