Merge branch 'weapons_lib' into 'master'

Use weapons_lib

Closes #115

See merge request zughy-friends-minetest/block_league!46
This commit is contained in:
Zughy 2024-03-23 22:59:42 +00:00
commit 271c74ebf2
29 changed files with 489 additions and 1522 deletions

View File

@ -85,11 +85,16 @@ function ball:reset()
block_league.HUD_ball_update(p_name, extS("Ball reset"))
local wielder = minetest.get_player_by_name(p_name)
local p_meta = wielder:p_meta()
local ball_obj = self.object
self._p_name = nil
wielder:set_physics_override({speed = block_league.SPEED})
wielder:get_meta():set_int("bl_has_ball", 0)
if p_meta:get_int("wl_weapon_state") == 0 then
wielder:set_physics_override({speed = block_league.SPEED})
end
p_meta:set_int("bl_has_ball", 0)
ball_obj:set_detach()
ball_obj:set_properties({textures={"bl_ball_unclaimed.png"}})
ball_obj:set_animation({x=0,y=40}, 20, 0, true)

View File

@ -145,7 +145,7 @@ function rotate_and_shoot(sentry, dir)
sentry:set_bone_position("Rotation", vector.new(0,1,0), new_rot)
local sentry_centre = 0.3
local pointed_object = block_league.get_pointed_objects(sentry, 20, false, {height = sentry_centre, dir = dir})
local pointed_object = weapons_lib.get_pointed_objects(sentry, 20, false, {height = sentry_centre, dir = dir})
draw_particles(dir, vector.add(sentry:get_pos(), vector.new(0, sentry_centre, 0)))
audio_lib.play_sound("bl_smg_shoot", {pitch = 2.3, object = sentry, max_hear_distance = SENTRY_RANGE + 5})

View File

@ -230,7 +230,6 @@ function phase3(player)
inv:set_stack("main", 2, ItemStack("block_league:propulsor"))
arena.weapons_disabled = false
arena.players[p_name].weapons_magazine[smg] = minetest.registered_nodes[smg].magazine
panel_lib.get_panel(p_name, "bl_weapons"):show()
block_league.HUD_weapons_update(arena, p_name, smg)
@ -340,7 +339,7 @@ function bl_tutorial.kill(player)
player:set_hp(20)
player:set_pos(start_coords)
arena.players[p_name].stamina = 99
arena.players[p_name].weapons_magazine[smg] = minetest.registered_nodes[smg].magazine
weapons_lib.refill(p_name, minetest.registered_nodes[smg])
block_league.HUD_weapons_update(arena, p_name, smg)
bl_tutorial.hud_show(player)
@ -536,7 +535,7 @@ end
function anchor_player(player)
local p_pos = player:get_pos()
local p_y = player:get_look_horizontal()
local dummy = minetest.add_entity(p_pos, "block_league:dummy")
local dummy = minetest.add_entity(p_pos, "weapons_lib:dummy")
player:set_attach(dummy, "", {x=0,y=-5,z=0}, {x=0, y=-math.deg(p_y), z=0})
end

View File

@ -1,5 +1,5 @@
block_league.SPEED = 2.5
block_league.SPEED_LOW = 1.5
block_league.SHOOT_SPEED_MULTIPLIER = 0.6
block_league.PHYSICS = {
speed = block_league.SPEED,
@ -7,6 +7,4 @@ block_league.PHYSICS = {
gravity = 1.15,
sneak_glitch = true,
new_move = true
}
block_league.MELEE_RANGE = 4
}

View File

@ -77,7 +77,6 @@ arena_lib.register_minigame("block_league", {
kills = 0,
points = 0,
--entering_time = 0, -- inutilizzato, servirà prob in futuro per calcolare exp
weapons_magazine = {}, -- KEY: w_name, VALUE: curr_ammo
current_weapon = "",
dmg_received = {}, -- KEY: p_name, VALUE: {timestamp, dmg, weapon}
dmg_dealt = 0
@ -143,14 +142,10 @@ dofile(srcpath .. "/player/exp.lua")
dofile(srcpath .. "/skills/hp+.lua")
dofile(srcpath .. "/skills/sp+.lua")
-- abstract weapons
dofile(srcpath .. "/weapons/bullets.lua")
dofile(srcpath .. "/weapons/weapons.lua")
dofile(srcpath .. "/weapons/weapons_utils.lua")
-- weapons
dofile(srcpath .. "/weapons/grenade_launcher.lua")
dofile(srcpath .. "/weapons/pixelgun.lua")
dofile(srcpath .. "/weapons/propulsor.lua")
dofile(srcpath .. "/weapons/rocket_launcher.lua")
dofile(srcpath .. "/weapons/sword.lua")
dofile(srcpath .. "/weapons/smg.lua")

View File

@ -1,4 +1,4 @@
name = block_league
description = Massive hack'n'slash FPS shooter inspired by S4 League. Pew pew!
depends = achievements_lib,arena_lib,controls,panel_lib,skills
depends = achievements_lib,arena_lib,controls,panel_lib,skills,weapons_lib
optional_depends = visible_wielditem

View File

@ -70,7 +70,7 @@ function get_formspec(p_name)
elseif skill then
item = "image[2,1.7;1.5,1.5;bl_skill_" .. elem .. ".png]"
elem_name = skill.name
body = "hypertext[0.3,4.2;4.48,4.3;elem_desc;<global size=15 halign=center><style color=#abc0c0><i>" .. skill.profile_description .. "</i>]"
body = "hypertext[0.3,4.2;4.48,4.3;elem_desc;<global size=15 halign=center><style color=#abc0c0><i>" .. skill._profile_description .. "</i>]"
if elem_technical ~= p_skill then
button = "image_button[1.45,7.9;2.2,0.8;bl_gui_profile_button_equip.png;equip;" .. S("EQUIP") .. "]"
@ -166,37 +166,37 @@ function get_weapon_details(weap)
-- azioni varie
if weap.action1 then
action1 = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_lmb.png]" ..
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action1.description .. "</i>]"
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action1._description .. "</i>]"
action_y = action_y + 0.8
end
if weap.action1_hold then
action1_hold = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_lmb_hold.png]" ..
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action1_hold.description .. "</i>]"
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action1_hold._description .. "</i>]"
action_y = action_y + 0.8
end
if weap.action1_air then
action1_air = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_lmb_air.png]" ..
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action1_air.description .. "</i>]"
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action1_air._description .. "</i>]"
action_y = action_y + 0.8
end
if weap.action2 then
action2 = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_rmb.png]" ..
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action2.description .. "</i>]"
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action2._description .. "</i>]"
action_y = action_y + 0.8
end
if weap.action2_hold then
action2_hold = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_rmb_hold.png]" ..
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action2_hold.description .. "</i>]"
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action2_hold._description .. "</i>]"
action_y = action_y + 0.8
end
if weap.action2_air then
action1_air = "image[0," .. action_y .. ";0.4,0.55;bl_gui_profile_action_rmb_air.png]" ..
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action2_air.description .. "</i>]"
"hypertext[0.6," .. action_y - 0.12 .. ";3.8,0.8;elem_desc;<global size=15 valign=middle><i>" .. weap.action2_air._description .. "</i>]"
action_y = action_y + 0.8
end
@ -211,7 +211,7 @@ function get_weapon_details(weap)
end
local attributes = table.concat({
"hypertext[0.3,4.12;4.48,0.9;elem_desc;<global size=15 halign=center valign=middle><style color=#abc0c0><i>" .. weap.profile_description .. "</i>]",
"hypertext[0.3,4.12;4.48,0.9;elem_desc;<global size=15 halign=center valign=middle><style color=#abc0c0><i>" .. weap._profile_description .. "</i>]",
"container[0.4,5.1]",
action1 or "",
action1_hold or "",

View File

@ -91,7 +91,7 @@ function block_league.HUD_weapons_update(arena, p_name, w_name, is_reloading)
end
local weapon = minetest.registered_nodes[w_name]
local current_magazine = not weapon.magazine and "" or arena.players[p_name].weapons_magazine[w_name]
local current_magazine = not weapon.magazine and "" or weapons_lib.get_magazine(p_name, w_name)
local bg_pic = ""
if is_reloading then

View File

@ -25,3 +25,11 @@ audio_lib.register_sound("voices", "bl_voice_critical", S("\"Critical!\""), {eph
audio_lib.register_sound("voices", "bl_voice_fight", S("\"Fight!\""))
audio_lib.register_sound("voices", "bl_voice_ball_reset", S("\"Ball reset\""))
audio_lib.register_sound("voices", "bl_voice_countdown_3", S("\"3, 2, 1...\""), {ephemeral = false})
----------------------------------------------
-----------------WEAPONS_LIB------------------
----------------------------------------------
weapons_lib.register_mod("block_league", {
SHOOT_SPEED_MULTIPLIER = block_league.SHOOT_SPEED_MULTIPLIER
})

View File

@ -4,7 +4,7 @@ arena_lib.on_celebration("block_league", function(arena, winners)
for pl_name, pl_stats in pairs(arena.players) do
local player = minetest.get_player_by_name(pl_name)
block_league.deactivate_zoom(player)
weapons_lib.deactivate_zoom(player)
player:get_meta():set_int("bl_immunity", 1)
panel_lib.get_panel(pl_name, "bl_info_panel"):show()

View File

@ -45,12 +45,10 @@ arena_lib.on_death("block_league", function(arena, p_name, reason)
local p_meta = player:get_meta()
p_meta:set_int("bl_weapon_state", 0)
p_meta:set_int("bl_immunity", 1)
p_meta:set_int("bl_death_delay", 1)
block_league.deactivate_zoom(player)
block_league.reset_weapons(p_name)
wait_for_respawn(arena, p_name, arena.death_waiting_time)
end)

View File

@ -13,6 +13,7 @@ arena_lib.on_load("block_league", function(arena)
for pl_name, stats in pairs(players) do
reset_meta(pl_name)
init_dmg_table(pl_name, players)
block_league.reset_weapons(pl_name)
equip(arena, pl_name)
create_and_show_HUD(arena, pl_name)
block_league.HUD_keys_create(pl_name) -- a parte perché non la voglio nell'on_join. Poi rimossa su on_start
@ -55,6 +56,7 @@ arena_lib.on_join("block_league", function(p_name, arena, as_spectator, was_spec
reset_meta(p_name)
init_dmg_table(p_name, players, true)
weapons_lib.reset_state(minetest.get_player_by_name(p_name))
equip(arena, p_name)
create_and_show_HUD(arena, p_name, false, was_spectator)
block_league.HUD_spectate_addplayer(arena, p_name)
@ -80,11 +82,8 @@ function reset_meta(p_name)
local p_meta = minetest.get_player_by_name(p_name):get_meta()
p_meta:set_int("bl_has_ball", 0)
p_meta:set_int("bl_propulsor_delay", 0)
p_meta:set_int("bl_death_delay", 0)
p_meta:set_int("bl_is_speed_locked", 0)
p_meta:set_int("bl_immunity", 0)
p_meta:set_int("bl_weapon_state", 0)
end

View File

@ -17,7 +17,7 @@ arena_lib.on_end("block_league", function(arena, winners, is_forced)
-- a separation from the game, whereas the latter is to prevent to keep the
-- gunsight view after the match (I don't want to disable it as I really like
-- the fact you can zoom during the loading phase)
block_league.deactivate_zoom(minetest.get_player_by_name(pl_name))
weapons_lib.reset_state(minetest.get_player_by_name(pl_name))
remove_HUD(pl_name)
stop_sounds(pl_name)
pl_name:get_skill(block_league.get_player_skill(pl_name)):disable()
@ -55,7 +55,7 @@ arena_lib.on_quit("block_league", function(arena, p_name, is_spectator, reason)
end
end
block_league.deactivate_zoom(minetest.get_player_by_name(p_name))
weapons_lib.deactivate_zoom(minetest.get_player_by_name(p_name))
end
remove_spectate_HUD(arena, p_name, is_spectator)

View File

@ -214,8 +214,12 @@ function ball:reset()
-- se è agganciata a qualcunə...
if self._p_name then
local wielder = minetest.get_player_by_name(self._p_name)
local p_meta = wielder:get_meta()
if wielder:get_hp() > 0 and wielder:get_meta():get_int("bl_is_speed_locked") == 0 then
if wielder:get_hp() > 0
and p_meta:get_int("wl_is_speed_locked") == 0
and p_meta:get_int("wl_zooming") == 0
and p_meta:get_int("wl_weapon_state") == 0 then
wielder:set_physics_override({speed = block_league.SPEED})
end

View File

@ -16,10 +16,10 @@ end
function block_league.refill_weapons(arena, p_name)
for _, w_name in pairs(block_league.get_player_weapons(p_name)) do
local magazine = minetest.registered_nodes[w_name].magazine
local weapon = weapons_lib.get_weapon_by_name(w_name)
if magazine then
arena.players[p_name].weapons_magazine[w_name] = magazine
if weapon then
weapons_lib.refill(p_name, weapon)
block_league.HUD_weapons_update(arena, p_name, w_name)
end
end
@ -27,6 +27,15 @@ end
function block_league.reset_weapons(p_name)
local player = minetest.get_player_by_name(p_name)
weapons_lib.reset_state(player)
player:set_physics_override(block_league.PHYSICS)
end
----------------------------------------------

View File

@ -1,4 +1,5 @@
local recursive_time = 0.1
local SPEED_LOW = block_league.SPEED * block_league.SHOOT_SPEED_MULTIPLIER
@ -37,7 +38,7 @@ function block_league.stamina_drain(arena, w_name)
block_league.HUD_stamina_update(arena, w_name)
else
w_data.stamina = 0 -- in case went to -1
wielder:set_physics_override({speed = block_league.SPEED_LOW})
wielder:set_physics_override({speed = SPEED_LOW})
return
end

View File

@ -4,7 +4,7 @@ local S = minetest.get_translator("block_league")
skills.register_skill("block_league:hp", {
name = "HP+",
icon = "bl_skill_hp.png",
profile_description = S("Increases your health points by 5 @1(20>25)", "<style color=#abc0c0>") .. "</style>\n\n"
_profile_description = S("Increases your health points by 5 @1(20>25)", "<style color=#abc0c0>") .. "</style>\n\n"
.. S("Great for remaining in action longer, providing firepower to sustain your team. Get tanky!"),
passive = true,
on_start = function(self)

View File

@ -9,7 +9,7 @@ local S = minetest.get_translator("block_league")
skills.register_skill("block_league:shield", {
name = S("Shield"),
icon = "bl_skill_shield.png",
profile_description = S("Summons a shield in front of you that assorbs bullets at the cost of stamina") .. "</style>\n\n"
_profile_description = S("Summons a shield in front of you that assorbs bullets at the cost of stamina") .. "</style>\n\n"
.. S("Expose yourself without any risk"),
attachments = {

View File

@ -4,7 +4,7 @@ local S = minetest.get_translator("block_league")
skills.register_skill("block_league:sp", {
name = "SP+",
icon = "bl_skill_sp.png",
profile_description = S("Increases your stamina points by 25 @1(100>125)", "<style color=#abc0c0>") .. "</style>\n\n"
_profile_description = S("Increases your stamina points by 25 @1(100>125)", "<style color=#abc0c0>") .. "</style>\n\n"
.. S("Great choice for strikers, as it allows players to run more and perform tricks more often."),
passive = true,
on_start = function(self)

View File

@ -1,6 +1,4 @@
local function stop_and_update_last_sound() end
local sounds = {} -- KEY: p_name; VALUE: { sounds_name = handle }
local S = minetest.get_translator("block_league")
@ -14,13 +12,130 @@ end
-- interrompi l'ultimo suono chiamato "sound" e lo aggiorna a quello passatogli
function stop_and_update_last_sound(p_name, sound, handle)
sounds[p_name] = sounds[p_name] or {}
function block_league.hitter_or_suicide(arena, player, dmg_rcvd_table, no_hitter_img)
-- se le armi son disabilitate (quindi o in caricamento o dopo punto o in celebrazione) non mostrare niente
if arena.weapons_disabled then
block_league.HUD_spectate_update(arena, player:get_player_name(), "alive")
return end
if sounds[p_name][sound] then
minetest.sound_stop(sounds[p_name][sound])
local last_hitter = ""
local last_hitter_timestamp = 99999
for pla_name, dmg_data in pairs(dmg_rcvd_table) do
if arena.current_time > dmg_data.timestamp - 5 and last_hitter_timestamp > dmg_data.timestamp then
last_hitter = pla_name
last_hitter_timestamp = dmg_data.timestamp
end
end
sounds[p_name][sound] = handle
if last_hitter ~= "" then
block_league.kill(arena, minetest.registered_nodes[dmg_rcvd_table[last_hitter].weapon], minetest.get_player_by_name(last_hitter), player)
else
local p_name = player:get_player_name()
block_league.HUD_spectate_update(arena, p_name, "alive")
block_league.HUD_log_update(arena, no_hitter_img, p_name, "")
end
end
function block_league.kill(arena, weapon, player, target)
local p_name = player:get_player_name()
local t_name = target:get_player_name()
-- riproduco suono morte e aggiorno avatar per spettatorɜ
arena_lib.sound_play(p_name, "bl_kill")
block_league.HUD_spectate_update(arena, t_name, "alive")
if t_name ~= p_name then
-- informo dell'uccisione
block_league.HUD_kill_update(p_name, S("YOU'VE KILLED @1", t_name))
minetest.chat_send_player(t_name, minetest.colorize("#d7ded7", S("You've been killed by @1", minetest.colorize("#eea160", p_name))))
if arena_lib.is_player_spectated(p_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
block_league.HUD_kill_update(sp_name, S("@1 HAS KILLED @2", p_name, t_name))
end
end
if arena_lib.is_player_spectated(t_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(t_name)) do
minetest.chat_send_player(sp_name, minetest.colorize("#d7ded7", S("@1 has been killed by @2", minetest.colorize("#eea160", t_name), minetest.colorize("#eea160", p_name))))
end
end
local p_stats = arena.players[p_name]
local team_id = p_stats.teamID
local team = arena.teams[team_id]
local points
-- aggiungo l'uccisione
team.kills = team.kills + 1
p_stats.kills = p_stats.kills + 1
-- calcolo i punti
if arena.mode == 1 then
if player:get_meta():get_int("bl_has_ball") == 1 or target:get_meta():get_int("bl_has_ball") == 1 then
points = 4
else
points = 2
end
else
points = 2
end
p_stats.points = p_stats.points + points
local dmg_table = arena.players[t_name].dmg_received
local a_dmg = 0
local a_name
-- controlla per assist..
for pl_name, _ in pairs(dmg_table) do
local dmg = dmg_table[pl_name].dmg
if pl_name ~= p_name and arena.current_time > dmg_table[pl_name].timestamp - 5 and dmg > 5 and dmg > a_dmg then
a_name = pl_name
a_dmg = dmg
end
end
-- ..e se esiste, esegui tutte le operazioni anche su chi l'ha
if a_name and arena.players[a_name] then
arena_lib.sound_play(a_name, "bl_kill")
block_league.HUD_kill_update(a_name, S("YOU'VE CONTRIBUTED TO KILL @1", t_name))
if arena_lib.is_player_spectated(a_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
block_league.HUD_kill_update(sp_name, S("@1 HAS CONTRIBUTED TO KILL @2", a_name, t_name))
end
end
arena.players[a_name].points = arena.players[a_name].points + (points / 2)
block_league.HUD_spectate_update(arena, a_name, "points")
end
-- aggiorno HUD
block_league.HUD_infopanel_update_points(arena, team_id)
block_league.HUD_spectate_update(arena, p_name, "points")
block_league.HUD_log_update(arena, weapon.inventory_image, p_name, t_name, a_name)
-- se è DM e il limite è raggiunto, finisce partita
if arena.mode == 2 then
block_league.HUD_scoreboard_update_score(arena)
if team.kills == arena.score_cap then
local mod = arena_lib.get_mod_by_player(p_name)
arena_lib.load_celebration(mod, arena, team_id)
end
end
else
block_league.HUD_kill_update(t_name, S("You've killed yourself"))
block_league.HUD_log_update(arena, "bl_log_suicide.png", p_name, t_name)
end
end
function block_league.print_error(pl_name, msg)
minetest.chat_send_player(pl_name, minetest.colorize("#e6482e", arena_lib.mods["block_league"].prefix .. msg))
end

View File

@ -1,270 +0,0 @@
local function bullet_set_entity() end
local function spawn_particles_sphere() end
function block_league.register_bullet(bullet, damage, bullet_trail)
local bullet_entity = bullet_set_entity(bullet.name, bullet, damage, bullet_trail)
minetest.register_entity("block_league:" .. bullet.name .. "_entity", bullet_entity)
return bullet_entity
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
function bullet_set_entity(name, def, dmg, trail)
local bullet = {
initial_properties = {
name = def.name,
visual = def.mesh and "mesh" or "item",
mesh = def.mesh,
visual_size = def.visual_size,
textures = def.textures,
collisionbox = def.collisionbox,
damage = dmg,
speed = def.speed,
lifetime = def.lifetime,
explosion_range = def.explosion_range,
explosion_damage = def.explosion_damage,
explosion_texture = def.explosion_texture,
bullet_trail = trail,
explode_on_contact = def.explode_on_contact,
gravity = def.gravity,
on_destroy = def.on_destroy,
on_right_click = def.on_right_click,
physical = true,
collide_with_objects = true,
is_bullet = true
}
}
function bullet:_destroy()
-- Crea le particelle dell'esplosione
spawn_particles_sphere(self.object:get_pos(), self.initial_properties.explosion_texture)
self.initial_properties.on_destroy(self)
self.object:remove()
end
-- Ottiene gli staticdata ogni 18 secondi circa
function bullet:get_staticdata(self)
if self == nil or self.p_name == nil then return end
return self.p_name
end
-- L'entità esplode quando colpita
function bullet:on_punch()
if self.initial_properties.on_right_click then
self.initial_properties.on_right_click(self)
end
end
-- quando si istanzia un'entità
function bullet:on_activate(staticdata)
if staticdata ~= "" and staticdata ~= nil then
self.p_name = staticdata -- nome utente come staticdata
self.lifetime = 0 -- tempo in aria
self.sliding = 0 -- se sta scivolando
self.particle = 0 -- contatore di buffer per le particelle della granata
self.object:set_armor_groups({immortal = 1}) -- lo imposta come immortale
else -- se non ci sono gli staticdata necessari allora rimuove l'entità
self.object:remove()
return
end
end
function bullet:on_step(dtime, moveresult)
self.lifetime = self.lifetime + dtime
if self.lifetime >= self.initial_properties.lifetime then
-- ESPLODE
self:_destroy()
return
end
local obj = self.object
local velocity = obj:get_velocity()
local pos = obj:getpos()
-- Controlla che il timer per mostrare le particelle che tracciano la granata sia superiore al valore definito e che eista una definizione delle particelle da creare
if self.initial_properties.bullet_trail and self.particle >= self.initial_properties.bullet_trail.interval then
-- Imposta il timer a 0
self.particle = 0
-- Aggiunge le particelle di tracciamento
minetest.add_particle({
pos = obj:get_pos(),
velocity = vector.divide(velocity, 2),
acceleration = vector.divide(obj:get_acceleration(), -5),
expirationtime = self.initial_properties.bullet_trail.life,
size = self.initial_properties.bullet_trail.size,
collisiondetection = false,
collision_removal = false,
vertical = false,
texture = self.initial_properties.bullet_trail.image,
glow = self.initial_properties.bullet_trail.glow
})
-- Controlla che il timer per mostrare le particelle che tracciano la granata sia inferiore al valore definito e che eista una definizione delle particelle da creare
elseif self.initial_properties.bullet_trail and self.particle < self.initial_properties.bullet_trail.interval then
-- Incrementa il timer
self.particle = self.particle + 1
end
if self.initial_properties.explode_on_contact then
-- controlla se collide con qualcosa
if moveresult.collides == true then
local buffer_boolean = false
for k, collision in pairs(moveresult.collisions) do
--object è l'oggetto(player/entità) con cui collide il proiettile
if collision.object then
--controlla se è un player
if collision.object:is_player() then
if collision.object:get_player_name() ~= self.p_name then
-- TODO: non funziona, la funzione è stata cambiata. Bisogna far passare l'arma
block_league.apply_damage(minetest.get_player_by_name(self.p_name), collision.object, self.initial_properties.bullet_damage, 0, false)
buffer_boolean = true
elseif collision.object:get_player_name() == self.p_name then
if self.lifetime < (15 / self.initial_properties.speed) then
obj:set_velocity({
x=(collision.old_velocity.x),
y=(collision.old_velocity.y),
z=(collision.old_velocity.z),
})
end
end
elseif collision.object:get_luaentity() then
--quando non è un player allora è una entity quindi la memorizzo per alleggerire il numero di accessi
local entity = collision.object:get_luaentity()
--i prossimi 2 check servono a verificare l'entità sia un proiettile
if entity and entity.initial_properties ~= nil then
if entity.initial_properties.is_bullet then
--distrugge sia il proiettile con cui collide che se stesso
buffer_boolean = true
entity:_destroy()
end
end
end
elseif collision.type == "node" then
buffer_boolean = true
end
end
if buffer_boolean then
self:_destroy()
return
end
end
else
if moveresult.collides and moveresult.collisions[1] and not vector.equals(moveresult.collisions[1].old_velocity, velocity) and vector.distance(moveresult.collisions[1].old_velocity, velocity) > 4 then
if math.abs(moveresult.collisions[1].old_velocity.x - velocity.x) > 5 then -- Controlla se c'è stata una grande riduzione di velocità
velocity.x = moveresult.collisions[1].old_velocity.x * (self.initial_properties.gravity and -0.5 or -1) -- Inverte la velocità e la riduce
end
if math.abs(moveresult.collisions[1].old_velocity.y - velocity.y) > 5 then -- Controlla se c'è stata una grande riduzione di velocità
velocity.y = moveresult.collisions[1].old_velocity.y * (self.initial_properties.gravity and -0.3 or -1) -- Inverte la velocità e la riduce
end
if math.abs(moveresult.collisions[1].old_velocity.z - velocity.z) > 5 then -- Controlla se c'è stata una grande riduzione di velocità
velocity.z = moveresult.collisions[1].old_velocity.z * (self.initial_properties.gravity and -0.5 or -1) -- Inverte la velocità e la riduce
end
obj:set_velocity(velocity)
end
if self.initial_properties.gravity then
if self.sliding == 0 and velocity.y == 0 then -- Controlla se la granata sta scivolando
self.sliding = 1 -- Attiva l'attrito
elseif self.sliding > 0 and velocity.y ~= 0 then
self.sliding = 0 -- Non influisce sull'attrito
end
if self.sliding > 1 then -- Sta scivolando?
if vector.distance(vector.new(), velocity) <= 1 and not vector.equals(velocity, vector.new()) then -- Se la granata si muove a malapena
obj:set_velocity(vector.new(0, -9.8, 0)) -- Si assicura sia ferma
obj:set_acceleration(vector.new())
end
end
end
end
if self.initial_properties.gravity then
local direction = vector.normalize(velocity)
local node = minetest.get_node(pos)
local speed = vector.length(velocity)
local drag = math.max(minetest.registered_nodes[node.name].liquid_viscosity, 0.1) * self.sliding -- Ottiene l'attrito generato dal liquido che attraversa
local yaw = minetest.dir_to_yaw(direction)
local pitch = math.acos(velocity.y/speed) - math.pi/3
-- Controlla che il pitch sia un numero
if tostring(pitch) ~= 'nan' then
obj:set_rotation({x = 0, y = yaw + math.pi/2, z = pitch}) -- Imposta la rotazione
end
local acceleration = vector.multiply(velocity, -drag)
acceleration.x = acceleration.x * (self.sliding * 10 * 2 + 1) -- Modifica la x in base a se sta scivolando o meno
acceleration.y = acceleration.y - 10 * ((7 - drag) / 7) -- Perdita in altezza del proiettile in base all' attrito
acceleration.z = acceleration.z * (self.sliding * 10 * 2 + 1) -- Modifica la Z in base a se sta scivolando o meno
-- Controlla che l'accelerazione sia un numero
if tostring(acceleration) ~= 'nan' then
obj:set_acceleration(acceleration) -- Imposta l'accelerazione
end
end
end
-- Restituisce la definizione dell'entità
return bullet
end
function spawn_particles_sphere(pos, particle_texture)
if not pos then return end
minetest.add_particlespawner({
amount = 80,
time = .1,
minpos = {x=pos.x,y=pos.y,z=pos.z},
maxpos = {x=pos.x,y=pos.y,z=pos.z},
minvel = {x=-4, y=-4, z=-4},
maxvel = {x=4, y=4, z=4},
minacc = {x=0, y=-0.4, z=0},
maxacc = {x=0, y=-0.8, z=0},
minexptime = .5,
maxexptime = .5,
minsize = 1,
maxsize = 5,
collisiondetection = false,
vertical = false,
texture = particle_texture,
})
end

View File

@ -1,10 +1,10 @@
local S = minetest.get_translator("block_league")
local dmg = 18
block_league.register_weapon("block_league:pixelgun", {
weapons_lib.register_weapon("block_league:pixelgun", {
description = S("Pixelgun"),
profile_description = S("Sniping weapon: you'll never be too far away"),
_profile_description = S("Sniping weapon: you'll never be too far away"),
groups = {bl_weapon_mesh = 1},
mesh = "bl_pixelgun.obj",
tiles = {"bl_pixelgun_texture.png"},
@ -15,11 +15,32 @@ block_league.register_weapon("block_league:pixelgun", {
weapon_type = "snipe",
magazine = 4,
reload_time = 4,
slow_down_user = true,
sound_reload = "bl_pixelgun_reload",
can_use_weapon = function(player, action)
return block_league.util_weapon_use_check(player)
end,
can_alter_speed = function(player)
return block_league.util_on_can_alter_speed(player:get_player_name())
end,
on_reload = function(player, weapon)
block_league.util_on_reload(player:get_player_name(), weapon.name)
end,
on_reload_end = function(player, weapon)
block_league.util_on_reload_end(player:get_player_name(), weapon.name)
end,
on_after_hit = function(hitter, weapon, action, objects_hit, total_damage)
block_league.util_on_after_hit(hitter, weapon, objects_hit, total_damage)
end,
action1 = {
type = "raycast",
description = S("piercing shot, @1♥", "<style color=#f66c77>" .. dmg),
_description = S("piercing shot, @1♥", "<style color=#f66c77>" .. dmg),
damage = dmg,
range = 150,
delay = 0.9,
@ -33,11 +54,19 @@ block_league.register_weapon("block_league:pixelgun", {
image = "bl_pixelgun_trail.png",
amount = 20,
},
on_use = function(player, weapon, action)
block_league.util_update_mag_hud(player:get_player_name(), weapon.name)
end,
on_hit = function(hitter, target, weapon, action, damage, hit_ppint)
return block_league.util_on_hit(hitter, target, weapon, action, damage, hit_ppint)
end,
},
action2 = {
type = "zoom",
description = S("zoom"),
_description = S("zoom"),
fov = 20,
-- TODO
--HUD = "",

View File

@ -4,44 +4,54 @@ local function dash() end
local function register_propulsor(name, desc, stamina)
minetest.register_tool("block_league:" .. name, {
weapons_lib.register_weapon("block_league:" .. name, {
description = desc,
wield_scale = {x=1.3, y=1.3, z=1.3},
wield_image = "bl_" .. name .. ".png",
inventory_image = "bl_" .. name .. ".png",
crosshair = "bl_propulsor_crosshair.png",
jump_height = 5,
groups = {oddly_breakable_by_hand = "2", propulsor = 1},
on_use = function(itemstack, user, pointed_thing)
if not can_use(user) then return end
weapon_type = "melee",
crosshair = "bl_propulsor_crosshair.png",
slow_down_user = false,
-- se non sta puntando nulla o sta puntando un giocatore, annullo
if pointed_thing.type == "nothing" or (pointed_thing.type == "object" and minetest.is_player(pointed_thing.ref)) then return end
can_use_weapon = function(player, action)
return can_use(player)
end,
local p_name = user:get_player_name()
local arena = arena_lib.get_arena_by_player(p_name)
action1 = {
type = "custom",
delay = 0.3,
if arena then
-- se non ha abbastanza energia, annullo
if not (arena.players[p_name].stamina >= stamina) then return end
arena.players[p_name].stamina = arena.players[p_name].stamina - stamina
on_use = function(player, weapon, action, pointed_thing)
-- se non sta puntando nulla o sta puntando un giocatore, annullo
if pointed_thing.type == "nothing" or (pointed_thing.type == "object" and minetest.is_player(pointed_thing.ref)) then return end
local p_name = player:get_player_name()
local arena = arena_lib.get_arena_by_player(p_name)
if arena then
-- se non ha abbastanza energia, annullo
if not (arena.players[p_name].stamina >= stamina) then return end
arena.players[p_name].stamina = arena.players[p_name].stamina - stamina
end
local dir = player:get_look_dir()
local knockback = player:get_velocity().y < 1 and -15 or -10
player:add_velocity(vector.multiply(dir, knockback))
arena_lib.sound_play(p_name, "bl_propulsor_bounce")
end
},
local dir = user:get_look_dir()
local knockback = user:get_velocity().y < 1 and -15 or -10
action2 = {
type = "custom",
delay = 0.3,
user:add_velocity(vector.multiply(dir, knockback))
arena_lib.sound_play(p_name, "bl_propulsor_bounce")
end,
on_secondary_use = function(itemstack, user, pointed_thing)
dash(user, stamina)
end,
on_place = function(itemstack, user, pointed_thing)
dash(user, stamina)
end
on_use = function(player, weapon, action, pointed_thing)
dash(player, stamina)
end
}
})
end
@ -59,8 +69,6 @@ register_propulsor("propulsor_dm", "Deathmatch Propulsor", 50)
----------------------------------------------
function dash(player, stamina)
if not can_use(player) then return end
local p_name = player:get_player_name()
local arena = arena_lib.get_arena_by_player(p_name)
@ -81,20 +89,9 @@ end
function can_use(player, stamina)
function can_use(player)
local meta = player:get_meta()
if meta:get_int("bl_propulsor_delay") == 1 or
meta:get_int("bl_death_delay") == 1 or
meta:get_int("bl_weapon_state") == 3 or
meta:get_int("bl_weapon_state") == 4 or
meta:get_int("bl_is_speed_locked") == 1 then return end
meta:set_int("bl_propulsor_delay", 1)
minetest.after(0.3, function()
if not player then return end
player:get_meta():set_int("bl_propulsor_delay", 0)
end)
if meta:get_int("bl_death_delay") == 1 or meta:get_int("wl_is_speed_locked") == 1 then return end
return true
end

View File

@ -3,7 +3,7 @@ local S = minetest.get_translator("block_league")
block_league.register_weapon("block_league:rocket_launcher", {
description = S("Rocket Launcher"),
profile_description = "Description test",
_profile_description = "Description test",
mesh = "bl_rocketlauncher.obj",
tiles = {"bl_rocketlauncher.png"},

View File

@ -3,10 +3,10 @@ local dmg1 = 3
local dmg2 = 5
local ammo2 = 3
block_league.register_weapon("block_league:smg", {
weapons_lib.register_weapon("block_league:smg", {
description = S("Submachine Gun"),
profile_description = S("Your go-to weapon for close combat"),
_profile_description = S("Your go-to weapon for close combat"),
groups = {bl_weapon_mesh = 1},
mesh = "bl_smg.obj",
tiles = {"bl_smg_texture.png"},
@ -17,11 +17,32 @@ block_league.register_weapon("block_league:smg", {
weapon_type = "gun",
magazine = 30,
reload_time = 2,
slow_down_user = true,
sound_reload = "bl_smg_reload",
can_use_weapon = function(player, action)
return block_league.util_weapon_use_check(player)
end,
can_alter_speed = function(player)
return block_league.util_on_can_alter_speed(player:get_player_name())
end,
on_reload = function(player, weapon)
block_league.util_on_reload(player:get_player_name(), weapon.name)
end,
on_reload_end = function(player, weapon)
block_league.util_on_reload_end(player:get_player_name(), weapon.name)
end,
on_after_hit = function(hitter, weapon, action, objects_hit, total_damage)
block_league.util_on_after_hit(hitter, weapon, objects_hit, total_damage)
end,
action1 = {
type = "raycast",
description = S("shoot, decrease damage with distance, @1♥", "<style color=#f66c77>" .. dmg1),
_description = S("shoot, decrease damage with distance, @1♥", "<style color=#f66c77>" .. dmg1),
damage = dmg1,
range = 30,
delay = 0.1,
@ -35,11 +56,19 @@ block_league.register_weapon("block_league:smg", {
image = "bl_smg_trail.png",
amount = 5
},
on_use = function(player, weapon, action)
block_league.util_update_mag_hud(player:get_player_name(), weapon.name)
end,
on_hit = function(hitter, target, weapon, action, damage, hit_ppint)
return block_league.util_on_hit(hitter, target, weapon, action, damage, hit_ppint)
end,
},
action2 = {
type = "raycast",
description = S("slower steadier shot with less reach, @1♥ @2►", "<style color=#f66c77>" .. dmg2, "<style color=#f6c33b>" .. ammo2),
_description = S("slower steadier shot with less reach, @1♥ @2►", "<style color=#f66c77>" .. dmg2, "<style color=#f6c33b>" .. ammo2),
damage = dmg2,
range = 20,
delay = 0.5,
@ -53,5 +82,13 @@ block_league.register_weapon("block_league:smg", {
image = "bl_smg_trail2.png",
amount = 10
},
on_use = function(player, weapon, action)
block_league.util_update_mag_hud(player:get_player_name(), weapon.name)
end,
on_hit = function(hitter, target, weapon, action, damage, hit_point)
return block_league.util_on_hit(hitter, target, weapon, action, damage, hit_point)
end
}
})
})

View File

@ -5,10 +5,10 @@ local dmg1hold = 6.8
local dmg1air = 3.7
local dmg2 = 7
block_league.register_weapon("block_league:sword", {
weapons_lib.register_weapon("block_league:sword", {
groups = {bl_sword = 1},
description = S("2H Sword"),
profile_description = S("Keep your friends close and your enemies further -Sun Tzu"),
_profile_description = S("Keep your friends close and your enemies further -Sun Tzu"),
wield_image = "bl_sword.png",
wield_scale = {x=1.3, y=1.3, z=1.3},
@ -16,6 +16,19 @@ block_league.register_weapon("block_league:sword", {
crosshair = "bl_sword_crosshair.png",
weapon_type = "melee",
slow_down_user = true,
can_use_weapon = function(player, action)
return block_league.util_weapon_use_check(player)
end,
can_alter_speed = function(player)
return block_league.util_on_can_alter_speed(player:get_player_name())
end,
on_after_hit = function(hitter, weapon, action, objects_hit, total_damage)
block_league.util_on_after_hit(hitter, weapon, objects_hit, total_damage)
end,
--[[action1 = {
type = "punch",
@ -32,11 +45,23 @@ block_league.register_weapon("block_league:sword", {
-- Vedasi https://github.com/minetest/minetest/issues/13733
action1 = {
type = "punch",
description = S("push, @1♥", "<style color=#f66c77>" .. dmg1hold),
_description = S("push, @1♥", "<style color=#f66c77>" .. dmg1hold),
damage = dmg1hold,
knockback = 40,
delay = 1.2,
sound = "bl_sword_hit",
on_hit = function(hitter, target, weapon, action, damage, hit_point)
return block_league.util_on_hit(hitter, target, weapon, action, damage, hit_point)
end,
on_end = function(player, weapon, action)
block_league.util_on_end_melee(player:get_player_name(), weapon.name)
end,
on_recovery_end = function(player, weapon, action)
block_league.util_on_recovery_melee(player:get_player_name(), weapon.name)
end,
},
--[[action1_air = {
@ -77,14 +102,14 @@ block_league.register_weapon("block_league:sword", {
action2 = {
type = "custom",
description = S("dash forward, @1♥", "<style color=#f66c77>" .. dmg2),
_description = S("dash forward, @1♥", "<style color=#f66c77>" .. dmg2),
damage = dmg2,
delay = 2.5,
physics_override = { speed = 0.5, jump = 0 },
sound = "bl_sword_dash",
on_use = function(player, weapon, action)
local pointed_objects = block_league.get_pointed_objects(player, 5, true)
local pointed_objects = weapons_lib.get_pointed_objects(player, 5, true)
local dir = player:get_look_dir()
dir.y = 0
@ -97,7 +122,11 @@ block_league.register_weapon("block_league:sword", {
player:add_velocity(player_vel)
if not pointed_objects then return end
block_league.apply_damage(player, pointed_objects, weapon, action)
end
weapons_lib.apply_damage(player, pointed_objects, weapon, action)
end,
on_recovery_end = function(player, weapon, action)
block_league.util_on_recovery_physics_override(player)
end,
}
})

View File

@ -1,864 +0,0 @@
local S = minetest.get_translator("block_league")
local function register_action() end
local function calc_action() end
local function wait_for_held_action() end
local function wait_for_charged_action() end
local function can_use_weapon() end
local function set_attack_stance() end
local function run_action() end
local function attack_loop() end
local function decrease_magazine() end
local function attack_hitscan() end
local function attack_melee() end
local function attack_bullet() end
local function attack_end() end
local function after_damage() end
local function weapon_zoom() end
local function weapon_reload() end
local function draw_particles() end
-- ogni volta che un'arma spara, se il suo ritardo è minore di 0.5s, viene eseguita
-- una funzione dopo 0.5s. Tuttavia, se si spara con un arma con ritardo minore e
-- subito dopo con un'altra (prima dei fatidici 0.5s), quella funzione da 0.5s va
-- annullata. Ne tengo traccia qui
local slow_down_func = {} -- KEY: p_name; VALUE: timer func
local MELEE_RANGE = block_league.MELEE_RANGE
--v---------------- globalstep -------------------v--
minetest.register_globalstep(function(dtime)
for _, p_name in pairs(arena_lib.get_players_in_minigame("block_league")) do
if not arena_lib.is_player_spectating(p_name) then
local p_data = arena_lib.get_arena_by_player(p_name).players[p_name]
local player = minetest.get_player_by_name(p_name)
local w_name = player:get_wielded_item():get_name()
local curr_weap = p_data.current_weapon
-- disattivo zoom
if player:get_fov() == 20 and (w_name ~= "block_league:pixelgun" or player:get_meta():get_int("bl_weapon_state") == 4) then
block_league.deactivate_zoom(player)
end
-- cambio mirino
if w_name ~= curr_weap and curr_weap then -- non so perché ma fa circa 2 step con curr_weap `nil` nonostante non ci siano ritardi
if player:get_meta():get_int("bl_weapon_state") == 2 then
player:get_meta():set_int("bl_weapon_state", 0)
end
p_data.current_weapon = w_name
block_league.HUD_crosshair_update(p_name, w_name)
end
end
end
end)
--^---------------- globalstep -------------------^--
function block_league.register_weapon(name, def)
-- usato per avere una dichiarazione pulita E al tempo stesso non dover passare
-- anche il nome in on_use (che lo richiede)
def.name = name
local groups
-- specifica il gruppo per capire come renderizzare l'arma in 3D
if def.mesh then
groups = {bl_weapon_mesh = 1}
elseif def.weapon_type == "melee" then
groups = {bl_sword = 1}
else
groups = {bl_weapon = 1}
end
minetest.register_node(name, {
name = def.name,
groups = groups,
description = def.description,
profile_description = def.profile_description or "",
drawtype = def.mesh and "mesh" or "item",
mesh = def.mesh or nil,
tiles = def.tiles or nil,
wield_image = def.wield_image or nil,
wield_scale = def.wield_scale,
inventory_image = def.inventory_image,
crosshair = def.crosshair,
use_texture_alpha = def.mesh and "clip" or nil,
weapon_type = def.weapon_type,
action1 = register_action(def.action1, "LMB"),
action1_hold = register_action(def.action1_hold, "LMB"),
action1_air = register_action(def.action1_air, "LMB"),
action2 = register_action(def.action2, "RMB"),
action2_hold = register_action(def.action2_hold, "RMB"),
action2_air = register_action(def.action2_air, "RMB"),
magazine = def.magazine,
reload_time = def.reload_time,
sound_reload = def.sound_reload,
range = def.weapon_type == "melee" and MELEE_RANGE or 0,
node_placement_prediction = "", -- disable prediction
-- LMB = first fire
on_use = function(itemstack, user, pointed_thing)
calc_action(def, 1, user, pointed_thing)
end,
-- RMB = secondary fire
on_secondary_use = function(itemstack, user, pointed_thing)
calc_action(def, 2, user, pointed_thing)
end,
on_place = function(itemstack, user, pointed_thing)
calc_action(def, 2, user, pointed_thing)
end,
-- Q = reload
on_drop = function(itemstack, user, pointed_thing)
weapon_reload(user, def)
end
})
end
-- può avere uno o più obiettivi: formato ObjectRef
function block_league.apply_damage(user, targets, weapon, action)
local knockback = action.knockback
local killed_objects = 0
local tot_damage = 0 -- in caso di più obiettivi colpiti, sommo tutto il danno per poi fare i calcoli alla fine
local p_name = user:get_player_name()
local arena = arena_lib.get_arena_by_player(p_name)
if not arena or arena.in_queue or arena.in_loading or arena.in_celebration then return end
if type(targets) ~= "table" then
targets = {targets}
end
-- per ogni obiettivo colpito
for _, target in pairs(targets) do
local damage = action.damage
local headshot = target.headshot
local target = target.object
local is_player = target:is_player()
local t_name = is_player and target:get_player_name() or target:get_luaentity().name
if target:get_hp() <= 0 then return end
if is_player and target:get_meta():get_int("bl_immunity") == 1 then return end
-- se giocatorə e obiettivo sono nella stessa squadra, annullo
if arena_lib.is_player_in_same_team(arena, p_name, t_name) then return end -- TODO: funzione block_league che controlla anche entità come le torrette (integrando questa)
-- eventuale spinta
if knockback then
local knk = vector.multiply(user:get_look_dir(), knockback)
target:add_velocity(knk)
end
-- eventuale colpo in testa
if headshot and action.type ~= "melee" then
damage = damage * 1.5
block_league.HUD_critical_show(p_name)
arena_lib.sound_play(p_name, "bl_voice_critical")
end
-- eventuale danno decrementato a seconda della distanza
if action.decrease_damage_with_distance then
local dist = vector.distance(user:get_pos(), target:get_pos())
damage = damage - (damage * dist / action.range)
end
-- aggiorno la tabella danni in caso fosse unə giocatorə
if is_player then
local dmg_table = arena.players[t_name].dmg_received
dmg_table[p_name] = {
timestamp = arena.current_time,
dmg = arena.current_time > dmg_table[p_name].timestamp - 5 and dmg_table[p_name].dmg + damage or damage,
weapon = weapon.name
}
end
-- applico il danno
target:punch(user, nil, {damage_groups = {fleshy = damage}})
-- se è ancora vivo, riproduco suono danno
if target:get_hp() > 0 then
arena_lib.sound_play(p_name, "bl_hit")
-- sennò kaputt
else
if is_player then -- TODO: dovrebbe valere anche per le torrette, ma c'è troppo da cambiare al momento
block_league.kill(arena, weapon, user, target)
end
if t_name ~= p_name then
killed_objects = killed_objects +1
end
end
tot_damage = tot_damage + damage
end
-- calcoli post-danno
after_damage(arena, p_name, weapon, tot_damage, killed_objects)
end
function block_league.kill(arena, weapon, player, target)
local p_name = player:get_player_name()
local t_name = target:get_player_name()
-- riproduco suono morte e aggiorno avatar per spettatorɜ
arena_lib.sound_play(p_name, "bl_kill")
block_league.HUD_spectate_update(arena, t_name, "alive")
if t_name ~= p_name then
-- informo dell'uccisione
block_league.HUD_kill_update(p_name, S("YOU'VE KILLED @1", t_name))
minetest.chat_send_player(t_name, minetest.colorize("#d7ded7", S("You've been killed by @1", minetest.colorize("#eea160", p_name))))
if arena_lib.is_player_spectated(p_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
block_league.HUD_kill_update(sp_name, S("@1 HAS KILLED @2", p_name, t_name))
end
end
if arena_lib.is_player_spectated(t_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(t_name)) do
minetest.chat_send_player(sp_name, minetest.colorize("#d7ded7", S("@1 has been killed by @2", minetest.colorize("#eea160", t_name), minetest.colorize("#eea160", p_name))))
end
end
local p_stats = arena.players[p_name]
local team_id = p_stats.teamID
local team = arena.teams[team_id]
local points
-- aggiungo l'uccisione
team.kills = team.kills + 1
p_stats.kills = p_stats.kills + 1
-- calcolo i punti
if arena.mode == 1 then
if player:get_meta():get_int("bl_has_ball") == 1 or target:get_meta():get_int("bl_has_ball") == 1 then
points = 4
else
points = 2
end
else
points = 2
end
p_stats.points = p_stats.points + points
local dmg_table = arena.players[t_name].dmg_received
local a_dmg = 0
local a_name
-- controlla per assist..
for pl_name, data in pairs(dmg_table) do
local dmg = dmg_table[pl_name].dmg
if pl_name ~= p_name and arena.current_time > dmg_table[pl_name].timestamp - 5 and dmg > 5 and dmg > a_dmg then
a_name = pl_name
a_dmg = dmg
end
end
-- ..e se esiste, esegui tutte le operazioni anche su chi l'ha
if a_name and arena.players[a_name] then
arena_lib.sound_play(a_name, "bl_kill")
block_league.HUD_kill_update(a_name, S("YOU'VE CONTRIBUTED TO KILL @1", t_name))
if arena_lib.is_player_spectated(a_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
block_league.HUD_kill_update(sp_name, S("@1 HAS CONTRIBUTED TO KILL @2", a_name, t_name))
end
end
arena.players[a_name].points = arena.players[a_name].points + (points / 2)
block_league.HUD_spectate_update(arena, a_name, "points")
end
-- aggiorno HUD
block_league.HUD_infopanel_update_points(arena, team_id)
block_league.HUD_spectate_update(arena, p_name, "points")
block_league.HUD_log_update(arena, weapon.inventory_image, p_name, t_name, a_name)
-- se è DM e il limite è raggiunto, finisce partita
if arena.mode == 2 then
block_league.HUD_scoreboard_update_score(arena)
if team.kills == arena.score_cap then
local mod = arena_lib.get_mod_by_player(p_name)
arena_lib.load_celebration(mod, arena, team_id)
end
end
else
block_league.HUD_kill_update(t_name, S("You've killed yourself"))
block_league.HUD_log_update(arena, "bl_log_suicide.png", p_name, t_name)
end
end
function block_league.deactivate_zoom(player)
--TODO: rimuovere HUD zoom armi
player:set_fov(0, nil, 0.1)
local p_name = player:get_player_name()
-- TODO: mettere FOV personalizzato così da evitare questo controllo; essendo un
-- FPS, è più che sensato
if not arena_lib.is_player_in_arena(p_name) then return end
local p_meta = player:get_meta()
local arena = arena_lib.get_arena_by_player(p_name)
if arena.players[p_name].stamina > 0 and
p_meta:get_int("bl_weapon_state") == 0 and
p_meta:get_int("bl_is_speed_locked") == 0 then
player:set_physics_override({speed = block_league.SPEED})
end
end
function block_league.hitter_or_suicide(arena, player, dmg_rcvd_table, no_hitter_img)
-- se le armi son disabilitate (quindi o in caricamento o dopo punto o in celebrazione) non mostrare niente
if arena.weapons_disabled then
block_league.HUD_spectate_update(arena, player:get_player_name(), "alive")
return end
local last_hitter = ""
local last_hitter_timestamp = 99999
for pla_name, dmg_data in pairs(dmg_rcvd_table) do
if arena.current_time > dmg_data.timestamp - 5 and last_hitter_timestamp > dmg_data.timestamp then
last_hitter = pla_name
last_hitter_timestamp = dmg_data.timestamp
end
end
if last_hitter ~= "" then
block_league.kill(arena, minetest.registered_nodes[dmg_rcvd_table[last_hitter].weapon], minetest.get_player_by_name(last_hitter), player)
else
local p_name = player:get_player_name()
block_league.HUD_spectate_update(arena, p_name, "alive")
block_league.HUD_log_update(arena, no_hitter_img, p_name, "")
end
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
function register_action(action, key)
if not action then return end
action.key = key
if action.type == "raycast" then
action.ammo_per_use = action.ammo_per_use or 1
action.delay = action.delay or 0.5
action.fire_spread = action.fire_spread or 0
action.loading_time = action.loading_time or 0
elseif action.type == "bullet" then
assert(action.bullet, "Missing bullet in bullet action type")
block_league.register_bullet(action.bullet, action.damage, action.trail)
elseif action.type == "punch" then
assert(action.continuous_fire == nil, "Punch actions can't have continuous fire")
end
return action
end
function calc_action(weapon, action_id, player, pointed_thing)
local is_holdable = ((action_id == 1 and weapon.action1_hold) or (action_id == 2 and weapon.action2_hold)) and true
local in_the_air = weapon.weapon_type == "melee" and block_league.is_in_the_air(player)
local action, held_action
if not in_the_air and is_holdable then
action = action_id == 1 and weapon.action1_hold or weapon.action2_hold
held_action = true
else
if action_id == 1 then
action = (in_the_air and weapon.action1_air) and weapon.action1_air or weapon.action1
else
action = (in_the_air and weapon.action2_air) and weapon.action2_air or weapon.action2
end
end
if not action or not can_use_weapon(player, weapon, action) then return end
set_attack_stance(player, action)
-- TODO: funzione per tempo d'attesa, prob sotto va poi messo in funzione a parte
if action.attack_on_release then
local held_key = action_id == 1 and "LMB" or "RMB"
player:get_meta():set_int("bl_weapon_state", 2)
wait_for_charged_action(weapon, action, held_key, player, action.load_time, 0)
elseif held_action then
local held_key = action_id == 1 and "LMB" or "RMB"
player:get_meta():set_int("bl_weapon_state", 2)
wait_for_held_action(weapon, action, held_key, player, 0.3)
else
run_action(weapon, action, player, pointed_thing)
end
end
function wait_for_held_action(weapon, action, held_key, player, countdown)
minetest.after(0.1, function()
if not can_use_weapon(player, weapon, action, true) then return end
if player:get_player_control()[held_key] then
if countdown <= 0 then
run_action(weapon, action, player)
else
countdown = countdown - 0.1
wait_for_held_action(weapon, action, held_key, player, countdown)
end
else
local action = held_key == "LMB" and weapon.action1 or weapon.action2
run_action(weapon, action, player)
end
end)
end
function wait_for_charged_action(weapon, action, held_key, player, load_time, time)
minetest.after(0.1, function()
if not can_use_weapon(player, weapon, action, nil, true) then return end
if player:get_player_control()[held_key] then
if load_time > time then
time = time + 0.1
end
wait_for_charged_action(weapon, action, held_key, player, load_time, time)
else
run_action(weapon, action, player)
end
end)
end
function can_use_weapon(player, weapon, action, held, charged)
local p_name = player:get_player_name()
local p_meta = player:get_meta()
if not arena_lib.is_player_in_arena(p_name)
or player:get_hp() <= 0
or p_meta:get_int("bl_death_delay") == 1 then
return end
if action.type == "zoom" then
return p_meta:get_int("bl_weapon_state") ~= 4
end
local arena = arena_lib.get_arena_by_player(p_name)
if arena.weapons_disabled then return end
if held then
if p_meta:get_int("bl_weapon_state") > 2 then
return end
elseif charged then
if p_meta:get_int("bl_weapon_state") > 2 then
return end
else
local w_magazine = arena.players[p_name].weapons_magazine[weapon.name]
if p_meta:get_int("bl_weapon_state") ~= 0 or
(weapon.magazine and (w_magazine <= 0 or action.ammo_per_use > w_magazine)) then
return end
end
return true
end
function set_attack_stance(player, action)
local p_name = player:get_player_name()
block_league.remove_immunity(player)
if slow_down_func[p_name] then
slow_down_func[p_name]:cancel()
end
local p_meta = player:get_meta()
if p_meta:get_int("bl_is_speed_locked") == 0 then
if action.physics_override then
if action.physics_override == "FREEZE" then
local p_pos = player:get_pos()
local p_y = player:get_look_horizontal()
local dummy = minetest.add_entity(p_pos, "block_league:dummy")
player:set_attach(dummy, "", {x=0,y=-5,z=0}, {x=0, y=-math.deg(p_y), z=0})
else
player:set_physics_override(action.physics_override)
end
p_meta:set_int("bl_is_speed_locked", 1)
else
player:set_physics_override({ speed = block_league.SPEED_LOW })
end
end
end
function run_action(weapon, action, player, pointed_thing)
if action.type == "raycast" or action.type == "bullet" or action.type == "custom" then
player:get_meta():set_int("bl_weapon_state", 2)
attack_loop(weapon, action, player)
elseif action.type == "punch" then
player:get_meta():set_int("bl_weapon_state", 2)
attack_loop(weapon, action, player, pointed_thing)
elseif action.type == "zoom" then
weapon_zoom(action, player)
elseif action.type == "install" then
player:get_meta():set_int("bl_weapon_state", 2)
-- TODO
elseif action.type == "parry" then
-- player:get_meta():set_int("bl_weapon_state", 5)
end
end
function attack_loop(weapon, action, player, pointed_thing)
local p_name = player:get_player_name()
arena_lib.sound_play(p_name, action.sound)
if action.type == "punch" then
attack_melee(player, weapon, action, pointed_thing)
elseif action.type == "custom" then
action.on_use(player, weapon, action)
else
decrease_magazine(player, weapon, action.ammo_per_use)
if action.type == "raycast" then
attack_hitscan(player, weapon, action)
elseif action.type == "bullet" then
attack_bullet(player, weapon.bullet)
end
end
-- interrompo lo sparo se non è un'arma a fuoco continuo
if not action.continuous_fire then
attack_end(player, weapon, action.delay)
else
minetest.after(action.delay, function()
if not arena_lib.is_player_in_arena(p_name, "block_league") then return end
local arena = arena_lib.get_arena_by_player(p_name)
local w_magazine = arena.players[p_name].weapons_magazine[weapon.name]
if player:get_player_control()[action.key]
and player:get_meta():get_int("bl_weapon_state") == 2
and (weapon.magazine and (w_magazine > 0 and action.ammo_per_use <= w_magazine)) then
attack_loop(weapon, action, player)
else
attack_end(player, weapon, action.delay)
end
end)
end
end
function decrease_magazine(player, weapon, amount)
local p_name = player:get_player_name()
local w_name = weapon.name
local arena = arena_lib.get_arena_by_player(p_name)
local p_data = arena.players[p_name]
p_data.weapons_magazine[w_name] = p_data.weapons_magazine[w_name] - amount
-- automatically reload if the magazine is now empty
if p_data.weapons_magazine[w_name] == 0 then
weapon_reload(player, weapon)
else
block_league.HUD_weapons_update(arena, p_name, w_name)
return true
end
end
function attack_hitscan(user, weapon, action)
local pointed_objects = block_league.get_pointed_objects(user, action.range or MELEE_RANGE, action.pierce)
if action.trail then
local dir = user:get_look_dir()
local pos_head = vector.add(vector.add(user:get_pos(), vector.new(0,1.475,0)), dir)
draw_particles(action.trail, dir, pos_head, action.range, action.pierce)
end
if pointed_objects then
block_league.apply_damage(user, pointed_objects, weapon, action)
end
end
function attack_melee(user, weapon, action, pointed_thing)
if pointed_thing.type ~= "object" then return end
local object = pointed_thing.ref
-- TEMP: non posso calcolare il colpo alla testa perché i `pointed_thing` nativi
-- non ritornano `intersection_point`. Vedasi https://github.com/minetest/minetest/issues/13734
--local headshot = (pointed_thing.intersection_point.y - object:get_pos().y) > 1.275 and true
local headshot = false
local target = {{object = object, headshot = headshot}}
block_league.apply_damage(user, target, weapon, action)
end
function attack_bullet(user, bullet)
local pos = user:get_pos()
local pos_head = {x = pos.x, y = pos.y + user:get_properties().eye_height, z = pos.z}
local bullet_name = bullet.name .. '_entity'
local bullet = minetest.add_entity(pos_head, bullet_name, user:get_player_name())
local speed = bullet.speed
local dir = user:get_look_dir()
bullet:set_velocity({
x=(dir.x * speed),
y=(dir.y * speed),
z=(dir.z * speed),
})
local yaw = user:get_look_horizontal()
local pitch = user:get_look_vertical()
local rotation = ({x = -pitch, y = yaw, z = 0})
bullet:set_rotation(rotation)
end
function attack_end(player, weapon, delay)
local p_name = player:get_player_name()
local p_meta = player:get_meta()
if p_meta:get_int("bl_weapon_state") == 4 then return end
p_meta:set_int("bl_weapon_state", 3)
local arena = arena_lib.get_arena_by_player(p_name)
local w_name = weapon.name
-- se sono armi bianche, aggiorno l'HUD qui che segnala che son state usate
if not weapon.magazine then
block_league.HUD_weapons_update(arena, p_name, w_name, true)
block_league.HUD_crosshair_update(p_name, w_name, true)
end
-- finisce attesa e ripristina eventuale fisica personalizzata
minetest.after(delay, function()
if not arena_lib.is_player_in_arena(p_name, "block_league") then return end
if p_meta:get_int("bl_weapon_state") ~= 4 then
p_meta:set_int("bl_weapon_state", 0)
end
-- se ha la fisica personalizzata, ripristinala
if p_meta:get_int("bl_is_speed_locked") == 1 then
p_meta:set_int("bl_is_speed_locked", 0)
if player:get_attach() then
player:get_attach():remove()
else
player:set_physics_override(block_league.PHYSICS)
if arena.players[p_name].stamina == 0
or p_meta:get_int("bl_weapon_state") ~= 0
or player:get_fov() ~= 0 then
player:set_physics_override({speed = block_league.SPEED_LOW})
end
end
-- TEMP: se `delay` è 0.5, c'è il rischio che la funzione sotto venga chiamata
-- prima di questa. Serve https://github.com/minetest/minetest/issues/13477
elseif player:get_physics_override().speed ~= block_league.SPEED
and arena.players[p_name].stamina > 0
and p_meta:get_int("bl_weapon_state") == 0
and player:get_fov() == 0 then
player:set_physics_override({speed = block_league.SPEED})
end
-- ripristino colore HUD per le armi bianche (faccio qui per non aver un terzo after più in alto)
if not weapon.magazine then
local curr_weap = arena.players[p_name].current_weapon
block_league.HUD_weapons_update(arena, p_name, w_name, false)
block_league.HUD_crosshair_update(p_name, curr_weap, false)
end
end)
-- ripristina velocità dopo 0.5 secondi
slow_down_func[p_name] = minetest.after(0.5, function()
if not arena_lib.is_player_in_arena(p_name, "block_league")
or arena.players[p_name].stamina == 0
or p_meta:get_int("bl_weapon_state") ~= 0
or p_meta:get_int("bl_is_speed_locked") == 1
or player:get_fov() ~= 0
then return end
player:set_physics_override({ speed = block_league.SPEED })
end)
end
function after_damage(arena, p_name, weapon, damage, killed_players)
if arena.mode == 0 then return end -- nessun prestigio nel tutorial
-- aggiorno danno totale inflitto ed eventualmente aumento i punti
local p_data = arena.players[p_name]
local prev_dmg_dealt = p_data.dmg_dealt
local dmg_dealt = prev_dmg_dealt + damage
local dmg_points = math.floor(dmg_dealt/10) - math.floor(prev_dmg_dealt/10)
if dmg_points > 0 then
p_data.points = p_data.points + dmg_points
block_league.HUD_infopanel_update_points(arena, p_data.teamID)
block_league.HUD_spectate_update(arena, p_name, "points")
end
p_data.dmg_dealt = dmg_dealt
-- medaglie
--
-- eventuale medaglia doppia/tripla uccisione
if killed_players > 1 then
if killed_players == 2 then
block_league.show_medal(p_name, "bl_medal_doublekill.png")
elseif killed_players >= 3 then
block_league.show_medal(p_name, "bl_medal_triplekill.png")
end
arena_lib.send_message_in_arena(arena, "both",minetest.colorize("#d7ded7", S("@1 has killed @2 players in a row!", minetest.colorize("#eea160", p_name), killed_players)))
end
-- prestigi
--
-- niente prestigi se non ci sono almeno 6 persone
if arena.players_amount < 6 then return end
--TODO
--[[
if killed_players >= 2 and weapon.name == "block_league:pixelgun" then
achvmt_lib.award("block_league:quellochesarà", p_name)
end
]]
end
function weapon_zoom(action, player)
local p_meta = player:get_meta()
if player:get_fov() ~= action.fov then
player:set_fov(action.fov, nil, 0.1)
-- TODO: applica texture, riproduci suono
else
block_league.deactivate_zoom(player)
end
end
function weapon_reload(player, weapon)
local w_name = weapon.name
local p_name = player:get_player_name()
local p_meta = player:get_meta()
local arena = arena_lib.get_arena_by_player(p_name)
if not arena or not arena.in_game or player:get_hp() <= 0
or arena.weapons_disabled or weapon.weapon_type == "melee" or not weapon.magazine
or weapon.magazine == 0 or p_meta:get_int("bl_weapon_state") == 4
or arena.players[p_name].weapons_magazine[w_name] == weapon.magazine
then return end
arena_lib.sound_play(p_name, weapon.sound_reload)
p_meta:set_int("bl_weapon_state", 4)
-- rimuovo eventuale zoom
if weapon.action2 and weapon.action2.type == "zoom" and player:get_fov() == weapon.action2.fov then
block_league.deactivate_zoom(player)
end
if p_meta:get_int("bl_is_speed_locked") == 0 then
player:set_physics_override({ speed = block_league.SPEED_LOW })
end
block_league.HUD_weapons_update(arena, p_name, w_name, true)
block_league.HUD_crosshair_update(p_name, w_name, true)
minetest.after(weapon.reload_time, function()
if not arena_lib.is_player_in_arena(p_name, "block_league") then return end
p_meta:set_int("bl_weapon_state", 0)
if p_meta:get_int("bl_is_speed_locked") == 0 then
local vel = arena.players[p_name].stamina > 0 and block_league.SPEED or block_league.SPEED_LOW
player:set_physics_override({ speed = vel })
end
local p_data = arena.players[p_name]
local curr_weap = p_data.current_weapon
p_data.weapons_magazine[w_name] = weapon.magazine
block_league.HUD_weapons_update(arena, p_name, w_name, false)
block_league.HUD_crosshair_update(p_name, curr_weap, false)
end)
end
function draw_particles(particle, dir, origin, range, pierce)
local check_coll = not pierce
minetest.add_particlespawner({
amount = particle.amount,
time = 0.3, -- TODO: meglio funzione che approssima distanza? Time era 0.3, min/max erano impact_dist/(range * 1.5)
pos = vector.new(origin),
vel = vector.multiply(dir, range),
size = 2,
collisiondetection = check_coll,
collision_removal = check_coll,
texture = particle.image
})
end

View File

@ -1,308 +1,186 @@
local function cast_raycast() end
local function get_shooter_left_dir() end
local function get_shooter_up_dir() end
local function debug_particles() end
local S = minetest.get_translator("block_league")
local SPEED_LOW = block_league.SPEED * block_league.SHOOT_SPEED_MULTIPLIER
-- per bloccare fisica
local dummy = {
initial_properties = {
physical = true,
pointable = false,
collide_with_objects = false,
visual = "sprite",
visual_size = {x = 0, y = 0, z = 0},
textures = { "blank.png" }
},
function block_league.util_weapon_use_check(player)
local p_name = player:get_player_name()
if not arena_lib.is_player_playing(p_name, "block_league") then return true end
-- quando sbuca, se non ha prole, cancellala
on_activate = function(self, staticdata, dtime_s)
minetest.after(0.1, function()
if #self.object:get_children() == 0 then
self.object:remove()
end
end)
end
}
local arena = arena_lib.get_arena_by_player(p_name)
minetest.register_entity("block_league:dummy", dummy)
if arena.weapons_disabled or player:get_meta():get_int("bl_death_delay") == 1 then
return end
-- I cast a 2x2 grid (assisted aim) to prevent the 0.1 delay. The grid value is
-- actually hardcoded because:
-- 1. it works and I don't need more features from it
-- 2. I haven't got enough knowledge about vectors and rotations anyway
function block_league.get_pointed_objects(shooter, range, has_piercing, entity_table)
local height, look_dir
if entity_table then
height = entity_table.height
look_dir = entity_table.dir
else
height = 1.475
look_dir = shooter:get_look_dir()
end
local hit_pointed_things = {}
local left_dir = get_shooter_left_dir(shooter)
local head_up_dir = get_shooter_up_dir(shooter, look_dir)
local center = shooter:get_pos() + look_dir + {x=0, y=height, z=0}
local grid_width = 0.46
local r_amount = 3
local x_step = (grid_width / r_amount) * (-left_dir)
local y_step = (grid_width / r_amount) * head_up_dir
local ray_pos = center + (x_step / r_amount) + (y_step / r_amount)
for row = 1, r_amount do
for column = 1, r_amount do
local pthings = cast_raycast(shooter, ray_pos, look_dir, range, has_piercing)
--debug_particles(look_dir, ray_pos, 30)
if pthings then
-- rimuovo giocator3 già colpit3 da altro raggio
for k, possible_target in pairs(pthings) do
local object = possible_target.object
local target_name = possible_target.object:get_player_name() or possible_target.object:get_luaentity().name
for _, target in pairs(hit_pointed_things) do
local hit_target_name = target.object:get_player_name() or target.object:get_luaentity().name
if target_name == hit_target_name then
pthings[k] = nil
break
end
end
end
table.insert_all(hit_pointed_things, pthings)
end
ray_pos = ray_pos - x_step
end
ray_pos = ray_pos - y_step
ray_pos = ray_pos + x_step * r_amount
end
return hit_pointed_things
block_league.remove_immunity(player)
return true
end
function block_league.util_on_can_alter_speed(p_name)
if not arena_lib.is_player_playing(p_name, "block_league") then return true end
local arena = arena_lib.get_arena_by_player(p_name)
return arena.players[p_name].stamina > 0
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
-- ritorna un array di giocatori con il numero di giocatori trovati a indice 1.
-- Se non trova giocatori diversi da se stesso ritorna nil
function cast_raycast(user, origin, dir, range, has_piercing)
function block_league.util_update_mag_hud(p_name, w_name)
if not arena_lib.is_player_playing(p_name, "block_league") then return end
local a = vector.add(origin, vector.multiply(dir, 0))
local b = vector.add(origin, vector.multiply(dir, range))
local ray = minetest.raycast(a, b)
local objects = {}
local arena = arena_lib.get_arena_by_player(p_name)
block_league.HUD_weapons_update(arena, p_name, w_name)
end
-- controllo su ogni cosa attraversata dal raycast (da a a b)
for hit in ray do
-- se è un oggetto
if hit.type == "object" then
-- se è un'entità
if not hit.ref:is_player() then
table.insert(objects, {object=hit.ref, headshot=false})
--[[if entity.initial_properties.is_bullet or entity.initial_properties.is_grenade then
--distrugge sia il proiettile con cui collide che se stesso
entity.old_p_name = entity.p_name
entity.p_name = user:get_player_name()
entity:_destroy()
end]]
function block_league.util_on_hit(hitter, target, weapon, action, damage, hit_point)
local p_name = hitter:get_player_name()
local is_target_player = target:is_player()
local t_name = is_target_player and target:get_player_name() or target:get_luaentity().name
-- se è un giocatore (e non chi spara)
elseif hit.ref ~= user then
if (hit.intersection_point.y - hit.ref:get_pos().y) > 1.275 then
table.insert(objects, {object=hit.ref, headshot=true})
else
table.insert(objects, {object=hit.ref, headshot=false})
end
end
if not arena_lib.is_player_playing(p_name, "block_league") or (is_target_player and not arena_lib.is_player_playing(t_name, "block_league")) then return 0 end
local is_player = hit.ref:is_player()
local t_name = is_player and hit.ref:get_player_name() or hit.ref:get_luaentity().name
local arena = arena_lib.get_arena_by_player(p_name)
if not has_piercing then return objects end
if arena_lib.is_player_in_same_team(arena, p_name, t_name) then return 0 end
local is_critical = hit_point and hit_point.y - target:get_pos().y > 1.275 -- TODO: la spada non lo passa
if is_critical then
damage = damage * 1.5
block_league.HUD_critical_show(p_name)
audio_lib.play_sound("bl_voice_critical", {to_player = p_name})
end
if is_target_player then
local dmg_table = arena.players[t_name].dmg_received
dmg_table[p_name] = {
timestamp = arena.current_time,
dmg = arena.current_time > dmg_table[p_name].timestamp - 5 and dmg_table[p_name].dmg + damage or damage,
weapon = weapon.name
}
end
return damage
end
function block_league.util_on_after_hit(hitter, weapon, objects_hit, total_damage)
local p_name = hitter:get_player_name()
if not arena_lib.is_player_playing(p_name, "block_league") then return end
local arena = arena_lib.get_arena_by_player(p_name)
if arena.mode == 0 then return end -- nessun prestigio nel tutorial
-- aggiorno danno totale inflitto ed eventualmente aumento i punti
local p_data = arena.players[p_name]
local prev_dmg_dealt = p_data.dmg_dealt
local dmg_dealt = prev_dmg_dealt + total_damage
local dmg_points = math.floor(dmg_dealt/10) - math.floor(prev_dmg_dealt/10)
if dmg_points > 0 then
p_data.points = p_data.points + dmg_points
block_league.HUD_infopanel_update_points(arena, p_data.teamID)
block_league.HUD_spectate_update(arena, p_name, "points")
end
p_data.dmg_dealt = dmg_dealt
local killed_players = 0
for _, t_data in pairs(objects_hit) do
if t_data.type == "player" and t_data.ref:get_hp() <= 0 then
block_league.kill(arena, weapon, hitter, t_data.ref)
killed_players = killed_players + 1
else
-- se è un nodo mi fermo, e ritorno l'array se > 0 (ovvero ha trovato obiettivi)
if hit.type == "node" then
if #objects > 0 then
return has_piercing and objects or {objects[1]}
else
return
end
end
end
end
-- se ho sparato a un obiettivo senza incrociare blocchi
if #objects > 0 then
return has_piercing and objects or {objects[1]}
else
return
end
end
function get_shooter_left_dir(shooter)
local yaw = shooter:get_look_horizontal() or shooter:get_yaw()
local pl_left_dir = vector.new(math.cos(yaw), 0, math.sin(yaw))
return vector.normalize(pl_left_dir)
end
function get_shooter_up_dir(shooter, dir)
return vector.rotate_around_axis(dir, get_shooter_left_dir(shooter), math.pi/2)
end
function debug_particles(dir, origin, range)
minetest.add_particlespawner({
amount = 5,
time = 0.3,
pos = vector.new(origin),
vel = vector.multiply(dir, range),
size = 2,
texture = "bl_smg_trail.png"
})
end
------------------------------
-- not my code, don't know, don't ask
------------------------------
block_league.explode = function(self)
local explosion_range = self.initial_properties.explosion_range
local explosion_damage = self.initial_properties.explosion_damage
local origin = self.object:get_pos()
local p_name = self.p_name
if origin == nil then return end
if origin.x == nil or origin.y == nil or origin.z == nil then return end
local objs = minetest.env:get_objects_inside_radius(origin, explosion_range)
local entities = {}
-- Se ho colpito qualcosa
if objs then
for _, obj in ipairs(objs) do
if obj:is_player() then
local p_pos = obj:get_pos()
local lenx = math.abs(p_pos.x - origin.x)
local leny = math.abs(p_pos.y - origin.y)
local lenz = math.abs(p_pos.z - origin.z)
local hypot = math.sqrt((lenx * lenx) + (lenz * lenz))
local dist = math.sqrt((hypot * hypot) + (leny * leny))
local damage = explosion_damage - (explosion_damage * dist / explosion_range)
local target_name = obj:get_player_name()
if self.old_p_name and p_name == target_name then
p_name = self.old_p_name
end
-- Se colpisco me stesso, prendo 1/5 di danno
if (target_name ~= p_name) then
-- TODO: non funziona, la funzione è stata cambiata. Bisogna far passare l'arma
block_league.apply_damage(minetest.get_player_by_name(p_name), obj, damage, 0, false)
else
block_league.apply_damage(minetest.get_player_by_name(p_name), obj, (damage/5), 0, false)
end
elseif obj ~= self.object and obj:get_luaentity() then
local entity = obj:get_luaentity()
table.insert(entities, entity)
end
arena_lib.sound_play(p_name, "bl_hit")
end
end
if #entities == 0 then return end
self.object:remove()
for _,entity in pairs(entities) do
if entity.initial_properties ~= nil then
if entity.initial_properties.is_bullet then
entity.old_p_name = entity.p_name
entity.p_name = p_name
entity:_destroy()
end
-- medaglie
--
-- eventuale medaglia doppia/tripla uccisione
if killed_players > 1 then
if killed_players == 2 then
block_league.show_medal(p_name, "bl_medal_doublekill.png")
elseif killed_players >= 3 then
block_league.show_medal(p_name, "bl_medal_triplekill.png")
end
arena_lib.send_message_in_arena(arena, "both",minetest.colorize("#d7ded7", S("@1 has killed @2 players in a row!", minetest.colorize("#eea160", p_name), killed_players)))
end
-- prestigi
--
-- niente prestigi se non ci sono almeno 6 persone
if arena.players_amount < 6 then return end
--TODO
--[[
if killed_players >= 2 and weapon.name == "block_league:pixelgun" then
achvmt_lib.award("block_league:quellochesarà", p_name)
end
]]
end
function block_league.util_on_end_melee(p_name, w_name)
local arena = arena_lib.get_arena_by_player(p_name)
if not arena then return end
block_league.HUD_weapons_update(arena, p_name, w_name, true)
end
function block_league.util_on_recovery_melee(p_name, w_name)
local arena = arena_lib.get_arena_by_player(p_name)
if not arena then return end
block_league.HUD_weapons_update(arena, p_name, w_name, false)
end
function block_league.util_on_recovery_physics_override(player)
local p_name = player:get_player_name()
local arena = arena_lib.get_arena_by_player(p_name)
if not arena then return end
local p_meta = player:get_meta()
if player:get_physics_override().speed == SPEED_LOW and
p_meta:get_int("wl_weapon_state") == 0 and
p_meta:get_int("wl_zooming") == 0 and
p_meta:get_int("bl_has_ball") == 0 and
arena.players[p_name].stamina > 0 then
player:set_physics_override({speed = block_league.SPEED})
end
end
block_league.grenade_explode = function(self)
local explosion_range = self.initial_properties.explosion_range
local explosion_damage = self.initial_properties.explosion_damage
local origin = self.object:get_pos()
local p_name = self.p_name
if origin == nil then return end
if origin.x == nil or origin.y == nil or origin.z == nil then return end
local objs = minetest.env:get_objects_inside_radius(origin, explosion_range)
local entities = {}
-- Se ho colpito qualcosa
if objs then
for _, obj in ipairs(objs) do
if obj:is_player() then
function block_league.util_on_reload(p_name, w_name)
if not arena_lib.is_player_playing(p_name, "block_league") then return end
local p_pos = obj:get_pos()
local lenx = math.abs(p_pos.x - origin.x)
local leny = math.abs(p_pos.y - origin.y)
local lenz = math.abs(p_pos.z - origin.z)
local hypot = math.sqrt((lenx * lenx) + (lenz * lenz))
local dist = math.sqrt((hypot * hypot) + (leny * leny))
local damage = explosion_damage - (explosion_damage * dist / explosion_range)
local target_name = obj:get_player_name()
if self.old_p_name and p_name == target_name then
p_name = self.old_p_name
end
-- TODO: non funziona, la funzione è stata cambiata. Bisogna far passare l'arma
block_league.apply_damage(minetest.get_player_by_name(p_name), obj, damage, 0, false)
elseif obj ~= self.object and obj:get_luaentity() then
local entity = obj:get_luaentity()
table.insert(entities, entity)
end
end
end
if #entities == 0 then return end
self.object:remove()
for _,entity in pairs(entities) do
if entity.initial_properties ~= nil then
if entity.initial_properties.is_bullet then
entity.old_p_name = entity.p_name
entity.p_name = p_name
entity:_destroy()
end
end
end
local arena = arena_lib.get_arena_by_player(p_name)
block_league.HUD_weapons_update(arena, p_name, w_name, true)
end
function block_league.util_on_reload_end(p_name, w_name)
if not arena_lib.is_player_playing(p_name, "block_league") then return end
local arena = arena_lib.get_arena_by_player(p_name)
block_league.HUD_weapons_update(arena, p_name, w_name, false)
end